Replaces the Status-only backfill with a faithful presentational restructure bringing the whole back-catalogue to 4-section conformance (no grandfathering). Adds the faithfulness rule and per-file worklist. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
8.5 KiB
Design — ADR structure & lifecycle
- Date: 2026-06-10
- Status: Approved design — implementation plan to follow
- Resolves: the absence of a written standard for how ADRs in
docs/decisions/are structured. The newest ADRs (019–022) have converged on a clean pattern (Status→Context→Decision→Consequences→Related), but it lives only as imitation; ADRs 001–018 predate it and most lack aStatussection. - Becomes: ADR-023 (this design is the basis for that ADR).
- Reuses: boma's existing
*-template.mdconvention (service-security-template.md,service-verify-template.md,service-access-template.md,service-backup-template.md); ADR-014 (knowledge-sourcing → the optionalVerified factssection); ADR-019/020/021/022 (the emergent structure being codified); the/review-repocommand (enforcement home).
Problem
boma documents architectural decisions as numbered ADRs in docs/decisions/, and
CLAUDE.md treats them as load-bearing ("Before assuming a role, provider, or pipeline
exists, check STATUS.md"; the entire "Further reading" table points into them). Yet
there is no ADR that says how an ADR is written. The result:
- Structural drift. ADRs 001–018 are freeform; 019–022 converged on a consistent shape but only by imitation. A new ADR's structure depends on which existing one the author happened to copy.
- No status discipline. Most early ADRs have no
## Statussection, so there is no uniform way to tell an active decision from a superseded or deprecated one — and no written rule for how a decision gets reversed without silently rewriting history. - No scaffold. Every other recurring document type in boma has a template
(
service-security-template.md, etc.). ADRs do not.
This design codifies the structure 019–022 already demonstrate, pins a status lifecycle, ships a template, and reconciles the back-catalogue.
Scope
- In: the canonical section set (mandatory + optional); title and filename
convention; the
Accepted / Superseded / Deprecatedstatus lifecycle and the no-silent-rewrite rule; cross-reference convention; an ADR template file; a lightweight/review-repostructure check; a one-time retroactive restructure of ADRs 001–018 to full conformance (all four mandatory sections + a parseable Status line), reorganizing existing content under canonical headings. - Out (for now): changing the substance of any existing decision (the restructure
is presentational — relabel/regroup/demote existing content, add a dated Status, never
alter what was decided); a
make lint/ CI gate for ADR structure (explicitly rejected in favour of the/review-repocheck — consistent with boma's other doctrine ADRs, which add no CI gate); a "Proposed" draft stage (rejected — boma is single-contributor and trunk-based with no review gate, so ADRs are born Accepted); grandfathering pre-convention ADRs from the check (rejected — the whole corpus is brought to conformance instead).
Decision
1. Title & filename
- Title line:
# ADR-NNN — <Title>: <optional clarifying subtitle>(em-dash—, matching every existing ADR). - Filename:
NNN-kebab-title.md, zero-padded 3-digit, monotonic, never reused (a superseded ADR keeps its number and file). - A new ADR is registered as a row in the CLAUDE.md "Further reading" table.
2. Canonical sections
Mandatory — every ADR, in this order:
| Section | Holds |
|---|---|
## Status |
Accepted (YYYY-MM-DD), plus an optional one-line note (what it resolves/supersedes, or a doctrine-not-yet-built caveat as ADR-022 uses) |
## Context |
the forces, the problem, what exists today, why now |
## Decision |
what we are doing — numbered sub-decisions for multi-part ADRs, as 020/021/022 do |
## Consequences |
results, trade-offs explicitly accepted, follow-on work |
Optional — use only where genuinely applicable, never as padding:
## Related— links to other ADRs by number.## Scope— explicit in/out-of-scope boundaries.## Guardrails/## Enforcement— how the decision is mechanically enforced (lint, CI, hooks).## What was ruled out— rejected alternatives, each with its reason.## Verified facts (ADR-014)— version-stamped facts per the knowledge-sourcing rule.
3. Status lifecycle
Three states; no "Proposed" stage.
- Born
Accepted (YYYY-MM-DD)— the sole author commits to it on writing. - Replaced by a later decision → the old ADR's Status becomes
Superseded by ADR-NNN (YYYY-MM-DD); the superseding ADR recordsSupersedes ADR-MMMin its own## Statusand## Related. The link is bidirectional — both files must point at each other. - Retired with no replacement →
Deprecated (YYYY-MM-DD)plus a one-line reason.
Load-bearing rule — no silent rewrites. An Accepted ADR is not edited to reverse
its decision. Typo and clarity fixes are fine; a material reversal requires a new ADR
and a Superseded by marker on the old one. The history of decisions stays legible.
4. Cross-references
Reference other ADRs by number inline (ADR-019), and collect the relationships in a
## Related section.
5. Template file
Ship docs/decisions/adr-template.md — consistent with boma's existing
*-template.md convention. It contains the mandatory section headers pre-filled with
short HTML-comment hints, and the optional sections listed as commented stubs to
uncomment when relevant. It is a skeleton, not a numbered decision, so it does not take
an ADR number.
6. Retroactive restructure (001–018)
A separate step after the ADR and template land: bring every pre-convention ADR to full conformance — all four mandatory sections present and a parseable Status line. This is a presentational restructure, governed by a strict faithfulness rule:
- Add a
## Statussection valuedAccepted (YYYY-MM-DD), the date reconstructed from the file's first git-commit date. For 016–018, whose existing trailing build-state note is unparseable, prepend the datedAccepted (...)clause so the note becomes a parseable Status line's tail. - Reorganize existing content under the canonical headings: relabel a synonym
(
## Decisions→## Decision), or introduce a## Decisionumbrella and demote the existing topical##headings to###beneath it. No sentence of existing prose is altered. - Add a
## Consequencessection built only from implications the ADR already states (trade-offs, "what was ruled out", "open questions", follow-on work already named). If an ADR genuinely states nothing that can be faithfully cast as a consequence, that file is escalated for a human decision rather than inventing one. - Never change the substance of a decision. A
git diffof the restructure should show heading-level changes, a new Status section, and a Consequences section assembled from existing material — not edits to existing argument.
ADRs already conformant (019–022) are left alone. End state: the adr-structure check
reports zero findings across the whole corpus, with no grandfathering.
7. Enforcement
Lightweight, no CI gate. The /review-repo command gains an ADR-structure check:
every file in docs/decisions/ matching NNN-*.md has the four mandatory sections and
a parseable ## Status line. The template carries the convention forward for new ADRs.
Consequences
- New ADRs have one obvious shape and a scaffold to start from; structural drift stops.
- Every ADR declares its lifecycle state uniformly, and reversals are traceable rather than silent — the back-catalogue becomes a legible decision history.
- One-time churn: a restructure touching ~18 files (heading reorganization + a Status section + a Consequences section per file). Larger and more judgment-heavy than a Status-only backfill, hence the faithfulness rule and per-file review.
- The whole corpus conforms — the check needs no grandfathering or number threshold, and stays simple (presence + parseable Status, applied uniformly).
/review-repogrows a new check; no new CI machinery, matching boma's habit of not gating doctrine in CI.- This ADR is itself the first conformant example — it must follow its own structure.
Open questions
None outstanding — title/filename, the 3-state lifecycle, template name
(adr-template.md), enforcement (/review-repo, no CI gate), and the full
retroactive restructure of 001–018 (no grandfathering) were all confirmed during
brainstorming.