Contracts
census-predicate.md
Contract — Census Predicate (FR-010 / SC-006)
Owner: tests/architectural/test_verdict_seam_census.py::_derive_census + verdict_seam_census.yaml.
Guarantees
constructed via a .from_dict/factory helper (concrete prior gap: backfill_runtime_state.py::_runtime_repair_delta) — reds the census. (SC-006)
status/wp_review.py, _snapshot_review_override) and the new provenance-backfill migration stay excluded via named _EXCLUDED_MODULE_REASONS, so test_review_slot_is_event_authoritative… stays green.
the yaml in the same change. (C-004)
- G1 (completeness): a new writer/resolver/reader of the review-cycle verdict — including a record
- G2 (no over-match): event-authority deserializers (
status/reducer.py,status/models.py, - G3 (shrinkage-red): the derived active set must equal the fixture exactly; retirements land in
Predicate extension
Recognize <Record>.from_dict( in the scope regex and the writer classifier (reuse _call_base_name); optionally key the reader predicate on "opens a path matching review-cycle-*.md by name" rather than a fixed verb list.
Sequencing
Lands before IC-03 so the census can prove reader retirement during the collapse. (C-008)
Verified by
≥1 synthetic .from_dict poison test (red today) + ≥1 real-data test asserting _runtime_repair_delta is classified + a negative control asserting an event-authority deserializer stays excluded.
gate-artifact-write-surface.md
Contract — Gate-Artifact Write Surface (#2804 / #2404 — FR-009 / SC-005)
Owner: accept acceptance-matrix home resolver + merge/executor.py + merge_driver.py + init.py.
Guarantees
under a coordination topology. accept fills it on the COORD surface only, so there is no add/add divergence for the merge to mis-resolve. Verified by a write-side check (greps the write path, not just the merge outcome). (SC-005)
spec-kitty-acceptance-matrix / spec-kitty-issue-matrix drivers are registered/active in the repo before the squash, so -X theirs never clobbers a filled matrix.
(m_3_2_6_gate_artifact_merge_drivers.py seeding the retired .md pattern) is fixed so the issue-matrix driver is not inert.
- G1 (single write surface, #2404): no code path authors a PRIMARY-partition
acceptance-matrix.json - G2 (driver registration, defense-in-depth): the merge executor guarantees the row-aware
- G3 (legacy retired):
issue-matrix.mdis retired; the.md→.jsondriver seed drift
Independence
This concern (IC-06) touches none of the verdict-seam files and no census yaml — it runs on a parallel lane.
Verified by
Green the existing red-first pin tests/regression/test_issue_2804_merge_resets_gate_artifacts.py (a filled acceptance + issue matrix survives a real merge) + the G1 write-side check.
provenance-backfill.md
Contract — Verdict-Provenance Backfill + Gate (FR-012 / SC-008)
Owner: new migration/verdict_provenance_backfill.py + a provenance gate (extends doctor review-cycle-reconcile predicate or a sibling surface).
Backfill
For each mission/WP with a terminal .md verdict and no event review_result slot: reduce the .md verdict into status.events.jsonl via append_events_atomic_verified (status/store.py:509) with a hand-constructed review_result event — not emit_status_transition (D-PLAN-10: it derives from_lane from the WP's current lane and runs validate_transition, so it cannot replay a historical edge onto a settled WP). The event's at MUST be the historical verdict timestamp from the .md/git record, never now().
distinct from the reconcile doctor's two physical-location classes (deleted_coord_branch_absorption, live_coord_pre_adr_primary_record).
- G1 (idempotent): keyed on
(mission_id, wp_id, verdict, cycle)— a re-run adds nothing. - G2 (provenance, not location): the predicate examines verdict provenance (event slot vs
.md),
Gate
terminal .md verdict and no event slot. Parses --json; asserts zero findings as a test artifact.
- G3 (blocks reader deletion): IC-03's frontmatter-reader deletion is blocked while any WP has a
Sequencing
Lands in IC-02, before IC-03. (C-008)
Verified by
A seeded mission whose only rejection is a pre-event .md: after backfill + reader deletion, the approval guard still refuses. (SC-008; US6)
verdict-authority-read.md
Contract — Verdict-Authority Read
Owner: status/reducer.py::event_sourced_review_result (+ ReviewResultLookup). Consumers (all repointed here in IC-03): approval guard resolve_review_verdict_facts; merge gate find_rejected_review_artifact_conflicts; dashboard show_kanban_status/_get_wp_review_verdict; status-display review/verdict fields; fix-mode has_prior_rejection / implement_try_render_fix_mode_prompt.
Signature (stable)
event_sourced_review_result(feature_dir, wp_id) -> ReviewResultLookup
ReviewResultLookup three-way:
slot_present=False→ absent (no verdict recorded)slot_present=True, result=None→ damagedslot_present=True, result=ReviewResult(verdict=…)→ present
Guarantees
damaged as fail-closed (never approve, never crash uncaught). (SC-004)
direction-dependently: the approval guard fails closed (absent = "no approval" ⇒ a WP that cannot be proven approved is refused, so it never reaches approved and never merges), while the merge-rejection block gate is fail-open on the same value (absent = "no block") — safe only because it is backstopped by that fail-closed approval guard, never a standalone gate. The end-to-end property (a corrupt log never lets a real rejection merge) holds via the approval guard, not the block gate.
- G1: no consumer parses
review-cycle-N.mdfrontmatter for a verdict. (SC-002) - G2: safety-gate consumers (approval guard, merge gate) treat absent as "no approval" and
- G3: on a corrupt log (
StoreError → slot_present=False), "absent" is read
Verified by
test_2093_authority_invariant.py (derived ratchet, extended in IC-03) + the verdict-seam census + a parametrized damaged-record test over every safety-gate consumer.
verdict-durability-write.md
Contract — Verdict-Durability Write (SC-004 / D2)
Owner: status/emit.py::emit_status_transition (the authoritative durable write). Demoted: review/cycle.py per-file .md commit → best-effort render.
Guarantees
verdict is the authoritative durable act. The .md render commit is best-effort and MAY fail without erroring. (NFR-004)
refusal; never a silent drop, never a spurious crash. The event log is union-merge-driver protected, so concurrent appends union rather than clobber. (SC-003)
event-log append discipline, not a lock spanning git.
- G1 (single authoritative call): exactly one
emit_status_transitionappend per recorded - G2 (concurrency): two concurrent distinct verdicts → two durable event records or one explicit
- G3 (NFR-001): no inter-process lock is held across a
gitsubprocess. Serialization is the - G4 (responsiveness): one verdict record incl. durable persistence completes < 2 s. (NFR-005)
Retired (as authoritative machinery)
The per-file _commit_review_cycle_artifact retry loop, hard-error-on-non-committed, and orphan-cleanup are retired as the authoritative durability path (kept at most as best-effort-render defense-in-depth during migration).
Verified by
tests/integration/test_review_durability_matrix.py (50 iterations × 2 OS processes, serial -n0); tests/review/test_cycle.py (perf).
vocabulary-bridge.md
Contract — Vocabulary Bridge (FR-005)
Owner: one canonical surface beside status/models.py (e.g. verdict_vocab.py). Single source.
Mapping (total, both directions)
Artifact vocabulary → event vocabulary:
| Artifact verdict | Event verdict |
|---|---|
approved | approved |
rejected | changes_requested |
arbiter_override | approved (override is an approval outcome; distinguishability lives in the ReviewOverride record, not the verdict) |
approved_after_orchestrator_fix | approved |
Event vocabulary → artifact/render (for prose display): approved → approved, changes_requested → rejected.
Guarantees
through to "damaged". (FR-005; edge case)
rejected↔changes_requested equivalence inline. Enforced by an architectural guard test (grep-guard on co-occurring literals outside the owner module). (paula finding — today inline in 9 modules)
- G1: the mapping is total over all four inbound artifact values — no inbound value falls
- G2 (no drift surface): no module other than this canonical surface spells the
Verified by
An arch-test forbidding inline equivalence + an end-to-end test driving an arbiter_override record through to a resolved verdict.