Skip to content

Architecture Decision Records

Why we record decisions here:

  • The repo grows; the why behind a constraint stops being obvious.
  • AI agents and new contributors need durable, searchable context for rules they will otherwise question or accidentally undo.
  • git log carries the what. ADRs carry the why + the trade-offs considered + the consequences if you break the rule.

Convention

  • Filename: NNNN-kebab-title.md — zero-padded sequence, never reused.
  • First line: # NNNN — Title, with the number matching the filename.
  • One decision per file. Short. ≤1 page when possible.
  • Every ADR uses the same structure: see TEMPLATE.md.
  • Status: proposedaccepted → optionally superseded by NNNN / deprecated. Never delete an ADR; supersede it.
  • Date: the date status changed (ISO YYYY-MM-DD).
  • Cite source files (path:line) and tests so the rule is verifiable.

ADR vs features/ / technical/

  • docs/adr/ — historical decisions that shape today's code. Read to understand why a rule exists.
  • docs/features/ — forward-looking product / UX briefs. What and why of a feature being shaped.
  • docs/technical/ — implementation plans and cross-cutting tech reference. How a feature is being built.

A design brief or tech plan may graduate to an ADR once the decision is locked in and worth defending against future drift.

When to write a new ADR

Triggers (any one):

  • A rule has been broken once and we want to make sure it isn't again.
  • A reviewer asked "why is it this way?" and the answer isn't in code.
  • We chose between two reasonable approaches and the loser will keep resurfacing.
  • A constraint is imposed by an external system (regulator, vendor, licensor) and we need to capture it once.

Index

There is deliberately no index table here. The one this section used to hold rotted silently — it stopped at 0006 while the directory held 21 files (issue #300) — and an index that reads as complete while covering a fraction of the decisions invites re-litigating what was already locked in.

The directory listing is the index. Filenames carry number and title (ls docs/adr/ reads as a table of contents), the first line of each file repeats them, and status/date live inside the file. CI's docs-layout job enforces the invariants that keep the listing trustworthy: strict NNNN-kebab-title.md names, no duplicate and no skipped numbers, and a first-line heading that matches the filename (issue #299, scripts/check_docs_layout.py::check_adrs).