Appearance
Service Agent Wave Board
Status: orchestrator-owned dispatch board for service owner agents.
Use this board with docs/agents/service-agent-manifest.json, docs/agents/service-agent-proof-ledger.json, docs/agents/service-agent-closeout-ledger.json, docs/architecture/service-responsibility-matrix.md, docs/agents/service-agent-dispatch-roster.md, and the per-service packs in docs/agents/service-tasks/. Each worker owns one canonical service row for a small vertical slice. The worker must read its task pack first, audit legacy evidence, then code/test/fix only inside the assigned writable scope.
Dispatch Rules
- One service owner per implementation directory at a time.
- Alias services must use the current implementation directory listed here; do not create duplicate directories for canonical names.
- Shared files such as root Make targets, Compose, Helm, K8s, gateway route tables, generated OpenAPI indexes, and docs navigation stay orchestrator-owned unless explicitly delegated.
- Public route cutovers are separate tasks. A service foundation or route rehearsal does not imply default gateway promotion.
- Persisted
sourceServiceids in search/sync/event projections use the current implementation id unless a versioned migration says otherwise. Current examples:question-bank-service,course-service,exam-service,document-service,docx-import-service, andai-classifier-service. - Every worker closeout must list docs read, legacy files read, files changed, tests run, rollback notes, and next task.
- The service-agent closeout ledger is the machine-readable acceptance gate for that handoff evidence; update it only after the handoff exists and passes
make test-service-agent-closeout-ledger. spawn-readyin the proof ledger is a dispatch state only. It is not a service completion claim.
Current Waves
| Wave | Services | Purpose | Parallelism |
|---|---|---|---|
| 0 | Orchestrator | Keep matrix, task packs, deploy/env coverage, and shared route examples coherent. | Single owner. |
| 1 | api-gateway, iam-service, profile-service, organization-service, classroom-service, bff-service | Entry, identity, profile, tenant/class foundations. | Parallel by service; IAM/organization membership changes need explicit contract handoff. |
| 2 | question-service, exam-service, attempt-service, course-service, file-service, import-service, formula-docx-service, search-service | Learning, import, exam runtime, and rebuildable discovery. | Parallel by service; import approval/exam/question/search contracts must be versioned before shared edits. |
| 3 | ai-service, billing-service, wallet-service, usage-service, payment-service | AI workload and monetization foundations. | Parallel by service; usage/wallet/billing/payment event contracts stay orchestrator-owned until stabilized. |
| 4 | notification-service, audit-service, analytics-service, admin-service | Operational read models, governance, admin workflows. | Parallel by service; admin must not absorb audit/payment/wallet/IAM source-of-truth logic. |
| R | user-service | Retirement only. No new product work. | One compatibility owner when parity evidence is ready. |
Service Rows
| Dispatch ID | Canonical service | Current implementation | Task pack | Current agent mission | Required verification |
|---|---|---|---|---|---|
| SVC-001 | api-gateway | services/api-gateway | docs/agents/service-tasks/api-gateway.md | Keep frontend entrypoint single, JWT/JWKS verification compatible with IAM, and route rehearsals rollback-safe. | GOTOOLCHAIN=go1.25.11 go test ./services/api-gateway/... plus named route targets for touched surfaces such as make test-auth-routes test-auth-routes-live test-auth-routes-browser test-auth-routes-session-browser test-profile-routes test-organization-routes test-attempt-routes test-bff-routes; exam_start_adapter slices also require make test-attempt-live and make test-attempt-browser before public promotion. |
| SVC-002 | bff-service | services/bff-service | docs/agents/service-tasks/bff-service.md | Build frontend-specific aggregation without a primary business DB and without hiding domain logic. | GOTOOLCHAIN=go1.25.11 go test ./services/bff-service/... and make test-bff-routes when gateway routes change. |
| SVC-003 | iam-service | services/iam-service | docs/agents/service-tasks/iam-service.md | Own identity, credentials, sessions, JWT/JWKS, roles, permissions, invites, and permission-bearing org membership. | GOTOOLCHAIN=go1.25.11 go test ./services/iam-service/..., make test-auth-routes, AUTH_ROUTE_LIVE_SELF_TEST=1 make test-auth-routes-live, AUTH_ROUTE_BROWSER_SELF_TEST=1 make test-auth-routes-browser, AUTH_SESSION_BROWSER_SELF_TEST=1 make test-auth-routes-session-browser, make test-organization-routes, and ORGANIZATION_MEMBERSHIP_WRITE_SELF_TEST=1 make test-organization-membership-write-live when membership routes change. |
| SVC-004 | profile-service | services/profile-service | docs/agents/service-tasks/profile-service.md | Own education profile/display data and keep password/JWT/role/payment state out. | GOTOOLCHAIN=go1.25.11 go test ./services/profile-service/... plus make test-profile-routes test-profile-kyc-routes test-profile-admin-kyc-routes, PROFILE_ROUTE_LIVE_SELF_TEST=1 make test-profile-routes-live, and PROFILE_ROUTE_BROWSER_SELF_TEST=1 make test-profile-routes-browser when profile gateway routes change; default promotion remains orchestrator-owned. |
| SVC-005 | organization-service | services/school-service alias | docs/agents/service-tasks/organization-service.md | Own schools/centers/campuses/org metadata; coordinate IAM-owned membership policy. | GOTOOLCHAIN=go1.25.11 go test ./services/school-service/... and make test-organization-routes when gateway routes change. |
| SVC-006 | classroom-service | services/classroom-service | docs/agents/service-tasks/classroom-service.md | Own classes, members, teacher assignments, and class progress read models. | GOTOOLCHAIN=go1.25.11 go test ./services/classroom-service/... plus make test-classroom-route-guard when classroom public routes change. |
| SVC-007 | course-service | services/course-service | docs/agents/service-tasks/course-service.md | Own courses/modules/lessons/material metadata/enrollments/progress, not question/exam attempts. | GOTOOLCHAIN=go1.25.11 go test ./services/course-service/... plus make test-student-course-routes test-student-course-progress-routes and STUDENT_COURSE_BROWSER_SELF_TEST=1 make test-student-course-browser; docs/qa/student-course-route-rehearsals.md keeps live/browser proof required before course gateway promotion. |
| SVC-008 | question-service | services/question-bank-service alias | docs/agents/service-tasks/question-service.md | Own canonical questions, answers, solutions, types, tags, taxonomy refs, editor write save/reload parity, and question search projections. | GOTOOLCHAIN=go1.25.11 go test ./services/question-bank-service/... plus make test-question-read-routes test-question-types-routes test-question-classification-apply-routes, make test-question-write-routes, QUESTION_WRITE_SELF_TEST=1 make test-question-write-live, QUESTION_WRITE_BROWSER_SELF_TEST=1 make test-question-write-browser, make test-question-types-live test-question-types-browser, and make test-question-read-browser test-question-read-browser-admin for route slices. |
| SVC-009 | exam-service | services/exam-service | docs/agents/service-tasks/exam-service.md | Own exam authoring, snapshots, publish/access workflow, assignments, and exam search projections. | GOTOOLCHAIN=go1.25.11 go test ./services/exam-service/... plus make test-exam-authoring-routes; docs/qa/exam-authoring-route-rehearsals.md keeps live/browser proof required before exam authoring promotion; runtime-access/start-adapter slices also require make test-attempt-routes, make test-attempt-live, and make test-attempt-browser. |
| SVC-010 | attempt-service | services/attempt-service | docs/agents/service-tasks/attempt-service.md | Own attempt sessions, attempt-owned snapshots, answers, grading, events, results, and copied result-release propagation. | GOTOOLCHAIN=go1.25.11 go test ./services/attempt-service/...; public attempt/start slices also require make test-attempt-routes, make test-attempt-live, and make test-attempt-browser. |
| SVC-011 | file-service | services/document-service alias | docs/agents/service-tasks/file-service.md | Own files/media/object metadata/signed reads and keep parsing/credit charging out. | GOTOOLCHAIN=go1.25.11 go test ./services/document-service/... plus make test-storage-media-parity; docs/qa/storage-media-parity-smoke.md keeps browser proof required before public storage promotion. |
| SVC-012 | import-service | services/docx-import-service alias | docs/agents/service-tasks/import-service.md | Own import jobs, parse orchestration, preview/review, approval handoffs, and next PDF/OCR/MathType status/download slices. | GOTOOLCHAIN=go1.25.11 go test ./services/docx-import-service/... plus make test-import-create-routes test-import-status-routes test-import-approval-routes test-import-review-roundtrip-routes and the matching live/browser smoke target for changed workflows. |
| SVC-013 | formula-docx-service | source-controlled runtimes/go-formula-docx runtime behind import adapters | docs/agents/service-tasks/formula-docx-service.md | Maintain parser runtime integration and adapter evidence; do not create services/formula-docx-service without a later ADR. | sh scripts/test/go-formula-runtime-coverage.sh, make test-docx-corpus, and GOTOOLCHAIN=go1.25.11 go test ./services/docx-import-service/internal/parser/docx -count=1 when parser behavior changes. |
| SVC-014 | search-service | services/search-service | docs/agents/service-tasks/search-service.md | Own rebuildable copied indexes and sync checkpoints; never owner business data or course-service-owned /api/public/catalog* compatibility. | GOTOOLCHAIN=go1.25.11 go test ./services/search-service/... -count=1, make test-search-rebuild, and make test-search-routes; any route rehearsal must cite the exact legacy route/controller mapping first. |
| SVC-015 | ai-service | services/ai-classifier-service alias | docs/agents/service-tasks/ai-service.md | Own AI provider adapters/jobs/prompts/results plus generate/explain/grade contracts; call usage/wallet through explicit APIs only and never own quota checks or credit movement. | GOTOOLCHAIN=go1.25.11 go test ./services/ai-classifier-service/..., make test-ai-classification-job-route-guard, AI_CLASSIFICATION_JOB_SELF_TEST=1 make test-ai-classification-job-live, and make test-question-classification-apply-routes; run make test-monetization-event-chain when touching usage/wallet handoff contracts, and use make test-question-classification-apply-live only for explicit live write smoke. |
| SVC-016 | billing-service | services/billing-service | docs/agents/service-tasks/billing-service.md | Own plans, subscriptions, invoices, and commercial entitlements. | GOTOOLCHAIN=go1.25.11 go test ./services/billing-service/... plus make test-monetization-event-chain and make test-monetization-broker-transport. |
| SVC-017 | wallet-service | services/wallet-service | docs/agents/service-tasks/wallet-service.md | Own AZ Credits, balances, immutable ledger, grants/debits/refunds. | GOTOOLCHAIN=go1.25.11 go test ./services/wallet-service/... plus make test-monetization-event-chain test-monetization-routes and make test-monetization-broker-transport. |
| SVC-018 | usage-service | services/usage-service | docs/agents/service-tasks/usage-service.md | Own feature gates, quota periods, usage counters, check/consume/reset APIs. | GOTOOLCHAIN=go1.25.11 go test ./services/usage-service/... plus make test-monetization-event-chain and make test-monetization-broker-transport. |
| SVC-019 | payment-service | services/payment-service | docs/agents/service-tasks/payment-service.md | Own payment orders, provider transactions, webhooks, reconcile/idempotency. | GOTOOLCHAIN=go1.25.11 go test ./services/payment-service/... plus make test-monetization-event-chain test-monetization-routes and make test-monetization-broker-transport. |
| SVC-020 | notification-service | services/notification-service | docs/agents/service-tasks/notification-service.md | Own notifications, preferences, read/delete state, event fanout, and delivery metadata for already-resolved recipients; attempt-service is a bounded grade-release producer dependency, not an SVC-020 implementation owner. | GOTOOLCHAIN=go1.25.11 go test ./services/notification-service/... plus GOTOOLCHAIN=go1.25.11 go test ./services/attempt-service/... and make test-notification-routes test-parent-alert-routes test-attempt-routes for producer/route cutovers. |
| SVC-021 | audit-service | services/audit-service | docs/agents/service-tasks/audit-service.md | Own append-only compliance/security event history, producer replay, retention metadata, and future audit compatibility storage. | GOTOOLCHAIN=go1.25.11 go test ./services/audit-service/... and make test-audit-admin-compat-routes when admin audit compatibility routing changes. |
| SVC-022 | analytics-service | services/analytics-service | docs/agents/service-tasks/analytics-service.md | Own dashboard/result/progress/mastery projections, weak-topic rollups, and rebuildable analytics events. | GOTOOLCHAIN=go1.25.11 go test ./services/analytics-service/... plus make test-analytics-routes and event projection fixtures for changed producers. |
| SVC-023 | admin-service | services/admin-service | docs/agents/service-tasks/admin-service.md | Own admin read models, feature maintenance, moderation, support/admin workflows, and ops controls without absorbing source services or synthesizing source-service totals. | GOTOOLCHAIN=go1.25.11 go test ./services/admin-service/... plus owner-source/source-snapshot tests, make test-feature-maintenance-routes test-admin-audit-routes, and route/browser proof before admin default promotions. |
Alias And Retirement Rows
| Row | Dispatch rule | Verification |
|---|---|---|
auth-service | Not a service row. Route auth/login/session/access work to iam-service; do not create an auth-service task pack, API doc, OpenAPI contract, deployment, or runtime directory. | Use iam-service verification. |
entitlement-service | Alias concept only. Route implementation work to usage-service unless an ADR renames the canonical service. | Use usage-service verification. |
RET-USER user-service | Deprecated compatibility scaffold. Route product work to iam-service or profile-service; use docs/agents/service-tasks/user-service-retirement.md only for retirement/quarantine after parity evidence. | GOTOOLCHAIN=go1.25.11 go test ./services/user-service/... plus IAM/Profile parity tests before removal. |
Agent Prompt Template
txt
You own <canonical-service> for one vertical slice.
Read first:
- docs/architecture/service-responsibility-matrix.md
- docs/agents/service-agent-dispatch-roster.md
- docs/agents/service-agent-wave-board.md
- docs/agents/service-workflow-test-matrix.md
- <task-pack>
- legacy evidence cited by the task pack
Rules:
- Work only in <writable-scope>.
- Do not edit orchestrator-owned shared files unless explicitly delegated.
- Do not revert unrelated worktree changes.
- Keep default gateway routes legacy unless the task is specifically a route
rehearsal/cutover with rollback evidence.
Deliver:
- Audit notes with exact legacy/current source references.
- One small code or docs slice that moves the service toward its mission.
- Focused tests plus the service verification command.
- Closeout with changed files, tests, rollback notes, and next task.Prioritized Cross-Service Backlog
These are orchestrator-owned contract slices that should be completed before spawning service workers that depend on them.
| Priority | Slice | Owner | Agent handoff |
|---|---|---|---|
| P0 | IAM canonical organization membership guardrails | Orchestrator with iam-service and organization-service owners | IAM membership -> refresh -> org_ids/role/permission/security-event coverage exists, school-service member writes now require explicit IAM read-model sync, IAM emits add/remove membership events, IAM persists an iam_membership_outbox, and the school-service read model records IAM event ordering/tombstones so stale upserts do not recreate newer deletes. IAM-sync deletes can remove the last local OWNER because IAM is canonical. Non-default gateway membership-write rehearsal now routes add/remove through organization_membership_adapter, translating legacy userId to IAM accountId; default writes and PATCH member updates stay legacy. Added opt-in make test-organization-membership-write-live for add/remove route smoke; next run it against a live gateway with an IAM admin bearer token and keep default routes legacy until rollback proof exists. |
| P0 | IAM/Profile UUID, backfill, and default cutover hardening | Orchestrator with iam-service, profile-service, gateway, and migration owners | Native IAM/Profile foundations exist, but public routes remain conservative and text ids remain for string-id API compatibility. IAM/Profile legacy backfill now has a read-only report scaffold and guard target, and make test-iam-profile-runtime-proof covers static/render migration-before-runtime wiring for Compose, offline K8s, and Helm. IAM_PROFILE_CLEAN_COMPOSE_CONFIRM=clean-runtime make test-iam-profile-clean-compose is the opt-in live clean Compose proof for IAM/Profile migration records, Postgres health, readiness, and JWKS; it preflights default ports 5433, 8081, and 8082, supports host-port overrides, and can use IAM_PROFILE_CLEAN_COMPOSE_USE_LOCAL_IMAGES=1 with Docker Compose --no-build when local service images are already present. Clean Compose live proof was refreshed on 2026-07-08 after the new IAM 13-file/Profile 10-file readiness/FK/PK-promotion migrations with rebuilt IAM/Profile/migrator images, Compose project hoctapaz-iam-profile-smoke, host ports 55433, 58081, and 58082, migration container completion, per-file schema_migrations, Postgres health, service health/readiness, and IAM JWKS. IAM_PROFILE_K8S_LIVE_CONFIRM=local-k8s make test-iam-profile-local-k8s was refreshed on 2026-07-08 against kind-hoctapaz-go after loading rebuilt IAM/Profile/migrator :local images, namespace hoctapaz-iam-profile-uuidpk2-20260708, host ports 58191 and 58192, migration Jobs, per-file schema_migrations for the current IAM 13/Profile 10 migration sets, service health/readiness, JWKS, port-forward, and namespace cleanup. Additive UUID shadow columns, dual-write triggers, read-only UUID primary-key readiness views, owner-local UUID FK constraints, and UUID primary-key promotion now have guard coverage; public text ids remain unique for API/upsert compatibility. Staff per-account permission source mapping is explicit zero-source legacy reconciliation, IAM_PROFILE_BACKFILL_POPULATED_CONFIRM=populated-fixture make test-iam-profile-backfill-populated is the opt-in fixture proof for loader/migration/UUID-shadow/UUID-PK compatibility, and IAM_PROFILE_LIVE_VALIDATION_CONFIRM=live-populated IAM_PROFILE_LIVE_VALIDATION_RUN_REPORT=/path/to/migrator-run.json IAM_PROFILE_LIVE_VALIDATION_REQUIRE_RUN_REPORT=1 make test-iam-profile-live-populated-validation is the cutover-grade read-only validation path for already-populated target DBs; the attached run report must include matched postload-reconciliation items with zero issues and zero rejected rows. The fixture path passed with completed migration_runs and hash evidence; production-like populated target DSN validation, live UUID readiness/FK/promotion output, final text-id cleanup, and default route/browser promotion evidence remain blockers. Use docs/agents/service-tasks/iam-profile-cutover-hardening.md before claiming UUID/backfill/default route cutover completion. |
| P0 | OpenAPI mirror drift guard | Orchestrator | Keep every services/*/api/openapi.yaml byte-identical with contracts/openapi/services/*.yaml; make test-service-task-packs enforces this. |
| P1 | Payment-to-billing/wallet event replay path | Payment, billing, wallet workers | Durable payment event outbox dispatch is in place over the current internal HTTP sink: payment records payment.order.paid.v1, persists pending/delivered/retry/dead state, dispatches due paid events to billing/wallet /v1/events/payment-order-paid, billing activates subscriptions idempotently by source payment event id, and wallet writes one top-up ledger entry by source payment event id. Next: replace the HTTP sink with shared broker transport when selected and keep public routes legacy until runtime parity evidence exists. |
| P1 | Billing-to-usage entitlement sync | Billing and usage workers | Durable billing event outbox dispatch is in place: billing records billing.entitlements.updated.v1, persists pending/delivered/retry/dead state, dispatches due entitlement events to usage /v1/events/billing-entitlements-updated, and usage consumes them with processed-event replay plus stale snapshot guards without cross-DB reads. Next: replace the HTTP sink with shared broker transport when selected, then keep quota callers legacy until service-route parity exists. |
| P1 | Billing-to-wallet subscription credits | Billing and wallet workers | Durable billing event outbox dispatch now also records billing.subscription.activated.v1, routes it to wallet /v1/events/billing-subscription-activated, and wallet grants one replay-safe SUBSCRIPTION_CREDIT ledger entry from monthlyCredits. Next: define renewal/proration/backfill policy before promoting subscription public routes. |
| P1 | Exam runtime/access decision API | Exam and attempt workers after contract acceptance | Local exam-service resolver is in place at POST /v1/exams/{id}/runtime-access with data.startInput, link/password/window/snapshot checks, exam_assignments, verifier hooks, and IAM/classroom verifier clients behind IAM_SERVICE_URL/CLASSROOM_SERVICE_URL. Attempt-service start now requires the trusted exam-service decision marker plus idempotency/correlation context, persists replay keys, and has submitted-retake count coverage. Non-default gateway attempt route tables now use the exam_start_adapter state so /api/exams/:id/start calls exam-service first and only forwards data.startInput to attempt-service when allowed. Static, live, and browser proof hooks are named as make test-attempt-routes, make test-attempt-live, and make test-attempt-browser. Next: run live/browser smoke with real disposable fixtures and keep default routes legacy until rollback evidence exists. |
| P1 | Document search projection | Document and search workers | Local owner projection and rebuild route are in place: document-service exposes GET /v1/documents/search-projections, search-service pulls it through POST /v1/rebuild/document-service/documents, fixture coverage exists, and deploy env includes DOCUMENT_SERVICE_BASE_URL. Search-service now has an opt-in SEARCH_REBUILD_WORKER_ENABLED=1 projection freshness worker that cycles question-bank/course/exam/document sources, resumes sync-state cursors, caps pages per tick, and records owner-source failures as sync-state ERROR without taking the service down. make test-search-routes keeps public search routing blocked until a real legacy route/controller mapping selects search-service; /api/public/catalog* remains course-service-owned. Next: event/subscriber freshness or runtime worker proof against disposable owner-service fixtures plus a gateway/public route rehearsal only after that mapping exists. |
| P2 | BFF admin overview route rehearsal | BFF and gateway workers | Non-default route rehearsal is in place for GET /api/admin/overview -> bff-service /v1/bff/admin/overview, with make test-bff-routes static and gateway behavior coverage. BFF admin overview and operations summary can call admin-service /v1/admin/operations/source-map and /v1/admin/operations/source-snapshots, returning optional ownerSources and ownerSourceSnapshots trace metadata while degrading only the affected metadata on upstream failure. Document-service now provides owner document review counts at /v1/admin/documents/review-summary, school-service now provides owner organization roster counts at /v1/admin/organizations/roster-summary while IAM keeps permission-bearing membership authority, IAM provides access-control counts at /v1/admin/identity/summary, profile-service provides display/read-model counts at /v1/admin/profiles/summary, classroom-service provides classroom count summaries at /v1/admin/classrooms/summary, exam-service provides exam counts at /v1/admin/exams/summary, attempt-service provides local attempt metrics at /v1/admin/attempts/summary while analytics-service keeps derived rollups, docx-import-service provides import queue/failure summaries at /v1/admin/import/docx/queue-summary for queue.failures and the DOCX side of queue.depths, ai-classifier-service provides provider readiness at /v1/ai/providers/status for ai.providers plus queue/failure summaries at /v1/admin/ai-classifier/queue-summary for the AI side of queue.depths, and notification-service provides support notification queue/event/delivery summaries at /v1/admin/support/notification-summary for support.queues. Next: more owner-service metric adapters, browser proof, and rollback rehearsal before default route promotion. |
| P2 | AI question-context client | AI and question workers | Local client is in place: ai-classifier consumes question-bank POST /v1/questions/ai-classify/context when QUESTION_BANK_SERVICE_BASE_URL or QUESTION_BANK_SERVICE_URL is configured, persists scope.questionContext, and includes it in provider prompts. Next: BullMQ/job worker parity, gateway RBAC/maintenance checks, and browser proof before public route promotion. |
| P2 | Operational producer event contracts | Notification, analytics, audit, admin, gateway workers | Use docs/agents/service-tasks/operational-producer-events.md for each producer/consumer handoff. Attempt submitted/graded, course enrollment/progress/material/video, exam publish/assignment/result-release, exam assignment notification, classroom student/parent notification through profile resolver, explicit-recipient admin broadcast notification, explicit-recipient support ticket notification, classroom membership snapshot analytics, and gateway route-operation audit producers are now covered as best-effort event handoffs. Next slices need recipient discovery/resolver handoff for support and admin inbox, richer audit/security retry and runtime proof for IAM/payment/billing/wallet/admin/gateway, organization-membership audit semantics, and admin dashboard reads from owner APIs. Keep broad admin/notification/analytics routes legacy until route guards, browser/runtime proof, and rollback evidence exist. |
| P2 | IAM security-event projection contract | IAM and audit workers | IAM keeps credential/session/security decisions local, while audit-service owns compliance-grade security history. The current optional AUDIT_SERVICE_URL/AUDIT_SERVICE_BASE_URL sink posts IAM security_events to audit-service with sourceService=iam-service, stable sourceEventId, metadataSchemaVersion=1, retentionPolicy=security, and redacted metadata; local IAM logs stay authoritative and sink failures are non-blocking. Next slices are outbox-backed retry/replay, legacy security-event backfill reports, runtime smoke, and rollback evidence, with no raw passwords, reset tokens, Google tokens, refresh tokens, or provider secrets crossing the boundary. |
Orchestrator Checkpoint
Run these after integrating any service-agent wave:
bash
make test-service-readiness
make test-runtime-foundation
pnpm docs:build
git diff --check