Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion docs/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

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

- Links to RFCs, issues, PRs, or external resources that informed the decision

## Changelog

(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).
```

`**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.
Expand All @@ -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'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/`

Expand Down
28 changes: 27 additions & 1 deletion docs/src/content/docs/decisions/Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

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

- Links to RFCs, issues, PRs, or external resources that informed the decision

## Changelog

(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).
```

`**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.
Expand All @@ -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'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/`

Expand Down
Loading