ADR 技能
理念
使用此技能创建的 ADR 是智能体编码的可执行规范。人类批准决策,智能体负责实施。ADR 必须包含智能体编写正确代码所需的所有信息,无需追问。
这意味着:
- 约束条件必须明确且可衡量,而非模糊概念
- 决策必须具体到可操作(“使用 PostgreSQL 16 与 pgvector”,而非“使用数据库”)
- 后果必须映射到具体的后续任务
- 必须明确非目标以防止范围蔓延
- ADR 必须是自包含的——不依赖隐性知识
- ADR 必须包含实施计划——需要修改哪些文件、遵循哪些模式、编写哪些测试以及如何验证决策已正确实施
何时编写 ADR
在以下情况下编写 ADR:
- 决策改变了系统的构建或运行方式(新依赖项、架构模式、基础设施选择、API 设计)
- 决策一旦基于其编写代码就很难逆转
- 决策会影响将来在此代码库中工作的其他人或智能体
- 决策有真正考虑并拒绝的替代方案
在以下情况下不要编写 ADR:
- 在已建立的模式内进行常规实现选择
- Bug 修复或拼写错误更正
- 已在现有 ADR 中捕获的决策(改为更新它)
- 已由 linter 或格式化工具覆盖的风格偏好
如有疑问:如果未来在此代码库中工作的智能体会受益于了解为什么做出此选择,请编写 ADR。
主动 ADR 触发条件(针对智能体)
如果你是代码库中编码的智能体,遇到以下任何情况,请在继续之前停下来并提议编写 ADR:
- 你即将引入项目中尚不存在的新依赖项
- 你即将创建其他代码需要遵循的新架构模式(处理错误的新方式、新的数据访问层、新的 API 约定)
- 你即将在两个或多个真正替代方案之间做出选择,且权衡结果不明显
- 你即将更改与现有已接受 ADR 相矛盾的内容
- 你发现自己正在编写一段冗长的代码注释来解释“为什么”——该理由应属于 ADR
如何提议:告诉人类你遇到了什么决策、为什么它重要,并询问他们是否要将其捕获为 ADR。如果同意,则运行完整的四阶段工作流。如果不同意,则在代码注释中注明该决策并继续。
创建 ADR:四阶段工作流
每个 ADR 经历四个阶段。不要跳过任何阶段。
阶段 0:扫描代码库
在提问之前,从仓库收集上下文:
-
查找现有 ADR。 检查
contributing/decisions/、docs/decisions/、adr/、docs/adr/、decisions/中的现有记录。阅读它们。注意:- 现有约定(目录、命名、模板风格)
- 与此决策相关或约束此决策的决策
- 此新决策可能取代的任何 ADR
-
检查技术栈。 阅读
package.json、go.mod、requirements.txt、Cargo.toml或等效文件。注意相关依赖项和版本。 -
查找相关代码模式。 如果决策涉及特定领域(例如“我们如何处理身份验证”),则扫描现有实现。确定将受此决策影响的特定文件、目录和模式。
-
在代码中查找 ADR 引用。 在注释和文档中查找 ADR 引用(参见下面的“代码 ↔ ADR 链接”)。这揭示了哪些现有决策管理代码库的哪些部分。
-
记录你的发现。 将此上下文带入阶段 1——这将使你的问题更加精准,并防止 ADR 与现有决策相矛盾。
阶段 1:捕获意图(苏格拉底式)
采访人类以理解决策空间。一次问一个问题,基于之前的答案逐步深入。不要一次性提出所有问题。
核心问题(大致按此顺序询问,如果上下文或阶段 0 已明确则跳过):
- 你在做什么决策? —— 获取一个简短、具体的标题。推使用动词短语(“选择 X”、“采纳 Y”、“用 W 替换 Z”)。
- 为什么是现在? —— 什么出了问题、什么在变化、或者如果什么都不做会出什么问题?这是触发条件。
- 存在哪些约束? —— 技术栈、时间线、预算、团队规模、现有代码、合规要求。要具体。参考你在阶段 0 中的发现(“我看到你已经在使用 X——这会约束这个决策吗?”)。
- 成功是什么样的? —— 可衡量的成果。超越“它能工作”到具体指标(延迟、吞吐量、开发者体验、维护负担)。
- 你考虑过哪些选项? —— 至少两个。对于每个选项:核心权衡是什么?如果他们只有一个选项,帮助他们阐明为什么拒绝了替代方案。
- 你目前倾向于什么? —— 尽早捕捉直觉。通常能揭示未明说的优先级。
- 谁需要知道或批准? —— 决策者、咨询的专家、知情的利益相关者。
- 智能体需要什么来实现这个决策? —— 哪些文件/目录受到影响?它应该遵循哪些现有模式?它应该避免什么?哪些测试可以证明它正常工作?这直接为实施计划提供信息。
自适应跟进问题:根据答案,在决策模糊的地方深入探究。常见的跟进问题:
- “如果这个决策是错误的,最坏的结果是什么?”
- “什么会让你在 6 个月后重新审视这个决策?”
- “你是否明确选择不做什么?”
- “代码库中的现有先例或模式与此决策相关吗?”
- “我找到了 [现有 ADR/模式] —— 这个新决策与它交互吗?”
何时停止:当你可以填写 ADR 的每个部分——包括实施计划——而无需编造内容时,你就有了足够的信息。如果你对任何部分不确定,再问一个问题。
意图摘要关卡:在进入阶段 2 之前,呈现你捕获内容的结构化摘要,并请人类确认或更正:
我正在为 ADR 捕获以下内容:
- 标题:{标题}
- 触发条件:{为什么是现在}
- 约束条件:{列表}
- 选项:{选项 1} vs {选项 2} [vs ...]
- 倾向:{选择哪个选项以及为什么}
- 非目标:{明确排除的范围}
- 相关 ADR/代码:{存在的与此交互的内容}
- 受影响的文件/区域:{代码库中此决策落地的位置}
- 验证:{我们如何知道它已正确实施}
这能捕获你的意图吗?需要添加或更正什么吗?
在人类确认摘要之前,不要进入阶段 2。
阶段 2:起草 ADR
-
选择 ADR 目录。
- 如果存在(在阶段 0 中找到),使用它。
- 如果不存在,创建
contributing/decisions/(如果存在contributing/)、docs/decisions/(MADR 默认)或adr/(更简单的仓库)。
-
选择文件名策略。
- 如果现有 ADR 使用日期前缀(
YYYY-MM-DD-...),继续使用。 - 否则使用纯 slug 文件名(
choose-database.md)。
- 如果现有 ADR 使用日期前缀(
-
选择模板。
- 对于直接决策(一个明确的赢家,最少权衡),使用
assets/templates/adr-simple.md。 - 当需要记录多个选项并带有结构化优缺点/驱动因素时,使用
assets/templates/adr-madr.md。 - 参见
references/template-variants.md获取指导。
- 对于直接决策(一个明确的赢家,最少权衡),使用
-
用确认的意图摘要填写每个部分。 不要留占位符文本。每个部分应包含真实内容,否则应删除(仅限可选部分)。
-
编写实施计划。 对于智能体优先的 ADR,这是最重要的部分。它告诉下一个智能体确切该做什么。参见模板了解结构。
-
将验证标准编写为复选框。 这些必须足够具体,以便智能体可以编程或手动检查每个复选框。
-
生成文件。
- 首选:运行
scripts/new_adr.js(处理目录、命名和可选的索引更新)。 - 如果无法运行脚本,从
assets/templates/复制一个模板并手动填写。
- 首选:运行
阶段 3:对照清单复核
起草后,对照 references/review-checklist.md 中的智能体准备就绪清单复核 ADR。
以摘要形式呈现复核结果,而不是原始清单。格式:
ADR 复核
✅ 通过:{列出哪些是可靠的——例如,“上下文自包含,实施计划涵盖受影响的文件,验证标准可检查”}
⚠️ 发现的差距:
- {具体差距 1——例如,“实施计划未提及测试文件——哪个测试套件应该覆盖这个?”}
- {具体差距 2}
建议:{发布 / 先修复差距 / 需要更多阶段 1 工作}
仅指出失败和值得注意的优势——不要逐项背诵每个通过的复选框。
如果存在差距,提出具体的修复建议。不要只是标记问题——提供解决方案并请人类批准。
在 ADR 通过清单或人类明确接受差距之前,不要最终确定。
查阅 ADR(读取工作流)
智能体在拥有 ADR 的代码库中实施更改之前应阅读现有 ADR。这不是创建 ADR 工作流的一部分——它是任何智能体都应执行的独立操作。
何时查阅 ADR
- 在开始涉及架构(身份验证、数据层、API 设计、基础设施)的功能工作之前
- 当你在代码中遇到一个模式并想知道“为什么这样做?”时
- 在提议可能与现有决策相矛盾的更改之前
- 当人类说“检查 ADR”或“对此有一个决策”时
- 当你在代码注释中找到 ADR 引用时
如何查阅 ADR
-
找到 ADR 目录。 检查
contributing/decisions/、docs/decisions/、adr/、docs/adr/、decisions/。同时检查索引文件(README.md或index.md)。 -
扫描标题和状态。 阅读索引或列出文件名。重点关注
accepted状态的 ADR——这些是活跃的决策。 -
完整阅读相关 ADR。 不要只看标题——阅读上下文、决策、后果、非目标和实施计划。实施计划告诉你需要遵循哪些模式以及哪些文件受此决策管理。
-
尊重决策。 如果已接受的 ADR 说“使用 PostgreSQL”,不要在没有创建新 ADR 取代它的情况下提议切换到 MongoDB。如果发现代码实际执行情况与 ADR 不一致,请向人类报告。
-
遵循实施计划。 在受 ADR 管理的区域实施代码时,遵循其实施计划中指定的模式。如果计划说“所有新查询都通过
src/db/中的数据访问层”,请执行。 -
在你的工作中引用 ADR。 在代码注释和 PR 描述中添加 ADR 引用(参见下面的“代码 ↔ ADR 链接”)。
代码 ↔ ADR 链接
ADR 应与其管理的代码进行双向链接。
ADR → 代码(在实施计划中)
实施计划部分命名具体的文件、目录和模式:
## 实施计划
- **受影响路径**:`src/db/`、`src/config/database.ts`、`tests/integration/`
- **模式**:所有数据库查询通过 `src/db/client.ts`
代码 → ADR(在注释中)
在由 ADR 指导实施代码时,添加引用注释:
// ADR:使用 better-sqlite3 作为测试数据库
// 参见:docs/decisions/2025-06-15-use-sqlite-for-test-database.md
import Database from 'better-sqlite3';
保持这些轻量级——在入口点添加一条注释,而不是每一行。目标是可发现性:当未来的智能体阅读此代码时,他们可以找到推理过程。
为什么这很重要
- 在
src/db/中工作的智能体可以找到管理该区域的 ADR - 阅读 ADR 的智能体可以找到实施它的代码
- 当 ADR 被取代时,代码引用使得轻松找到所有需要更新的代码
其他操作
更新现有 ADR
-
确定意图:
- 接受 / 拒绝:更改状态,添加任何最终上下文。
- 弃用:状态 →
deprecated,解释替代路径。 - 取代:创建新 ADR,双向链接(旧 → 新,新 → 旧)。
- 添加经验教训:追加到
## 更多信息,并带有日期戳。不要重写历史。
-
使用
scripts/set_adr_status.js进行状态更改(支持 YAML 前置元数据、项目符号状态和部分状态)。
接受后生命周期
ADR 被接受后:
- 创建实施任务。 实施计划中的每个项目以及后果中的每个跟进项目都应成为可跟踪的任务(问题、工单或 TODO)。
- 在 PR 中引用 ADR。 在 PR 描述中链接到 ADR,例如“实施
contributing/decisions/2025-06-15-use-sqlite-for-test-database.md。” - 添加代码引用。 在关键实施点添加 ADR 路径注释。
- 检查验证标准。 实施完成后,逐项检查验证复选框。在
## 更多信息中更新 ADR 结果。 - 在触发条件触发时重新审视。 如果 ADR 指定了重新审视条件(“如果 X 发生,重新考虑”),监控这些条件。
索引
如果仓库有 ADR 索引/日志文件(通常是 ADR 目录中的 README.md 或 index.md),保持其更新。
首选:让 scripts/new_adr.js --update-index 来做。否则:
- 为新 ADR 添加一个项目符号条目。
- 保持排序一致(如果编号则数字;如果使用 slug 则按日期或字母)。
引导
在没有任何 ADR 的仓库中引入 ADR 时:
node /path/to/adr-skill/scripts/bootstrap_adr.js
这将创建目录、索引文件和一份填写好的第一条 ADR(“采用架构决策记录”),其中包含真实内容,解释为什么团队使用 ADR。使用 --json 获取机器可读输出。使用 --dir 覆盖目录名称。
分类(大型项目)
对于有许多 ADR 的仓库,按子目录组织:
docs/decisions/
backend/
2025-06-15-use-...
frontend/
...
cross-cutting/
...
如果 new_adr.js 脚本支持,使用 --dir backend 生成时将其放入子目录。否则手动组织。在所有子目录中保持单一索引(在根目录中列出所有 ADR 的排序列表)以保持可发现性。
审查代码注释
扫描代码库以查找可能应该成为 ADR 或引用现有 ADR 的注释。查找模式:
- “这是因为...”——可能的决策意图
- “我们正在使用 X 而不是 Y...”——明显的决策被埋没
- TODO 解释他们为什么做出选择
将这些标记给人类,并询问是否要捕获为 ADR 或链接到现有 ADR。
删除 ADR
不要物理删除 ADR 文件。ADR 提供了审计轨迹。相反,将其状态设置为 deprecated 或 superseded。
例外:如果在人类确认后创建了草稿 ADR 但从未接受,可以使用 scripts/set_adr_status.js --purge 删除。在草稿状态下有多个陈旧 ADR 会污染索引并使真实的决策难以找到。
配置
此技能支持通过 SKILL.md 中的 YAML 前置元数据或通过由 scripts/ 中的脚本管理的 .adr-config 文件进行配置。
环境变量:
ADR_DIR:覆盖 ADR 目录路径(例如,ADR_DIR=docs/adr)。ADR_TEMPLATE:覆盖默认模板路径(例如,ADR_TEMPLATE=custom-template.md)。ADR_STRICT:设置为true以在复核失败时阻止最终确定(除非显式解除)。
脚本:
scripts/new_adr.js:使用可选的--dir、--template、--update-index、--json标志创建新的 ADR。scripts/set_adr_status.js:更新现有 ADR 的状态。支持--purge用于草稿 ADR。scripts/bootstrap_adr.js:使用初始 ADR 和索引引导新仓库。
参考
- 模板:
assets/templates/(对于简单决策使用adr-simple.md,对于结构化选项使用adr-madr.md) - 模板比较:
references/template-variants.md - 智能体准备就绪清单:
references/review-checklist.md