Skip to content

How we record decisions

Updated View as Markdown

An architecture decision record exists to stop a settled argument being had again. It earns its number when a decision had genuinely live alternatives, when choosing wrongly would have cost something real, and when someone reading the code a year from now would otherwise reopen it — usually by “fixing” the thing the record explains.

Most of what looks like a decision is not one. The STOP sentinel file, the status file, dedup_bleed’s overlap and containment thresholds, Vad::turns against Vad::chunks, using rustfmt’s defaults, the pnpm version pin in CI, and CDLA-Permissive-2.0 sitting in the licence allowlist are all reasoned choices with no serious rival. Each is a good paragraph in the chapter that owns it — capture, sessions, what CI checks — and none is an ADR. A record whose alternatives were never seriously live is a paragraph with a number on it, and a directory of those is how the practice dies: nobody reads records that mostly say nothing.

Filenames and numbering

Files are NNNN-kebab-slug.md: four digits, monotonic, never reused and never renamed. Commit messages cite records by number, so renaming 0004-vad-chunking.md silently breaks every message that said ADR-0004. A withdrawn record keeps its number and gains a status; the number is not returned to the pool.

Immutability

A record is immutable once accepted. Fix a typo; do not revise an argument. When the decision changes, write a new record and add reciprocal links: the new one carries **Supersedes:** [ADR-NNNN](NNNN-slug.md) on its metadata line, the old one gains a matching Superseded by. Both files stay in the tree, because the point of the record is the reasoning at the time, and that reasoning is what a superseding record has to argue against.

rejected records are kept for the same reason, and are often the most useful files here — the alternative someone is about to propose, already measured and already declined.

The date is the date the decision was made. It is never touched afterwards.

Adding one

cp docs/adr/TEMPLATE.md docs/adr/0014-<slug>.md

Then give it title: and sidebar.order: frontmatter, matching the record above it. CI fails on a record without both: no frontmatter means the content collection rejects the file and the build stops, and no sidebar.order means the record lands unplaced in the nav, which is nearly as good as unwritten.

The records

Navigation

Type to search…

↑↓ navigate↵ selectEsc close