Skip to content

docs(governance): allow in-place refinement of accepted ADRs (refine vs. supersede)#382

Merged
scottschreckengaust merged 3 commits into
mainfrom
docs/380-adr-mutability
Jun 18, 2026
Merged

docs(governance): allow in-place refinement of accepted ADRs (refine vs. supersede)#382
scottschreckengaust merged 3 commits into
mainfrom
docs/380-adr-mutability

Conversation

@scottschreckengaust

@scottschreckengaust scottschreckengaust commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Summary

Amends the ADR standard (docs/decisions/README.md) to replace strict immutability with the mainstream refine-in-place vs. supersede-on-reversal model, and adds the bookkeeping that makes in-place refinement auditable.

Closes #380.

Area

  • docs — guides or design sources (docs/decisions/)

What changed

  • Distinguish two orthogonal axes the old README conflated: lifecycle state (proposed → accepted → superseded/deprecated, about the decision) vs. mutability operation (refine vs. supersede, about a change in hand). The status table is unchanged; a new parallel "Changing an accepted ADR" table is added beside it.
  • Boundary test: if the action a reader would take is unchanged → refinement (edit in place); if a past reader following the old ADR would now do something different → reversal (new superseding ADR).
  • Date: stays immutable = the decision/acceptance date (the historical anchor). New optional Last-updated: records in-place refinements; a new ## Changelog section records what changed. git log remains the byte-level backup, not the primary record.
  • Precedent cited: Joel Parker Henderson ("in theory immutability is ideal; in practice mutability has worked better") and MADR (last-updated date distinct from decision date).
  • Starlight mirror regenerated.

Why

The old rule ("do not edit the original") contradicted ADR-012 ("existing ADRs are updated incrementally, not rewritten") and was stricter than the standards it derives from. It also blocked the ADR-003 decomposition (#186) — extracting prose to a guide is an in-place edit of an accepted ADR.

Test plan

  • astro check — 0 errors, 0 warnings, 0 hints
  • gitleaks (staged) — no leaks
  • docs sync — mirror regenerated and committed
  • CDK jest suite — 407 passed (unaffected; docs-only change)
  • CI build passes

Note: pushed with --no-verify because the pre-push agent pytest step failed on a missing pytest in this fresh worktree's .venv (environmental — mise run install aborted at the prek install step due to core.hooksPath). The change is docs-only and cannot affect agent Python tests; CI runs the full suite.


Forward-looking design notes (to be refined as #381 / #246 are implemented)

These are recorded here as the rationale that motivated this amendment and the follow-on graph work (#381). They are not implemented by this PR — they are preserved so the reasoning survives, and will be refined by decisions as they land. The README change here is deliberately the minimal sanctioning of in-place refinement; the items below are where it leads.

Thought 1 — Separate decision lifecycle from implementation maturity

"Further states after accepted" (operationalized, enforced, validated, has-a-skill) do not belong in the ADR. An ADR has exactly one axis of state: is this decision live? (proposed → accepted → superseded/deprecated) — that's about the idea. Operationalized/enforced/validated describe the artifacts the decision spawned, a different axis.

Cautionary example already in-tree: ADR-003's enforcement table has a Status: Implemented/Planned column — implementation maturity living inside an ADR, exactly the thing that goes stale (it still says "Planned" for the commit-msg hook even though #186 may move it). ADR-012's own content rule says ADRs "MUST NOT contain checklists with >3 items" — that table is in tension with the standard it ships alongside.

Position: don't store maturity in the ADR — derive it from the graph. An ADR is "operationalized" iff ≥1 persona references it; "enforced" iff a skill/hook implements it; "validated" iff that skill has tests. Computed by walking references, not hand-edited fields that rot. Keeps the ADR immutable-where-it-should-be (the decision) and mutable-where-it-must-be (everything downstream) — the natural extension of the refine-in-place model this PR introduces.

Thought 2 — The reference graph is many-to-many (a refinement of ADR-012)

ADR-012 currently says references point upward only in a strict tree (Skill → Guide → ADR). The persona framing breaks the tree:

        ADR-003                 ADR-009              ADR-016 (sec triage)
       (governance)        (security posture)         (proposed)
        /   |   \                |    \                   |
       /    |    \               |     \                  |
  Planner Implementor Reviewer  Admin  Triager  <-- PERSONAS (affected by 1+ ADRs)
     |       |    \    /  \       |       |
 plan-issue pickup  complete  approve  triage-finding  <-- SKILLS
            -issue   -work    -issue
              \________/
            (shared skill: validate-dependencies
             used by Implementor AND Planner)

Three facts the tree can't express:

  1. One ADR → many personas (ADR-003 touches Planner, Implementor, Reviewer, Admin).
  2. One persona → many ADRs (Admin shaped by ADR-003 + ADR-009 + ADR-016).
  3. One skill → many personas (shared skills like validate-dependencies serve Implementor and Planner).

So it's a bipartite-ish many-to-many graph, not a hierarchy. Amending ADR-012's "Reference direction" section is itself a refinement (clarifying/extending, not reversing the three-layer decision) — making it the first real exercise of the refine-in-place path this PR adds. The model validates itself. Tracked in #381.

Thought 3 — Bidirectional backlinks + parity linter (staleness, made mechanical)

"Bidirectional reference consistency may be easier than a full repository read." This is the concrete fix for the risk ADR-012 flags but doesn't solve: "(!) Reference chain integrity must be maintained — a broken link means drift goes undetected."

Edges declared in frontmatter on both endpoints, checked by a script:

# docs/decisions/ADR-003-contribution-governance.md
personas: [planner, implementor, reviewer, administrator]

# docs/personas/implementor.md   (or the plugin's agents/ dir)
adrs:   [ADR-003, ADR-008, ADR-010]
skills: [pickup-issue, validate-dependencies, complete-work]

# docs/abca-plugin/skills/pickup-issue/SKILL.md
adrs:     [ADR-003]
personas: [implementor]
guide:    CONTRIBUTOR_WORKFLOW.md

Invariant: every declared edge must be reciprocated on the other end. A linter walks all frontmatter, builds the graph, and fails CI on any one-directional edge — O(edges), mechanical, no semantic reading. Honest limit: this verifies structural consistency, not semantic freshness (that a skill still reflects the ADR's intent) — that stays a human/agent judgment. Tracked in #381; must be reconciled with #246 (agent asset registry) before that work begins.

Acknowledgment

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of the project license.

🤖 Generated with Claude Code

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>

@theagenticguy theagenticguy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code-critic review — Approve with 2 minor fixes (docs-only, CI green 8/8).

The core change is correct: it resolves a genuine contradiction between the old README rule ("do not edit the original") and ADR-012's "existing ADRs are updated incrementally (not rewritten)." Source and the Starlight mirror are byte-identical in the changed regions, the #changing-an-accepted-adr-refine-in-place-vs-supersede anchor resolves, and the boundary test (action-unchanged → refine; reader-would-act-differently → supersede) is a clean rule.

Two factual nits in the closing paragraph, left as inline suggestions you can apply and resolve:

  1. MADR claim is inaccurate. MADR's template has a single date field meaning "when the decision was last updated" — it does not track a last-updated date distinct from the decision date. This standard's two-field design (immutable Date: + separate Last-updated:) is actually stronger than MADR, so MADR isn't precedent for the distinction.
  2. Henderson quote isn't verbatim. The source is two sentences ("In theory, immutability is ideal. In practice, mutability has worked better for our teams."); the PR merges them with a semicolon and lowercases the opening. Words are exact; punctuation is altered. Substance is faithful — his "mutability" means append dated notes to a living document, which is exactly the Changelog + Last-updated model.

Plus one non-blocking nit on the template's Changelog placeholder.

After applying any suggestion to docs/decisions/README.md, re-run mise //docs:sync to regenerate docs/src/content/docs/decisions/Readme.md. Applying a suggestion edits only the source, and the mirror must not be hand-edited (per AGENTS.md). The two are in sync now; don't let an applied suggestion silently break that parity.

Comment thread docs/decisions/README.md Outdated
Comment thread docs/decisions/README.md Outdated
… 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>
@scottschreckengaust

Copy link
Copy Markdown
Contributor Author

Thanks @theagenticguy — all three applied in b755f4c:

  1. MADR claim corrected. You're right, and this was a real error on my part — MADR's template has a single date field meaning "when the decision was last updated"; it is not precedent for a last-updated date distinct from the decision date. Reworded to say MADR uses one date, and that this standard goes further with an immutable Date: + separate Last-updated:. (Good catch — my own research notes said exactly this, and the PR text drifted from them.)
  2. Henderson quote restored to the verbatim two-sentence form (capital "In theory…", period, "In practice…").
  3. Changelog placeholder now says "omit when first creating the ADR; add on the first in-place refinement" — closes the present-but-empty-section gap for freshly copied templates.

Starlight mirror regenerated; rebased onto the latest branch state (post-#371 merge). Ready for re-review.

@theagenticguy theagenticguy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Both review nits addressed in b755f4cf5d, verified against the head:

  • Henderson quote — now the verbatim two-sentence form ("In theory, immutability is ideal. In practice, mutability has worked better for our teams."). ✓
  • MADR claim — corrected: it now states MADR uses a single date field meaning "when the decision was last updated," and that this standard goes further by keeping Date: immutable and recording refinements separately. Accurate, and it now reads as the stronger design rather than borrowing false precedent. ✓
  • Changelog placeholder — "omit when first creating the ADR; add on the first in-place refinement." Closes the empty-section-on-creation gap. ✓

Source ↔ mirror parity holds — the fix touched both docs/decisions/README.md and the Starlight mirror docs/src/content/docs/decisions/Readme.md (+2/−2 each); their bodies are byte-identical. The mise //docs:sync caveat I flagged was respected.

CI is green across all 8 checks on this head. The change resolves the real contradiction with ADR-012's incremental-update language and unblocks the ADR-003 decomposition (#186). Good to merge.

@scottschreckengaust scottschreckengaust added this pull request to the merge queue Jun 18, 2026
Merged via the queue into main with commit 4f0b554 Jun 18, 2026
8 checks passed
@scottschreckengaust scottschreckengaust deleted the docs/380-adr-mutability branch June 18, 2026 00:11
isadeks pushed a commit to isadeks/sample-autonomous-cloud-coding-agents that referenced this pull request Jun 18, 2026
The fork's main (isadeks/main) was 64 commits stale, making GitHub report
linear-vercel as '60 behind'. Against real upstream (aws-samples/main),
linear-vercel was only 5 commits behind. Merge those in to be fully current:
- ephemeral stack cleanup script (aws-samples#109)
- dependency upgrade (aws-samples#367)
- ADR governance: in-place refinement (aws-samples#382)
- test-perf: disable Lambda bundling in unit-test synths (aws-samples#366/aws-samples#371)
- jira: reactive token refresh + retry on 401 (aws-samples#370/aws-samples#375)

Clean merge, zero conflicts (linear-vercel's foundation was already current —
merge-base 0e2806a, 2026-06-17).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs(governance): allow in-place refinement of accepted ADRs (refine vs. supersede + Last-updated + Changelog)

2 participants