关于 decisions-to-specs
decisions-to-specs 是一项工作流技能,用于将已解决的 GitHub 决策 issue 整理为仓库中的持久规格文件。它协助把决策分配到现有规格、新规格或 ADR,并在专用 worktree 中提交更改、创建 PR,同时将讨论记录与规格分开管理。
主要功能
- 01将决策分配到现有规格、新规格或 ADR
- 02写入前确认文件目标位置
- 03在专用 worktree 中修改仓库
- 04提交更改并创建拉取请求
- 05为源 issue 标记已取代
- 06在地图中更新规格交接信息
适用场景
- 01将已解决的 wayfinder issue 转为仓库规格
- 02避免重复并更新现有规格
- 03将复杂权衡记录为 ADR
- 04为后续生成工单准备规格
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mtngtools/ agents --skill decisions-to-specs安装后在 Claude Code 中输入/decisions-to-specs确认已加载。
详细介绍
决策 → 规格说明
仅限人工操作。 只有在人类明确点名要求时才启动此流程。如果你是从另一个技能来到这里,请停止,并在执行任何步骤前取得明确确认。
/wayfinder 将决策记录为 GitHub issue——记录当时的对话。这些 issue 是记录,而非决策的归属之处。此技能将 wayfinder 地图中的已解决决策落实为仓库中的持久规格说明文件,让下一步 /specs-to-tickets 有具体内容可供拆分。
从 GitHub 读取决策;将规格说明写入仓库。这两个界面有意保持分离(参见分离界面)。此技能只是桥梁——也仅仅是桥梁——绝不会创建 issue,也不会把规格说明移到跟踪器上。
在独立工作树中写入仓库。 其他会话共享主检出目录,而此技能会编辑整个目录树中的规格说明。在共享检出目录中工作,会将只写了一半的规格说明放进别人的构建中,或在别人工作时切换分支。以下所有仓库写入操作,都在此技能创建的独立工作树和专属分支中进行——参见步骤 4。步骤 1–3 只读取 GitHub 和目录树,可在任何位置安全执行。
落实决策后,其票据即被取代。 issue 是某次对话的快照;此后,决策归属于规格说明,后续决策、评审和实现只会完善规格说明。因此,几个月后再读决策票据时,它很可能已经过时,所以步骤 8 会在每张票据上添加指向对应规格说明的已取代横幅。issue 保持关闭状态,作为决策依据的追溯记录;/specs-to-tickets 会从规格说明中拆分出实现票据。
审批记录在跟踪器上,而不是规格说明中。 如果人类在此技能运行期间确定了某事项——例如需要审核的名称、规格说明的存放位置,或决定舍弃某项内容——请遵循 approval-policy 技能,了解应将记录写在哪里。规格说明保留由此产生的规则;谁批准、何时批准,以及该决策取代了什么,属于决策票据或地图。ADR 的备选方案讨论部分是目录树中唯一记录备选方案的地方,且只将其作为决策记录,而不记录对话过程。
流程
1. 加载地图及其决策
根据参数解析地图(issue URL 或编号)。如果未提供,则查找标有 wayfinder:map 的开放 issue。阅读其正文中的 Destination 和 Decisions so far。对于列出的每项决策,获取其子票据,并阅读 /wayfinder 在关闭时记录的答案——即解决说明。
完成标准: 已掌握 Decisions-so-far 中每项已解决决策的答案。没有持久影响的决策(死胡同、明确的“无需更改”)应附注后舍弃,而不是强行写入规格说明。
2. 梳理现有规格说明
开始写入前,先了解规格说明已有的存放位置,确保决策能够更新现有内容,而非重复创建:
- 软件包/程序集的
spec/文件夹(以及任何位于更靠近代码位置的规格说明) - 根目录下的
spec/——跨领域规格说明 spec/adr/——现有 ADR(ADR 文件夹是spec/文件夹的子文件夹,位于负责该决策的spec/作用域中)
阅读 CONTEXT.md 以及涉及这些决策影响范围的任何 ADR。撰写所有内容时使用词汇表中的术语;如果某项决策与 ADR 冲突,应明确指出,而不是悄悄覆盖。
完成标准: 对于每项决策,都能指出对应的规格说明文件,或说明目前尚无此文件。
3. 为每项决策确定去向——写入前确认
应用归属规则,为每项决策确定归属:要更新的现有规范、要新建的规范,或 ADR。“如果合适,就放在离代码更近的地方”需要斟酌判断——请完整列出路由表(决策 → 目标文件 → 新建/更新),并在写入任何文件之前征得用户确认。
**完成标准:**用户已批准每项决策的目标。
4. 写入前先切换到 worktree
从这里开始,所有会修改仓库的操作都必须在此技能专属的 worktree 中进行,该 worktree 需从远程仓库全新创建——绝不可在主检出目录中操作,也绝不可直接操作 main:
git fetch origin
git worktree add <worktree-path> -b docs/specs-<map-number> origin/main
将其放在仓库内,而不是旁边,并以地图命名。 将会话移到项目外的目录,通常需要人类单独批准,这与任何工具权限都无关,只会多出一道提示。在工作目录内使用路径即可完全避免此事。遵循仓库现有的分支和 worktree 命名方式,并以地图命名二者,以便清楚识别其归属。
如果你使用 Claude Code——使用 .claude/worktrees/specs-<map-number>,即该运行环境专用的 worktree 目录,这样就无需信任任何新路径。使用 EnterWorktree 并传入 path 参数进入该目录;这要求该 worktree 已出现在 git worktree list 中,因此要按上述顺序操作。
其他 Agent——使用工具已忽略的仓库本地目录;.worktrees/specs-<map-number> 是安全的默认选项,而 .git/info/exclude 会将其隐藏,无需修改受跟踪的 .gitignore。然后,通过运行环境提供的任意机制,将该目录设为下文所有写入操作的工作目录。如果无法切换目录,请显式传入路径(git -C <worktree-path> …),以免误写入主检出目录。
如果获取远程内容后,基线已超出你在步骤 2 中阅读的版本,请在此重新阅读规范全貌——你实际写入的是 worktree,而不是主检出目录。
有些运行环境会限制在 worktree 中使用 shell 重定向。如果 heredoc 或 > 被拒绝,请改用文件写入工具和单一用途的简单命令,不要与限制较劲。
**完成标准:**会话位于新分支上的干净 worktree 中,从这里开始的所有写入都落在该目录中。
5. 编写和更新
- **更新现有规范:**将决策融入相关章节。不要复述对话——问题单记录原因,规范记录已确定的决策。
- **新建规范:**采用新规范结构,以便
/to-tickets以相同方式处理。 - **ADR:**采用 ADR 结构。
每项决策都必须链接回其来源 GitHub 问题单——规范说明的是 做什么,问题单说明的是 为什么做出该决定。
**完成标准:**步骤 3 中路由的每项决策都已反映在 worktree 的文件中。
6. 使用 /concise-copy 精简内容
对你修改的每个文件运行 /concise-copy。规范会被反复阅读,因此要精简篇幅。
7. 提交规格并创建 PR
规格只存在于当前会话可见的工作树中时,还不能算定稿。使用 /draft-commit-message 起草提交消息;提交规范由它负责——请遵循它的要求,不要在此重复其格式。
提供它无法自行判断的信息:涉及哪些议题,以及每个议题与本次提交的关系。
- 映射议题是这项工作的归属工单。
- 决策议题是相关文件的详细依据。
- 不要关闭其中任何议题。
/wayfinder已在相关讨论结束时关闭决策议题,而映射议题会保持开放,直到/specs-to-tickets将这些规格拆分为工单。
然后在工作树中提交,推送分支,并针对 main 创建 PR。
此技能绝不执行合并。 /squash-merge-and-clean-up 会合并 PR 并移除分支和工作树;在它运行前,请保留两者。
**完成条件:**第 5 步写入的每个文件都已提交到此技能的分支,且 PR 已创建。
8. 将每个决策工单标记为已被取代
返回每个为规格提供依据的决策议题,并在其正文开头添加以下横幅;如果重新运行,则替换已有横幅:
> **Superseded by spec — do not build from this ticket.**
> This decision now lives in `src/<Package>/spec/<feature>.md`, which is the source of truth and has almost certainly moved on since this was written. Below is *why* the decision was made; build from the spec.
列出该决策议题所支撑的每个规格。第 1 步中被舍弃的决策不添加横幅——没有内容取代它。
**完成条件:**第 3 步中分派的每个决策议题都带有横幅,并列出其规格文件。
9. 更新映射议题,然后汇报
将工作概述写回映射议题正文中的 ## Specs settled 标题下(参见约定)。这是下一步 /specs-to-tickets 将读取的持久指引;映射议题仍是展示工作进展唯一的地方。
然后向用户汇报:内容写入了哪些位置、规格所在的 PR、哪些决策议题已添加标记,以及 PR 合并后接下来要运行 /specs-to-tickets <map>。
**完成条件:**映射议题中包含 ## Specs settled 部分,并列出第 5 步写入的每个文件。
映射议题的 Specs-settled 部分
交接给 /specs-to-tickets 的内容。将其写入映射议题正文(如果没有该标题则新建;重新运行时则更新)。每个规格文件占一行——包含路径、处置方式,以及为其提供依据的决策议题:
## Specs settled
- `src/<Package>/spec/<feature>.md` — new — decisions: #12, #15
- `spec/<cross-cutting>.md` — updated — decisions: #13
- `src/<Package>/spec/adr/0003-<slug>.md` — ADR — decision: #14
处置方式为 new、updated 或 ADR。ADR 行也要记录,但需标明,以便下一步知道不要将其拆分为工单。
文件放置规则(局部性阶梯)
优先选择能够完整涵盖该决策的最小作用域:
- 包/程序集的
spec/——决策仅影响一个包。若更适合,也可以放得更靠近代码(例如模块旁边)。 - 根目录的
spec/——跨领域:涉及多个包,或影响系统整体结构。 spec/adr/(ADR)——当决策难以撤销、缺少背景信息时出人意料,且源于真实的权衡取舍(三项都符合 Matt 的 ADR 标准)。少于三项则不是 ADR。ADR 文件夹嵌套在与决策作用域相同的spec/下:包级 ADR 放在<package>/spec/adr/,跨领域 ADR 放在根目录的spec/adr/。
**规格与 ADR:**规格描述要构建什么;ADR 记录某项决策及其依据。同一个决策可以同时产出两者——ADR 说明“为什么”,规格说明“是什么”——但只有在两者各自都足够重要时才拆分。
新规格的结构
仿照 /to-spec 的模板,以便 /to-tickets 能以相同方式读取。删去决策衍生规格不需要的部分:
- 问题陈述——从用户角度描述
- 解决方案——从用户角度描述
- 用户故事——
As an <actor>, I want <feature>, so that <benefit> - 实现决策——模块、接口、契约、架构(不含文件路径或代码)
- 测试决策——边界,以及良好测试应覆盖的内容
- 范围之外
ADR 结构
遵循套件的 ADR 格式:在所属范围内使用带编号的 spec/adr/NNNN-slug.md(扫描该文件夹,找到最大编号并递增)。标题 + 1–3 句话:背景、决策及原因。只有确有必要时才添加 Status / Consequences。ADR 可以只有一段——它的价值在于记录 做出了 什么决策,以及 原因。
分离界面
GitHub 用于保存讨论(wayfinder 映射 + 决策 issue),之后也用于保存实现任务。仓库用于保存规范。将两者分开正是目的:记录不会让仓库变得臃肿,规范也不会埋没在 issue 跟踪器中。
在流程中的位置
/wayfinder → GitHub 决策 issue(已关闭、注明理由、标记为已取代)→ /decisions-to-specs → 工作树分支上的仓库规范文件,作为 PR 提交(并在映射中添加 ## Specs settled)→ /squash-merge-and-clean-up → /specs-to-tickets → /to-tickets → GitHub 实现任务(新建,与决策 issue 相互独立)→ /implement。
可选:将最后一步写入 wayfinder 映射的 ## Notes——"路线明确后,运行 /decisions-to-specs"——或者在决策积累到足以敲定时手动运行。