# Coverage ledger Provenance for every requirement in `docs/REQUIREMENTS.md`. One row per source atom. Kept under `.audit/` on purpose, so it is not part of the `docs/` structure contract. `tools/check_coverage.py` reads every `*.md` in this directory except this file. ## Row format ``` | Source | Atom | Requirement | Disposition | PoR ID | Rationale | ``` - **Source** — where the atom came from, prefixed by kind: `tag:TEST-SPEC`, `tag:OPENAPI`, `prd`, `cur:CREATE`, `issue:#5`, `audit:14`. - **Atom** — the stable key inside that source, e.g. `H-1`, `settings-PUT-reject`. - **Requirement** — a short restatement, enough to recognise it. - **Disposition** — one of the values below. - **PoR ID** — the `docs/REQUIREMENTS.md` ID(s), comma-separated. `—` when none. - **Rationale** — required for everything that is not plain `ported`. ## Dispositions | Value | Meaning | PoR ID | Rationale | |---|---|---|---| | `ported` | fully represented by the cited row(s) | required | optional | | `duplicate` | same rule as another atom | optional | required | | `new` | PoR row with no source atom; a reconciliation decision | required | required | | `superseded` | replaced by a later source or decision | optional | required | | `deferred` | intentionally out of current scope | optional | required | | `dropped` | deliberately discarded | `—` | required | | `gap` | not represented, not deliberately dropped: an open hole | `—` | required | `gap` is the finding. It is the thing this ledger exists to surface. ## Checks Forward (always): 1. Every row has six well-formed columns and a known disposition. 2. A `(Source, Atom)` pair is unique across the ledger. 3. `ported` and `new` cite at least one defined requirement ID; every cited ID resolves. 4. `dropped` and `gap` carry no ID and a non-empty rationale. 5. Every non-`ported` row carries a non-empty rationale. Reverse (`--strict` only, once coverage is complete): 6. Every ID in `docs/REQUIREMENTS.md` is claimed by at least one atom, or is `new`. 7. No `gap` rows remain. ## Run ``` python tools/check_coverage.py python tools/check_coverage.py --strict python tools/check_coverage.py --ledger-dir # for negative tests ```