Contracts

behavioral-contracts.md

Behavioral Contracts — Write-Side Context-Factory Adoption (Mission B)

Function-over-form contracts per concern. Observable behaviors, not structure. Every contract has a topology-true test obligation (NFR-002): full 26-char ULID, real coord-worktree + real submodule. Adoption is proven by deletion of the inline re-derivation with the suite green + read and write routed through the same existing public pure resolver (D-12 / SC-002), NOT by threading the composite fragment (NFR-003). Idempotency (NFR-004): the bounded cut MUST NOT change any on-disk write target. Note: the FR-004 write-target divergence DOES have at least one witnessing contract test (tests/unit/status/test_mission_status_aggregate.py::test_save_supports_identity_bearing_legacy_mission asserts the buggy git-HEAD value) — WP05 owns updating it before→after; WP01's net adds the topology-true oracle.

C-ROOT (IC-EMIT / IC-WPL / IC-LE / IC-STORE / IC-COORD-root — FR-001)

projection), not feature_dir.parent.parent / ancestor scans.

  • Each adopted root site MUST resolve the primary root from workspace.primary_root (the factory
  • MUST be CWD-invariant (resolves the same root from primary checkout, coord worktree, and submodule).
  • Deletion proof: removing the .parent.parent walk keeps the status/lifecycle suite green.
  • MUST NOT change the lock/anchor root value vs the hand-rolled result (equivalence test, D-5).

C-PLACEMENT (IC-WT — FR-002)

naming via the mission_dir_name seam (unchanged).

  • The two core/worktree.py placement joins MUST compose from the factory placement projection;
  • MUST NOT change the on-disk placement path (idempotency).

C-SURFACE (IC-COORD — FR-003, the highest-risk)

the status/coord authority (coord-worktree feature dir when materialized) and MUST NOT degrade to primary_root (C-007; fail-closed preserved).

(NFR-001).

write-target branch selection is a separate concern owned by C-TARGET (FR-004, now IN scope per the reversed D-2) — not by this surface contract.

  • The status-transition write MUST consume status_surface.status_write_dir, which MUST resolve to
  • Read and write MUST resolve the same surface for the same mission across primary/coord/submodule
  • MUST NOT change which on-disk directory a status event is written to (idempotency, NFR-004). The

C-RETIRE (IC-RETIRE — FR-006)

behavior-neutral (no caller passes surface=; prompt_source has 0 readers).

  • Deleting the prompt_source fragment + the StatusSurfaceFragment.surface= read-param MUST be
  • The suite stays green after deletion.

C-BOUNDARY (FR-005, cross-cutting)

independently (the boundary contract). An optional tests/architectural/ ratchet flags write-side re-derivation in the adopted modules.

  • After adoption, no write site in the adopted scope re-derives mission_id/mid8/primary_root

C-TARGET (IC-COORD — FR-004, the branch-target core)

coord_branch or _current_branch derivation is deleted.

resolves to target_branch (the base) — CWD-invariant, NOT git HEAD.

on-disk target as before; the flat case writes to target_branch (the latent-bug-fix vs the old _current_branch=HEAD is the intended correction, proven, not silent churn).

  • The write/merge-target MUST be sourced from branch_ref.destination_ref; the inline
  • Coord topology: destination_ref resolves to the coordination branch. Flat/base topology: it
  • MUST carry a before/after on-disk-target idempotency test (NFR-004): the coord case writes to the same

C-LANES (IC-LANES — FR-008, the third artifact family)

(resolve_lanes_dir(<coord feature dir>)), the coordination authority (C-LANES-1/#1991) — never primary_root under coord topology.

  • The lanes-dir write (lanes.json) MUST resolve from the context's coord surface
  • Deletion proof: the inline lanes-dir derivation is removed; the suite stays green.

C-SIMPLECASE (IC-SIMPLECASE — NFR-006, the KEYSTONE)

context object MUST resolve every diff-type fragment (root, placement, status surface, lanes, write-target) to the base branch.

byte-identical to the historical pre-lane behavior.

to the simple case "as it used to be."

  • On a real single-branch repo (full ULID, no coordination branch declared, no lane worktree), the
  • spec-kitty MUST run flat — zero .worktrees/ or coordination-surface paths read or written —
  • This is the binding guard for C-TARGET: the all-base case proves the branch-target object degrades cleanly