ADR-<topic>-<n>; the Numbered Records Keep Their Numbers Until a Consolidation Replaces ThemStatus: Accepted
Date: October 28, 2026
Answers: how a decision record is named, so that a reader finds it by what it decides and two sessions writing at once do not take the same name
Supersedes / Related: README.md (Writing a new one, Reserved numbers: the next free number was the name), TEMPLATE.md, scripts/check-adr-refs.py (one record per name, every citation resolves), ADR-258 (the weights a record is decided by)
A record has been named by the next free number: ADR-296, cited as
ADR-296 D7 in about 17 000 places, more than 7 000 of them comments in
crates/. A number says nothing about what it names. A comment that cites
ADR-296 D7 is followed only with the index open; a reader who looks for the
record on regular expressions has to search the titles. And the next free
number is one counter for every session: two sessions writing at once took the
same number more than once (check-adr-refs.py checks for it because it
happened), and a record written on a branch took a number develop gave to
another record meanwhile.
Is a record named by its topic, and if so, how?
| a record’s name | found by | |
|---|---|---|
Nygard’s ADRs, adr-tools, MADR |
a sequence number and a slug, 0042-use-postgres.md |
the slug in the file name; cited by number |
| Rust RFCs, Python PEPs | a number given when merged or accepted | an index |
| Kubernetes KEPs | a number and a directory per area, sig-network/1234-… |
the area |
| IETF RFCs | a number | an index |
A number with a slug finds the file, but the citation is the number, and the counter stays one for everyone.
ADR-<topic>-<n>.<topic> is one to three words, each lowercase letters and digits starting
with a letter, joined by -: regex, decision-records, text-positions.
<n> counts the records of that topic from 1. The record is the file
adr-<topic>-<n>.md, its first line is # ADR-<topic>-<n>: <the decision>,
and a decision in it is cited as ADR-regex-1 D4.
Why. A name that says what it decides is found without the index, in a
comment, in a file list, in a search. A counter per topic is shared only by
sessions working on the same topic, who have to know of each other anyway.
Rejected: numbers alone (found only through the index; one counter for
everyone); words in CamelCase (ADR-RegEx-1) - the default filesystems of
macOS and Windows do not tell RegEx from Regex, so two names that look
different are one file there; the number of the issue that asked (not every
record has one issue, and the issue numbers overlap the record numbers already
given); more than three words (a name, not a title).
A record that touches several topics takes the one it decides about and names the others under Supersedes / Related. The next record on a topic takes the next number; a change to a decision is still made in the record that holds it (README, updated in place). A new topic is taken when none of the existing ones fits; the index lists the topics in use.
No record is renamed. A numbered record leaves the live set the way records
always have: a consolidating record of the new scheme states its decisions in
their current form, the numbered record moves to
docs/history/adr/, and every citation of it moves to the
new record in the same change. Nothing live cites an archived record, as
before. The archive’s README maps each archived decision to the live one.
The index’s Reserved numbers table holds names of both schemes: a row
regex-2 claims that name as a row 385 claims that number. A row is deleted
in the commit that adds the record.
check-adr-refs.py checks both schemes, and stays Python until std::regex exists.It checks that every record has a valid name, one index row and a title that
agrees, that every Dn and § cited resolves, that no live file cites an
archived record, and that every topic name cited names a record.
The rule that a Python tool moves to Nikaia when it is reworked
(CLAUDE.md) is broken here on purpose: the tool is made of regular
expressions, and std::regex (#673)
is decided but not built. Written in Nikaia today it would be the hand-written
scanning #673 exists to replace. It moves when #673’s run-time patterns are
built, and is their first program.