From 33acf1032d152be50c72393b876a6d0ead93d80e Mon Sep 17 00:00:00 2001 From: bgagent <345885+scottschreckengaust@users.noreply.github.com> Date: Wed, 17 Jun 2026 23:10:11 +0000 Subject: [PATCH 1/2] 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 --- docs/decisions/README.md | 28 ++++++++++++++++++++++- docs/src/content/docs/decisions/Readme.md | 28 ++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 930c6bb9..038db483 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -20,6 +20,7 @@ Do **not** write an ADR for routine implementation choices that are self-evident **Status:** proposed | accepted | superseded | deprecated **Date:** YYYY-MM-DD +**Last-updated:** YYYY-MM-DD (optional; add when the ADR is refined in place after acceptance) **Supersedes:** ADR-NNN (if applicable) **Superseded by:** ADR-NNN (if applicable) @@ -41,8 +42,16 @@ What follows from this decision: ## References - Links to RFCs, issues, PRs, or external resources that informed the decision + +## Changelog + +(Optional; present once the ADR has been refined in place. One dated bullet per refinement. The decision date in `**Date:**` is never overwritten.) + +- YYYY-MM-DD — What was refined and why (decision unchanged). ``` +`**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). + ## Numbering 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 | `superseded` | Replaced by a newer ADR (link to successor) | | `deprecated` | No longer applicable (context changed) | -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. +A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges. + +### Changing an accepted ADR: refine in place vs. supersede + +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: + +- **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`. +- **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`. + +**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.* + +| Change | What it is | What to do | Status effect | Date fields | +|--------|-----------|------------|---------------|-------------| +| 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:` | +| 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:` | +| The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` | + +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 likewise tracks a last-updated date distinct from the decision date. 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). ## Relationship to `docs/design/` diff --git a/docs/src/content/docs/decisions/Readme.md b/docs/src/content/docs/decisions/Readme.md index bca2568b..b40dcd30 100644 --- a/docs/src/content/docs/decisions/Readme.md +++ b/docs/src/content/docs/decisions/Readme.md @@ -24,6 +24,7 @@ Do **not** write an ADR for routine implementation choices that are self-evident **Status:** proposed | accepted | superseded | deprecated **Date:** YYYY-MM-DD +**Last-updated:** YYYY-MM-DD (optional; add when the ADR is refined in place after acceptance) **Supersedes:** ADR-NNN (if applicable) **Superseded by:** ADR-NNN (if applicable) @@ -45,8 +46,16 @@ What follows from this decision: ## References - Links to RFCs, issues, PRs, or external resources that informed the decision + +## Changelog + +(Optional; present once the ADR has been refined in place. One dated bullet per refinement. The decision date in `**Date:**` is never overwritten.) + +- YYYY-MM-DD — What was refined and why (decision unchanged). ``` +`**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). + ## Numbering 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 | `superseded` | Replaced by a newer ADR (link to successor) | | `deprecated` | No longer applicable (context changed) | -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. +A decision starts as `proposed` during RFC discussion and moves to `accepted` when the implementing PR merges. + +### Changing an accepted ADR: refine in place vs. supersede + +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: + +- **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`. +- **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`. + +**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.* + +| Change | What it is | What to do | Status effect | Date fields | +|--------|-----------|------------|---------------|-------------| +| 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:` | +| 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:` | +| The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` | + +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 likewise tracks a last-updated date distinct from the decision date. 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). ## Relationship to `docs/design/` From b755f4cf5d099b4fb2b13d38b4f0f376fb462fba Mon Sep 17 00:00:00 2001 From: bgagent <345885+scottschreckengaust@users.noreply.github.com> Date: Wed, 17 Jun 2026 23:55:44 +0000 Subject: [PATCH 2/2] docs(governance): address PR #382 review nits (Henderson quote, MADR, Changelog) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- docs/decisions/README.md | 4 ++-- docs/src/content/docs/decisions/Readme.md | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 038db483..ffe106b5 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -45,7 +45,7 @@ What follows from this decision: ## Changelog -(Optional; present once the ADR has been refined in place. One dated bullet per refinement. The decision date in `**Date:**` is never overwritten.) +(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.) - YYYY-MM-DD — What was refined and why (decision unchanged). ``` @@ -82,7 +82,7 @@ Lifecycle state (above) is **orthogonal** to ordinary upkeep. Two different oper | 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:` | | The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` | -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 likewise tracks a last-updated date distinct from the decision date. 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). +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). ## Relationship to `docs/design/` diff --git a/docs/src/content/docs/decisions/Readme.md b/docs/src/content/docs/decisions/Readme.md index b40dcd30..4d6d3395 100644 --- a/docs/src/content/docs/decisions/Readme.md +++ b/docs/src/content/docs/decisions/Readme.md @@ -49,7 +49,7 @@ What follows from this decision: ## Changelog -(Optional; present once the ADR has been refined in place. One dated bullet per refinement. The decision date in `**Date:**` is never overwritten.) +(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.) - YYYY-MM-DD — What was refined and why (decision unchanged). ``` @@ -86,7 +86,7 @@ Lifecycle state (above) is **orthogonal** to ordinary upkeep. Two different oper | 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:` | | The decision no longer applies (context evaporated) | **Obsolescence** | Mark `deprecated`; note why | `deprecated` | bump `Last-updated:` | -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 likewise tracks a last-updated date distinct from the decision date. 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). +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). ## Relationship to `docs/design/`