Skip to content

Commit 4f0b554

Browse files
docs(governance): allow in-place refinement of accepted ADRs (refine vs. supersede) (#382)
* docs(governance): allow in-place refinement of accepted ADRs Replace the strict-immutability rule in docs/decisions/README.md ("do not edit the original") with the mainstream refine-in-place vs. supersede-on- reversal model, and add the bookkeeping that makes in-place refinement auditable. - Distinguish lifecycle state (proposed/accepted/superseded/deprecated) from the orthogonal mutability operation (refine vs. supersede). - Add a boundary test: if the action a reader takes is unchanged it is a refinement (edit in place); if a past reader would now act differently it is a reversal (new superseding ADR). - Add a parallel "Changing an accepted ADR" table (Refinement / Reversal / Obsolescence). - Add optional **Last-updated:** field (distinct from immutable **Date:** = decision date) and a ## Changelog convention to the template. - Cite precedent (Joel Parker Henderson; MADR last-updated date). - Regenerate the Starlight mirror. Removes the contradiction with ADR-012 ("existing ADRs are updated incrementally") and unblocks the ADR-003 decomposition (#186). Refs #380 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * docs(governance): address PR #382 review nits (Henderson quote, MADR, Changelog) - Henderson quote: restore verbatim two-sentence form ("In theory, immutability is ideal. In practice, mutability has worked better for our teams."). - MADR: correct the claim — MADR uses a single `date` field ("last updated"), not a last-updated date distinct from the decision date; note that this standard's two-field design (immutable `Date:` + separate `Last-updated:`) goes further. - Changelog template: make "omit when first creating" explicit so a freshly copied template doesn't ship a present-but-empty section. - Regenerate Starlight mirror. Refs #380 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: bgagent <345885+scottschreckengaust@users.noreply.github.com> Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 17eba2f commit 4f0b554

2 files changed

Lines changed: 54 additions & 2 deletions

File tree

docs/decisions/README.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ Do **not** write an ADR for routine implementation choices that are self-evident
2020

2121
**Status:** proposed | accepted | superseded | deprecated
2222
**Date:** YYYY-MM-DD
23+
**Last-updated:** YYYY-MM-DD (optional; add when the ADR is refined in place after acceptance)
2324
**Supersedes:** ADR-NNN (if applicable)
2425
**Superseded by:** ADR-NNN (if applicable)
2526

@@ -41,8 +42,16 @@ What follows from this decision:
4142
## References
4243

4344
- Links to RFCs, issues, PRs, or external resources that informed the decision
45+
46+
## Changelog
47+
48+
(Optional; omit when first creating the ADR. Add this section on the first in-place refinement, one dated bullet per refinement. The decision date in `**Date:**` is never overwritten.)
49+
50+
- YYYY-MM-DD — What was refined and why (decision unchanged).
4451
```
4552

53+
`**Date:**` records when the decision was **made/accepted** and is never overwritten — it is the historical anchor (which other ADRs existed, what the constraints were). `**Last-updated:**` records when the record was last **refined in place**; the `## Changelog` records *what* changed. See [Changing an accepted ADR](#changing-an-accepted-adr-refine-in-place-vs-supersede).
54+
4655
## Numbering
4756

4857
ADRs are numbered sequentially with zero-padded three-digit prefixes: `ADR-001-slug.md`, `ADR-002-slug.md`, etc. Numbers are never reused.
@@ -56,7 +65,24 @@ ADRs are numbered sequentially with zero-padded three-digit prefixes: `ADR-001-s
5665
| `superseded` | Replaced by a newer ADR (link to successor) |
5766
| `deprecated` | No longer applicable (context changed) |
5867

59-
A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges. To change an accepted decision, write a new ADR that supersedes it — do not edit the original.
68+
A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges.
69+
70+
### Changing an accepted ADR: refine in place vs. supersede
71+
72+
Lifecycle state (above) is **orthogonal** to ordinary upkeep. Two different operations apply to an accepted ADR, and the status table does not decide between them:
73+
74+
- **Refinement** — the decision is unchanged; you are clarifying wording, adding a consequence or risk, extracting operational prose to a guide/skill (see ADR-012), or fixing a reference. **Edit the file in place.** Status stays `accepted`.
75+
- **Reversal** — the decision itself changes: a different approach is chosen, or what a reader must do changes. **Write a new ADR that supersedes the old one.** The old ADR becomes `superseded`.
76+
77+
**The boundary test:** *If the action a reader would take is unchanged, it's a refinement — edit in place. If a past reader following the old ADR would now do something different, it's a reversal — write a superseding ADR.*
78+
79+
| Change | What it is | What to do | Status effect | Date fields |
80+
|--------|-----------|------------|---------------|-------------|
81+
| Clarify wording; add a consequence/risk; extract prose to a guide/skill (per ADR-012); fix a broken reference | **Refinement** | Edit in place; append a dated `## Changelog` entry | none (`accepted`) | `Date:` unchanged; bump `Last-updated:` |
82+
| Reverse the decision; choose a different approach; change what a reader must do | **Reversal** | New ADR with `**Supersedes:** ADR-NNN`; mark the old `**Superseded by:** ADR-MMM` | both change | new ADR gets its own `Date:` |
83+
| The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` |
84+
85+
This replaces strict immutability with the mainstream ADR practice. Joel Parker Henderson's widely-cited guidance notes that *"In theory, immutability is ideal. In practice, mutability has worked better for our teams."* — insert new information into the existing ADR with a date stamp and a note. MADR's template uses a single `date` field meaning "when the decision was last updated"; this standard goes further, keeping the decision `Date:` immutable and recording refinements separately. The **decision date is never overwritten**; refinements are recorded in the `## Changelog` and the `Last-updated` field, keeping the record self-contained (an agent should not need to excavate git history to learn what was refined and when).
6086

6187
## Relationship to `docs/design/`
6288

docs/src/content/docs/decisions/Readme.md

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ Do **not** write an ADR for routine implementation choices that are self-evident
2424

2525
**Status:** proposed | accepted | superseded | deprecated
2626
**Date:** YYYY-MM-DD
27+
**Last-updated:** YYYY-MM-DD (optional; add when the ADR is refined in place after acceptance)
2728
**Supersedes:** ADR-NNN (if applicable)
2829
**Superseded by:** ADR-NNN (if applicable)
2930

@@ -45,8 +46,16 @@ What follows from this decision:
4546
## References
4647

4748
- Links to RFCs, issues, PRs, or external resources that informed the decision
49+
50+
## Changelog
51+
52+
(Optional; omit when first creating the ADR. Add this section on the first in-place refinement, one dated bullet per refinement. The decision date in `**Date:**` is never overwritten.)
53+
54+
- YYYY-MM-DD — What was refined and why (decision unchanged).
4855
```
4956

57+
`**Date:**` records when the decision was **made/accepted** and is never overwritten — it is the historical anchor (which other ADRs existed, what the constraints were). `**Last-updated:**` records when the record was last **refined in place**; the `## Changelog` records *what* changed. See [Changing an accepted ADR](#changing-an-accepted-adr-refine-in-place-vs-supersede).
58+
5059
## Numbering
5160

5261
ADRs are numbered sequentially with zero-padded three-digit prefixes: `ADR-001-slug.md`, `ADR-002-slug.md`, etc. Numbers are never reused.
@@ -60,7 +69,24 @@ ADRs are numbered sequentially with zero-padded three-digit prefixes: `ADR-001-s
6069
| `superseded` | Replaced by a newer ADR (link to successor) |
6170
| `deprecated` | No longer applicable (context changed) |
6271

63-
A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges. To change an accepted decision, write a new ADR that supersedes it — do not edit the original.
72+
A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges.
73+
74+
### Changing an accepted ADR: refine in place vs. supersede
75+
76+
Lifecycle state (above) is **orthogonal** to ordinary upkeep. Two different operations apply to an accepted ADR, and the status table does not decide between them:
77+
78+
- **Refinement** — the decision is unchanged; you are clarifying wording, adding a consequence or risk, extracting operational prose to a guide/skill (see ADR-012), or fixing a reference. **Edit the file in place.** Status stays `accepted`.
79+
- **Reversal** — the decision itself changes: a different approach is chosen, or what a reader must do changes. **Write a new ADR that supersedes the old one.** The old ADR becomes `superseded`.
80+
81+
**The boundary test:** *If the action a reader would take is unchanged, it's a refinement — edit in place. If a past reader following the old ADR would now do something different, it's a reversal — write a superseding ADR.*
82+
83+
| Change | What it is | What to do | Status effect | Date fields |
84+
|--------|-----------|------------|---------------|-------------|
85+
| Clarify wording; add a consequence/risk; extract prose to a guide/skill (per ADR-012); fix a broken reference | **Refinement** | Edit in place; append a dated `## Changelog` entry | none (`accepted`) | `Date:` unchanged; bump `Last-updated:` |
86+
| Reverse the decision; choose a different approach; change what a reader must do | **Reversal** | New ADR with `**Supersedes:** ADR-NNN`; mark the old `**Superseded by:** ADR-MMM` | both change | new ADR gets its own `Date:` |
87+
| The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` |
88+
89+
This replaces strict immutability with the mainstream ADR practice. Joel Parker Henderson's widely-cited guidance notes that *"In theory, immutability is ideal. In practice, mutability has worked better for our teams."* — insert new information into the existing ADR with a date stamp and a note. MADR's template uses a single `date` field meaning "when the decision was last updated"; this standard goes further, keeping the decision `Date:` immutable and recording refinements separately. The **decision date is never overwritten**; refinements are recorded in the `## Changelog` and the `Last-updated` field, keeping the record self-contained (an agent should not need to excavate git history to learn what was refined and when).
6490

6591
## Relationship to `docs/design/`
6692

0 commit comments

Comments
 (0)