Contracts
class-a-residual-cleanups.md
Contract: Class A Residuals — Residue-Free Finalize, Canonical Read Surfaces, Baseline Coverage (#1814, #1735, #1827)
A-r1: Finalize leaves no primary residue (#1814 → FR-006)
Surface: _stage_finalize_artifacts_in_coord_worktree (cli/commands/agent/mission.py:99-131).
GIVEN task finalization on a coordination-topology mission WHEN staging into the coordination worktree completes THEN git status --porcelain on the primary checkout reports no planning-artifact residue (lanes.json, tasks/*, matrices) created by the stager AND subsequent record-analysis proceeds (no DIRTY_WORKTREE refusal from stager residue) AND no operator-authored file is deleted (cleanup is scoped to paths the stager itself materialized — research R6). CONSTRAINT (C-003): COORD_OWNED_STATUS_FILES is not widened.
Ratchet: extend tests/specify_cli/test_wp06_sc2_paused_mission_blockers.py (AC-A1).
A-r2: Canonical status-read surface (#1735 → FR-009)
Surfaces: retrospective/gate.py:597, cli/commands/agent_retrospect.py:432.
GIVEN retrospective completion gating under coordination topology THEN both read sites obtain events via resolve_status_surface (never resolved.feature_dir + direct file read) AND the AC10 architectural ratchet (extend tests/architectural/test_execution_context_parity.py) forbids resolved.feature_dir-anchored read_events()/status.events.jsonl access outside the surface resolver. Ratchet lands after the two sites are routed.
A-r3: Baseline-recording regression coverage (#1827 → FR-010)
GIVEN a coordination-topology merge completing THEN git show <target>:kitty-specs/<slug>/meta.json contains baseline_merge_commit (real, unmocked _record_baseline_merge_commit — unmock helpers at test_merge_coord_topology_1772.py:224-225 or add a sibling test) AND the crash-between-record-and-commit re-run edge is documented in the test as a known bounded behavior (fix itself landed in rc42 9c8bff06f).
class-b-ref-advance-resync.md
Contract: Class B — Ref Advance with Worktree Resync (#1826)
Surface: internal merge-pipeline helper (shape per research R1) replacing raw git update-ref at lanes/merge.py:440, lanes/merge.py:474, cli/commands/merge.py:993-998.
Behavior
GIVEN a branch ref advanced by the merge pipeline (lane→mission merge or mission-number baking) WHEN any git worktree has that branch checked out THEN after the advance, that worktree's HEAD, index, and working tree match the new branch tip (CONSISTENT state) AND the subsequent bookkeeping safe-commit succeeds without SafeCommitBackstopError.
GIVEN the checked-out worktree holds uncommitted local state at advance time THEN the operation raises a structured refusal (no reset --hard executes) naming: worktree path, ref, old→new SHA, and the dirty entries AND merge state remains resumable (merge-state.json preserved).
GIVEN no worktree has the branch checked out THEN behavior is identical to today's raw update-ref (no extra work beyond the worktree scan).
Postconditions & Ratchets
- AC-B1: end-to-end coord-topology merge (≥2 lanes + baking) completes unattended —
tests/specify_cli/cli/commands/test_merge_coord_worktree_resync_1826.py. - AC-B2: after each Stage-1 advance, coord worktree index == HEAD (direct assertion).
- AC-B3: architectural ratchet — no raw
git update-refsubprocess invocation insrc/specify_clioutside the helper. - AC-B4: dirty-worktree refusal test (plant a file in the coord worktree; assert refusal + no data loss).
- FR-012 rider:
SafeCommitBackstopErrormessage names which worktree/ref diverged and the likely cause.
Non-goals (C-002)
Migration of any ref-advance outside the merge pipeline; changes to update-ref semantics elsewhere; BookkeepingTransaction self-heal (rejected, research R1).
class-c-validate-only-readonly.md
Contract: Class C — validate-only Is Read-Only (#1861 Part 1)
Surface: spec-kitty agent mission finalize-tasks --validate-only (guard at cli/commands/agent/mission.py:2462).
Behavior
GIVEN a repository where the mission target branch differs from the currently checked-out branch WHEN the operator runs finalize-tasks --validate-only THEN git symbolic-ref HEAD is byte-identical before and after AND git status --porcelain output is byte-identical before and after (no staging, no checkout, no writes) AND validation results are identical to those produced by the commit-phase run's validation step.
GIVEN finalize-tasks WITHOUT --validate-only THEN behavior is unchanged from today (existing tests stay green — AC-C2).
Postconditions & Ratchets
- AC-C1: before/after HEAD + porcelain assertions —
tests/specify_cli/cli/commands/test_finalize_tasks_validate_only_readonly.py. - AC-C2: existing finalize-tasks suite green unmodified.
- AC-C3 (hygiene rider): issue #1861 updated — Part 2 recorded as already resolved by
SafeCommitHeadMismatch(8e79b3f6d).
Non-goals (C-001)
Deleting the _ensure_branch_checked_out shim; converting commit-phase positioning to plumbing reads (deferred to #1666 umbrella).
class-d-workspace-resolution.md
Contract: Class D — Workspace Resolution Fall-Through Is Failure (#1833)
Surfaces: workspace/context.py:148-150 (ResolvedWorkspace.exists), cli/commands/agent/workflow.py:2237/2243/2265 (review claim), cli/commands/agent/tasks.py:1346 (move-task), doctor husk check (FR-007).
Behavior
GIVEN a directory under .worktrees/ that lacks a .git entry (a HUSK) WHEN any command resolves it as a lane workspace THEN resolution fails with a structured error naming the husk path and the failed check AND zero git commands execute against the primary repository as a result of that resolution AND the error is NOT a misattributed verdict ("No implementation commits on lane branch!", primary-repo dirty-tree complaints).
GIVEN git worktree add fails during review claim THEN the claim fails hard (no warning-and-continue), and no ReviewLock is held afterward (lock acquired only after the workspace exists).
GIVEN move-task receives a resolved workspace path THEN it asserts git -C <path> rev-parse --show-toplevel == <path> before any other git invocation.
GIVEN an operator machine with pre-existing husks WHEN they run the doctor husk check THEN every .worktrees/* entry lacking .git is reported, and --fix removes entries not registered in git worktree list (registered worktrees are never removed).
Postconditions & Ratchets
- AC-D1: planted-husk test —
tests/specify_cli/cli/commands/test_workspace_husk_resolution_1833.py. - AC-D2:
ResolvedWorkspace.existsFalse for husk; lock-after-create ordering asserted; worktree-add failure is an error. - AC-D3: doctor check reports and (with
--fix) removes husks.
Non-goals (C-001)
Worktree-naming allocator unification; workspace-lifecycle/ReviewLock redesign; "is-a-worktree" as a type invariant across all resolvers (#1666 umbrella).
class-f-merge-driver-hardening.md
Contract: Class F — Merge-Driver Hardening (#1736 residuals)
Surfaces: lanes/merge.py (subprocess environment), coordination/status_transition.py:399-400 (exception discipline), tests/status/test_event_log_merge.py (schema ratchet).
F-1: Single environment authority (FR-008b)
GIVEN any subprocess invocation inside the lane-merge pipeline (_merge_branch_into and peers) THEN its environment is produced by _make_merge_env() (extracted helper) — no inline os.environ copies with ad-hoc PATH/GIT_* mutations. Ratchet (AC-F1): test asserting every subprocess call site in the module routes through the helper.
F-2: Deterministic mixed-schema event sort (FR-008c)
GIVEN an event log containing entries with at, entries with legacy timestamp, and entries with neither WHEN merge_event_payloads sorts them THEN the order is deterministic and total (documented tie-break), identical across repeated runs. Ratchet (AC-F2): test_merge_event_payloads_mixed_at_timestamp_neither in tests/status/test_event_log_merge.py.
F-3: Narrow exception mask (FR-008d)
GIVEN the lane status read at coordination/status_transition.py:399-400 THEN only (ValueError, FileNotFoundError) trigger the documented GENESIS fallback; all other exceptions propagate. Ordering (C-004): lands with/after the Class B resync so stale-worktree reads don't newly throw. Ratchet (AC-F3): test injecting a non-expected exception and asserting propagation; test for each expected type asserting fallback.