ADR-311: The adr tool checks shape and references; git keeps the history¶
Summary¶
- Decided: records are a ledger of decisions and who made them, kept in git-tracked files. The adr tool writes records, checks their shape, and checks that their references resolve. It enforces no policy about how decisions relate or whether a record changed; that is convention, taught by the ADR way, and git holds every version.
- Trades away: automatic detection of an accepted record edited in place, a capability with no
add, achangewith no prior, and a precedent chain that stays inside the corpus. A reviewer or a reader of git history finds those now. - One-way? No. A removed check can come back as its own decision if its absence costs more than it did.
- Probes: Confident (shape-is-enough): the records stay readable and navigable with shape and reference checks alone, since those are what a reader relies on. Not confident (convention-holds): whether agents follow "correct by appending" and "a change names what it replaces" without a check, or drift once nothing flags it.
- Inversion: at one end the tool only formats files and nothing is checked. At the other it audits every record against the corpus and its history, and the checks need their own configuration and exceptions. This checks what a reader of one record needs: its fields are there, and its links go somewhere.
Context¶
ADR-304 made records typed and added lint rules that enforce relationships: frozen decisions (§1, §6), enactment checked against the code (§5), an add for every capability, a prior for every change, precedent that reaches outside the corpus (§11), labelled probes (§12). ADR-305 added a baseline to excuse capabilities that predate adoption, and ADR-308 extended the prior rule to lists. Building the frozen check on moved records took three designs in #604, each adding configuration. An audit of the rules found the same pattern across the policy gates.
Decision¶
- What the tool checks. A record's fields and their values (kind, status, verb, capability in the vocabulary, a basis whose entries each name a source, agent,
imported,observable), its required sections, leftover placeholders,adr.yaml's own shape, and every reference: supersession pairs,amendssections, precedent, andadr cite's citations. - What it no longer checks. Frozen records and
mutable_after_accept; anaddper capability andbaseline; a prior perchange, for one capability or a list; a precedent chain reaching outside; vocabulary stems across layers; Summary probe labels and inversion; enactment inventories,surfaces, andcite's warnings on citations of a cut capability; a retire decision'stargets.enactedandtargetsstay fields. - Commands.
adr acceptrefuses a record that fails its own shape check, and does not lint the corpus.adr setrefusesstatus, which the lifecycle commands own.adr supersedewrites both sides on any record.consideredstays a field; accept does not require it. - Conventions. Correct an accepted record by appending; record a change as a new decision that names what it replaces; quote the operator. The ADR way teaches these.
- Git is the backstop. Earlier versions, and who changed them, are read with git.
Consequences¶
Positive¶
- The tool shrinks by several hundred lines, and
adr.yamllosesbaseline,surfacesand the per-kind mutable lists. - A move or a correction never needs an exception in configuration.
Negative¶
- An in-place edit or a missing
amendsgoes unflagged until someone reads the record or its history.
Neutral¶
- Supersedes ADR-305. ADR-308's allowance for a list of capabilities stands; its rule that each needs a prior goes.
- Records already written keep their fields; nothing needs rewriting.
Alternatives Considered¶
- Keep the gates as warnings. Warnings that fire on legitimate history train readers to ignore them.
- Check only the change under review against its base. Accepted briefly on an unmerged branch; still a check that git makes unnecessary.