boma/docs/superpowers/specs/2026-06-10-adr-structure-design.md
sjat 89179dd7c9 docs(adr): revise spec+plan — full retroactive restructure of 001-018
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>
2026-06-10 14:28:20 +02:00

8.5 KiB
Raw Blame History

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 (019022) have converged on a clean pattern (StatusContextDecisionConsequencesRelated), but it lives only as imitation; ADRs 001018 predate it and most lack a Status section.
  • Becomes: ADR-023 (this design is the basis for that ADR).
  • Reuses: boma's existing *-template.md convention (service-security-template.md, service-verify-template.md, service-access-template.md, service-backup-template.md); ADR-014 (knowledge-sourcing → the optional Verified facts section); ADR-019/020/021/022 (the emergent structure being codified); the /review-repo command (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 001018 are freeform; 019022 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 ## Status section, 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 019022 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 / Deprecated status lifecycle and the no-silent-rewrite rule; cross-reference convention; an ADR template file; a lightweight /review-repo structure check; a one-time retroactive restructure of ADRs 001018 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-repo check — 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 records Supersedes ADR-MMM in its own ## Status and ## 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 (001018)

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 ## Status section valued Accepted (YYYY-MM-DD), the date reconstructed from the file's first git-commit date. For 016018, whose existing trailing build-state note is unparseable, prepend the dated Accepted (...) 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 ## Decision umbrella and demote the existing topical ## headings to ### beneath it. No sentence of existing prose is altered.
  • Add a ## Consequences section 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 diff of 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 (019022) 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-repo grows 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 001018 (no grandfathering) were all confirmed during brainstorming.