Contracts
charter-read-authority.md
Contract: Charter Read/Path Authority
Owning FRs: FR-001, FR-002, FR-003, FR-004, FR-006, FR-016 Landed by: WP01, WP02, WP03, WP04, WP11
The contract
There is exactly one door for a "does a charter exist / where is it" decision: charter/bundle.py's CHARTER_YAML / CHARTER_MD constants, read through charter/charter_yaml_io.load_charter_yaml.
schema-guarded resolution authority. Every authority-presence surface — dashboard (resolve_project_charter_presence), analysis-report staleness, retrospective policy resolution — keys on this file and survives charter.md deletion.
readable, free-form prose/rationale companion. It is never a resolving override. One legitimate exception class survives by design (C-003): the charter/context.py gate at if not charter_yaml_path.exists() and not charter_path.exists(): (line 270 as of this writing — non-authoritative, jump-to only, per this same mission's line-number convention in tests/architectural/charter_path_literal_allowlist.yaml), which renders prose if either file exists (an operator-facing "is there anything to show" gate, not an authority-presence check) — pinned, not retired, by WP01.
pre-consolidation charter.md-only shape, explicitly scoped and regression-pinned.
charter.yaml(.kittify/charter/charter.yaml) is the deterministic,charter.md(.kittify/charter/charter.md) is a secondary,- One legitimate migration-compat exception (FR-006):
_status_collectors.py's
Non-vacuous durability guard
tests/architectural/test_charter_path_literal_authority.py (WP11) AST-walks for inline .kittify/charter/charter.{yaml,md} path-literal construction outside charter/bundle.py, and for new charter.md-keyed .exists() presence gates. A frozen, shrink-only, per-site-justified allowlist (38 entries at mission close) captures the sanctioned residue — migration historical-determinism sites, the C-003 prose class, and the layering-forced src/doctrine/** sites that cannot import charter.bundle at all.
Evidence
tests/charter/test_context_prose_presence_pin.py(WP01)tests/specify_cli/dashboard/test_charter_path_presence_probe.py(WP02)tests/specify_cli/test_analysis_report_charter_yaml_staleness.py(WP03)tests/specify_cli/cli/commands/charter/test_status_collectors_legacy_md_shape.py(WP04)tests/architectural/test_charter_path_literal_authority.py+charter_path_literal_allowlist.yaml(WP11)
meta-json-fail-closed.md
Contract: meta.json Fail-Closed Authority
Owning FR: FR-007 Landed by: WP07, WP08, WP09 Tracker: #3140
The contract
A corrupt or non-dict meta.json always fails closed — a typed MissionMetaReadError (a RuntimeError subclass) or None, never a raw ValueError — through exactly one public reader: specify_cli.core.paths.load_meta_fail_closed.
home, no competing second authority. Its load_meta import stays function-local to avoid re-forming the core.paths ↔ mission_metadata import cycle.
(specify_cli/mission_metadata.py:275 feature_dir — note: NOT under core/, despite sitting next to the specify_cli.core.paths reference above — vs specify_cli/task_utils/support.py:599 meta_path) — every routed call site is disambiguated against the correct one.
are preserved untouched; only raise-default/unwrapped and divergent-wrapper callers route through the authority.
- The reader promotes the pre-existing
_load_meta_fail_closedin-place — one - Two distinct
load_metasignatures exist in the tree - Deliberately-silent callers (
load_meta_or_empty,on_malformed="none")
Non-vacuous durability guard
tests/specify_cli/test_meta_fail_closed_full_census_contract.py (WP09) independently AST-discovers every load_meta(-shaped call site in the tree (resolving import aliases, not a text grep) and cross-references it against a frozen, reasoned ledger of accounted-for sites. It fails if a new, unaccounted site appears, or if any accounted site regresses to a raw ValueError. This closed a real gap the original WP07 grep-count census missed (an aliased load_meta as _x import invisible to text grep).
Evidence
census (WP07)
(the two pre-existing reds this contract turns green)
notes/meta-load-census.md— the classified, grep-count-reconciled callertests/specify_cli/core/test_load_meta_fail_closed_authority.py(WP07)tests/specify_cli/test_meta_fail_closed_batch_a.py(WP08)tests/specify_cli/test_meta_fail_closed_full_census_contract.py(WP09)tests/unit/status/test_mission_status_aggregate.py::TestLoadCoordUnavailableFailsClosed