mattpocock/skills 不是一组“让 AI 把代码写得更漂亮”的提示词,而是一套面向真实软件工程的工作流。它把需求澄清、外部调研、原型验证、规格沉淀、任务拆分、实现、审查和故障诊断连接起来,让一个复杂功能可以跨越多个会话继续推进。

如果是第一次接触这个项目,可以先记住三个答案:

  1. 它解决什么问题?

    它主要解决 AI 编程中最容易失控的部分:需求没有说清就开始写代码、长对话丢失上下文、任务拆得无法独立验收、实现偏离规格,以及复杂缺陷只能靠猜。

  2. 第一次应该安装哪些 Skill?

    使用 Claude Code 原生插件时直接安装整个插件即可。真正需要先学会的,是本文重点介绍的 10 个高频入口;grillingdomain-modelingtddcode-review 会由主流程在内部调用。

  3. 面对一个任务应该从哪个 Skill 开始?

    第一次在仓库中使用先运行 /setup-matt-pocock-skills;不知道如何选择流程时运行 /ask-matt;如果需求本身还不清楚,通常从 /grill-with-docs 开始,而不是直接 /implement

本文不逐项解释仓库中的所有 Skill。低频工具、作者个人工作流、开发中能力和已弃用能力并不是首次使用这套 Skills 的重点。下面只围绕最常用的 10 个 Skill,完成一个从模糊需求到上线前修复的完整案例。

一、先建立正确的使用模型

1. Skill 不是必须全部执行的流水线

这套 Skills 提供的是一组可以组合的工程阶段,而不是每个任务都必须走完的固定流程。

  • 改一处已经明确的文案,不需要先写规格。
  • 只有通过实际交互才能判断的界面问题,才值得制作原型。
  • 一个可以在单次会话内安全完成的小改动,通常不需要先拆成多个 Ticket。
  • 已经有稳定复现和明确原因的简单缺陷,不必启动完整的系统诊断。

真正重要的是:在信息不足时不要过早进入实现,在上下文过长时不要勉强留在同一会话,在任务较大时不要让一个 Agent 同时记住所有设计和代码细节。

2. 本文会用到的工程术语

这套 Skills 来自软件工程场景,其中一些英文词在日常语言中可能有不同含义。先明确本文的用法:

  • Agent(智能体):能够读取仓库、调用工具并完成编程任务的 AI,例如 Claude Code 中正在工作的 Claude。
  • Skill(技能):提供给 Agent 的一套可复用工作说明。它规定什么时候使用、按什么步骤执行以及应该产生什么结果,不等同于一个独立应用。
  • Issue Tracker(工作项跟踪系统):保存需求、缺陷和开发任务的地方,例如 GitHub Issues、GitLab Issues、Linear、Jira,或者项目中的本地 Markdown 文件。
  • Issue(工作项):Issue Tracker 中的一条记录。它可以记录一个缺陷、一份完整功能规格,也可以记录一项具体开发任务。
  • Ticket(任务单):从规格中拆出、准备交给开发者或 Agent 实施的工作单元。它应包含明确范围、验收标准和依赖关系。Ticket 不是某种固定文件格式:在 GitHub 中通常表现为一条 Issue,在 Linear 中是一个工作项,使用 Local Markdown 时则是一个 Markdown 文件。
  • Spec(规格,也常称 PRD):对“要解决什么问题、系统应该如何表现、如何验收以及哪些内容不做”的正式说明。它比一句需求描述更完整,但通常不包含容易过期的逐行代码方案。
  • ADR(Architecture Decision Record,架构决策记录):记录重要技术决策及其背景、备选方案和取舍理由的文档,用来回答“为什么当时这样设计”。
  • Test seam(测试接缝):测试能够从外部控制输入并观察结果的稳定边界,例如 API、领域服务或 Worker 入口。提前确认 seam,是为了避免测试只能依赖内部实现细节。
  • Queue、Job 与 Worker:Queue 是等待处理的任务队列;Job 是队列中的一项具体后台任务;Worker 是取出并执行 Job 的进程。本例使用 BullMQ 管理它们。
  • 幂等(Idempotency):同一个操作因为重试或并发被执行多次时,最终业务结果仍然只出现一次。例如 Worker 重试三次,用户也只能收到一条提醒。
  • Out of Scope(范围之外):本次规格明确不实现的内容。主动写出非目标,可以防止 Agent 在实现时顺手扩大需求。
  • 垂直切片(Vertical Slice):围绕一个很小但完整的用户行为,贯穿该行为所需的界面、API、数据、后台处理和测试。to-tickets 章节会用任务提醒案例详细说明。

后文第一次出现其他不常见术语时,也会结合当前步骤解释其具体含义。

3. 本文贯穿场景:TaskBoard 的任务到期提醒

假设我们正在维护一个名为 task-board 的任务管理应用。它包含 Web 前端、API 服务、PostgreSQL 数据库,以及使用 BullMQ 和 Redis 运行的后台任务。

产品只给出了一句话:

给任务增加到期提醒,用户可以在截止时间前收到通知。

这句话还不能直接实现。至少有以下问题尚未确定:

  • 通知通过站内消息、邮件还是短信发送?
  • 可以提前多久提醒?
  • 修改任务截止时间后,旧提醒如何处理?
  • 创建时已经过期的任务是否补发提醒?
  • Worker 重试时如何避免重复通知?
  • 第一个版本是否需要重复提醒、免打扰和时区设置?

接下来会看到,不同 Skill 的职责并不是“换一种方式继续问 AI”,而是分别消除这些问题中的不同风险。

4. 一条典型主流程

对于需要跨多个会话完成的功能,常见顺序是:

1
2
3
4
5
6
7
8
9
10
仓库初始化
→ 选择流程
→ 调研外部事实
→ 澄清需求与领域规则
→ 必要时制作一次性原型
→ 发布规格
→ 拆分垂直 Ticket
→ 在新会话中逐张实现
→ 遇到复杂缺陷时系统诊断
→ 上下文过长时交接

其中,调研和原型是按需分支;交接可以出现在任意阶段。

二、安装:Claude Code 为主,skills.sh 为辅

1. Claude Code 原生插件

在 Claude Code 中,先添加项目提供的插件市场,再安装插件:

1
2
/plugin marketplace add mattpocock/skills
/plugin install mattpocock-skills@mattpocock

安装完成后,进入实际项目目录并启动 Claude Code。本文中的调用都使用斜杠命令,例如:

1
/ask-matt 我准备给任务系统增加到期提醒,但需求还不完整,而且会跨前后端。

原生插件适合希望直接获得完整依赖关系和后续更新的使用者。某个主 Skill 需要 tddcode-review 时,插件能够提供对应的支撑能力,不需要手工复制提示词。

2. skills.sh:适合需要修改 Skill 的项目

如果希望把 Skill 安装为本地文件,以便阅读、定制或纳入自己的配置,可以使用:

1
npx skills@latest add mattpocock/skills

这种方式更适合以下情况:

  • 团队需要调整 Issue 模板、标签名称或文档路径;
  • 希望审查每个 SKILL.md 后再启用;
  • 需要把工作流固定在项目或个人的 Agent 配置中;
  • 准备基于原 Skill 派生自己的内部流程。

手工挑选 Skill 时,不要只复制 10 个入口文件而忽略依赖。本文涉及的内部支撑能力至少包括:

  • grillingdomain-modeling:支撑 grill-with-docs
  • tddcode-review:支撑 implement

3. Codex 兼容性

这些 Skill 使用的是通用的 Agent Skills 结构,也可以通过 skills.sh 安装到支持该结构的 Codex 环境。区别主要在调用方式:Claude Code 可以直接使用 /skill-name;在 Codex 中通常明确写出 Skill 名称和任务,例如“使用 research 调研 BullMQ 的 Job ID 规则”。本文后续仍以 Claude Code 的原生命令为准。

三、setup-matt-pocock-skills:让工作流认识当前仓库

setup-matt-pocock-skills 是一次性的仓库初始化入口。它不是安装命令,而是把这套通用工作流与当前项目的 Issue Tracker、领域文档和 Agent 说明连接起来。

什么时候使用

  • 第一次在某个仓库中使用这套 Skills;
  • 仓库还没有说明使用 GitHub Issues、Linear 还是本地文件管理工作;
  • 缺少统一的领域文档位置;
  • 安装了 triage,但 Agent 还不知道哪些标签表示“待分流”“缺少信息”或“可以交给 Agent”。

什么时候不需要使用

  • 同一仓库已经完成初始化,而且 Tracker、标签与文档约定没有改变;
  • 只是进入一个新会话继续工作;
  • 只想临时试用某个不依赖仓库约定的 Skill。

精确调用

task-board 仓库根目录启动 Claude Code,先单独发送:

1
/setup-matt-pocock-skills

发送后等待 Agent 开始初始化并询问 Issue Tracker、标签和文档位置,再把下面的配置作为下一条消息发送,不要与斜杠命令拼在同一条消息中:

1
2
3
4
5
这个项目使用 GitHub Issues。
如果已经安装 triage,请使用默认标签:
needs-triage、needs-info、ready-for-agent、ready-for-human 和 wontfix。
领域文档放在 docs/agents/domain.md。
仓库已经有 CLAUDE.md,请在现有内容上补充,不要覆盖。

这里的 triage 指“对新工作项进行分类并决定下一步”。默认标签的含义是:

  • needs-triage:尚未完成分类;
  • needs-info:缺少继续处理所需的信息;
  • ready-for-agent:范围已经清楚,可以交给 Agent 实施;
  • ready-for-human:需要人类判断或操作;
  • wontfix:确认不处理。

只有已经安装 triage Skill 时,初始化流程才需要配置这些标签。项目已有自己的标签体系时可以进行映射,不必创建含义重复的新标签。

Agent 接下来会做什么

它会先检查仓库当前约定,而不是假定所有项目都使用同一种工具。随后确认:

  1. 工作项记录在哪里;
  2. 如何创建、关联和关闭工作项;
  3. 使用哪些状态与分流标签;
  4. 领域知识保存在哪里;
  5. 应该把这些约定写入 CLAUDE.md 还是 AGENTS.md

会生成或修改什么

常见结果包括:

1
2
3
4
docs/agents/issue-tracker.md
docs/agents/domain.md
docs/agents/triage-labels.md # 仅在需要时创建
CLAUDE.md # 在现有内容上更新

对于示例项目,issue-tracker.md 应说明 GitHub Issues 的使用方式,domain.md 应先记录 Task、Due Date、Reminder 等核心术语。这里建立的是项目级约定,不是某一个功能的详细规格。

如果仓库已经有 CLAUDE.mdAGENTS.md,应先审查差异。初始化的目标是补充工作流入口,不是覆盖团队现有规范。

下一阶段

初始化只回答“如何在这个仓库工作”,不回答“当前需求该走什么流程”。下一步通常是 /ask-matt,或者在已经确认需求模糊时直接使用 /grill-with-docs

四、ask-matt:不知道从哪里开始时先做路由

ask-matt 是工作流路由器。它根据任务状态推荐接下来使用哪个 Skill,本身不会代替调研、写规格或实现。

什么时候使用

  • 知道自己要做什么,但不知道应该先调研、澄清、写规格还是实现;
  • 一个任务同时包含产品、架构和代码问题;
  • 不确定任务是否需要跨多个会话;
  • 刚接触这套 Skills,希望避免选错入口。

什么时候不需要使用

  • 已经知道下一步,例如外部 API 行为不确定,明确需要 /research
  • 只是执行既有 Ticket,直接 /implement <Issue> 即可;
  • 正在按照上一阶段给出的明确下一步继续工作。

精确调用

1
/ask-matt 我准备给 task-board 增加任务到期提醒。需求还不完整,预计会修改 Web 前端、API、数据库和 BullMQ Worker,可能需要多个会话完成。我应该从哪个流程开始?

Agent 接下来会做什么

ask-matt 会判断任务目前缺少的是哪类信息。例如:

  • 需求语义不清楚:推荐 grill-with-docs
  • 关键实现依赖第三方工具行为:先执行 research
  • 只能通过交互体验决定:插入 prototype
  • 需求已确定但工作量较大:进入 to-specto-tickets
  • 已有明确、可执行的 Ticket:进入 implement
  • 是难以定位的缺陷:使用 diagnosing-bugs

在这个场景中,一个合理的路由结果是:

1
2
3
4
先 research BullMQ 的调度与重试语义
→ 再 grill-with-docs 确认产品和领域规则
→ 如提醒选择器仍有交互分歧,再 prototype
→ 最后 to-spec → to-tickets → implement

会生成或修改什么

通常不会修改源码、文档或远程 Issue。它的主要产物是一条带理由的推荐路径。

这也是理解它的关键:如果 /ask-matt 已经开始替你实现功能,就超出了路由器的职责。

下一阶段

按照推荐结果进入最先需要的阶段。本例先调研 BullMQ 的官方行为,因此下一步是 /research

五、research:先把外部事实查清,再做内部决策

research 用于调查仓库之外的事实,例如框架行为、API 限制、协议规范和公开实现。如果 Claude Code 已启用网页搜索或网页读取工具,并且当前网络可用,Agent 会主动访问互联网查找资料,不需要使用者提前收集所有链接。它会优先使用官方文档、官方仓库、标准文本和论文等一手资料,再把带引用的结论写回仓库。

需要注意,research 只是规定调研方法,并不会凭空为 Claude Code 增加网络能力。实际能否联网取决于当前环境:

  • Claude Code 可以使用 WebSearchWebFetch 等工具时,Agent 会自行搜索和打开网页;
  • 工具调用触发权限确认时,需要允许本次网页访问;
  • 当前环境不能联网时,Agent 应明确报告限制,改用使用者提供的资料或仓库中的现有文档;
  • 没有实际读取来源时,Agent 不能把模型记忆包装成“已经查阅官方文档”的结论。

什么时候使用

  • 实现依赖第三方库的具体语义;
  • 团队对框架行为存在不同记忆;
  • 设计决策必须建立在官方限制之上;
  • 需要让后续会话复用调研结果,而不是重复搜索。

什么时候不需要使用

  • 答案可以直接从当前仓库代码、测试或配置中确定;
  • 这是产品偏好,而不是外部事实;
  • 只需要确认一个简单且稳定的本地类型定义;
  • 已有近期、可信并且可追溯的项目调研文档。

精确调用

research 是带任务参数的命令。与需要先启动、再等待提问的 /setup-matt-pocock-skills 不同,应该把 /research 和完整的调研要求写在同一条消息中发送:

1
2
3
4
5
6
7
/research 调研 task-board 使用 BullMQ 实现任务到期提醒时必须确认的官方行为:
1. delayed job 的执行时间语义;
2. attempts 与 backoff 如何触发重试;
3. 自定义 Job ID 的唯一性、重复任务行为和字符限制;
4. 任务截止时间修改后,旧 delayed job 的移除或重新调度方式;
5. Worker 在外部通知已经成功、但任务确认失败时的重复执行风险。
只使用 BullMQ 官方文档和官方仓库等一手资料。将带引用的结论写入仓库中的一份 Markdown 文件,并区分“官方事实”和“对本项目的设计建议”。

发送后,Agent 会自行搜索 BullMQ 官方网站和官方 GitHub 仓库。除非它遇到网页访问权限、登录限制或无法确认的问题,否则不需要再逐条告诉它应该打开哪些页面。如果希望进一步限制资料范围,也可以在命令中直接附上允许使用的链接或域名。

Agent 接下来会做什么

该 Skill 通常会启动独立的调研过程,搜索并比较一手资料,然后完成以下工作:

  1. 将问题拆成可以验证的子问题;
  2. 为每条事实找到直接来源;
  3. 区分文档明确保证的行为与根据资料做出的工程推论;
  4. 标记仍然无法确认的部分;
  5. 形成一份后续规格可以引用的调研文档。

这里必须避免一个常见错误:把“我们准备怎么设计”写成“BullMQ 本来就是这样”。例如,使用稳定 Job ID 避免重复入队是项目方案;Job ID 的去重范围和字符限制才是需要从官方资料确认的事实。

会生成或修改什么

应生成一份有明确主题的 Markdown 文档,例如:

1
docs/research/bullmq-task-reminders.md

内容可以采用以下结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# BullMQ 任务提醒调研

## 已确认的官方行为
- delayed job ...
- attempts/backoff ...
- custom Job ID ...

## 对 task-board 的影响
- 调度延迟不能被当作精确到秒的定时器
- 通知发送需要业务级幂等记录

## 尚待确认
- 当前项目使用的 BullMQ 版本是否支持计划采用的重新调度方法

## 参考资料
- 官方文档链接

它不会直接改业务代码,也不应该在调研阶段擅自确定通知渠道等产品规则。

下一阶段

外部约束明确后,使用 /grill-with-docs 澄清产品语义,并把最终决定写入领域上下文。

六、grill-with-docs:通过提问把模糊需求变成可执行决策

grill-with-docs 是需求澄清的主入口。它不只是进行一轮访谈,还会通过内部的 grillingdomain-modeling,将已确认的规则持续写入 CONTEXT.md 和必要的 ADR。

什么时候使用

  • 需求只有一句目标描述;
  • 多种解释都会产生合理但不同的实现;
  • 领域术语、边界条件或失败语义尚未统一;
  • 需要在写规格前确认什么属于首个版本。

什么时候不需要使用

  • 已有经过确认且足够具体的规格;
  • 修改是机械性的,没有产品或领域歧义;
  • 当前问题只是第三方行为未知,应先使用 research
  • 只是需要在已有 Ticket 上执行实现。

精确调用

1
/grill-with-docs 我们要为 task-board 增加任务到期提醒。当前只有一句需求:“用户可以在任务截止时间前收到通知”。请结合 docs/research/bullmq-task-reminders.md,逐个澄清通知渠道、提前时间、任务改期、取消截止时间、创建时已过期、重复提醒和 Worker 重试的语义。把确认后的领域规则维护到项目文档中,不要开始实现。

Agent 接下来会做什么

这个 Skill 内部组合了两个支撑能力。

grilling:一次只解决一个关键问题

grilling 不会一次抛出二十个问题让使用者填表。它会优先选择当前最影响设计的问题,一次提问一个,并通常给出推荐答案和理由。

例如第一问可能是:

1
2
3
4
5
首个版本使用哪种通知渠道?

建议:只支持站内通知。
原因:邮件和短信会引入供应商、投递状态、退订与成本问题,
这些都不是验证“到期提醒”核心价值所必需的。

确定渠道后,再继续确认提前时间:

1
2
3
4
首个版本是否允许任意分钟数?

建议:先提供 10 分钟、30 分钟、1 天三个预设值。
原因:可以覆盖主要场景,同时避免自由输入、上下限和复杂校验扩大范围。

在完整访谈后,本例可能得到以下规则:

  • V1 只发送站内通知;
  • 提供提前 10 分钟、30 分钟和 1 天三个选项;
  • 没有截止时间的任务不能启用提醒;
  • 修改截止时间或提前量时,旧计划失效并建立新计划;
  • 移除截止时间或关闭提醒时,取消尚未触发的计划;
  • 创建或修改时已经错过提醒时间,不补发历史提醒;
  • 同一个“任务 + 截止时间版本”最多产生一条业务通知;
  • Queue 重试不能让用户收到重复通知;
  • V1 不包含邮件、短信、重复提醒、免打扰和用户自定义提前量。

这些答案不是 Skill 自动替产品负责人决定的。Agent 会给出建议,但关键选择仍应由拥有产品上下文的人确认。

domain-modeling:让答案进入长期上下文

访谈中已经确认的稳定概念会被及时写入 CONTEXT.md 或项目指定的领域文档,而不是等对话结束后依靠记忆整理。

例如:

1
2
3
4
5
6
7
8
## Reminder

A Reminder schedules one in-app notification for a Task due-date version.

- A Task without `dueAt` cannot enable a Reminder.
- Changing `dueAt` invalidates the previous Reminder schedule.
- A missed reminder time is not delivered retroactively.
- Delivery is idempotent per Task due-date version.

如果某项决定同时满足以下条件,才值得记录为 ADR:

  1. 难以轻易撤销;
  2. 对不了解背景的人并不显然;
  3. 存在真实的方案权衡。

例如“为什么除了稳定 Queue Job ID 之外,还需要数据库中的通知幂等记录”可能值得写成 ADR,因为外部发送成功与 Queue 确认失败之间存在跨系统边界。相反,“按钮放在表单右侧”不应该成为架构决策记录。

会生成或修改什么

根据仓库约定,可能更新:

1
2
3
CONTEXT.md
docs/agents/domain.md
docs/decisions/ADR-00x-reminder-delivery-idempotency.md

它不会生成实现代码,也不会直接发布正式规格。访谈结束时应得到“共同理解”,而不是一堆仍然互相冲突的聊天记录。

下一阶段

  • 如果某个交互只有实际体验后才能决定,进入可选的 /prototype
  • 如果关键规则已经确认,直接使用 /to-spec

七、prototype:只有必须体验才能决定时才使用

prototype 用最少代码回答一个具体设计问题。它产生的是一次性实验,不是生产实现的开端。

在本例中,领域规则已经确定了三个提醒预设值,但团队仍无法仅凭文字判断选择器应该放在哪里、采用什么交互。这个问题适合原型验证。

什么时候使用

  • 只有实际点击、输入或观察运行结果才能做决定;
  • 两到三个 UI 方案都合理,讨论无法继续收敛;
  • 某项技术可行性需要用最小实验验证;
  • 结论的价值高于一次性代码的成本。

什么时候不需要使用

  • 通过文档、代码阅读或简单讨论就能回答;
  • 产品规则尚未澄清,原型目标仍在变化;
  • 已有明确设计稿和验收标准;
  • 只是希望“先写一点生产代码看看”,这会混淆实验与实现。

精确调用

建议先切换到一次性分支,再调用:

1
2
3
4
5
/prototype 为 task-board 的任务编辑表单制作三个可切换的一次性 UI 方案,用来比较提醒时间选择器:
A. 截止时间下方的内联 Select;
B. “启用提醒”后展开的设置区;
C. 单独的 Reminder Popover。
三个方案使用相同的 10 分钟、30 分钟、1 天选项。提供一个运行命令,并允许通过 URL 查询参数切换方案。不要接数据库、不要写完整测试、不要进行生产级抽象。

Agent 接下来会做什么

它会先把问题限制为“哪种提醒选择器最容易理解”,然后只实现回答这个问题所需的界面:

  • 复用最少的项目基础设施;
  • 使用固定的示例任务数据;
  • 让三个方案可以快速并排或切换比较;
  • 提供一条本地运行命令;
  • 记录观察结果与最终选择。

原型不应扩展为完整功能。持久化、权限、无障碍细节、完整错误处理和长期测试,除非它们正是要验证的问题,否则都应留到正式实现。

会生成或修改什么

它会产生临时原型代码和一份结论。推荐在 throwaway 分支中完成,例如:

1
codex/reminder-picker-prototype

验证后保留的应该是决策,而不是原型代码。这里的 throwaway branch 指“只用于实验、验证结束后不合并的临时分支”。例如:

1
2
3
4
5
6
选择方案 B:启用提醒后展开设置区。

原因:
- 未启用提醒时不增加表单噪声;
- 截止时间与提醒设置仍处于同一编辑上下文;
- 移除截止时间时,提醒不可用状态更容易解释。

不要把实验分支直接合并到主分支。正式实现应该根据规格重新完成,避免把为了快速验证而省略的边界处理带入生产代码。

下一阶段

把原型结论带回主工作分支,然后运行 /to-spec。如果原型对话已经很长,可以先使用 /handoff 将结论交给一个干净会话。

八、to-spec:把共同理解发布成稳定规格

to-spec 将已经完成的调研、访谈和原型结论整理为可以被后续 Agent 独立读取的规格。它不是新的需求访谈,因此调用前应先解决关键歧义。

是否一定会创建远程 GitHub Issue

不一定。to-spec 的固定目标是“把规格发布到当前项目配置的 Issue Tracker”,但这个 Tracker 不一定是 GitHub。/setup-matt-pocock-skills 会把选择记录在 docs/agents/issue-tracker.md,后续 Skill 根据该文件决定发布位置:

  • 配置为 GitHub:创建远程 GitHub Issue;
  • 配置为 GitLab:创建远程 GitLab Issue;
  • 配置为 Linear、Jira 等其他平台:按照项目记录的工作流发布;
  • 配置为 Local Markdown:只在本地写入 Markdown 工作项,不访问远程 Tracker。

本文的 task-board 场景在初始化阶段明确选择了 GitHub Issues,所以后面的 #142 才代表远程 GitHub Issue。这是本例的配置结果,不是 to-spec 对所有项目都固定执行的行为。

如果项目配置的是 GitHub,但当前只想审阅草稿、不希望立刻创建远程 Issue,可以在调用中明确增加:

1
先在对话中展示完整规格草稿,得到我确认后再发布到 Issue Tracker。

什么时候使用

  • 功能需要多个会话或多张 Ticket 才能完成;
  • 需要将聊天中的决定转化为稳定、可引用的工作项;
  • 参与实现的人不一定经历了前面的讨论;
  • 希望在拆票前冻结范围、验收方式与非目标。

什么时候不需要使用

  • 改动足够小,可以在一个会话内完成并验证;
  • 关键需求仍未确认,应返回 grill-with-docs
  • 只是调查问题,还没有计划进入实现;
  • 已经存在内容充分且仍然有效的规格。

精确调用

1
/to-spec 将当前关于 task-board“任务到期提醒”的已确认上下文整理为规格。引用 docs/research/bullmq-task-reminders.md、领域文档和提醒选择器原型结论。规格必须包含用户故事、领域规则、实现决策、测试 seam、验收标准、失败语义和 Out of Scope。先在对话中展示完整草稿,得到我确认后,再发布到项目配置的 Issue Tracker 并应用 ready-for-agent 标签。

Agent 接下来会做什么

to-spec 会从当前上下文中提取已经确认的内容,并检查规格能否独立回答以下问题:

  • 用户为什么需要这个功能;
  • 哪些行为属于首个版本;
  • 系统在正常、改期、取消、过期和重试情况下如何表现;
  • 哪些技术决定已经确定,哪些仍留给实现者;
  • 从哪个公共 seam 验证行为;
  • 哪些内容明确不做。

它还会确认测试 seam。对于本例,合理的 seam 可能包括:

  • API 层:保存任务提醒设置后,计划记录与响应是否正确;
  • 调度层:给定任务、截止时间和提前量,生成确定的计划标识与执行时间;
  • Worker 层:重复处理同一提醒时,只产生一次站内通知;
  • UI 层:没有截止时间时提醒控件不可用,修改截止时间后提交正确设置。

测试 seam 不是把内部私有函数全部暴露出来,而是提前确定“后续如何证明功能真的成立”。

会生成或修改什么

它会把规格发布到 docs/agents/issue-tracker.md 指定的位置,并应用相应状态。由于本例配置的是 GitHub,所以最终结果是一个远程 GitHub Issue;如果配置的是 Local Markdown,结果则是本地工作项文件。规格的核心结构为:

1
2
3
4
5
6
7
8
9
# Task due reminders

## Problem Statement
## Solution
## User stories
## Implementation decisions
## Testing decisions
## Out of scope
## Further notes

当 Tracker 配置为 GitHub、GitLab、Linear 或 Jira 等外部系统时,这是一个会修改远程状态的 Skill。发布前应确认目标项目和标签。配置为 Local Markdown 时则只修改本地文件。

本例的 Out of Scope 至少包括:

  • 邮件和短信通知;
  • 重复提醒;
  • 免打扰时间;
  • 任意分钟数输入;
  • 为已经错过提醒时间的任务补发通知。

下一阶段

如果规格可以在一个会话内实现,可以直接进入实现;本例横跨 UI、API 和 Worker,应使用 /to-tickets 将规格拆成可独立验证的垂直切片。

九、to-tickets:把规格拆成可独立验收的垂直切片

to-tickets 的目标不是按照技术目录分工,而是把规格拆成多个可以在单个上下文中实现、验证和审查的行为切片。

先理解什么是“垂直切片”

这里的“垂直”不是指界面布局,而是指一张 Ticket 会跨过让某个行为成立所需的多个技术层。可以把 task-board 想象成由以下部分组成:

  • 前端:让用户启用提醒;
  • API:接收并校验提醒设置;
  • 数据库:保存设置和通知记录;
  • BullMQ:在正确时间调度任务;
  • Worker:触发站内通知;
  • 测试:从可观察入口证明整条路径成立。

如果按照技术层拆票,会得到“建表”“写 API”“写页面”“最后补测试”等水平任务。完成“建表”后,用户仍然不能启用提醒;完成“API”后也不一定能收到通知。每张 Ticket 都只是零件,只有所有任务结束后才能判断功能是否可用。

垂直切片换一个方向拆:**每张 Ticket 选择一个很小的用户行为,并贯穿实现该行为所必需的所有层。**例如第一张 Ticket 只交付以下行为:

用户为一个 12:00 到期的任务启用固定提前 30 分钟提醒后,系统保存设置、创建 11:30 执行的 Job,并在 Job 执行时生成一条站内通知。

为了让这个行为真的成立,这张 Ticket 可以同时包含少量 UI、API、数据库、Queue、Worker 和测试改动。范围虽然窄,却已经形成完整闭环。完成后可以独立演示,也可以通过自动化测试验收,不必等后续 Ticket。

这就是项目原文所说的 tracer bullet:先用一条很窄但贯穿系统的路径证明整条链路可行,再逐步增加多个提前量、改期处理和重试幂等。这里并不是要求每张 Ticket 机械地修改所有目录,而是要覆盖该行为成立所必需的层,避免交付无法单独运行的半成品。

什么时候使用

  • 规格需要多个会话才能完成;
  • 功能包含多个可逐步交付的行为;
  • 希望每张 Ticket 都能独立验证;
  • 需要明确 Ticket 之间的依赖和阻塞关系。

什么时候不需要使用

  • 整个规格可以在一个会话内安全完成;
  • 当前还没有稳定规格;
  • 只是一个不可再拆的修复;
  • 拆分后每个任务都只能产生无法运行的半成品。

精确调用

假设规格发布在 GitHub Issue #142

1
2
/to-tickets https://github.com/example/task-board/issues/142
请拆成能在单个 Agent 会话内完成并独立验证的垂直切片,标明依赖关系。不要按照“数据库、后端、前端、测试”拆成水平任务。

Agent 接下来会做什么

它会先阅读完整规格,寻找最小的端到端 tracer bullet,然后提出一个编号拆分方案。此时还不会立即发布 Ticket,而是先询问使用者:

  • 每张 Ticket 的大小是否适合一个新会话;
  • 是否有 Ticket 过粗或过细;
  • 阻塞关系是否正确;
  • 是否需要合并或继续拆分。

只有使用者确认拆分方案后,它才会把 Ticket 发布到已配置的 Tracker。每张 Ticket 应包含:

  • 清晰的用户可见行为;
  • 必要的上下文和规格链接;
  • 明确的范围与非目标;
  • 可执行的验收标准;
  • 测试 seam;
  • 对其他 Ticket 的阻塞关系。

“阻塞关系”通常写成 Blocked by,表示当前 Ticket 必须等哪些前置 Ticket 完成后才能开始。例如 Ticket 2 — Blocked by Ticket 1 表示 Ticket 1 没有完成时,Ticket 2 还不具备可靠的实施基础;Blocked by: None 则表示可以立即开始。

错误的水平拆分如下:

1
2
3
4
Ticket A:设计数据库表
Ticket B:编写后端接口
Ticket C:编写前端页面
Ticket D:补充测试

这种拆法会导致前三张 Ticket 都无法独立证明用户获得了任何能力,而且“测试”被推迟到最后。

更合适的垂直拆分可以是:

Ticket 1:固定提前 30 分钟的站内提醒

  • 用户可以为有截止时间的任务启用提醒;
  • 从 API、计划记录、BullMQ Job 到站内通知形成最小闭环;
  • 使用固定的 30 分钟提前量;
  • 包含端到端行为测试;
  • 不包含改期和多个预设值。

Ticket 2:支持三个提醒提前量

  • UI 提供 10 分钟、30 分钟和 1 天;
  • API 校验仅接受三个合法值;
  • 修改提前量会更新计划;
  • 每个选项都有可观察的行为测试。

Ticket 3:截止时间改期、移除和过期语义

  • 修改截止时间时使旧计划失效;
  • 移除截止时间或关闭提醒时取消计划;
  • 已错过提醒时间时不补发;
  • 覆盖旧 Job 未触发的回归测试。

Ticket 4:重试与业务幂等

  • 重复执行同一提醒不会产生第二条站内通知;
  • 记录通知唯一键和发送状态;
  • 覆盖“已写入通知但 Worker 重试”的场景;
  • 明确可观测性与失败恢复方式。

这里的每一张 Ticket 都跨越必要的数据库、服务和测试层,但只交付一个完整行为。这就是垂直切片。

会生成或修改什么

发布方式同样由 docs/agents/issue-tracker.md 决定:

  • Local Markdown:在 .scratch/<feature-slug>/issues/ 下为每张 Ticket 写一个独立文件,并在文件中记录 Blocked by
  • GitHub、GitLab、Linear 等真实 Tracker:每张 Ticket 创建一个远程 Issue,使用平台支持的阻塞关系;平台不支持时,在正文中写明 Blocked by

在本文场景中,Tracker 配置为 GitHub,因此会创建多张相互关联的远程 Issue,并链接回规格 Issue。

使用远程 Tracker 时,这一步会修改远程状态;使用 Local Markdown 时只修改本地文件。Skill 会先展示拆分方案并等待确认,仍应在确认时检查数量、依赖和范围。

下一阶段

按照依赖顺序,每张 Ticket 都开启一个新的 Claude Code 会话,并分别执行 /implement <Issue URL>。不要在已经承载整个规格讨论的长会话中连续实现所有 Ticket。

十、implement:在新会话中完成一张 Ticket

implement 是执行阶段。它的输入应该是一张范围明确、能够独立验证的 Ticket,而不是一句模糊需求。它会在内部使用 tddcode-review,完成实现、验证、审查和提交。

什么时候使用

  • 已经有明确的 Ticket、验收标准和测试 seam;
  • 当前分支和工作区状态已经确认;
  • 任务适合在本次会话中完成;
  • 依赖的前置 Ticket 已经落地。

什么时候不需要使用

  • 需求仍然不完整;
  • Ticket 大到无法在单个上下文中完成,应先重新拆分;
  • 当前目标只是探索或原型;
  • 正在诊断一个原因不明的复杂缺陷,应使用 diagnosing-bugs

精确调用

为 Ticket 1 开启一个新的 Claude Code 会话,在正确分支中运行:

1
2
/implement https://github.com/example/task-board/issues/143
先确认工作区和依赖状态。按照 Ticket 的测试 seam 实施,只完成固定提前 30 分钟的站内提醒,不提前实现后续 Ticket。

处理 Ticket 2 时再开启另一个新会话:

1
/implement https://github.com/example/task-board/issues/144

Agent 接下来会做什么

它会先读取 Ticket、规格、仓库规范和相关代码,然后形成一个受 Ticket 范围约束的实现计划。接下来通常包含以下阶段。

1. 内部使用 tdd 完成单个红—绿行为切片

tdd 不是“先把所有测试写完,再一次性补实现”,而是反复完成小的行为闭环:

1
2
3
4
5
6
选择一个公共行为
→ 写一个会因为缺少该行为而失败的测试
→ 运行并确认失败原因正确
→ 写最少实现使其通过
→ 重构但保持测试为绿
→ 再进入下一个行为

以 Ticket 1 为例,第一个切片可以是:

1
2
行为:为 dueAt=12:00 的任务启用提醒时,
系统创建 runAt=11:30 的 Reminder 计划。

测试先通过 API 或领域服务这一公共 seam 表达行为:

1
2
3
4
5
6
7
8
9
10
it("schedules an in-app reminder 30 minutes before the due date", async () => {
const task = await createTask({ dueAt: "2026-08-01T12:00:00Z" });

await enableReminder(task.id);

await expectReminder(task.id).toMatchObject({
runAt: "2026-08-01T11:30:00Z",
channel: "in_app",
});
});

先运行它并确认失败是因为提醒能力尚不存在,而不是测试环境错误。随后只实现让这一行为通过所需的最少代码,再进入“计划被送入 Queue”“Worker 生成站内通知”等下一个切片。

这种做法有两个边界:

  • 测试公共行为,不锁死私有函数的内部结构;
  • 一次只推进一个红—绿切片,避免失败时无法判断是哪部分引入问题。

2. 运行分层验证

目标行为通过后,implement 不会把单个测试变绿当作完成。它还应依次运行:

  1. 与改动直接相关的测试;
  2. 类型检查;
  3. 仓库要求的静态检查;
  4. 完整测试套件;
  5. Ticket 指定的手工或端到端验证。

如果完整测试出现回归,应该继续修正,不应以“目标测试已经通过”为理由忽略。

3. 内部使用 code-review 做双轴审查

code-review 会从一个固定比较点审查当前改动,而不是只看最后编辑的文件。审查包含两条轴:

  • Standards 轴:是否遵守仓库约定、类型和错误处理是否可靠、是否引入安全或性能问题;
  • Spec 轴:是否真正满足 Ticket 和上游规格,是否越界实现了后续功能,是否遗漏验收条件。

例如,代码可能在技术上完全正确,却擅自增加了邮件通知。它能通过 Standards 审查,但会在 Spec 审查中被指出超出 Ticket 1 的范围。

审查时应基于分支与固定基线之间的完整差异,例如 Git 的 three-dot diff。three-dot diff 表示“当前分支相对于它和目标分支共同祖先所新增的改动”,适合只查看本次分支带来的变化。审查不能只依赖 Agent 对自己刚才操作的记忆;发现问题后应修复,并重新运行受影响的验证。

4. 创建提交

当前 implement 工作流默认会在完成验证和审查后创建 Git 提交。这是一个必须提前知道的副作用。

调用前应检查:

1
2
git status --short
git diff --check

确保工作区没有其他人的未提交改动,也没有不属于当前 Ticket 的文件。否则自动提交可能把无关内容一起带入历史。

会生成或修改什么

它会:

  • 修改实现代码和测试;
  • 可能更新与 Ticket 直接相关的文档;
  • 运行项目验证;
  • 完成代码审查;
  • 默认创建一个 Git 提交。

它不应:

  • 修改规格之外的行为;
  • 顺手实现后续 Ticket;
  • 自动把实验原型当作生产代码;
  • 把未验证的改动标记为完成。

下一阶段

  • 当前 Ticket 完成后,在新会话中实现下一张 Ticket;
  • 出现原因不明、反复修补仍失败的缺陷时,切换到 /diagnosing-bugs
  • 上下文已经过长但工作尚未完成时,使用 /handoff

十一、diagnosing-bugs:定位并修复难以解释的运行时 Bug

假设到期提醒上线前出现一个缺陷:

同一个任务偶尔收到两条完全相同的提醒。

如果直接在 Queue、数据库和前端各加一个“去重判断”,可能暂时隐藏现象,却无法知道重复发生在哪个边界。diagnosing-bugs 的目标是先建立快速、可重复的反馈回路,再通过证据缩小原因。

它能不能用来定位程序运行时 Bug

可以,这正是 diagnosing-bugs 的主要用途。它不是只阅读代码的“错误扫描器”,而是一套让 Agent 运行程序、复现问题、收集证据、定位原因并验证修复的诊断流程。

例如,以下问题都适合使用:

  • 程序启动后崩溃,但从报错堆栈看不出真正原因;
  • 某个接口偶尔返回错误结果;
  • 同一个请求被处理两次;
  • 只在特定数据、并发量或操作顺序下出现异常;
  • 测试偶发失败;
  • 程序突然变慢、内存持续增长或 CPU 占用异常;
  • 已经尝试过直觉修复,但问题仍然出现。

调用时应尽量提供以下信息:

  • 预期结果:正常情况下应该发生什么;
  • 实际结果:现在出现了什么错误;
  • 复现步骤:执行哪些操作或命令能够看到问题;
  • 错误证据:报错信息、堆栈、日志或失败截图;
  • 运行环境:操作系统、运行方式、相关依赖版本;
  • 出现频率:必现、偶发,还是只在生产环境出现;
  • 最近变化:问题出现前修改过哪些代码、配置或依赖。

例如,一个普通 Node.js 运行时错误可以这样调用:

1
2
3
4
5
6
/diagnosing-bugs task-board 启动正常,但调用 POST /tasks 时会返回 500。
预期:创建任务并返回 201。
实际:日志出现 TypeError: Cannot read properties of undefined (reading 'id')。
复现命令:npm run dev,然后执行 tests/repro/create-task.ps1。
Node.js 版本为 22,问题每次都能复现,昨天修改过任务创建事务。
请先运行复现步骤并建立会失败的最小测试,再定位根因;不要只根据堆栈猜测。

如果 Agent 可以访问代码和运行环境,它会实际执行复现命令、测试与必要的插桩。如果问题只存在于无法访问的生产环境,它仍然可以根据脱敏后的日志和监控信息制定排查方案,但不能在没有证据的情况下保证已经找到根因。

使用这个 Skill 时会发生什么

调用 /diagnosing-bugs 后,Claude Code 不会切换成另一个更强的模型,Skill 也不会为 Agent 增加原本没有的文件、终端、生产环境或网络权限。它的作用是把一套严格的诊断方法加载到当前 Agent 的工作上下文中,让 Agent 按证据推进,而不是看到报错后立即修改第一处可疑代码。

在权限允许的范围内,Agent 通常会:

  1. 阅读相关代码、测试、配置、错误堆栈和日志;
  2. 运行程序或测试,确认问题是否能够复现;
  3. 缩小复现范围,排除无关模块和环境因素;
  4. 提出 3~5 个按可能性排序、能够被证据推翻的原因假设;
  5. 添加临时日志、断言或诊断测试,一次验证一个假设;
  6. 根据证据确定根因,而不是根据第一印象猜测;
  7. 添加能够稳定重现原问题的回归测试;
  8. 实施针对根因的最小修复;
  9. 运行相关测试与完整测试;
  10. 删除没有长期价值的临时插桩。

如果缺少复现命令、运行依赖或必要日志,Agent 可能先向使用者索取信息。它不能访问的生产环境也不会因为调用 Skill 而自动变得可访问。

与直接要求 Agent 定位并修复有什么区别

两种方式使用的仍然是同一个 Agent,区别在于是否强制执行系统化的诊断过程。

直接要求“定位并修复 Bug” 使用 /diagnosing-bugs
Agent 可能直接根据堆栈猜测原因 先建立复现,再根据证据判断
容易修改第一处看起来可疑的代码 先提出可证伪假设,再逐项排除
可能只让表面现象暂时消失 要求说明能够解释现象的真正根因
修复后可能只运行已有测试 要求增加针对原问题的回归测试
多处修改可能同时进行,难以判断哪一项有效 一次验证一个假设,保持反馈清晰
临时日志可能遗留在代码中 诊断结束后清理临时插桩
更适合原因明确、改动局部的小问题 更适合偶发、并发、重试、缓存和性能问题

以“同一个任务收到两条提醒”为例,直接要求修复时,Agent 可能马上增加一个 notificationExists 判断。这可能隐藏重复结果,却没有解释重复调度发生在哪里。

diagnosing-bugs 会先区分:

  • API 是否创建了两个 Job;
  • 两个 Job 是否使用了不同的 Job ID;
  • Worker 是否因为失败而重试;
  • 通知是否已经写入,但 Worker 在确认 Job 完成前崩溃;
  • 数据库是否缺少业务唯一约束。

只有证据表明“通知已经写入,但 Worker 确认失败后再次执行”时,才应该使用数据库唯一约束或幂等写入修复,并用回归测试模拟这个失败边界。

可以只定位,不立即修改代码吗

可以。diagnosing-bugs 的完整流程包含修复,但使用者可以在命令中限制本轮权限。如果只希望先确认根因:

1
2
/diagnosing-bugs 调查 task-board 的重复提醒问题。
先建立复现并定位根因,在我确认之前不要修改生产代码。

如果希望 Agent 完成诊断、修复和验证:

1
2
/diagnosing-bugs 调查并修复 task-board 的重复提醒问题。
先复现并用证据确认根因,然后添加回归测试、实施最小修复并运行完整测试。

这个 Skill 可能在本地修改诊断测试、临时插桩和业务代码,但它本身不会默认创建远程 Issue、推送分支或创建 Git 提交。实际文件修改仍受调用要求和当前工具权限约束。

什么时候使用

  • 缺陷无法稳定解释;
  • 已经尝试过一两个直觉修复但问题仍在;
  • 涉及并发、重试、缓存、时序或性能;
  • 需要插桩才能观察内部状态;
  • 错误横跨多个系统边界。

什么时候不需要使用

  • 已有稳定复现、明确根因和局部修复;
  • 只是编译错误、拼写错误或显然的条件判断错误;
  • 当前只有产品行为争议而不是代码缺陷;
  • 缺少任何复现信息,此时应先收集基本环境和日志。

精确调用

1
2
3
/diagnosing-bugs task-board 中同一个任务偶尔收到两条相同的到期提醒。
已知现象:生产环境 BullMQ Worker 开启 attempts=3;重复通知的 taskId 和 dueAt 相同,时间相差约 2 秒。
请先建立能够变红的最小反馈回路,再提出可证伪假设并逐项验证。不要先添加泛化的去重条件。修复后补充回归测试,并移除临时插桩。

Agent 接下来会做什么

1. 建立反馈回路

首先找到能够快速重复运行并观察“重复通知”的方式。理想情况是一条自动化测试;如果暂时做不到,也可以是受控脚本、局部日志或最小测试环境。

反馈回路必须能够在缺陷存在时变红,否则后面的修复无法被证明。

2. 最小化复现

Agent 会逐步移除无关因素,例如:

  • 不经过浏览器,只直接调用 Worker;
  • 不等待真实时间,使用可控时钟;
  • 使用单个任务和固定 Job ID;
  • 模拟第一次通知写入成功后,Queue 确认失败;
  • 对比单 Worker 与多 Worker。

目标是找到仍然能够产生两条通知的最小系统。

3. 提出 3—5 个有排序、可证伪的假设

本例可能包括:

  1. 通知已写入数据库,但 Worker 在确认 Job 完成前失败,重试再次写入;
  2. API 并发保存导致同一任务版本被调度两次;
  3. 修改截止时间时旧 delayed job 没有失效;
  4. 多个 Worker 对同一业务事件分别完成了物化;
  5. 自定义 Job ID 没有按预期构造,两个调度使用了不同 ID。

“BullMQ 有问题”不是合格假设,因为它无法指导下一项观察。合格假设必须说明:如果它是真的,应该看到什么;如果看不到什么,就可以排除。

4. 添加针对性插桩

为了区分假设,可以临时记录:

1
2
3
4
5
6
7
8
9
taskId
dueAtVersion
queueJobId
attemptNumber
reminderRecordId
notificationId
workerStartedAt
notificationInsertedAt
workerCompletedAt

插桩应围绕系统边界,而不是无选择地输出全部对象。日志中也不能包含访问令牌、完整用户内容等敏感数据。

5. 修复、回归和清理

假设如果被证据证实,例如“通知写入后 Worker 重试造成第二次插入”,修复可能是建立数据库唯一约束和幂等写入,而不只是依赖 Queue Job ID。

回归测试应精确重现该边界:

1
2
3
4
第一次执行成功写入通知
→ 在 Job 完成确认前模拟失败
→ 第二次执行同一 reminder
→ 数据库仍只有一条通知

最后重新运行完整测试,并删除临时插桩或将真正有长期价值的指标整理为正式可观测性。

会生成或修改什么

诊断过程中可能产生:

  • 最小复现测试或脚本;
  • 临时的定向日志和指标;
  • 一份假设与证据记录;
  • 最终修复;
  • 能够阻止复发的回归测试。

它的核心产物不是“改了哪一行”,而是一条可以证明根因和修复有效的证据链。

下一阶段

修复被完整验证后回到正常交付流程。如果问题尚未解决但上下文已接近上限,使用 /handoff 保存复现方式、已排除假设和下一项实验。

十二、handoff:把必要上下文交给一个干净会话

handoff 用于结束当前会话并生成一份面向新会话的交接说明。它不会把整段聊天机械复制过去,而是引用已经存在的规格、Issue、ADR、提交和差异,只补充尚未持久化的关键信息。

什么时候使用

  • 对话已经很长,Agent 开始遗忘早期约束;
  • 即将从需求讨论切换到独立实现;
  • 原型实验完成,需要回到干净的正式实现环境;
  • 缺陷诊断尚未结束,但已经积累了复现和排除证据;
  • 需要把工作交给另一个人或另一个 Agent 会话。

什么时候不需要使用

  • 当前任务即将完成,剩余步骤很少;
  • 所有必要信息都已经在一张自包含 Ticket 中,新会话可以直接读取;
  • 只是暂停几分钟,不会更换上下文;
  • 尚未形成任何可复用结论。

精确调用

从原型分支返回正式流程

1
/handoff 为 task-board 到期提醒创建新会话交接。说明提醒选择器原型最终选择方案 B;引用规格 Issue #142、BullMQ 调研文档和提醒幂等 ADR;明确原型分支不能合并,下一步是在主工作分支执行 /to-tickets。

在缺陷诊断中交接

1
/handoff 交接“重复提醒”诊断。保留最小复现命令、已经排除的假设、当前插桩字段、相关提交和下一项实验。引用 Issue 与 ADR,不复制完整内容。检查并移除日志中的令牌、Cookie 和个人数据。

Agent 接下来会做什么

它会整理:

  • 当前目标和完成状态;
  • 已经确认的决定;
  • 规格、Issue、ADR、研究文档和提交引用;
  • 当前分支与工作区状态;
  • 已执行的验证及结果;
  • 未解决问题;
  • 新会话应该执行的第一条命令。

对诊断任务,还应特别记录:

  • 最小复现方法;
  • 哪些假设已经被什么证据排除;
  • 哪些临时插桩仍然存在;
  • 下一项最有信息价值的实验。

会生成或修改什么

handoff 通常会在操作系统临时目录中写入一份 Markdown 交接文件,供使用者在新会话中加载。它倾向于引用已有材料,而不是复制整份规格。

交接前会检查敏感信息。终端输出、环境变量、Cookie、令牌和真实用户数据不应进入交接文档。

它不会自动替你完成远程发布,也不会把未提交改动安全地“传送”到另一个分支。分支、提交和工作区状态仍需明确检查。

下一阶段

开启新会话,加载交接文件,先核对目标、分支和工作区,再执行交接中写明的下一步。例如:

1
2
请读取交接文件,然后继续 Issue #147 的重复提醒诊断。
先运行其中的最小复现,不要重复已经排除的实验。

十三、把整个案例连起来

下面是一套可以照着执行的顺序。命令中的仓库地址和 Issue 编号是示例,需要替换为真实值。

阶段 1:初始化仓库

1
/setup-matt-pocock-skills

确认 GitHub Issues、标签、领域文档路径和 CLAUDE.md 已经建立连接。这一步每个仓库通常只执行一次。

阶段 2:让路由器选择流程

1
/ask-matt 我准备给 task-board 增加任务到期提醒。需求还不完整,预计跨 Web、API、数据库和 BullMQ Worker,并需要多个会话。

获得调研、澄清、规格化和拆票的推荐顺序。

阶段 3:调查第三方约束

1
/research 调研 BullMQ delayed job、attempts/backoff、自定义 Job ID、重新调度和重复执行的官方语义。只使用一手资料,并把事实与项目建议分开写入 docs/research/bullmq-task-reminders.md。

确保后续设计建立在可引用的外部事实之上。

阶段 4:确认产品与领域语义

1
/grill-with-docs 结合 BullMQ 调研,逐个澄清 task-board 到期提醒的渠道、提前时间、改期、取消、过期和重复发送语义。将确定规则维护到领域文档,必要时记录 ADR,不要实现。

结束条件不是“所有问题都问过”,而是规格所需的关键决定已经一致。

阶段 5:按需验证交互

1
/prototype 为提醒时间选择器制作三个一次性 UI 方案。只验证交互选择,提供一个运行命令,不接持久化,不做生产抽象。

只有当实际体验会改变决定时才执行。完成后只保留结论。

阶段 6:发布规格

1
/to-spec 将任务到期提醒的确认上下文发布为规格,包含用户故事、领域规则、实现决策、测试 seam、验收标准和 Out of Scope。

检查生成的远程 Issue 是否准确,然后再继续。

阶段 7:拆分垂直 Ticket

1
2
/to-tickets https://github.com/example/task-board/issues/142
拆成单会话可完成且可独立验证的垂直切片,不按技术层拆分。

确认每张 Ticket 都交付一个完整行为,并具有清晰依赖。

阶段 8:逐张 Ticket 实施

每张 Ticket 都使用新会话:

1
/implement https://github.com/example/task-board/issues/143

观察它是否:

  • 先从公共 seam 写出一个会正确失败的测试;
  • 以单个红—绿切片推进;
  • 运行类型检查、目标测试和完整测试;
  • 同时按仓库规范与规格审查;
  • 只提交当前 Ticket 的文件。

阶段 9:系统诊断复杂缺陷

1
/diagnosing-bugs 同一任务偶尔收到两条提醒。先建立会变红的最小复现,提出并验证可证伪假设,修复后添加回归测试并清理临时插桩。

不要把“加一个去重判断”当作已经找到根因。

阶段 10:必要时交接

1
/handoff 引用规格、Ticket、ADR、调研和相关提交,记录当前状态、验证结果、未解决问题与新会话的第一步。

新会话应从交接中的第一项验证开始,而不是重新阅读整段历史对话。

十四、推荐的工作原则

1. 让文档承担跨会话记忆

对话适合探索,仓库文档和 Tracker 适合长期保存。外部事实进入 research 文档,领域规则进入 CONTEXT.md,重要权衡进入 ADR,可执行范围进入规格和 Ticket。

2. 一张 Ticket 对应一个新实现会话

规格讨论需要宽上下文,实现 Ticket 需要窄上下文。让新的 Agent 只读取当前 Ticket、上游规格和相关代码,通常比让同一会话连续处理整个功能更稳定。

3. 原型代码默认丢弃

原型的成功标准是帮助做出决定,而不是“已经写了不少代码,顺便继续做完”。保留结论,正式实现重新遵循仓库规范、测试和错误处理。

4. 区分事实、决策与实现

  • research 回答外部世界如何工作;
  • grill-with-docs 回答项目希望如何工作;
  • to-spec 固化已经确认的合同;
  • implement 在合同范围内修改代码。

混淆这四类信息,是 AI 编程最常见的返工来源之一。

5. 提前认识有副作用的阶段

setup-matt-pocock-skills 会修改项目文档,to-specto-tickets 可能创建远程工作项,implement 默认创建 Git 提交。调用前检查目标仓库、工作区和远程 Tracker,调用后审查实际差异。

十五、最后只记住这张决策图

1
2
3
4
5
6
7
8
第一次使用 → setup
不知道选什么 → ask-matt
需求不清楚 → grill-with-docs
需要外部事实 → research
必须实际体验才能决定 → prototype
多会话功能 → to-spec → to-tickets → implement
难处理缺陷 → diagnosing-bugs
需要新上下文 → handoff

这套 Skills 的价值不在于命令数量,而在于让 Agent 在正确的阶段做正确的事:不确定时先澄清,依赖事实时先调研,需要体验时才做原型,复杂工作先沉淀规格和垂直 Ticket,实现时用测试与审查收口,问题难以解释时依靠证据诊断,最后用交接把上下文安全地带入新会话。

参考资料