Warp-drive contract
Warp-drive contract
Section titled “Warp-drive contract”The warp-drive state machine is a table: PHASES (23 names) and TRANSITIONS (62 (from, event, to) edges) in scripts/warp-drive/state-machine.js, plus a per-phase DEFAULT_REASONING_BUDGET. Everything else in the loop — the hooks that auto-advance it, the graph the monitor draws, the phase-history log, the segmentation checkpoint, the bob warp CLI — is written against that table. This page explains why the table is frozen behind a committed fixture (#2042), what the freeze does and does not cover, and how a change lands while it holds.
The rule lives in one place in code — the fixture, tests/fixtures/phase-contract.json — and in one place in prose, this page. The moratorium itself is decision #2118.
Why freeze it
Section titled “Why freeze it”The table grew one edge at a time. The in-session QA loop added qa (#868); the preflight gate added preflight and blocked (#1923); skipping blocked items added work_skipped (#1270). Each was right on its own. What nothing checked was the set: tests/test-phase-meta.js proved every phase had tooltip metadata, but not which phases existed, and by the 2026-09-10 architecture review (#2027) DEFAULT_REASONING_BUDGET had silently drifted to 18 of 23 phases and the state reference’s transition table was missing four phases. The consolidation work that review queued — the glob test runner (#2043), the hook dispatchers (#2082), the flag registry (#2085) — is all written against the table, and it needs the table to hold still while it lands.
So the contract is pinned, and pinned the same way the checkpoint dirt rule was pinned a day earlier (#2037, Checkpoint dirt rules): a hand-authored fixture, a test that drives the real code against it, and a make check gate that keeps the prose honest.
What is pinned
Section titled “What is pinned”tests/fixtures/phase-contract.json (phase-contract/1) states:
| Section | Pins | Compared against |
|---|---|---|
phases |
every phase name, in order | PHASES |
transitions |
every (from, event, to) edge |
TRANSITIONS, flattened |
reasoning_defaults |
one level (standard | high) per phase — the key set equals phases |
DEFAULT_REASONING_BUDGET |
moratorium |
frozen_until (an ISO date) and decision (the linked decision issue) |
the rules below |
Two gates read it:
tests/test-phase-contract.js(make test-phase-contract) compares the live engine against the fixture in both directions and fails with the exact diff: a phase in code but not the fixture, a phase in the fixture but not in code, an edge added, removed or retargeted, a phase with no budget entry, a level that disagrees. Negative controls mutate copies of the tables so each class of drift is proven to be named, not merely absent today.scripts/checks/phase-contract.js(make check-phase-contract, inmake check) compares the fixture against the two doc tables that state it — the transition table in the state reference and the reasoning defaults in token monitoring — so the prose can never say something the fixture does not.--jsoncarries the contract identity.
The fixture is not a snapshot. A snapshot is regenerated on a whim; this file is edited by hand, in the same commit as the code, and during the moratorium only with a decision linked from it.
What is not pinned
Section titled “What is not pinned”The contract is the topology, not the behaviour inside a phase. Nothing here constrains:
- what a phase’s instruction says, or what data a transition accepts on
--data; - the display overlays — the bug-work labels (
bug_fixing,regression_gate,bug_verified, #518) and therevalidatingsub-mode (#1008) relabel existing phases and add no edges; - the budget breakers that route into
budget_exceeded(they use edges the fixture already lists), or thebudget_continuereturn to the interrupted phase (#1183) — the table edge is the fallback, the recorded phase is a runtime override; PHASE_META, hook wiring, or the_workflowconfig table — those have their own gates (test-phase-meta,test-declared-behaviours,check-workflow-keys).
The moratorium
Section titled “The moratorium”No new phase and no new or retargeted transition until 2026-10-11 without a decision issue. Concretely, while the freeze holds:
- A phase or transition changes only by editing the fixture in the same commit as the code. Any other route is red — the test names the diff and the fix.
- That commit must link a
decisionissue frommoratorium.decisionin the fixture, saying why the freeze is being broken. #2118 is the standing record; a new decision supersedes it for that one change. DEFAULT_REASONING_BUDGETkeeps a key set equal toPHASES. The documented default for a phase with no explicit override isstandard— the value the lookup falls back to — which is whatidle,preflight,blocked,awaiting_continueandcompletednow carry explicitly.
After 2026-10-11 the fixture stays: it is the contract, and the test still holds code and fixture together. What lapses is the decision-link requirement — a fixture-plus-code change is then an ordinary reviewed commit.
What the status surfaces name
Section titled “What the status surfaces name”The frozen contract is a declared behaviour (#1834) — contract:phase-contract:all in scripts/warp-drive/declared-behaviours.js, alongside the hook auto-advances and the commit gate — so the engine’s promises and the contract it runs under are listed in one registry. contractVersion() reads the fixture from the source checkout and renders one line:
phase-contract/1 — 23 phases, 64 transitions, frozen until 2026-10-11 (#4206)The decision named is the latest one the fixture links. #4206 broke the freeze for the two work_skipped exits from chunking and coding (#3476).
It appears on bob warp status (the Contract: line, from state-machine.js status’s contract field), in bob doctor (an INFO contract: line and a contract object in bob-host-drift/1 — named, never graded: the fixture is a source file, not a deployed surface), and in state-machine.js declared. The fixture is read from the BoB source checkout, resolved the way bob doctor resolves it, because the deployed copy under BOB_HOME has no tests/ (#3143). With no checkout the line says not measured, and an unreadable fixture is reported as such, never thrown.
See also
Section titled “See also”- Warp-Drive State Reference — the transition table the fixture generates, the
declaredCLI, the state file. - Token Monitoring — the reasoning defaults table and the
reasoning_budgetoverride. - Checkpoint dirt rules — the sibling contract (#2037), same fixture-plus-gate shape.
- Verification System — where
check-phase-contractsits inmake check. - Prime Directive — one owner per fact: the fixture owns the contract, the doc tables restate it, the gate keeps them equal.