Skip to content

Service Agent Goal Completion Audit

Status: active-not-complete.

Scope

This audit guards the difference between spawn-ready orchestration and full goal completion. The current service-agent manifest, task packs, proof ledger, and VitePress navigation can be coherent while the broad HocTapAZ microservice rollout is still not complete.

In this rollout, spawn-ready is not complete. Accepted per-service handoffs are allowed, but they do not complete the broad goal by themselves. A service row can move to a closeout-accepted-...-not-complete state only after its agent handoff includes route/default cutover status, rollback notes, focused test output, and remaining-risk closure for one bounded slice. IAM/Profile default promotion has the extra gate that production-like populated target validation must attach the captured migrator run report and enforce IAM_PROFILE_LIVE_VALIDATION_REQUIRE_RUN_REPORT=1.

Command

bash
make test-service-agent-goal-completion-audit

The guard passes only when:

  • docs/agents/service-agent-manifest.json keeps 23 canonical service packets and one retirement packet.
  • docs/agents/service-agent-proof-ledger.json keeps every service row in an explicit not-complete proof state with an open proof gate.
  • The proof ledger completion rules keep spawn-ready distinct from completion.
  • The closeout ledger keeps every service row in an explicit not-complete handoff state; accepted per-service handoffs are allowed only when the handoff file exists under docs/agents/handoffs/ and proves audit, investigate, code, test, and fix evidence for a bounded service slice.
  • Default route promotion remains gated by route-specific live/browser proof and rollback evidence.
  • The accepted SVC-006-public-route-guard-proof handoff proves classroom tenant scoping and owner-local profile/organization references while keeping the public classroom routes legacy-proxied; it does not approve promotion.
  • The accepted SVC-007-student-course-route-proof handoff proves enrolled student projection and route guards, while explicitly leaving live/browser and default-route promotion evidence open.
  • The accepted SVC-008-question-save-reload-route-proof handoff proves native question update/reload persistence and route guards, while explicitly leaving live editor/browser promotion evidence open.
  • The accepted SVC-009-exam-attempt-public-proof handoff proves the exam-to-attempt runtime access contract and sensitive-field boundary, while explicitly leaving live/browser start promotion evidence open.
  • The accepted SVC-010-attempt-public-idempotency-proof handoff proves the native attempt workflow, exact replay after grading, timeout/retake policy, and result visibility/redaction, while explicitly leaving live/browser and default attempt-route promotion evidence open.
  • The accepted SVC-011-storage-media-browser-proof handoff proves bounded document-service storage/media parity and lifecycle behavior. The Teacher Import Review now has local scoped-media browser evidence, while generic shared-store upload/read parity and default storage route promotion remain open.
  • The accepted SVC-012-import-route-proof-bundle handoff proves matching import route rehearsals, Teacher-native local browser creation, and review roundtrip contract coverage, while explicitly leaving deployed/default route promotion and rollback proof open.
  • The accepted SVC-003-default-auth-cutover-proof-bundle handoff records the conservative IAM auth candidate boundary and keeps production-like, browser, candidate-review, and rollback gates open.
  • The accepted SVC-004-default-profile-cutover-proof-bundle handoff records Profile ownership and non-default route evidence while keeping populated, candidate-diff, browser, and rollback gates open.
  • IAM/Profile promotion requires production-like populated target validation, a required migrator run report, and zero issue / zero rejected row reconciliation proof.
  • The IAM/Profile default proof bundle still records routePromotionApproved=false, defaultRouteTableModified=false, mode=live, targetProvenance=production-like, matching candidateRouteTableHash / gatewayRouteTableHash, and no *_SELF_TEST=1 command variables for cutover review.
  • A completed proof bundle must also pass make test-iam-profile-default-cutover-review-artifact, which validates the captured artifact offline and rejects fixture/self-test evidence before human route-promotion review.
  • Service-agent completion still requires make test-service-agent-closeout-ledger with accepted per-service handoff paths. A row with an accepted handoff can still remain not-complete when route/default, live/browser, migration, or rollback proof gates remain open.

Current Result

The expected current result is active-not-complete. This is intentional: the service responsibility matrix and spawn packets are ready for parallel service agents, but the broad objective still needs service-by-service closeout, production-like IAM/Profile data validation, default route promotion evidence, and browser/rollback proof before it can be marked complete.

Latest IAM/Profile default-cutover artifact triage reinforces that status: output/qa/iam-profile-default-cutover-proof-bundle-20260715-053933/ has all eight child self-tests passed, but is mode=self-test with targetProvenance=fixture_only. The offline review guard rejects it because it lacks production-like live minimums, a required migrator run report summary, and matching candidate/gateway route-table hashes. Per-step summaries now exist, but it is still runtime-guard evidence only, not completion evidence. The same-target fixture rehearsal at output/qa/iam-profile-target-validation-20260710/ now passes populated backfill, UUID readiness/FK/PK promotion, and 22-item reconciliation checks, but remains fixture-only and does not close the production-like cutover gate. That sequence was rerun after the IAM bootstrap-organization migration on 2026-07-13 under output/qa/iam-profile-target-validation-20260713-1783939084132/; the reconciliation was scoped to mapped legacy organizations and again reported zero issues. It remains fixture-only evidence. The read-only legacy source report was retried on 2026-07-10 and the configured PostgreSQL endpoint refused the connection; no source or target mutation was attempted, so the required source-side report remains missing.

On 2026-07-13, a fresh isolated Compose candidate recheck captured real Gateway live, public-web browser, and rollback artifacts under output/qa/iam-profile-default-candidate-isolated-20260713-121616/. The candidate table promoted only auth-google-config and auth-me; its served Gateway hash matched the generated table, the browser observed native route headers, and a replacement Gateway running the unchanged default table returned the promoted paths to broad legacy routes. This closes none of the production-like gates: the project used fresh volumes, no source report or required migrator report was attached, and deploy/gateway/routes.json was not modified.

Latest Local Regression Evidence

On 2026-07-13, make test-service-readiness passed every service-agent guard and GOTOOLCHAIN=go1.25.11 go test ./services/... -count=1. Frontend typecheck, lint, 276 Vitest cases, six-app build, and the 44-case Chromium Playwright suite also passed. The suite covers authenticated/anonymous and responsive workflows across admin, teacher, student, parent, staff, and public apps. Playwright owned isolated Vite ports 5301-5306 for that run, so it did not reuse a developer's 5201-5206 servers.

On 2026-07-14, after the Teacher similar-preview flow began retaining its Question Bank reference provenance in the reviewed draft, the current dirty worktree passed make test-service-readiness, including all service-agent guards and GOTOOLCHAIN=go1.25.11 go test ./services/... -count=1. pnpm frontend:test passed 317 tests, pnpm frontend:typecheck and the six-app build passed, and the 45-case Chromium Playwright suite passed across admin, teacher, student, parent, and staff apps; its isolated Vite ports 5301-5306 were no longer listening after completion. make test-docx-corpus again passed parser parity and the isolated Import-to-Question-Bank approval contract for Physics 28Q, Math 22Q, English 40Q, and DGNL 102Q. make test-import-pdf-ocr-workflow and pnpm docs:build also passed. This is local regression evidence: it neither promotes a default Gateway route nor turns the Mistral-compatible OCR contract into a billable provider proof.

On 2026-07-15, the current dirty worktree reran make test-service-readiness successfully: all service-agent/task-pack/README/ audit/queue guards passed, followed by GOTOOLCHAIN=go1.25.11 go test ./services/... -count=1. make local-dev-status also reported all five frontend apps and every local service endpoint ready. The follow-up GOTOOLCHAIN=go1.25.11 go test -race ./services/... -count=1 also passed. git diff --check was clean and deploy/gateway/routes.json remained unchanged. This is a local regression and readiness snapshot only; it does not prove a deployed/default Gateway route, production data parity, or a promotion rollback.

Also on 2026-07-15, the current frontend changes passed 220 Teacher Workspace Vitest cases, 53 Admin Web Vitest cases, and all 43 Chromium Playwright cases across Admin, Teacher, Student, Parent, and Staff. The browser suite owned its own Vite ports 5301-5306, which were no longer listening after completion; the user-owned 5201-5204 and 5206 development servers and all local service readiness endpoints remained available. This is isolated local UI regression evidence only, not browser parity against a deployed/default Gateway route.

The same local development servers then completed uncached root-to-login timing within 96-100 ms FCP and 80-85 ms DOMContentLoaded for all five applications. Their roughly 9.99 MB transfer is Vite development dependency traffic, not the production payload. The current production bundle-budget build measured 134,913-135,486 B initial gzip across the five apps, below the 147,456 B limit. This is local-device performance evidence; it does not establish deployed CDN or real-network latency.

Also on 2026-07-14, the document-service owner database proved an opt-in durable search.projection.changed.v1 outbox path: canonical insert/update, archive, physical delete, rollback, lease retry, and dead-letter handling ran against disposable PostgreSQL. A separate disposable Document -> NATS JetStream -> Search runtime smoke proved delivery, subscriber restart, duplicate/stale version rejection, and archive delete without exposing a new public endpoint. The transport is disabled unless explicitly configured. Search now fences a tuple with an accepted versioned event from delayed pull UPSERTs, so owner outbox retry/replay rather than a blind rebuild is the recovery path for that tuple; no default Gateway route changed.

Also on 2026-07-14, course-service proved the same opt-in durable search projection transport against disposable runtimes. Its owner database covered count coalescing, transaction rollback, organization move tombstone/new-scope UPSERT, archive ARCHIVED UPSERT, physical delete tombstone, and lease/retry/dead state. The separate Course -> NATS JetStream -> Search smoke covered subscriber restart, duplicate/stale replay, archive state, and physical delete. This is local disposable evidence only: the transport remains disabled by default, and no Gateway route changed.

Also on 2026-07-14, exam-service proved the fourth opt-in durable search projection producer against disposable PostgreSQL and NATS JetStream. The owner database covered its dedicated search revision/outbox, canonical and copied child-count mutations, rollback, redaction, and lease/retry/dead state. The separate Exam -> Search smoke covered subscriber restart, duplicate/stale replay, CLOSED as an owner UPSERT, and a physical-delete tombstone. Each committed canonical mutation writes its outbox event atomically; existing publish/snapshot workflows can span several transactions and are not claimed as a single atomic workflow. The transport remains disabled by default, no public endpoint or Gateway route changed, and this is not deployed-runtime or browser evidence.

Also on 2026-07-14, the optional search-service pull worker ran as the real compiled binary against a fresh disposable PostgreSQL container and four local owner fixtures. With one page per start, the first process persisted four PARTIAL cursors and four copied rows; the restarted process resumed each cursor to SYNCED, yielding two copied rows for each COURSE, DOCUMENT, EXAM, and QUESTION. Native /v1/search and /v1/sync-state/* reads and per-source latencyMs logs passed at 12-13 ms against the local owner fixtures; evidence is output/qa/search-projection-pull-worker-postgres-58220-1784046710/. This is local/disposable recovery evidence only: it does not add a public route, modify a default Gateway route, prove browser parity, or establish production owner latency.

The opt-in Student native course completion regression now proves that a successful progress POST updates the displayed completion state without a serial second course-detail GET. The focused Vitest assertion and scoped Chromium intercept both passed on 2026-07-13. This is local frontend latency evidence only; the default student route remains unchanged and its live/browser promotion gate remains open.

The Classroom Admin candidate has fresh isolated browser evidence at output/qa/classroom-read-admin-browser-runtime-20260713/. The non-default route restored session.user.defaultOrganizationId, sent exactly one organization-scoped GET /api/classrooms?limit=100, received credentialed CORS plus classrooms-teacher-list / native_read headers, and rendered only the authorized class. The direct Gateway and browser telemetry values were both below five seconds. The fixture processes and Vite server were removed after the run, request artifacts redact the bearer token, and this does not change the default classroom route, prove a deployed target, or establish legacy response parity.

A fresh Compose Physics DOCX workflow passed at output/qa/docx-physics-solution-parity-runtime-20260713/: 28 parsed and approved questions retained the 18/6/4 type split, 28 answer keys, seven media references, and 84 formula references through both online and offline Exam snapshots. Its five non-empty source solutions were verified by source question ID in Question Bank, both snapshots, and the generated Word XML. The project used fresh volumes and was removed after the run, so this is local owner/BFF evidence only and does not promote a Gateway route.

The composite routes.docx-physics-attempt-native-{example,localhost-example} candidate joins owner-scoped DOCX Fast upload, job-status reads, and approval with Question Bank readback, BFF matrix generation, publish, durable Word export list/content, and the student attempt adapter. make test-docx-physics-attempt-routes and DOCX_PHYSICS_GATEWAY_ATTEMPT_SELF_TEST=1 make test-docx-physics-attempt-live cover the static route/harness boundary. The harness requires explicit confirmation, a separately disposable runtime, teacher/student tokens, and a served /v1/routes table before any write.

On 2026-07-15, an isolated IAM invitation candidate passed under output/qa/iam-invite-runtime-local-postgres-20260715-015641/. The temporary PostgreSQL cluster seeded local IAM accounts, served IAM and a non-default Gateway table, and ran the Admin Vite organizations surface with ?adminInviteGateway=native. The browser observed iam-invites-create/native_write, received 201, and confirmed its raw invite token was neither rendered nor stored. The same candidate rejected a Teacher bearer with 403, created a second invite through Gateway, accepted it once with 200, rejected replay with 401, and verified the resulting active membership, security events, and persisted token hash. Broad invite and API fallbacks remained legacy-proxied, request artifacts redacted the bearer, and the disposable services and database were removed after the run. This is local non-default evidence only: deploy/gateway/routes.json is unchanged, there is no deployed-target proof, and fixture organization IDs still need a real IAM-directory mapping before any default promotion.

On 2026-07-15, organization-service added tenant-owned academic-year storage in school-service. Migration 000004_academic_years.sql enforces a valid calendar range, unique name per organization, and one active row; owner tests preserve the DRAFT -> ACTIVE -> ARCHIVED lifecycle. The fresh initdb proof at output/qa/academic-year-postgres-isolated-20260715-042021/ applied all owner migrations and read the active record back after a service restart. The separate temporary-Gateway artifact at output/qa/academic-year-route-runtime-20260715-042017/ rejected anonymous and Teacher callers, then observed Admin create/activate/list candidate routes and an organizations / legacy_proxy default-table rollback. The isolated Admin candidate at output/qa/academic-year-browser-local-runtime-20260715-043216/ then proved browser list/draft/activate against a separate fresh school-service PostgreSQL cluster, persisted its ACTIVE row, and redacted bearer artifacts. All temporary runtimes were removed. This remains local owner-storage and non-default route evidence only: it does not establish legacy parity, deployed/default-route promotion, production migration, or rollback after deployment.

On 2026-07-15, the stronger DOCX_PHYSICS_GATEWAY_ATTEMPT_LOCAL_POSTGRES_CONFIRM=local-postgres make test-docx-physics-attempt-local-postgres recheck also passed against fresh, isolated IAM, Document, Classroom, Import, Question Bank, Exam, and Attempt databases. It created two IAM identities in org_local_center, compared the complete served Gateway table against its dynamic candidate, read the opaque job's exam-import-job-status route first as PROCESSING and then as COMPLETED, and wrote redacted per-phase evidence with the echoed correlation ID, route state, and counters. It first used the real Teacher native import path to select the Physics file, upload an owner-scoped opaque source, create the DOCX Fast job, poll it to COMPLETED, and open the native editor in 2,490 ms. Its sequence artifact keeps only the matching source asset hash and Resource Timing for four Gateway fetches. The browser then selected formula-bearing question 4, displayed R=8,31J/mol.K with mtef-ole provenance, and verified the formula id/LaTeX/source kind after review reload. It also selected media-bearing question 7, observed a 200 image/png response on exam-import-docx-fast-asset-content, rendered the authenticated Blob URL, then saved and reloaded its first-question review. The same runtime imported a second Physics job (28 questions: 18 single choice, 6 numeric, 4 true/false groups), published one online exam, created the durable Word export, then started, saved, submitted, and read a GRADED attempt. The isolated row counts were 2 identities, 25 media assets, 3 import jobs, 28 Question Bank rows, 1 exam, and 1 attempt. The current evidence bundle is output/qa/docx-physics-gateway-attempt-local-postgres-20260715013457/, with its dynamic served table, browser artifacts, status artifacts, source export, and summary.json. This is a non-default local Gateway proof: its object store is in-memory, it does not use a shared legacy database or legacy object store, no default route table changed, and it does not establish deployment or default-route promotion.

The current four-fixture corpus guard now joins parser parity to a real in-process Import approval and isolated Question Bank HTTP boundary. It parses Math 22Q, Physics 28Q, English 40Q, and DGNL 102Q from /Users/velikho/Desktop/test-hoctapaz; all 28 fully answered Physics rows are forwarded without payload loss, while incomplete Math, English, and DGNL input is rejected before any Question Bank call. The guard then saves only source-evidence review-safe rows and verifies exact owner payload plus recomputed review stats for Math 13, English 34, and DGNL 37. A nonnumeric Math placeholder (Lời giải) is not inferred as a short-answer key. This is a read-only parser plus isolated owner-contract check, not shared-database persistence, an Exam proof for all fixtures, or a public Gateway promotion.

The opt-in DOCX Question Bank approval accounting boundary is now proven at the code-contract level. Read-only legacy evidence establishes that every Question Bank approval, including native Teacher review, gates the questions entitlement by the completed question count and does not debit AZ Credits. The native approval saga therefore preflights usage-service before Question Bank ingest, then consumes the identical count with import-approval:usage:questions:{requestDigest} after the durable ingest checkpoint. Denial performs no owner write; consume retry does not re-ingest or double-consume; completed replay is read-only. The focused usecase/HTTP suite and the DOCX Fast completion hook passed locally. Compose, raw K8s, and Helm also now declare the canonical feature flag as disabled with a 3000 ms timeout, with a render guard to prevent accidental re-metering in a rollout. This is not a wallet debit, provider, browser, default Gateway, or production billing proof.

The follow-up fresh Compose artifact output/qa/docx-physics-ai-runtime-20260713/ connects the actual Physics DOCX Question Bank data to the AI review boundary. A mock similar preview cited one imported question but made no Question Bank write; a teacher-reviewed payload created one idempotent AI_GENERATED draft through Question Bank. A mock explanation preview for that same imported row appended one idempotent Question Bank version through the owner API while preserving the DOCX import provenance. It is local mock/owner-runtime evidence only, with no provider credential, usage/wallet settlement, default Gateway, browser, or production-route claim.

The PDF OCR contract suite and OCR/MathType route guard also passed through make test-import-pdf-ocr-workflow test-import-ocr-mathtype-routes. This exercises the Mistral-compatible request adapter and usage/wallet failure boundaries, but is not a billable Mistral credential proof because no provider credential was configured in this workspace.

The focused OCR, formula, and frontend recheck also passed on 2026-07-14: make test-import-pdf-ocr-workflow, the real-fixture TestMathTypeJobRealFixtureArtifactWorkflow against the read-only local Go Formula runtime, make test-frontend-boundary, pnpm frontend:typecheck, pnpm frontend:test (315 cases), pnpm frontend:build (six apps), and pnpm frontend:e2e (45 Chromium cases). The OCR test drives a Mistral-compatible HTTP adapter and usage/wallet owner-contract doubles; it is not a billable recognition-quality or provider-credential proof. The formula test reads the real Math fixture and verifies the document-service-scoped Word Equation artifact download, but is not a Docker Compose/Helm runtime check because Docker Desktop was unavailable. The frontend evidence covers admin-web, teacher-web, student-web, parent-web, and staff-web desktop/mobile smokes while the boundary gate rejects direct internal-service URLs; it does not promote their non-default Gateway candidates.

The local host-side Go Formula default is now aligned to Compose at http://127.0.0.1:8095. The current make test-docx-corpus recheck used that default to parse Math (22), Physics (28), English (40), and DGNL (102), then ran the isolated Import-to-Question-Bank approval contract. Its companion determinism artifact output/qa/docx-formula-determinism-runtime-20260714190949081/ retained the canonical Math and Physics fingerprints after repeated calls. The disposable Teacher MathType browser proof at output/qa/mathtype-artifact-browser-local-postgres-20260715114359/ converted 117 formulas with zero unresolved formulas and downloaded a valid 489,407-byte Word Equation DOCX through its candidate Gateway. The latest Physics owner/BFF artifact output/qa/docx-physics-exam-blueprint-local-postgres-20260715114605/ proved the 28 canonical Question Bank rows, online/offline snapshots, direct EXAM_DRAFT replay, blueprint, Word template, and reviewed AI handoffs. These are local, disposable, non-default proofs; they do not establish provider credentials, deployed behavior, or default-route promotion.

The Admin and Teacher app roots now defer their dashboard entry modules until FrontendAppRouter renders an authenticated dashboard. The production build measured the Admin entry at 288,651 bytes (87,773 bytes gzip), down from 350,682 bytes, with admin-dashboard split into a 62,072-byte async chunk. The Teacher entry measured 287,401 bytes (87,158 bytes gzip), down from 292,293 bytes; its dashboard root and TeacherWorkspace remain async chunks. This is local build evidence for unauthenticated initial-load work only, not a network waterfall or deployed performance measurement.

On 2026-07-14, Student section panels were confirmed already lazy by route and section. Parent now also loads only its selected overview, progress, or reports view through Suspense; the Parent production build emitted parent-dashboard as 17.91 kB (6.36 kB gzip) and parent-dashboard-views as a separate 6.67 kB (1.97 kB gzip) async chunk. The focused Parent suite passed all 11 tests after asserting the async progress content explicitly, and frontend TypeScript passed. This is local bundle-split evidence only, not a deployed or network-waterfall latency measurement.

The current production artifacts are now guarded by make test-frontend-bundle-budget. It builds all five role-specific apps and checks only the JavaScript, modulepreload, and stylesheet assets directly referenced by each index.html: JavaScript must remain at or below 96 KiB gzip, CSS at or below 48 KiB gzip, and the combined initial transfer at or below 144 KiB gzip. The 2026-07-14 baseline was 132-135 KiB gzip across the apps. This protects initial-load regressions while preserving lazy route chunks; it is a local build budget, not a deployed network or Core Web Vitals measurement.

Current Multi-App Frontend Recheck (2026-07-14)

make test-frontend-bundle-budget rebuilt all six Vite apps and passed the role-app initial-transfer guard: Admin 135,548 B, Teacher 134,998 B, Student 135,067 B, Parent 135,069 B, and Staff 135,070 B gzip. The matching make frontend-e2e run passed all 45 Chromium cases across Admin, Teacher, Student, Parent, Staff, and Public, including role authentication, desktop/mobile layouts, interactive workflows, and sanitized latency logs. The test servers use local Vite fixtures, so this is a frontend regression and bundle-latency baseline only; it does not prove a deployed Gateway or public route promotion.

Current Multi-App Frontend Recheck (2026-07-15)

The current worktree passed pnpm frontend:lint, pnpm frontend:typecheck, pnpm frontend:test (29 files, 325 tests), make test-frontend-boundary, make test-frontend-bundle-budget, and pnpm frontend:e2e (43 Chromium cases). The browser suite covers Admin, Teacher, Student, Parent, Staff, and Public role authentication, desktop/mobile layouts, interactive workflows, and sanitized latency logs; the focused Teacher rerun also passed all four cases after native DOCX formula-warning rendering changed. The bundle command rebuilt all six Vite apps and passed the role-app initial-transfer guard: Admin 135,486 B, Teacher 134,913 B, Student 134,991 B, Parent 134,987 B, and Staff 134,989 B gzip. This remains local frontend and build evidence only; it does not establish deployed Gateway behavior or default-route promotion.

With the persistent developer servers left running, the explicit FRONTEND_LOGIN_LATENCY_CONFIRM=local-dev make test-frontend-login-latency smoke then opened each uncached root in a separate Chromium context. Admin, Teacher, Student, Parent, and Staff all returned 200, redirected to /login, and stayed below the local 2,000 ms FCP and 2,500 ms DOM-content-loaded limits: observed FCP was 84-96 ms and DOM content loaded was 68-81 ms. Each uncached Vite development-server context transferred about 9,988-9,989 KB because it serves unminified optimized dependency modules. That number is not comparable to the production gzip guard above, which remains about 135 KB per role app. The reproducible local artifact is output/qa/frontend-login-latency-2026-07-15T05-15-06-753Z/summary.json. This is a Vite development-server latency baseline, not a production transfer, Cloudflare, authenticated-dashboard, or Gateway workflow measurement.

The strongest isolated AI worker variant also passed at output/qa/ai-classification-worker-runtime-20260713-refresh/: a fresh Postgres AI store, disposable Question Bank owner API, and non-default Gateway completed a 12-question job in three batches, retained SSE and Question Bank prompt context, authorized the disposable teacher token, and denied a student token. Its provider was the deterministic mock; it is local owner/runtime evidence only and does not promote public AI routes or validate a paid model credential.

On 2026-07-14, the opt-in P6-049 generation settlement worker gained durable forward recovery. Focused tests prove a partial owner sequence gets exactly one effective wallet debit and one effective consume per resource while the worker retries settlement without re-running provider or preflight. A new disposable Postgres 000001-000006 migration run proved an expired pending replay is still readable, SKIP LOCKED/lease prevents a second claim, and retry/error state survives a new store instance. This is local mock-owner and isolated DB evidence. A contract-shaped in-process HTTP fault injection now fails one usage mutation after the wallet debit, then proves the worker reuses owner idempotency keys without a second provider or preflight call. It is still not real usage/wallet binaries or stores, a provider credential, Gateway/default-route, browser, or promotion proof.

The same P6-049 boundary has a current Docker-independent local owner-runtime artifact at output/qa/ai-generation-settlement-local-postgres-20260715-053418/. It built current AI, Usage, and Wallet binaries, migrated three separate fresh PostgreSQL databases under /tmp, injected one credits_weekly failure after the real debit, restarted the AI process, and observed 1:true:0 become 1:false:1. The resulting wallet/counter/audit assertions prove real owner storage recovery and an identical cached replay that makes no owner call. Its cluster, fault proxy, and service processes were removed on exit. This remains local mock-provider evidence, not Gateway/browser/provider-credential/default-route proof.

The current runner also proves the AI-owned non-secret provider selection on a fresh local PostgreSQL cluster. Artifact output/qa/ai-generation-settlement-local-postgres-20260715-053418/ seeded only the disposable mock default setting, updated it through the native ADMIN endpoint, then observed the restarted AI binary report configurationSource=database and the persisted database-selected-mock-v2 model. This is local runtime configuration evidence only; it does not prove provider credentials, a provider-network request, or default-route promotion.

The same recovery also passed in disposable Compose at output/qa/ai-generation-settlement-runtime-20260714-084542/, using current AI, Usage, and Wallet binaries with unique owner Postgres volumes. The first failed credits_weekly consume left 1:true:0; AI recreation settled it as 1:false:1 with wallet 97, owner counters 3/3/3/3000, and audit summary 2:1:1. The runner then removed all project containers, volumes, and its loopback fault proxy. This is also local mock-provider evidence only.

On 2026-07-14, payment-service also closed a local atomicity gap in matched provider webhook handling: the webhook, payment transaction, order outcome, paid/review event, and paid-event outbox now commit together. An isolated PostgreSQL test deliberately failed event serialization, observed zero durable rows after rollback, then retried the same webhook and observed exactly one webhook, transaction, paid event, and outbox item. This preserves at-least-once downstream delivery and does not prove provider credentials, public hook behavior, production payment traffic, or default Gateway promotion.

On 2026-07-14, notification-service closed a recipient-fanout atomicity gap. The source event, every preference-approved inbox row, and deterministic delivery jobs now share one repository transaction. A disposable PostgreSQL test installed a trigger that failed the second recipient write, observed zero source-event, notification, and delivery-job rows after rollback, then retried the identical source event and observed one event, both inbox rows, and two jobs; a later replay did not duplicate them. The injectable worker unit suite also covers lease exclusivity, transient retry, terminal DLQ, and mute-after- fanout suppression. This is local owner-storage and injected-adapter evidence only: the default runtime has no provider registration, and this does not enable live delivery, promote notification or parent-alert Gateway routes, or replace browser and rollback proof. The reproducible bundle is output/qa/notification-event-fanout-postgres-20260715-034023/ with the focused Go test log and summary metadata.

On 2026-07-15, the refreshed SVC-020 candidate also passed make test-notification-routes test-parent-alert-routes, the disposable fanout test above, and make test-student-notification-browser. The browser artifact at output/qa/student-notification-browser-local-runtime-20260715-034031/ proves an anonymous list is denied, then a Student browser lists two owned notifications, reads one and all, and reads/writes preferences through only the temporary Gateway native_read/native_write routes. Its 1.06 ms shell list check and 14 ms browser trace are local candidate measurements; the request trace redacts the bearer token, all temporary processes/container were removed, and deploy/gateway/routes.json remains untouched. This does not cover the notification bell, parent-alert browser parity, delivery providers, or default-route promotion.

On 2026-07-14, analytics-service added a reproducible isolated PostgreSQL rebuild workflow. make test-analytics-postgres-rebuild ingests one valid attempt event through HTTP, materializes exactly one result and projection receipt, confirms replay remains unchanged, then rejects a bad schema version without partial projection rows. The named disposable container is removed on exit and no configured service database is used. The latest local evidence is output/qa/analytics-postgres-rebuild-20260715-033318/summary.json together with its focused Go test log. This is local owner-storage evidence only, not async-worker, browser, Gateway/default-route, or production proof.

On 2026-07-15, Course lesson-progress delivery stopped using the synchronous best-effort Analytics publisher. Migration 000007_course_learning_progress_outbox.sql writes an organization-scoped, replayable course.lesson_progress.saved.v1 record with the Course mutation; the existing opt-in Course worker later lease-claims and posts it to Analytics. COURSE_SEARCH_PROJECTION_OUTBOX_POSTGRES_CONFIRM=disposable-postgres make test-course-learning-progress-delivery-postgres created a disposable PostgreSQL container and proved initial claim, retry, delivery, a second mutable progress state, and dead-letter handling. This keeps learner request latency independent of Analytics availability. It is local Course-owned transport evidence only, not Analytics materialization, a deployed worker, or route promotion.

On 2026-07-15, COURSE_LEARNING_ANALYTICS_RUNTIME_CONFIRM=local-postgres make test-course-learning-analytics-runtime added full-chain isolated runtime evidence for Course -> temporary Gateway -> Attempt -> Analytics. The fresh three-owner-database cluster created a Course-bound student attempt, delivered Course catalog/progress events, ingested exactly one attempt.graded.v2, and read back one 100/100/100/100 mastery row. It also rejected a mismatched trusted Course context and preserved a single attempt after submit replay. The artifact is output/qa/course-learning-analytics-runtime-20260715-033520/. This remains local candidate-route evidence only: no browser, deployed worker, default-route, or production claim is made.

On 2026-07-15, audit-service revalidated its reproducible isolated PostgreSQL replay and retention workflow. make test-audit-replay-retention-postgres verifies audit source replay, audit/security filters, and append-only mutation-reject triggers in a random schema, then removes its named container. This is local owner-storage evidence only; it does not prove browser, Gateway/default-route, producer retry, or production behavior. Artifact output/qa/audit-replay-retention-postgres-20260715-034640/ retains its focused Go test log and non-secret summary metadata.

On 2026-07-15, make test-admin-audit-owner-browser added isolated Admin Operations browser evidence for the audit owner candidate. A fresh audit-only Postgres cluster, temporary audit-service, temporary Gateway, and Admin Vite process proved one ADMIN audit row rendered through audit-service-admin-operations-audit with native_read; STUDENT and anonymous requests were rejected by Gateway. The compatibility read now also requires Gateway internal-token authentication and a forwarded ADMIN principal. Artifact: output/qa/admin-audit-owner-browser-20260715-034649/; the local Gateway check took 2.19 ms, browser-observed read took 10 ms, and the request trace redacts the bearer token. This remains local candidate evidence only: deploy/gateway/routes.json was not promoted, real legacy backfill/response parity is unproven, and producer-write authentication/retry behavior is outside this slice.

On 2026-07-15, make test-admin-owner-source-browser added an actual Admin Operations source-status candidate at output/qa/admin-owner-source-browser-local-runtime-20260715-035834/. A memory-only admin-service, two authenticated owner fixture endpoints, temporary Gateway, and Admin Vite process proved the UI renders 20 owner sources and reloads its source statuses through the exact native_read route in desktop and mobile contexts. Only ai.providers and audit.history returned owner HTTP 200; wallet.reviews remained unconfigured, so no source total was synthesized. ADMIN passed while anonymous and TEACHER requests were rejected. The temporary default-route restart selected broad admin / legacy_proxy as expected, and all bearer traces were redacted. This is still candidate source-status UI evidence only: it does not establish dashboard parity, default-route promotion, production owner availability, or legacy admin data backfill.

On 2026-07-14, SVC-013 added read-only external Go Formula runtime repeat evidence for the real Math and Physics DOCX fixtures. The runtime returned identical import-visible fingerprints across two calls: Math 22 questions/125 formulas (117 MTEF-OLE plus 8 OMML) and Physics 28 questions/84 MTEF-OLE. TestGoFormulaCorpusImportVisibleDeterminism then passed the real Go adapter's byte-identical JSON comparison after its observational latency_ms was cleared. A raw OLE/WMF diagnostic packagePath can differ upstream, but the adapter filters those non-display assets before review or Question Bank persistence; formula LaTeX, MathML, MTEF provenance, warnings, questions, and display media remain covered. The artifact is output/qa/docx-formula-determinism-runtime-20260714122647510/summary.json. This is local read-only runtime evidence, not a deployable formula service, Gateway/default-route, frontend, or production proof.

The 2026-07-15 isolated corpus recheck passed Question Bank persistence for Math, Physics, English, and DGNL at output/qa/docx-corpus-question-bank-local-postgres-20260715122623/summary.json. The local Physics candidate then passed Teacher import/review and a real Student Web browser journey: its access-link page issued one request each for start, answer-save, submit, and result-read through the non-default Gateway, then rendered a visible GRADED score with one correct answer (1/28, 3.57%) at output/qa/docx-physics-gateway-attempt-local-postgres-20260715101402/summary.json and output/qa/docx-physics-gateway-attempt-local-postgres-20260715101402/student-attempt-browser/summary.json. The browser artifacts redact the access-link code and bearer header; the start request took 70 ms. output/qa/docx-corpus-exam-blueprint-local-postgres-20260715122636/summary.json revalidated the Math 13/22, English 34/40, and DGNL 37/102 review-safe subsets through direct EXAM_DRAFT replay, BFF ONLINE/OFFLINE snapshots, and checksum-verified owner Word exports. Every untouched approval was fail-closed before review, and all temporary databases and listeners were removed. The preceding make test-docx-corpus run also passed the real four-fixture parser/determinism/approval contract. None of these artifacts approve excluded rows, promote deploy/gateway/routes.json, or prove deployed, default-route, or production behavior.

Requirement Evidence Matrix

This matrix keeps the original goal scope intact. A green guard is not enough to mark the goal complete unless the current evidence proves every requirement below.

RequirementCurrent evidenceCompletion status
Bảng trách nhiệm service chuẩn hơn cho HocTapAZdocs/architecture/service-responsibility-matrix.md, docs/agents/service-agent-manifest.json, docs/agents/service-agent-dispatch-roster.md, and make test-service-task-packs keep 23 canonical service rows plus the RET-USER retirement row aligned.Spawn/dispatch ready, not rollout complete.
Spawn mỗi agents chịu trách nhiệm mỗi servicedocs/agents/service-agent-execution-queue.json, docs/agents/service-agent-next-slice-queue.json, docs/agents/service-agent-next-slice-closeout-ledger.json, docs/agents/service-agent-next-slice-spawn-packets.md, docs/agents/service-agent-spawn-packets.md, and docs/agents/service-agent-closeout-ledger.json define accepted first-slice handoff paths plus machine-readable nextTaskId, workflowVerification, requiredNextHandoffPath, next-slice closeout acceptance state, and prompt-ready packet fields for SVC-001 through SVC-023. SVC-001 now has an accepted gateway default-route proof handoff; SVC-002 now has an accepted BFF owner-source gateway proof handoff; SVC-005 now has an accepted IAM membership and school sync proof handoff; SVC-013 now has an accepted next-slice runtime-adapter proof handoff, SVC-014 has an accepted search legacy-owner rebuild proof handoff, SVC-015 has an accepted AI usage/wallet route-boundary proof handoff, SVC-016 has an accepted subscription entitlement replay proof handoff, SVC-017 has an accepted wallet ledger route proof handoff, SVC-018 has an accepted usage billing sync replay proof handoff, SVC-019 has an accepted payment webhook reconcile proof handoff, SVC-020 has an accepted notification recipient route proof handoff, SVC-021 has an accepted audit replay retention proof handoff, SVC-022 has an accepted analytics rebuildable projection proof handoff, SVC-023 has an accepted admin owner-source route proof handoff, and RET-USER has an accepted retirement readiness proof handoff.Bounded handoffs accepted and next slices are dispatchable proof-gate slices, not promotion-ready or complete. Rows remain not-complete until their open proof gates close.
Legacy source is reference onlydocs/agents/service-agent-spawn-runbook.md and task packs require /Users/velikho/Desktop/WORKING/HOCTAPAZ/ to stay read-only evidence.Guarded by task-pack coverage, still needs human discipline during future slices.
Hoàn thiện Go microservices và test workflowsOn 2026-07-15, make test-service-readiness passed its service-agent/task-pack/readme/audit guards and GOTOOLCHAIN=go1.25.11 go test ./services/... -count=1. The 2026-07-10 IAM/Profile build-mode clean Compose smoke passed with migration, schema-record, health, readiness, and JWKS artifacts under output/qa/iam-profile-clean-compose-20260710-1555/, then removed its isolated project and volume. make test-docx-corpus covers the four real DOCX fixtures through parser plus isolated Import-to-Question-Bank approval contract. Current local Formula defaults use 127.0.0.1:8095; fresh docx-formula-determinism-runtime-20260714190949081, mathtype-artifact-browser-local-postgres-20260715114359, ocr-review-browser-local-postgres-20260715113954, ocr-review-browser-local-postgres-batch-20260715114016, and docx-physics-exam-blueprint-local-postgres-20260715114605 artifacts add deterministic LaTeX/MathML conversion, Teacher Word Equation download, direct/batch candidate Mistral-compatible OCR review -> approval -> Question Bank readback, canonical Question Bank persistence, BFF 18/6/4 matrix, immutable online/offline snapshots, native Word template, source-keyed solution parity, mock AI preview -> teacher-reviewed Question Bank draft/version ownership, and direct EXAM_DRAFT replay. Fresh EXAM_RESULT_RELEASE_RUNTIME_CONFIRM=exam-result-release-isolated make test-exam-result-release-parent-browser evidence in output/qa/exam-result-release-notification-runtime-20260715-044805/ adds the disposable Exam -> Attempt -> Profile -> Notification handoff, exactly one GRADE_RELEASED and GRADE_RELEASED_PARENT row, replay suppression, and a parent-web candidate browser read/mark-read check through parent-alerts-list and parent-alerts-read (17 ms list latency). output/qa/course-learning-analytics-runtime-20260715-033520/ adds isolated Course -> temporary Gateway -> Attempt -> Analytics delivery with one v2 graded event and one 100/100/100/100 mastery row. Its temporary Gateway route table and fresh databases are removed on exit.Current code/test surface passes locally, but public/default route cutovers, browser proof where not yet captured, billed provider/settlement proof where required, reviewed approval for incomplete corpus fixtures, deployment parity, and production-like populated-data proof remain open.
Frontend chỉ gọi api-gateway hoặc BFFmake test-frontend-boundary and service task pack guards enforce gateway/BFF-only public caller boundaries. The isolated Admin Classroom candidate also observes its browser request only through Gateway, including tenant, CORS, and native-route headers.Boundary guarded; default route promotion still needs deployed route-specific proof, legacy parity, and rollback-after-live evidence.
Không có deployable auth-serviceservice-agent-wave-board.md, task packs, and guard text route all auth/login/session/access work to iam-service; auth-service remains allowed only as migration rationale or guard wording.Boundary guarded; IAM/Profile default cutover still incomplete.
Docs và VitePress được cập nhậtdocs/.vitepress/config.ts, docs/index.md, and pnpm docs:build cover the agent ledgers, execution queue, next-slice closeout ledger, readiness smoke, and completion audit pages.Docs build passes, but docs continue to report active-not-complete.
IAM/Profile default public promotiondocs/qa/iam-profile-default-cutover-proof.md defines the production-like proof bundle, offline review guard, candidate route hashes, browser proof, and rollback requirements. output/qa/iam-profile-default-candidate-isolated-20260713-121616/ adds current non-default Gateway/browser/rollback evidence.Blocked on a live production-like bundle with required migrator run report; the current isolated candidate is fresh-volume local evidence, not promotion.

Completion remains false until every row in this matrix is proven by current artifacts, not just documented intent.

Go-platform documentation is generated from repository Markdown.