cc-os/docs/adr-system/02-external-research.md

179 lines
11 KiB
Markdown
Raw Permalink Normal View History

# External Research: ADR Best Practices & Claude Code Integration
_Last updated: 2026-07-03_
Two research passes: (1) general ADR best practices independent of any AI tooling, (2) how
Claude Code / AI-coding-agent users specifically have integrated ADRs. Gathered by web-research
agents, 2026-07-03. Claims marked **[unverified]** were not independently checked against a
primary source in this pass — verify before relying on a specific tool/repo name.
---
## Part A — General ADR Best Practices
### 1. File/directory organization
Industry consensus favors **one-file-per-decision** over a monolithic running log, following
Michael Nygard's original 2011 convention: sequential numbered files (`0001-title.md`, …) in
`doc/adr/`, stored alongside code in version control ([Cognitect
Blog](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)). MADR refines
this with timestamped naming for sortability ([MADR docs](https://adr.github.io/madr/)).
Tradeoffs at scale:
- **Advantages**: immutable per-decision history, shallow git diffs (no merge conflicts on a
shared log file), sequential numbering creates a shared "decision language."
- **Disadvantages**: filesystem clutter past ~200 decisions, usually addressed with
subdirectory categorization (e.g. `decisions/backend/`).
Tools handle discoverability differently: **adr-tools** (bash, Nygard format) has no built-in
index, relying on naming discipline; **Log4brains** (Node.js) auto-generates a searchable
dashboard from git metadata with no enforced numbering; **Backstage** (Spotify's platform)
indexes ADRs across many repos for org-wide visibility. Across all of them, the common
discoverability mechanism is an `overview.md`/`README.md` table (title + status + date) plus
explicit `Supersedes:` / `Superseded by:` cross-links in each file.
No evidence surfaced of a monolithic single-file ADR log surviving past ~30 decisions in active
use **[unverified — multiple practitioner blogs, no single primary source]**; this is directly
relevant to cc-os's own 19-ADR, 601-line file trending toward that threshold.
### 2. Content template best practices
Three templates dominate:
- **Nygard minimal**: Status · Context · Decision · Consequences. Lowest friction, fits one
page; weaker audit trail since alternatives aren't a first-class section.
- **MADR (Markdown ADR)**: adds Decision Drivers, Considered Options (with pros/cons per
option), and RACI-style metadata (Deciders, Consulted, Informed). Two pages typical; the
de-facto default for teams >15 engineers or audit-sensitive contexts.
- **Y-Statements**: one paragraph — "In the context of `<use case>`, facing `<concern>`, we
decided for `<option>` and against `<alternatives>`, to achieve `<benefits>`, accepting
`<trade-offs>`." Writable in ~90 seconds; a lightweight complement, not a replacement, for
per-project decisions that don't warrant a full ADR.
What makes an ADR *useful later* rather than a wall of text nobody rereads:
1. **Status field** (Proposed/Accepted/Rejected/Superseded/Deprecated) — signals actionability
at a glance; accepted ADRs are treated as immutable, new insight → new ADR, not an edit.
2. **Alternatives-considered with reasoning** — the rejected options are often *more* valuable
to a future reader than the chosen one, because they prevent re-litigating a
already-evaluated path.
3. **Strong, short titles** ("Use PostgreSQL over MongoDB for user data," not "Database") —
enables index-skimming and grep.
4. **Explicit `Supersedes:` / `Superseded by:` cross-references** — prevents accidentally
applying an obsolete decision.
5. **Component/domain tagging** (`affected-components: [auth, api-gateway]`) — enables
filtering once ADR count exceeds ~50 **[unverified — inferred from MADR template fields]**.
6. **Deciders/date accountability** — prevents orphaned decisions once people leave.
Format-selection heuristic **[unverified, single secondary source]**: Nygard for <15-person
teams; MADR for 1550; MADR + tool-generated index for >50 or regulated industries;
Y-Statements for small per-project decision counts.
### 3. Lifecycle and governance
**When to write one** (Spotify engineering: "write an ADR whenever a decision of significant
impact is made; each team aligns on what 'significant' means" —
[source](https://engineering.atspotify.com/2020/04/when-should-i-write-an-architecture-decision-record)):
hard-to-reverse decisions, decisions affecting >1 team/service, decisions with real tradeoffs
and no obvious right answer, a question that's been re-litigated more than once (a sign of
undocumented institutional knowledge), non-functional requirements (security, availability,
latency). **When not to**: routine implementation choices, single-service decisions with no
cross-team impact, things already covered by standing policy.
**Immutability + supersession** (AWS Prescriptive Guidance): once Accepted, an ADR is
immutable. A conflicting new decision gets a *new* ADR in Proposed state with a
`Supersedes: ADR-NNNN` header; once accepted, the old ADR's status flips to `Superseded by
ADR-MMMM` and it stays in version control as history. "Deprecated" is a distinct state (the
decision is no longer relevant, e.g. the system was decommissioned) from "superseded" (replaced
by a newer decision).
**Review**: lightweight, PR-comment-style review (1015 min/ADR), not a formal approval board;
the author owns the final call rather than requiring full consensus (consensus causes scope
creep and decision fatigue).
**Keeping adoption high**: the #1 adoption barrier is template bloat — "a template that takes
an hour to fill out will not get used" (AWS). Practices: store ADRs in the code repo (not a
wiki), write them *during* the decision (not retroactively), markdown-only, provide a
copy-paste starting template, and periodically (e.g. quarterly) sweep for stale/undocumented
decisions.
**Sources**: [Cognitect/Nygard](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions),
[Martin Fowler bliki](https://martinfowler.com/bliki/ArchitectureDecisionRecord.html),
[MADR](https://adr.github.io/madr/),
[AWS Prescriptive Guidance](https://docs.aws.amazon.com/prescriptive-guidance/latest/architectural-decision-records/adr-process.html),
[Spotify Engineering](https://engineering.atspotify.com/2020/04/when-should-i-write-an-architecture-decision-record),
[Log4brains](https://github.com/thomvaill/log4brains),
[Y-Statements](https://medium.com/olzzio/y-statements-10eb07b5a177).
---
## Part B — Claude Code / AI-Agent Integration
### 1. Existing plugins/skills/MCP servers for ADRs **[names unverified — not independently confirmed in this pass]**
- **adr-kit** (`github.com/rvdbreemen/adr-kit`) — drop-in Claude Code toolkit; treats ADRs as
active guardrails, not passive docs.
- **zircote/adr** (GitHub) — lifecycle management across 7 template formats (MADR, Nygard,
Y-Statement, Alexandrian, Business Case…), with compliance auditing.
- **claude-plugin-adr** (`github.com/andronics/claude-plugin-adr`) and a plain
"architecture-decision-records" skill on a Claude plugin hub — basic creation workflows.
- An open Claude Code GitHub feature request (**issue #13853**) asks for native ADR support:
auto-loading records from `~/.claude/adr/` the same way `CLAUDE.md` auto-loads.
- **mcp-adr-analysis-server** (`github.com/tosin2013/mcp-adr-analysis-server`) — an MCP server
(agent-agnostic, not Claude-Code-specific) with 15 tools for reading/creating/managing ADRs,
using Tree-sitter AST analysis and secret-masking.
### 2. Triggering ADR creation
Most real-world usage is **reactive**, driven by an explicit user command (e.g. `/record-adr`),
not autonomous. adr-kit adds a smart-detection layer on top: `/adr:review` diffs commits
against existing ADRs to flag undocumented architectural changes; `/adr:init` audits an
existing codebase for decisions already "in effect" in the code and proposes batching them as
backfilled Accepted ADRs. One practitioner write-up (`beyondautocomplete.nl`) reports the
`/record-adr` flow takes 3060 seconds per decision and asks clarifying questions when context
is thin — but complex multi-decision changes still need to be split into separate invocations
manually.
### 3. Selective retrieval (avoiding context bloat)
This is the most directly relevant finding for cc-os's third HMW. Patterns observed:
- **Ranked, task-scoped filtering**: adr-kit's `adr-context` tool returns only the 35 most
relevant *Accepted* ADRs, using weighted signals — file-path/glob match against an ADR's
declared "enforcement path" ranked highest, keyword relevance second.
- **In-flight, path-triggered nudges**: an `adr-watch`-style mechanism surfaces an ADR only
when an edit touches a path the ADR governs — i.e., deterministic path matching rather than
semantic search for the common case.
- **Knowledge-graph retrieval**: converting ADRs into graph nodes lets a query find
*structurally* related decisions ("all ADRs that depend on this infra decision"), which is a
different (and complementary) axis to keyword/semantic similarity. This is directly relevant
to cc-os since Graphify is already the chosen knowledge-layer engine (ADR-010) — an ADR
system could plausibly be *another* node type in the same graph rather than a separate
retrieval mechanism.
- **Hook-based conditional injection**: a `SessionStart`/similar hook can filter which ADRs get
injected based on what files are about to be touched, keeping the default-context footprint
near zero and only pulling in ADRs when a matching path is active — architecturally identical
to cc-os's own lazy-freshness pattern (ADR-007).
- **Status-based filtering**: only surfacing `Accepted` ADRs by default; `Proposed` and
`Superseded` stay out of default retrieval paths.
### 4. Community sentiment / pain points **[incident detail unverified — single source, not independently confirmed]**
A recurring tension: ADRs record "why we decided," but an autonomous agent often needs
enforceable "what must never happen" constraints, which prose ADRs don't provide — cited as
part of the motivation for `AGENTS.md`-style "project constitution" files that encode operable
rules rather than narrative history. A cited (but unverified in this pass) Replit incident from
2025 describes an agent running `DROP DATABASE` despite an archived freeze decision, offered as
an argument that ADRs-as-prose are not a substitute for deterministic guardrails.
Separately, one source (MemU, 2026) claims **~2% context-retention loss per agent step**,
with tool-definition overhead alone consuming a large share of context on typical MCP setups
— cited as the underlying argument for "don't dump ADRs into context, filter them." Treat these
specific numbers as **[unverified]** (single-source, not cross-checked here), but the
qualitative point — naive full-ADR-dump retrieval degrades badly as ADR count grows — matches
both this repo's own experience (the 601-line `03-architecture-decisions.md` file) and the
structured-retrieval patterns in item 3 above.
**Sources**: adr-kit, zircote/adr, claude-plugin-adr, mcp-adr-analysis-server (GitHub repos,
names as given, not independently re-verified), Claude Code issue #13853,
[beyondautocomplete.nl write-up](https://www.beyondautocomplete.nl/how-i-use-claude-code-to-keep-my-architecture-decisions-on-track/),
Graphify/GraphRAG background, [Claude Code hooks docs](https://code.claude.com/docs/en/hooks),
`agentpedia.codes` AGENTS.md article, `thebcms.com` spec-driven-development article.