docs(adr): add Proposed lifecycle state; mark ADR-011 Proposed
Revisits the lifecycle decision on the evidence of ADR-011 (a real draft with open questions). Adds a fourth state, Proposed (YYYY-MM-DD), to ADR-023, the template, the adr-structure check (+test), spec and plan. Sets ADR-011's Status to Proposed and removes its now-redundant inline 'Proposed' line. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b3ca510380
commit
6d7d27b03b
7 changed files with 54 additions and 27 deletions
|
|
@ -2,9 +2,8 @@
|
|||
|
||||
## Status
|
||||
|
||||
Accepted (2026-06-04)
|
||||
|
||||
**Status: Proposed — draft for discussion (not yet accepted).**
|
||||
Proposed (2026-06-04) — draft for discussion; not yet accepted. The core decisions
|
||||
below are settled in intent, but several specifics remain open (see "Open questions").
|
||||
|
||||
## Context
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,8 @@ keeps its number and file. A new ADR is registered as a row in the CLAUDE.md
|
|||
|
||||
### 2. Mandatory sections, in this order
|
||||
|
||||
- `## Status` — `Accepted (YYYY-MM-DD)`, plus an optional one-line note.
|
||||
- `## Status` — a lifecycle line, usually `Accepted (YYYY-MM-DD)` (see §4), plus an
|
||||
optional one-line note.
|
||||
- `## Context` — the forces, the problem, what exists today, why now.
|
||||
- `## Decision` — what we are doing; numbered sub-decisions for multi-part ADRs.
|
||||
- `## Consequences` — results, trade-offs explicitly accepted, follow-on work.
|
||||
|
|
@ -42,10 +43,15 @@ keeps its number and file. A new ADR is registered as a row in the CLAUDE.md
|
|||
|
||||
### 4. Status lifecycle
|
||||
|
||||
Three states; no "Proposed" stage (boma is single-contributor and trunk-based with no
|
||||
review gate, so an ADR is born committed-to).
|
||||
Four states. Because boma is single-contributor and trunk-based with no review gate,
|
||||
most ADRs are **born `Accepted (YYYY-MM-DD)`** — committed-to on writing. A
|
||||
**`Proposed`** state exists for a genuine draft whose core direction is recorded but
|
||||
whose specifics are still open for discussion (e.g. ADR-011); it is promoted to
|
||||
`Accepted` once settled.
|
||||
|
||||
- Born **`Accepted (YYYY-MM-DD)`**.
|
||||
- **`Proposed (YYYY-MM-DD)`** — drafted, under discussion, not yet committed-to. May
|
||||
carry open questions. Promoted to `Accepted (YYYY-MM-DD)` when decided.
|
||||
- **`Accepted (YYYY-MM-DD)`** — committed-to. The common starting state.
|
||||
- Replaced → old ADR's Status becomes **`Superseded by ADR-NNN (YYYY-MM-DD)`**; the new
|
||||
ADR records `Supersedes ADR-MMM` in its Status and `## Related`. The link is
|
||||
**bidirectional**.
|
||||
|
|
@ -85,7 +91,6 @@ a consistent, legible decision history.
|
|||
|
||||
## What was ruled out
|
||||
|
||||
- **A "Proposed" draft stage** — no review gate exists for it to serve.
|
||||
- **A `make lint` / CI gate for ADR structure** — heavier than the risk warrants;
|
||||
the `/review-repo` check and the template suffice.
|
||||
- **Machine-enforcing section order** — brittle for marginal value; left as a
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@
|
|||
## Status
|
||||
|
||||
Accepted (YYYY-MM-DD)
|
||||
<!-- Lifecycle: "Accepted (YYYY-MM-DD)" → later "Superseded by ADR-NNN (YYYY-MM-DD)"
|
||||
or "Deprecated (YYYY-MM-DD)" + one-line why. Optional trailing note OK, e.g.
|
||||
<!-- Lifecycle: usually born "Accepted (YYYY-MM-DD)"; use "Proposed (YYYY-MM-DD)" for a
|
||||
genuine draft (open questions), promoted to Accepted once settled. Later:
|
||||
"Superseded by ADR-NNN (YYYY-MM-DD)" or "Deprecated (YYYY-MM-DD)" + one-line why.
|
||||
Optional trailing note OK, e.g.
|
||||
"Accepted (2026-06-10). Doctrine ADR — pins policy, builds nothing yet." -->
|
||||
|
||||
## Context
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
- **Mandatory sections, in this order:** `## Status`, `## Context`, `## Decision`, `## Consequences`.
|
||||
- **Optional sections:** `## Related`, `## Scope`, `## Guardrails` / `## Enforcement`, `## What was ruled out`, `## Verified facts (ADR-014)`.
|
||||
- **Status lifecycle (3 states):** `Accepted (YYYY-MM-DD)` → optionally `Superseded by ADR-NNN (YYYY-MM-DD)` or `Deprecated (YYYY-MM-DD)`. No "Proposed" stage.
|
||||
- **Status lifecycle (4 states):** `Proposed (YYYY-MM-DD)` (genuine drafts, e.g. ADR-011) → `Accepted (YYYY-MM-DD)` (the common starting state) → optionally `Superseded by ADR-NNN (YYYY-MM-DD)` or `Deprecated (YYYY-MM-DD)`. (`Proposed` was added on the evidence of ADR-011, which is a real draft with open questions.)
|
||||
- **No silent rewrites:** material reversal = new ADR + `Superseded by` marker; bidirectional link.
|
||||
- **Enforcement checks presence + parseable Status line, NOT section order.** Order is demonstrated by the template, not machine-enforced.
|
||||
- **Back-catalogue is fully restructured (no grandfathering)** — ADRs 001–018 are brought to all-four-section conformance. The restructure is **presentational**: relabel/regroup/demote existing headings, add a dated Status, assemble a Consequences section from implications the ADR already states. **The substance of no decision is changed.** If a faithful Consequences cannot be drawn from existing content, escalate that file rather than inventing one.
|
||||
|
|
@ -305,7 +305,8 @@ keeps its number and file. A new ADR is registered as a row in the CLAUDE.md
|
|||
|
||||
### 2. Mandatory sections, in this order
|
||||
|
||||
- `## Status` — `Accepted (YYYY-MM-DD)`, plus an optional one-line note.
|
||||
- `## Status` — a lifecycle line, usually `Accepted (YYYY-MM-DD)` (see §4), plus an
|
||||
optional one-line note.
|
||||
- `## Context` — the forces, the problem, what exists today, why now.
|
||||
- `## Decision` — what we are doing; numbered sub-decisions for multi-part ADRs.
|
||||
- `## Consequences` — results, trade-offs explicitly accepted, follow-on work.
|
||||
|
|
@ -317,10 +318,15 @@ keeps its number and file. A new ADR is registered as a row in the CLAUDE.md
|
|||
|
||||
### 4. Status lifecycle
|
||||
|
||||
Three states; no "Proposed" stage (boma is single-contributor and trunk-based with no
|
||||
review gate, so an ADR is born committed-to).
|
||||
Four states. Because boma is single-contributor and trunk-based with no review gate,
|
||||
most ADRs are **born `Accepted (YYYY-MM-DD)`** — committed-to on writing. A
|
||||
**`Proposed`** state exists for a genuine draft whose core direction is recorded but
|
||||
whose specifics are still open for discussion (e.g. ADR-011); it is promoted to
|
||||
`Accepted` once settled.
|
||||
|
||||
- Born **`Accepted (YYYY-MM-DD)`**.
|
||||
- **`Proposed (YYYY-MM-DD)`** — drafted, under discussion, not yet committed-to. May
|
||||
carry open questions. Promoted to `Accepted (YYYY-MM-DD)` when decided.
|
||||
- **`Accepted (YYYY-MM-DD)`** — committed-to. The common starting state.
|
||||
- Replaced → old ADR's Status becomes **`Superseded by ADR-NNN (YYYY-MM-DD)`**; the new
|
||||
ADR records `Supersedes ADR-MMM` in its Status and `## Related`. The link is
|
||||
**bidirectional**.
|
||||
|
|
@ -360,7 +366,6 @@ a consistent, legible decision history.
|
|||
|
||||
## What was ruled out
|
||||
|
||||
- **A "Proposed" draft stage** — no review gate exists for it to serve.
|
||||
- **A `make lint` / CI gate for ADR structure** — heavier than the risk warrants;
|
||||
the `/review-repo` check and the template suffice.
|
||||
- **Machine-enforcing section order** — brittle for marginal value; left as a
|
||||
|
|
|
|||
|
|
@ -46,10 +46,12 @@ lifecycle, ships a template, and reconciles the back-catalogue.
|
|||
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).
|
||||
ADRs, which add no CI gate); grandfathering pre-convention ADRs from the check
|
||||
(rejected — the whole corpus is brought to conformance instead).
|
||||
|
||||
The lifecycle uses four states — `Proposed / Accepted / Superseded / Deprecated`. An
|
||||
earlier draft of this design omitted `Proposed`, but ADR-011 (a real draft with open
|
||||
questions) is evidence boma occasionally needs it, so it was kept.
|
||||
|
||||
## Decision
|
||||
|
||||
|
|
@ -82,9 +84,13 @@ lifecycle, ships a template, and reconciles the back-catalogue.
|
|||
|
||||
### 3. Status lifecycle
|
||||
|
||||
Three states; no "Proposed" stage.
|
||||
Four states. Most ADRs are **born `Accepted (YYYY-MM-DD)`** — the sole author commits
|
||||
to it on writing (boma is single-contributor and trunk-based with no review gate).
|
||||
|
||||
- Born **`Accepted (YYYY-MM-DD)`** — the sole author commits to it on writing.
|
||||
- **`Proposed (YYYY-MM-DD)`** — a genuine draft whose core direction is recorded but
|
||||
whose specifics are still open (e.g. ADR-011, which carries open questions). Promoted
|
||||
to `Accepted (YYYY-MM-DD)` once settled.
|
||||
- **`Accepted (YYYY-MM-DD)`** — committed-to; the common starting state.
|
||||
- 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
|
||||
|
|
@ -151,7 +157,8 @@ a parseable `## Status` line. The template carries the convention forward for ne
|
|||
|
||||
## Open questions
|
||||
|
||||
None outstanding — title/filename, the 3-state lifecycle, template name
|
||||
None outstanding — title/filename, the **4-state lifecycle** (`Proposed / Accepted /
|
||||
Superseded / Deprecated`; `Proposed` adopted on the evidence of ADR-011), 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.
|
||||
brainstorming and execution.
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ RESOLVE_WORD_RE = re.compile(r"\b(?:resolv\w*|decid\w*|address\w*|complet\w*|don
|
|||
ADR_FILE_RE = re.compile(r"^\d{3}-.*\.md$")
|
||||
ADR_REQUIRED_SECTIONS = ("Status", "Context", "Decision", "Consequences")
|
||||
ADR_STATUS_LINE_RE = re.compile(
|
||||
r"^(Accepted \(\d{4}-\d{2}-\d{2}\)"
|
||||
r"^(Proposed \(\d{4}-\d{2}-\d{2}\)"
|
||||
r"|Accepted \(\d{4}-\d{2}-\d{2}\)"
|
||||
r"|Superseded by ADR-\d{3}"
|
||||
r"|Deprecated \(\d{4}-\d{2}-\d{2}\))")
|
||||
|
||||
|
|
@ -134,8 +135,9 @@ def adr_structure_findings(adr_files):
|
|||
if not ADR_STATUS_LINE_RE.match(status_text):
|
||||
out.append({"check": "adr-structure", "severity": "medium",
|
||||
"path": rpath, "line": headings["Status"] + 1,
|
||||
"detail": "Status not parseable (want 'Accepted (YYYY-MM-DD)', "
|
||||
"'Superseded by ADR-NNN', or 'Deprecated (YYYY-MM-DD)'); "
|
||||
"detail": "Status not parseable (want 'Proposed (YYYY-MM-DD)', "
|
||||
"'Accepted (YYYY-MM-DD)', 'Superseded by ADR-NNN', or "
|
||||
"'Deprecated (YYYY-MM-DD)'); "
|
||||
f"got: {status_text[:60]!r}"})
|
||||
return out
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,13 @@ def test_superseded_status_is_accepted():
|
|||
assert out == []
|
||||
|
||||
|
||||
def test_proposed_status_is_accepted():
|
||||
lines = [("Proposed (2026-06-04)\n" if ln == "Accepted (2026-06-10)\n"
|
||||
else ln) for ln in GOOD]
|
||||
out = _checks(rs.adr_structure_findings({"docs/decisions/099-example.md": lines}))
|
||||
assert out == []
|
||||
|
||||
|
||||
def test_non_numbered_file_is_skipped():
|
||||
bare = ["# ADR template\n", "\n", "## Status\n", "\n", "<!-- hint -->\n"]
|
||||
out = _checks(rs.adr_structure_findings({"docs/decisions/adr-template.md": bare}))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue