| name | adr |
| description | ADR (Architecture Decision Record) generation + supersession rules. Immutable per-file under docs/adr/ (Status line is the only mutable surface). Bootstrap enumerates from PRD; standalone `/blueprint adr` adds or supersedes. Python-backed renderer. |
| user-invocable | false |
ADR Generation — Unified Template (Python-Backed)
Each ADR is rendered to docs/adr/ADR-NNN.md by a deterministic Python
script from a structured input JSON. The agent's job is to enumerate
candidate decisions (from PRD or user input), interview the user, and
write a complete docs/.harness/adr-input.json; the script does all
markdown formatting, ID auto-assignment, schema enforcement, and
supersession orchestration.
Immutability: an ADR file is immutable EXCEPT its ## Status line.
The Status line gets surgically rewritten when the ADR is superseded by
a later one (Accepted (YYYY-MM-DD) → Superseded by ADR-NNN (YYYY-MM-DD)).
No other body content may be edited after creation. To record a changed
decision, write a NEW ADR-MMM with supersedes: "ADR-NNN" — never edit
the old file's decision/reason/tradeoff text.
Mandatory Workflow
-
Pre-flight check (Python)
python3 --version
If python3 is not on PATH, STOP. Report the blocker verbatim.
-
Load PRD — docs/PRD.md is the enumeration seed for Bootstrap mode.
Read the full PRD (not just tech_stack) to surface candidate
decisions: framework choices, library picks, auth/payment providers,
AI model routing, sync semantics, privacy policies, hard caps,
architectural patterns. Standalone /blueprint adr mode skips this and
uses the user's supplied seed instead.
-
Cross-validate via context7 / WebSearch (in-line) — for any
decision whose body mentions a named external library / framework /
model / API spec, the agent MUST run mcp__claude_ai_context7__resolve-library-id
followed by mcp__claude_ai_context7__query-docs to verify the named
entity actually exists with the claimed spec. WebSearch is used
secondarily for "success case" or comparative evidence. This is
in-line validation owned by the generator — there is no separate
adr-validator agent.
-
Interview — interview-protocol discipline: ambiguity = 0 before
writing. The main agent owns AskUserQuestion; the sub-agent
(adr-generator) enumerates ambiguities in Pass 1 and applies answers
in Pass 2.
-
Write input file
Write tool → docs/.harness/adr-input.json
-
Invoke Python
python3 "${CLAUDE_PLUGIN_ROOT}/skills/adr/scripts/generate_adr.py" \
--input docs/.harness/adr-input.json \
--output-dir docs/adr
-
Handle REJECT — script exits non-zero with a single [REJECT] <reason>
on stderr. Read the reason, fix the JSON, re-run. Maximum 2 retry
attempts; then surface to the user.
Output location is fixed: docs/adr/ADR-NNN.md. The script
auto-assigns N from Path("docs/adr").glob("ADR-*.md") max+1 when
id is null in the input. Existing ADR files are NEVER overwritten
(immutability) — [REJECT] if an explicit id collides with an
existing file.
ID auto-assignment
docs/adr/
ADR-001.md
ADR-002.md
ADR-005.md ← user manually created
→ next auto = ADR-006 (max + 1, gaps preserved)
The renderer reads existing ADR filenames once, computes max(int) + 1,
and assigns to every input ADR whose id is null (in input order). An
input that supplies an explicit id is respected only if the file does
not already exist — collision → [REJECT].
Template (6 sections — fixed)
# ADR-NNN: {title_ko}{supersedes_inline}
## Status
{status} ({status_date})
## Context
{context_ko}
## 결정
{decision_ko}
## 이유
{reasons_ko}
## 트레이드오프
{tradeoffs_ko}
{supersedes_inline} = " (supersedes ADR-MMM)" when supersedes is set, else empty.
{status} enum: Accepted | Proposed | Deprecated (initial). The
later transition Accepted → Superseded by ADR-NNN is performed by
supersede_adr.py, never by hand-editing.
{status_date} format: YYYY-MM-DD.
Supersession
When a new ADR-MMM supersedes ADR-NNN, the renderer performs a single
atomic operation:
- Write the new
docs/adr/ADR-MMM.md with supersedes: "ADR-NNN" in the
title's {supersedes_inline}.
- Invoke
supersede_adr.py (sub-process) which:
- Surgically rewrites
docs/adr/ADR-NNN.md Status line:
Accepted (YYYY-MM-DD) → Superseded by ADR-MMM (TODAY).
- Scans
docs/roadmap/tasks/T###-*.md and replaces only the
ADR-NNN ID in each task's "ADR References" list with ADR-MMM —
siblings are preserved.
- On
supersede_adr.py failure, the new ADR-MMM file is rolled back
(deleted) so the operation is all-or-nothing.
JSON Input Schema
Authoritative source: scripts/generate_adr.py dataclasses. Field outline
lives in references/input-schema.md.
Top-level keys: meta / adrs[].
Each adrs[] element:
| Field | Type | Notes |
|---|
id | "ADR-NNN" | null | null → auto-assign. Explicit must not collide with existing file. |
title_ko | str | Free Korean. |
status | enum | Accepted | Proposed | Deprecated. |
status_date | YYYY-MM-DD | Initial date. Renderer does not change. |
context_ko | str (markdown) | Background — why this decision was needed. |
decision_ko | str (markdown) | What was decided. |
reasons_ko | str (markdown) | Why this decision was made. |
tradeoffs_ko | str (markdown) | Costs / compromises / boundaries. |
supersedes | "ADR-NNN" | null | If set, triggers supersede_adr.py post-write. Must reference an existing ADR. |
NEVER Generate (Scope Discipline)
ADRs describe decisions, not features. The following belong elsewhere
and are excluded:
- Feature lists / user flows → PRD §3·§4
- Data model / entity definitions → PRD §7
- Directory structure / file placement → ARCHITECTURE.md
- Implementation code / function bodies / type definitions — ADRs
describe intent, never the code that realizes it
- Time-bound goals / KPI / business metrics — these aren't
architectural decisions
- References to specific PR numbers / commit SHAs — ADRs survive code
history; tying them to ephemeral identifiers creates rot. Use prose
("during the Q2 refactor", not "PR #142").
Writing Guidelines
- Body language is Korean for
context_ko / decision_ko /
reasons_ko / tradeoffs_ko. Section headers stay bilingual (rendered
by Python). Code identifiers (library names, version strings) remain
ASCII.
- One decision per ADR. If the user wants to capture two related
decisions, write two ADRs and cross-reference in
context_ko.
- Reasons must withstand future challenge — write as if a teammate
six months from now will ask "why did we pick this?". Vague reasons
("seems standard", "everyone uses it") are rejected during interview.
- Tradeoffs are mandatory and non-empty. If you cannot articulate
what was given up, the decision was not actually evaluated — push back
in the interview.
- Supersession is a NEW ADR, not an edit. Don't say "ADR-001's
reason was wrong" in ADR-015; say "context evolved" or "constraint
changed" — preserve the historical record.
Sub-agent integration
The skill is invoked by the adr-generator sub-agent which implements
the 2-pass interview pattern (Pass 1 enumeration + Pass 2 render). The
sub-agent is dispatched by blueprint:
- Bootstrap mode: after
prd-validate, before arch-gen. Reads PRD
in full and enumerates candidate decisions for the user to confirm.
- Standalone mode:
/blueprint adr. Used for ad-hoc new ADRs or for
supersession (Pass 1 asks the user which existing ADR is being
superseded, if any).