Contracts
boundary-contract.md
Contract: Contract-ownership boundary (MVP)
The observable contracts this mission upholds (verified by the tests + reviews cited in acceptance-matrix.json).
C1 — A shared contract is a modeled, owned artifact (#2441, FR-001..004)
- A Contract Record lives in
docs/contracts/contract-registry.yaml(schema…-schema.yaml):id,kind∈{fallback_name,retired_literal}, a content-anchoredanchor(symbol:ORliterals:— neverfile:line),status,owner,replaced_by,retirement, and the missing piece — a declared consumer set (scan_roots/exemptions/test_shards/call_sites),verification{enforcement: advisory}. - Invariant (NFR-003, DIR-041): the loader/validator (
src/specify_cli/contracts/registry.py,spec-kitty doctor contracts) rejects anyfile:lineanchor — both a positional field and a fragment-join reconstruction. The registry must not become the rot it replaces. Generalizes the proven shim-registry chain (not a fork).
C2 — Retirement is verified against the declared consumers, advisory-first (FR-005)
tests/architectural/test_retired_contracts_absent.pysweeps eachstatus=retiredrecord's anchor acrossscan_rootsminusexemptions. Advisory/report-only — never blocks CI on a live find (proven structural under-W error); a mandatory anti-vacuity control proves it bites.
C3 — Adoption proves the driver SUBSUMES the gates WITHOUT downgrading enforcement (#2441, FR-006, NFR-004)
- The literal sweeps (
test_no_legacy_terminology.py+ the CLI-tree path-literal) are modeled as records + a superset parity proof (test_contract_registry_parity.py): the advisory driver's detection is a superset of what the (still merge-BLOCKING) gates detect — it preserves all the gate's coverage (NFR-001) AND additionally over-flags comment-line / non-.pymentions the CLI-path gate carves out (an advisory-safe over-flag;driver ⊋ gate, pinned by a comment-line control). Set-equality holds only over the curated divergence-free envelope (non-comment lines in in-scope.pyfiles), not globally — proven via the gates' own logic against a fabricated repo. - Invariant (NFR-004): the enforcing gates are byte-for-byte unchanged and still block; nothing is retired (the actual delete-the-assertion + enforcing-driver mode are deferred #2441 follow-ups). No enforcing→advisory downgrade. The gate's comment-skip +
.py-scoping must be modeled in the driver before any enforcing flip, to avoid false friction.