An ADR records one architecturally significant decision: the context that forced it, the decision itself, the alternatives that were rejected, and the consequences we accept. ADRs exist so that later contributors (and later sessions) can distinguish "deliberate choice" from "historical accident" without archaeology through commit history.
- Any decision that constrains multiple modules or is expensive to reverse: language/toolchain choices, module boundaries, error handling, threading model, serialization formats, wire protocols.
- Adding a dependency with architectural weight (e.g. an HTTP server library) —
see the policy in
docs/dependencies.md. - Any deliberate deviation from a previously accepted ADR (written as a new ADR that supersedes the old one).
Subsystem-internal design (data structures, algorithms, API sketches) belongs in
docs/design/ instead; a design doc may cite ADRs but
never contradict one.
- Naming:
ADR-NNN-short-slug.md. Numbers are three-digit, monotonically increasing, and never reused — including for rejected or superseded ADRs. - Template: start from
template.md. The Status, Context, Decision, and Consequences sections are mandatory. - Status lifecycle:
Proposed→Accepted; an accepted ADR may later becomeSuperseded by ADR-NNN. Once accepted, an ADR is immutable except for status updates and links to superseding ADRs — if the decision changes, write a new ADR rather than editing history.
| ADR | Title | Status |
|---|---|---|
| ADR-001 | Language & toolchain: C++20 + CUDA | Accepted (CUDA half superseded by ADR-004) |
| ADR-002 | Repository layout & module dependency rules | Accepted (current through Amendment 4) |
| ADR-003 | Error handling: Status/StatusOr, CHECK, no exceptions | Accepted |
| ADR-004 | CPU-first pivot: SIMD engine, CUDA backend retired | Accepted |