Contracts
birth-cutover-and-repair.md
Contract — Birth-Cutover, Acceptance Lock, and Repair
Event-sourced authoring (FR-008)
- Scope: exactly two paths — claim (
shell_pid/agent) and subtask-completion (tasks.md checkboxes), per #2684. - Given a WP is claimed or a subtask completed, when the write occurs, then it is recorded as an event (not authored to frontmatter/
tasks.md), so no un-seeded runtime accrues. - Bound: no other authoring path changes (C-002).
Birth-cutover (FR-009, NFR-003, C-004)
- Given a mission is merged, when the cutover runs at the bake stage, then
cutover_mission reconciles residual runtime and stamps status_phase, with meta.json/status_phase routed to PRIMARY and seed events to COORD via the placement port (FR-002). - Timing (corrected): the
_bake_mission_number hook is pre-target (executor.py:1319 runs before _phase_mission_to_target). The PRIMARY meta flip therefore rides the mission→target merge atomically — if the merge aborts, the flip never reaches target, which stays consistent (the un-merged mission branch is discarded). The plan must choose ONE of: (a) keep the bake hook and rely on merge-atomicity for the PRIMARY leg, or (b) relocate the stamp to a post-_phase_commit_and_assert phase. Either way the earlier "fires only after the target commit is durable" wording was inaccurate for this hook. - Two-partition atomicity (OPEN — IC-08 must resolve):
cutover_mission(feature_dir) is single-feature_dir by signature and cannot natively split meta→PRIMARY (mission branch) from seed events→COORD (coord branch). IC-08 must either add a two-target form to the cutover spine OR delegate the COORD seed-event write to the existing coord projection (_phase_record_done_and_project), with a transactional envelope / resume-heal so a crash between the COORD write and the PRIMARY flip cannot leave a half-born mission. - Idempotent: a re-run (merge
--resume, or the one-time migration) seeds 0 events and leaves status_phase + the event log byte-identical. - Sole writer: reuses
cutover_mission / _flip_phase (no parallel status_phase writer) — a two-target form extends the spine, it does not fork it (C-004). - Gate: the birth-write itself must satisfy IC-02's whole-tree write-placement gate.
Acceptance lock (FR-010, NFR-006, C-003)
- Given a mission whose event log carries runtime (excluding the self-referential cutover mission), when
test_dogfood_corpus_backfilled runs, then it requires status_phase>=1 + a non-empty snapshot, and preserves the verify_backfill parity assertion (no green-wash). - Durable: the lock stays green after ≥3 subsequent mission merges with no manual backfill (SC-001).
- Migration coexistence: a regression proves the one-time
migrate backfill-runtime-state path still cuts over a legacy corpus after FR-008.
agent mission repair (FR-005, NFR-005)
- Given a mission with pre-existing content divergence across partitions:
- strict-ancestor + clean worktree → forward-only (fast-forward), zero data loss;
- non-ancestor divergence → refuse, emit a unified diff, zero mutation.
- Bound: distinct command;
doctor coordination --fix stays minimized (C-002/C-003).
placement-enforcement.md
Contract — Placement Enforcement (write + read)
Write (FR-001, NFR-001, NFR-004)
- Given any
src/ Python module, when it performs a mission-artifact commit (safe_commit(target=…) / constructs CommitTarget(ref=…) / calls write_meta(...) for a mission-artifact path), then the target MUST be derived from the placement seam (resolve_placement_only / placement_seam.write_target(kind)). - Gate:
tests/architectural/test_no_write_side_rederivation.py scans all of src/ (no module allowlist); test_safe_commit_import_boundary.py additionally asserts target=CommitTarget(...) is seam-derived. A synthetic non-seam-derived write in any module reds the gate. - Exclusions: only individually-justified sanctioned primitives (e.g. lane-deliverable commit, invocation/upgrade commits) — each carries an inline rationale; the exclusion set is NOT a module allowlist.
- Non-regression: the three existing gates stay green.
Read (FR-004, NFR-002)
- Given a mission-artifact read for a kind, when it resolves a surface, then it MUST resolve through
artifact_home_for(kind).read_surface; a coord-homed kind resolving to a primary substitute raises a typed partition-mismatch error (no silent fallback). - Gate: NEW
tests/architectural/test_read_surface_placement_guard.py, symmetric to the write gate. - Reconciliation: existing #2906 accept-time read guards remain; the new authority generalizes them, it does not double-guard or regress the lenient diagnose path.
Routing coverage (FR-003, FR-006)
- The
emit _current_branch HEAD-derived fallback (#1716) is removed; bookkeeping_projection / bookkeeping_commit / decision_log route through the port; decisions.events.jsonl and traces/ are classified in the partition SSOT (COORD).