关于 write-adr
write-adr 可将当前会话中的架构决策整理为 MADR 格式的架构决策记录。它涵盖决策确认、编号分配、文件生成和按标准验证记录。
主要功能
- 01从对话中提取决策
- 02确认要记录的决策
- 03预先分配 ADR 编号
- 04生成 MADR 格式记录
- 05按完成标准验证文件
适用场景
- 01记录会话中作出的架构选择
- 02整理备选方案与决策依据
- 03在评审前检查生成的 ADR
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ existential-birds/ beagle --skill write-adr安装后在 Claude Code 中输入/write-adr确认已加载。
详细介绍
编写 ADR
根据当前会话中作出的决策生成架构决策记录(ADR)。
工作流概述
- 背景 - 收集仓库背景信息和现有 ADR
- 提取 - 使用子 Agent 分析对话并提取决策
- 确认 - 向用户展示决策供其选择
- 编写 - 使用子 Agent 并行生成 ADR
- 报告 - 汇总已创建的文件和状态
- 验证 - 根据完成定义验证生成的 ADR
关卡(客观通过条件)
仅当通过条件满足时才继续。这些条件无需依赖“我已在内部验证”。
| 完成后 | 通过条件 |
|---|---|
| 第 2 步(提取) | 子 Agent 的响应是有效 JSON,且顶层包含 decisions 数组(可以为空)。每个非空条目都包含 id、title,并且至少有 context、decision、alternatives 或 rationale 中的一项,其值为非空字符串或非空数组。如果解析失败或结构不正确,请重新运行提取或修正载荷,再进入第 3 步。 |
| 第 4 步(预分配) | 在仓库根目录运行 python plugins/beagle-analysis/skills/adr-writing/scripts/next_adr_number.py --count N,输出恰好 N 行(每行一个编号)。在启动任何 ADR 编写单元之前,你已写好映射关系(记录在回复草稿或备注中),将每项已选决策对应到其中一行。 |
| 第 5 步(报告) | 汇总表中的每个文件路径都从子 Agent 的完成输出中复制而来(而非自行编造)。可选的抽查方式:对每个路径运行 test -f <path>,再标记为成功。 |
| 第 6 步(验证) | 对于每个 ADR 路径,打开文件后确认第 1 行为 ---、frontmatter 可解析为 YAML、包含 status 和 date,且正文符合下方第 6 步的要点(替代方案数量、Good/Bad 后果)。 |
第 1 步:收集背景信息
# Get current branch and recent commits
git branch --show-current
git log --oneline -5
# Check for existing ADRs
ls docs/adrs/ 2>/dev/null || echo "No ADR directory found"
# Count existing ADRs for numbering
find docs/adrs -name "*.md" 2>/dev/null | wc -l
这些背景信息可帮助 ADR 编写者:
- 在 ADR 中引用相关提交
- 避免重复记录已有文档说明的决策
- 确定正确的序列编号
第 2 步:提取决策
分析当前对话,找出架构决策。如果 Agent 支持子 Agent,则将此任务作为单个提取子 Agent 调度;否则直接运行相同的提取流程——输出完全相同。使用以下说明:
Load the **adr-decision-extraction** skill ([../adr-decision-extraction/SKILL.md](../adr-decision-extraction/SKILL.md)).
Analyze the conversation for decisions that warrant ADRs:
- Technology choices, architecture patterns, design trade-offs
- Rejected alternatives, significant implementation approaches
Return JSON:
{
"decisions": [
{
"id": 1,
"title": "Use PostgreSQL for primary datastore",
"context": "Brief context about why this came up",
"decision": "What was decided",
"alternatives": ["What was considered but rejected"],
"rationale": "Why this choice was made"
}
]
}
如果子 Agent 返回的 decisions 数组为空,则跳到第 5 步,并显示消息:“本次会话中未发现架构决策。”
**关卡:进入第 3 步之前,必须满足关卡(客观通过条件)**中的第 2 步要求。
第 3 步:向用户确认
完整展示所有提取出的决策详情,然后请用户选择:
## Detected Decisions
### 1. Use PostgreSQL for primary datastore
**Confidence:** high
**Problem:** Need ACID transactions for financial records
**Decision:** PostgreSQL for user data storage
**Alternatives discussed:**
- MongoDB
- SQLite
**Rationale:** ACID compliance, team familiarity, mature ecosystem
**Source:** Discussion about database selection in planning phase
---
### 2. Implement event sourcing for audit trail
**Confidence:** medium
**Problem:** Compliance requires complete audit history
**Decision:** Event sourcing pattern for state changes
**Alternatives discussed:**
- Database triggers
- Application-level logging
**Rationale:** Immutable audit trail, temporal queries, debugging capability
**Source:** Compliance requirements discussion
---
## Selection
Which decisions should I write ADRs for?
- Enter numbers (e.g., "1,2" or "1-2"), "all", or "none" to skip
**重要:**始终先根据提取输出完整展示决策详情(问题、决策、替代方案、理由),再请用户选择。不要只展示标题和背景信息。
解析用户响应:
"all"- 处理所有决策"none"或空 - 跳过,并显示消息“不会创建任何 ADR。”"1,2"或"1-2"- 处理指定决策
第 4 步:编写 ADR(并行)
启动子代理前,预先分配 ADR 编号,以避免编号冲突:
# Pre-allocate numbers for all confirmed decisions (from repository root)
# Example: If user selected 3 decisions
python plugins/beagle-analysis/skills/adr-writing/scripts/next_adr_number.py --count 3
# Output:
# 0003
# 0004
# 0005
启动子代理前,将每个预分配编号分配给对应的决策。
门槛: 启动第一个 ADR 编写单元前,满足 门槛(客观通过条件) 中第 4 步对应的要求。
对于每项已确认的决策,使用其预先分配的编号运行一个 ADR 编写单元。如果 Agent 支持子代理,则为每项决策并行派发一个编写单元;否则,依次编写每个 ADR,输出完全相同。使用以下任务说明:
Load the **adr-writing** skill ([../adr-writing/SKILL.md](../adr-writing/SKILL.md)).
Write an ADR for this decision:
```json
{decision JSON}
重要:使用此预先分配的 ADR 编号:{assigned_number}
说明:
- 探索代码库以获取更多上下文
- 在 docs/adrs/ 中编写符合 MADR 格式的 ADR
- 使用预先分配的编号 {assigned_number} ——不要调用 next_adr_number.py
- 文件名格式:{assigned_number}-slugified-title.md
- 返回创建的文件路径
**Critical:** Pass the pre-allocated number to each writer unit. Writers must NOT call `next_adr_number.py` themselves - this causes duplicate numbers when running in parallel.
Wait for all writer units to complete before proceeding.
## Step 5: Report Results
**Gate:** Meet the Step 5 row in **Gates (objective pass conditions)** when building the summary (paths from subagent outputs; optional `test -f`).
Collect outputs from all subagents and present summary:
```markdown
## ADR Generation Complete
| File | Decision | Status |
|------|----------|--------|
| docs/adrs/0003-use-postgresql.md | Use PostgreSQL for primary datastore | Draft |
### Next Steps
- Review generated ADRs for accuracy
- Update status from "proposed" to "accepted" when finalized
### Gaps Requiring Investigation
- [List any decisions where subagent noted missing context]
如果未处理任何决策:
No ADRs were created. Run this command again after making architectural decisions.
第 6 步:验证生成的 ADR
对于每个创建的 ADR,根据完成定义进行验证:
## Verification Checklist
| ADR | E | C | A | D | R | Status |
|-----|---|---|---|---|---|--------|
| 0003-use-postgresql.md | ✓ | ✓ | ✓ | ⚠ | ✗ | Incomplete |
Legend: E=Evidence, C=Criteria, A=Agreement, D=Documentation, R=Realization
门槛: 对于每个创建的 ADR,满足 门槛(客观通过条件) 中第 6 步对应的要求。
验证步骤:
- 打开每个生成的 ADR 文件
- 确认文件名符合
NNNN-slugified-title.md模式 - 确认文件开头存在 YAML 前置元数据:
- 文件必须以
---开头 - 包含
status: draft(或有效状态) - 包含
date: YYYY-MM-DD(实际日期) - 标题前以
---结束 - 如果缺少前置元数据,请立即添加
- 文件必须以
- 检查
[INVESTIGATE]提示——这些需要后续跟进 - 确认文档记录了至少 2 个备选方案
- 确认后果章节同时包含 Good 和 Bad 条目
如果存在缺漏:
- 在缺漏解决前保持状态为
draft - 使用
[INVESTIGATE]提示指导后续跟进 - 将评审安排到利益相关者参与的会议中,然后再将状态改为
accepted
输出位置
ADR 写入 docs/adrs/(与 adr-writing 使用相同约定)。如果 ADR 目录不存在,则创建该目录,并添加初始的 0000-use-madr.md 模板记录。
MADR 格式参考
---
status: draft
date: YYYY-MM-DD
---
# {TITLE}
## Context and Problem Statement
{What is the issue motivating this decision?}
## Decision Drivers
* {driver 1}
* {driver 2}
## Decision Outcome
Chosen option: "{option}", because {reason}.
### Consequences
* Good, because {positive}
* Bad, because {negative}