关于 record-a-decision
record-a-decision 是用于在项目 decisions/ 目录编写架构决策记录(ADR)的技能。它引导团队确认决策已定,再记录背景、备选方案、后果及相关记录链接。
主要功能
- 01确认决策已经确定
- 02搜索现有记录以发现冲突
- 03按模板创建编号 ADR
- 04记录背景、选择和后果
- 05维护取代关系并验证记录
适用场景
- 01记录已获接受的技术选择
- 02取代旧决策并保留其历史
- 03将 ADR 与提案及实现规范关联
MCP 相关
该技能依赖平台的 /open-knowledge 技能执行 Markdown 操作,并使用其 search、exec、write、edit、links 和 audit 工具创建及验证 ADR。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ inkeep/ open-knowledge-skills --skill record-a-decision安装后在 Claude Code 中输入/record-a-decision确认已加载。
详细介绍
记录一项决策 — 在 decisions/ 下编写 ADR
平台 /open-knowledge 技能仍负责此处所有 Markdown 操作(依据、链接,以及 OK 的 MCP 工具负责其范围内的 Markdown 的规则);本技能则在此基础上补充 ADR 的编写规范。
架构决策记录是一份简短、注明日期且定稿的文档,用来记录一项决策、促成这项决策的因素,以及团队现在必须接受的后果。其价值会随着时间不断累积:三年后加入的读者,不仅应该明白做出了什么决定,还应该明白为什么当时需要考虑这个问题。ADR 一经接受便会定稿——若要改变主意,绝不改写旧记录,而是用一份新记录取而代之,并保留旧记录作为历史。这样的取代链,才是诚实的决策日志与一堆过时观点之间的区别。
文件名格式为 NNNN-title.md(4 位数字的零填充序号 + kebab 标题)。状态词汇:proposed / accepted / deprecated / superseded。模板 ID 为 decision,正文必须依次包含 ## Context、## Decision、## Consequences 三个章节。
第 0 步 — 确认确实已经做出决策(硬性门槛)
ADR 记录决策;它不会替人做出决策。 在做其他事之前,先确认已经做出选择。
- 如果用户仍在权衡选项、比较方案,或询问“我们应该选 X 还是 Y?”——他们还没有做出决策。停止并引导他们使用
/frame-a-proposal技能。 提案用于探索和讨论选项;ADR 则用于记录已经确定的结果。记录用户尚未做出的决策,会产生一份虚假的记录,误导未来的每一位读者。 - 如果用户说“我们决定选 X”,但你无法判断哪些选项落选或为什么选它,就问一个问题:“有哪些备选方案?是什么让你们选了这个方案?”没有被否决选项的 ADR 只是宣传稿,不是记录。
- 如果问题在于设计本身是否可靠——而不是如何记录设计——则转交给
/review-a-design。本技能假设决策本身是可靠的;它只负责记录。
在用户确认具体决策之前,不要越过这道门槛。用一句话复述决策,并请用户确认。
第 1 步 — 检索已有记录(写入前指出可能被取代的记录)
新的 ADR 若悄然与已接受的记录相矛盾,决策日志就会逐渐腐坏。分配序号之前,先查找已有记录。
search({ query: "<subsystem or topic of the decision>" })— 通过语义搜索,查找相关决策、提案和规范。exec("ls -A decisions/")— 查看现有序号和标题。exec("grep -rln <subsystem-keyword> decisions/")— 查找涉及同一子系统、接口或约束的记录。- 对每条可能相关的记录,执行
exec("cat decisions/NNNN-x.md")— 阅读其中的 Decision 和 Status。
然后先对记录进行分类,并在写入前告知用户:
- 与已接受的记录相矛盾 → 这项新决策会撤销或替代旧决策。将该路径标记为
supersedes:候选项:“这看起来会取代 0007-use-rest-api,该记录当前状态为accepted。请确认;确认后我会在第 7 步补上关联链。”不要悄然写入相矛盾的记录。 - 扩展但不矛盾 → 记下相关记录;之后会链接它,而不是取代它。
- 确属新决策 → 继续。
如果这项决策是从 proposals/ 中已接受的提案发展而来,现在就找到该提案(exec("grep -rln <topic> proposals/"))——第 4 步会将它作为上级提案链接。
步骤 2 — 分配下一个编号并从模板创建
切勿猜测序列号。 列出文件夹并取下一个整数。
exec("ls -A decisions/")— 读取现有的最大NNNN。- 下一个编号 = 最大编号 + 1,补零至 4 位。首个决策编号为
0001。 - 选一个简短的 kebab 标题来命名决策,而非主题:
0012-adopt-event-sourcing-for-orders,而不是0012-orders。 - 从模板创建:
write({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md", template: "decision" } })
模板提供了 frontmatter 框架和三个 H2 章节。现在填写 frontmatter:
type: decision
description: "One line: the decision, active voice."
status: proposed # proposed until the deciders accept; then accepted
date: YYYY-MM-DD # today
deciders: [<user>] # who owns this decision
supersedes: [] # fill in Step 7 if this replaces an earlier record
tags: [decision]
起草时将 status: proposed 保持不变。只有在决策者批准后(步骤 8)才将其改为 accepted——在任何人同意之前就将 ADR 标为 accepted 并发布,属于追溯篡改。
步骤 3 — 背景:当前面临的各种因素(在此投入精力)
## Context 是最经得起时间考验的章节。请这样撰写,让三年后的读者无需参加会议、查看讨论串或依靠你的记忆,也能明白为什么当时会提出这个问题。涵盖:
- 决策被迫作出时系统的状态——已有些什么,哪些方面承受着压力。
- 发生了什么变化,使得现在必须作出选择,而不能一直搁置。新需求、触及扩展上限、依赖项弃用、截止日期。
- 限制选项范围的约束——团队规模、现有技术、延迟预算、合规要求、硬性日期。
- 相互冲突的因素——让这成为一个决策而不是显而易见的选择的原因。如果没有相互竞争的压力,就没什么需要记录。
以中立、客观的方式撰写。不要在此为决策辩护——那是步骤 4 的任务。背景应完整描述问题,让决策看起来是对问题的一种合理回应。如果读者读完背景仍看不出为什么需要作出选择,那这一章节就不合格;请重写。
每项有关系统的事实主张都应以可核查的内容为依据——链接提案、规范或先前的决策,而不是凭记忆断言。
步骤 4 — 决策:主动语态、一段话、明确无歧义
## Decision 用主动语态、现在时或将来时说明将采取的行动:“我们将……” 写成一段清晰的话。读者读完后必须毫无歧义地确切知道选择了什么。
然后,简要说明:
- 列出评估过的选项,并说明其他选项为何落选。 每个被否决的选项用两三句话说明即可——“我们考虑过 X,但它无法满足延迟预算;Y 更简单,但会让我们被单一供应商锁定。”这是记录的核心;没有明确列出备选方案的决策无法核实。
- 如果该决策由上级提案演变而来,请链接上级提案:“此决策接受了 0004-orders-rearchitecture-proposal。”使用普通的 Markdown 相对链接,不要加反引号,也不要使用 HTML 锚点。
不要把实现细节塞进决策章节——如何构建应写在规范中,而不是 ADR 中。决策应说明做什么以及为什么,而不是迁移步骤。
第 5 步 — 后果:坦诚地说明正反两面
## Consequences 记录团队现在需要面对的情况——好的和坏的。只写好处的后果部分是营销文案,不是 ADR。按适合的分组方式涵盖以下内容:
- 哪些事情变容易了 — 推动团队做出这一选择的收益。
- 哪些事情变难了 — 代价、新增的复杂性,以及现在变得更棘手的事情。
- 团队承担了哪些新义务 — 持续维护、需要招聘具备的新技能、需要跟踪的依赖项,或现在必须由某人维护的不变量。
- 这排除了哪些选择 — 哪些选项不再能以低成本采用,哪些道路因此被关闭。
- 中性后果 — 既非收益也非损失,但未来读者需要了解的事实。
强迫自己至少写出一项真实的负面影响和一项新义务。如果想不出来,说明考虑得还不够深入——每个真正的决定都会有所代价。负面影响是记录中最有价值的部分;当这个决定开始带来麻烦时,未来的团队会检查这些内容。
第 6 步 — 正确性自检(提交前进行对抗性审查)
以反对该决定的怀疑者视角阅读草稿。诚实地回答每个问题,并修正发现的问题:
- 这是单向门还是可逆的决定? 是否说明了这个决定的可逆性?单向门(难以或代价高昂才能撤销)必须在“后果”中明确说明——这是未来读者接手时最需要了解的事情。
- 背景是否确实促成了该决定? 还是说决定来得毫无缘由,背景中的因素并未指向这个决定?如果这两个部分没有关联,其中一个就有问题。
- 持反对意见的读者能否看到对其异议的回应? 最有力的反对理由应当出现在某个地方——列为被否决的选项,或写成明确的后果。如果遗漏了显而易见的异议,就把它补上。
- 是否因为某项后果不便提及而将其隐瞒? 你最不愿写下的代价,恰恰是最应该记录的内容。
如果这轮检查发现受到质疑的是设计本身——而不是记录的质量,而是该决定是否正确——就停下来并交由 /review-a-design 处理。这项技能用于记录正确的决定,而不是重新争论某个决定。
第 7 步 — Supersedes 链(两个方向都要连好,否则链条就断了)
如果此记录取代了较早的记录,必须在两个方向上建立关联,否则日志就会从一侧产生误导。
- 向前,在新记录中: 将旧记录的路径添加到
supersedes:frontmatter 中。
edit({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md",
frontmatter: { supersedes: ["decisions/0007-use-rest-api.md"] } } })
- 向后,在旧记录中: 更改其状态,并添加一个指向新记录的链接,确保打开旧决定的读者能跳转到新记录。
edit({ document: { path: "decisions/0007-use-rest-api.md",
frontmatter: { status: "superseded" } } })
然后在旧记录的“背景”部分顶部附近添加一行(或者添加简短的 > Superseded by ... 说明):Superseded by [0012-adopt-event-sourcing-for-orders](./decisions/0012-adopt-event-sourcing-for-orders.md).
绝不要编辑旧记录中的“背景”“决定”或“后果”正文。 ADR 是冻结的——旧决定在做出时是成立的,并会作为历史记录保留。你要添加的是状态变更和指向新记录的链接,而不是改写旧记录的内容。两处修改都必须提交,否则链条会在一个方向上断开,日志也将失去可信度。
第 8 步 — 链接并验证
- **添加反向链接:**确保父提案链接到此决策,任何落实此决策的规范也链接回此决策。运行
links({ kind: "backlinks", document: "decisions/0012-adopt-event-sourcing-for-orders" })查看哪些文档指向此处;补上缺失的链接,确保此记录可被查到。 - 验证:
audit({ path: "decisions/0012-adopt-event-sourcing-for-orders.md" })应返回无问题(包括所有 lint 违规和失效的内部链接)——修复每一项问题;指向已取代记录的失效链接会破坏整个链条。 - **补全 Frontmatter:**确保
type、description、status、date、deciders、supersedes、tags均存在且正确。 - **状态反映实际情况:**如果决策者已接受,将
status: proposed改为accepted。如果尚未接受,则保留proposed,并告知用户此决策仍待签署。不要代替用户将决策标记为accepted。 - **正文结构:**严格按顺序使用
## Context、## Decision、## Consequences。不要添加其他顶级章节——不适合放入这三部分的详细内容应放在链接到的规范中。
第 9 步 — 向用户回顾
在对话中用以下三点收尾:
- 用一句话概述决策——即“We will ...”这一行。
- 最重要的后果——团队最需要记住的一项代价或义务,尤其是这是个单向决策时。
- 任何被取代的记录——指出旧 ADR,并确认双向链接均已建立。
然后说明 status 是 accepted(决策者已签署)还是 proposed(等待签署),让用户了解是否还有待处理事项。
非目标
- **不要代替用户做决定。**如果尚未做出决策,请转到
/frame-a-proposal。此技能负责记录,不负责选择。 - **不要重写已接受的记录。**ADR 一经定稿便不可更改。要更改过去的决策,请将其取代(第 7 步),并保留旧记录原样——绝不要编辑其中的 Context/Decision/Consequences 正文。
- **不要将实现细节纳入 ADR。**迁移计划、API 形态和发布步骤应放在规范中(
/write-a-spec)。ADR 记录是什么以及为什么,而不是如何实现。 - **不要记录缺少后果章节的决策。**只有好处,或没有代价和新增义务的记录,都不是 ADR,而是宣传。每项真正的决策都有代价;找出代价并写下来。
- **不要在此评判设计是否合理。**如果问题在于决策是否正确,而不是记录是否完善,请转到
/review-a-design。