Skip to content

ADR-0000: Record architecture decisions and govern their lifecycle

ADR-0000: Record architecture decisions and govern their lifecycle

Status

Accepted

Date

2026-06-24

Context

The project is a clean restart onto the Reality Kernel architecture (see ADR-0001). The prior body of architecture docs in docs/ was retired wholesale. We are a 2–3 engineer team making a large number of consequential, interdependent decisions quickly, several of which are expensive to reverse (truth model, kernel language, identity scheme).

Two failure modes follow from that:

  1. Lost rationale. A decision made in conversation and then implemented in code loses its why — the constraints and rejected alternatives — within weeks. Six months later someone (human or agent) re-litigates it, or worse, silently violates it.
  2. Silent contradiction. Because the decisions are interdependent, a later decision can quietly invalidate an earlier one. Without an explicit supersession discipline, two contradictory “accepted” decisions can both sit in the repo, and nobody knows which is live.

We need a lightweight but strict mechanism that (a) captures the why, (b) makes the current state of every decision unambiguous, and (c) forces an explicit, recorded act whenever a new decision contradicts an old one.

Decision

We record significant architecture decisions as numbered ADRs in docs/adrs/, governed by the lifecycle and supersession rules below. An docs/adrs/README.md index is the single source of truth for which decisions are currently live.

What earns an ADR

Write an ADR when a decision is significant and costly to reverse: data model, identity scheme, consistency model, storage engine, language/runtime, authZ model, public API/SDK shape, agent surface, module/legacy boundaries, scope/sequencing commitments. Do not write an ADR for reversible implementation details, naming of internal functions, or throwaway spikes.

Status lifecycle

PROPOSED → ACCEPTED → (SUPERSEDED by ADR-XXXX | DEPRECATED)
  • PROPOSED — a decision we intend to make but which is gated on a spike or build-off. The ADR states the hypothesis and the falsification bar that resolves it. (Used today by ADR-0003 truth model and ADR-0006 kernel language.)
  • ACCEPTED — live. Code and other ADRs may rely on it.
  • SUPERSEDED — replaced by a specific later ADR. The header links forward; the body is left intact for historical context.
  • DEPRECATED — no longer relevant, but not replaced by anything (e.g. the feature was cut).

Supersession discipline (the part that keeps ADRs honest)

ADRs are append-only and immutable in spirit: we do not edit a decision’s substance after it is Accepted; we supersede it with a new ADR. Concretely:

  1. Never delete an ADR. History is the point.
  2. A new decision that contradicts an Accepted ADR MUST:
    • be written as a new, higher-numbered ADR;
    • state in its Context which prior ADR(s) it contradicts and why the earlier reasoning no longer holds;
    • carry Supersedes: ADR-XXXX in its header.
  3. The superseded ADR is then edited in exactly two places only: its Status becomes Superseded by ADR-YYYY, and a one-line banner is added at the top pointing forward. Its Context/Decision/Consequences text is not rewritten — a future reader must be able to see what we used to believe and why we changed.
  4. The index (README.md) is updated in the same commit so the live set never drifts from reality.
  5. Partial supersession (a new ADR overrides only part of an old one) is allowed: the new ADR names the specific clause it replaces; the old ADR’s banner says Partially superseded by ADR-YYYY (re: <topic>) and stays Accepted for the rest.

Keeping the set internally consistent

  • Cross-reference, don’t restate. Each ADR links the ADRs it depends on. If ADR-0012 relies on ADR-0007’s typed SDK, it links it rather than re-describing it. When a dependency is superseded, a grep for its number finds every dependent ADR.
  • Consistency gate on merge. A change that introduces or supersedes an ADR is not mergeable unless: the index is updated, every Supersedes/Superseded by link is bidirectional, and no Accepted ADR contradicts another Accepted ADR. (For now this is a human checklist; it becomes a CI link-checker once the repo has CI.)
  • Quarterly (or pre-freeze) sweep. Before any “architecture freeze” milestone, read the Accepted set end-to-end and confirm no latent contradictions. The grill that produced ADR-0001..0014 is the model for this.

File conventions

  • Filename: NNNN-kebab-title.md, zero-padded to four digits.
  • Numbers are assigned sequentially and never reused.
  • Each ADR uses the template in this directory’s README.

Alternatives Considered

A wiki / Notion / Confluence page per decision

  • Pros: richer formatting, easier for non-engineers.
  • Cons: drifts from the code, no diff/review, no supersession trail, invisible to coding agents working in-repo.
  • Rejected: decisions must live next to the code and move through the same review as code.

One growing “architecture.md” document

  • Pros: single place to read everything.
  • Cons: edited in place, so the why and the rejected alternatives get overwritten the moment a decision changes — exactly the lost-rationale failure we’re trying to prevent.
  • Rejected: immutability and supersession are the whole point; a living doc has neither.

No formal process — just commit messages and code comments

  • Pros: zero overhead.
  • Cons: rationale is scattered and unsearchable; contradictions go undetected; agents re-decide settled questions.
  • Rejected: the cost we’re avoiding (a 2-hour re-debate, or a silent violation of an invariant) dwarfs the 10-minute cost of an ADR.

Consequences

  • Every live architectural constraint is discoverable in one place, with its rationale and rejected alternatives intact.
  • Contradiction becomes a visible, deliberate act (write a superseding ADR) rather than an accident.
  • Coding agents can read the Accepted set to avoid re-deciding or violating settled questions — these ADRs are explicitly written to be agent-readable context.
  • There is a small recurring cost: every contradicting change now requires touching two ADRs and the index. That cost is the mechanism; it is intentional.
  • This ADR (0000) is itself superseded only by a future ADR that changes the process.