formax-semantics-parity-workflow
Goal
Use this skill when changing behavior that must stay consistent across TUI, app-server, and Web: mode, input lifecycle, tool sequencing, replay, or ordering.
Read First
docs/contracts/semantics-contract.mddocs/contracts/app-server-interaction-contract.mddocs/frontend/app-server-ui-spec.mddocs/contracts/interactive-input-contract.mdwhen input lifecycle changes
These docs are canonical. If stable cross-surface behavior changes, update them before or with code.
Code Map
1) Semantic single source of truth
packages/core/src/features/semantics/*canonicalEvents.tstranscriptProjection.tsmodeSemantics.tsreplModeTransition.tsturnInputBuilder.tsinputStateMachine.ts
2) App-server contract emit / restore
packages/core/src/app-server/turnRunner.tspackages/core/src/app-server/server.tspackages/core/src/app-server/threadStore.tspackages/core/src/app-server/store/sessionEventReader.tspackages/core/src/app-server/turn/inputStore.ts
3) TUI adapter (renderer can differ, semantics cannot)
packages/core/src/features/repl/controller/send/send.tspackages/core/src/features/repl/controller/streaming/streaming.tspackages/core/src/features/repl/useReplController.ts
4) Web adapter (renderer can differ, semantics cannot)
packages/web-reference-react/src/eventAdapters.tspackages/web-reference-react/src/App.tsxpackages/web-reference-react/src/store.tspackages/web-reference-react/src/turnEventCursor.ts
5) Canonical docs to keep in sync
docs/contracts/semantics-contract.mddocs/contracts/app-server-interaction-contract.mddocs/frontend/app-server-ui-spec.mddocs/contracts/interactive-input-contract.mdwhen input lifecycle changes
High-Signal Patterns
- Semantic-first implementation order:
- define contract / event shape / state transition
- update shared semantics
- update app-server emit / replay state
- update TUI and Web adapters
- update renderer-only UI last
- Ordering discipline:
replaySeqis the primary ordering keytraceId/seqare diagnostics and turn-local hints, not global order- on replay gap, rebuild from semantic baseline; do not keep stitching stale tails
- Tool semantics discipline:
- keep
toolUseId -> toolNamesticky behavior in semantics / adapter path - never depend on UI copy to infer tool state
- keep
- Mode/input discipline:
- mode is a semantic transition, not just a visual toggle
- input lifecycle remains a finite-state machine, not ad-hoc UI flags
Minimal Workflow
- Define the event / state transition in canonical docs and the shared semantics layer first.
- Update app-server emit / replay state so the semantics remain recoverable.
- Update TUI and Web adapters to consume the shared semantics; update renderer-only UI last.
- If
packages/core/src/features/repl/**semantic-flow files move, run the REPL semantic gate before review. - Run the minimum regression set below, then review via
AGENTS.md.
Minimum Regression
bun run type-checkbun run test -- packages/core/src/features/semanticsbun run test -- packages/core/src/features/semantics/__tests__/projectionParity.test.tsbun run test -- packages/core/src/app-server/turnRunner.test.ts packages/core/src/app-server/server.test.ts packages/core/src/app-server/turn/inputStore.test.tsnpm --prefix packages/web-reference-react run type-checknpm --prefix packages/web-reference-react run test -- src/App.test.tsx src/store.test.ts src/turnEventCursor.test.ts src/toolEventNormalizer.test.tsbun run test:repl-semantic-gatewhenpackages/core/src/features/repl/**semantic-flow files change
For fixture selection and parity assertions, use references/fixtures-checklist.md.
Guardrails
- Do not patch one renderer in isolation when the bug belongs to shared semantics.
- Do not add a second semantic state machine inside TUI or Web.
- Do not use UI text or copy as semantic-state input.
- Do not introduce new ordering rules outside the shared semantics layer.
- Do not call a parity change done until app-server, TUI, and Web consume the same semantic rule.