Move all hand-synced cross-app wire contracts into one built workspace package, @boocode/contracts, consumed by server/web/coder/coder-web via workspace:* + a per-subpath exports map. The ws-frames and provider-config Zod schemas are schema-first (z.infer); MessageMetadata, ErrorReason, AgentSessionConfig, the provider snapshot types, and WorktreeRiskReport are each single-sourced. Deletes the byte-identical copies and their parity tests, fixes a live AgentSessionConfig drift (coder dead copy removed, unified to the web required/nullable shape), removes the dead pending_change WS arms in the fallback SPA, and inverts the build order (contracts builds first) across root build, Dockerfile, and the coder deploy docs. Reverses the shared-package decision declined in v2.5.12. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
Tasks — @boocode/contracts SSOT
Nine phases, each independently verifiable. Phases 1–7 are the migration units (one contract group each after a proven tracer); Phase 8 is the audit gate; Phase 9 is the human smoke test. All shipped 2026-06-02.
Phase 1 — Tracer: scaffold package + build-order inversion + web proof ✅ SHIPPED
- Create
packages/contracts(@boocode/contracts):declaration:true, per-subpath exports map, zod^3.23.8. Placeholdersrc/index.ts. - Add
packages/*topnpm-workspace.yaml. - Invert build order everywhere: root
package.jsonbuild script,Dockerfile(COPY packages/*+ contracts build before web/server), coder deploy command. - Regenerate
pnpm-lock.yaml(Dockerfile uses--frozen-lockfile). - Prove the web consumption path end-to-end:
tsc -b(composite+Bundler),vite devHMR, andvite buildall resolve the built.d.ts+.jsvia the exports map. - Verify all consumer builds +
docker compose build boocodegreen. - Remove Phase 1 probe artifacts before Phase 2.
Phase 2a — Single-source the ws-frames runtime schema ✅ SHIPPED
- Move ws-frames schema to
packages/contracts/src/ws-frames.ts(./ws-framessubpath). - Repoint 8 server/coder importers + 2 web validators to
@boocode/contracts/ws-frames. - Delete
apps/server/src/types/ws-frames.ts; drop server./ws-framesexports subpath. - Delete
apps/web/src/api/ws-frames.ts. - Move KNOWN_FRAME_TYPES drift + accept/reject tests into the package (11/11); delete byte-parity test; keep broker fail-closed tests in server importing from the package.
- Container smoke:
docker compose up,/api/health200, broker imports from package.
Phase 3 — Single-source provider snapshot types ✅ SHIPPED
- Move
ProviderSnapshotEntry,ProviderModel,ProviderMode,ThinkingOption,AgentCommand,ProviderSnapshotStatustopackages/contracts/src/provider-snapshot.ts(./provider-snapshotsubpath). apps/coder/src/services/provider-types.tsre-exports them (importers unchanged).- Delete web mirror block; delete
provider-types-parity.test.ts(coder −6 tests). - All builds and typechecks green; server 543 / coder 293 unchanged.
Phase 4 — Single-source the Zod provider-config schemas ✅ SHIPPED
- Move
ProviderOverrideSchema,CoderProvidersFileSchema,ProviderConfigPatchSchema+z.infertypes topackages/contracts/src/provider-config.ts(./provider-configsubpath). apps/coder/src/services/provider-config.tsimports + re-exports (importers unchanged).- Delete 17-line web hand-mirror.
- Coder provider-config tests 13/13; all builds green.
Phase 5 — Single-source type-only contracts (MessageMetadata + AgentSessionConfig) ✅ SHIPPED
- Move
MessageMetadata,ErrorReason,AgentSessionConfigtopackages/contracts/src/message-metadata.ts(./message-metadatasubpath). - Unify
AgentSessionConfigto the web required/nullable shape; delete the coder's dead all-optional copy (zero live importers confirmed). - Delete all duplicate
MessageMetadata+ErrorReasoncopies (confirmed byte-identical). - Repoint server
api.ts, web types, andMessageBubble.tsxto the package. - Server 543 / coder 293 unchanged; all builds green.
Phase 6 — Single-source WorktreeRiskReport ✅ SHIPPED
- Move
WorktreeRiskReporttopackages/contracts/src/worktree-risk.ts(./worktree-risksubpath); unify name (coderRiskReport→WorktreeRiskReport). - Delete all three copies (shapes identical, names differed).
- Repoint
sessions.ts,ProjectSidebar.tsx,orphan-worktree-reaper.ts,worktree-safety.tsvia re-exports;checkWorktreeWorkAtRiskreturns shared type. - Server 543 / coder 293 unchanged; all builds green.
Phase 7 — Migrate apps/coder/web (fallback SPA) ✅ SHIPPED
- Add
@boocode/contractsworkspace:*dep toapps/coder/web/package.json. - Delete hand-copied 9-arm
WsFrameunion; import canonicalWsFramefrom the package. - Reconcile field conflicts:
tool_result.errorboolean→string;tokens_usednumber→number|null;snapshot.messagescastas Message[];chat_id ?? ''. - Delete dead
pending_change_added/pending_change_updatedreducer arms + the entire deadonPendingChangeWS plumbing (DiffPaneprop,Session.tsxlistener). - Confirm HTTP pending-change apply/reject path untouched.
apps/coder/webVite build green; root build + server 543 / coder 293 green.
Phase 8 — Audit every requirement bullet ✅ PASSED (12/12)
- Verify one definition per contract (file + line evidence for each).
- Verify
z.inferfor both Zod contracts (ws-frames, provider-config). - Verify all four consumers wired via exports map (no project refs, no src imports).
- Verify all hand-copies + parity tests deleted; drift/broker tests preserved.
- Verify single zod version; build-order inverted in root + Dockerfile + deploy docs.
- Verify
packages/*in workspace; deadpending_change_*arms gone. - Verify web strict union preserved + coherent post-migration.
- Close gap G: update coder deploy command in all 7 doc sites (CLAUDE.md, apps/coder/CLAUDE.md, BOOCODER.md, docs/ARCHITECTURE.md, docs/project-discovery.md, README.md, docs/coder-backends.md).
- Correct now-false byte-parity/duplication claims in CLAUDE.md conventions, apps/server/CLAUDE.md broker note, docs/coder-backends.md, and docs/coding-standards/cross-app-contract-parity.md (rewritten to describe the SSOT).
- Mark DEFERRED-WORK §3 + STALE-DEPRECATED item as shipped.
- Clean
docker compose build --no-cache boocodegreen; server 543 / coder 293 / contracts 11 at exact baselines; nothing staged (HEADe5ce01a).
Phase 9 — Human smoke test ✅ PASSED (Sam, 2026-06-02)
- Web dev HMR, web prod build at :9500, live WS stream rendering.
- Coder restart + a turn; fallback SPA; pending-change apply.
Verify (all runs green)
pnpm -C packages/contracts buildpnpm -C apps/server test(543)pnpm -C apps/coder test(293)pnpm -C apps/server build && pnpm -C apps/coder buildnpx tsc -p apps/web/tsconfig.app.json --noEmitdocker compose build --no-cache boocode