文章

mattpocock/skills 系列(3):先找出缺口,再决定要写规格还是拆工作单

需求谈完后,下一步该写规格、拆工作单,还是去问掌握答案的人?本文以按席位计费为例,说明 to-spec、to-tickets、triage、wayfinder 与 to-questionnaire 各自补上哪一种缺口。

mattpocock/skills 系列(3):先找出缺口,再决定要写规格还是拆工作单

上一篇已经把按席位计费的需求谈完。CONTEXT.md 写下了“计费席位”与“成员”的差别,对话中也确认了成员禁用后怎么处理。接下来要把这些结论变成可以开工的工作,眼前却有五个看起来都跟“规划”有关的 skill:to-spec、to-tickets、triage、wayfinder 与 to-questionnaire。

这五个 skill 都会产出文档,补的却是不同的缺口。选错了,AI 一样会把指令运行完,你却只多了一份暂时没人用得上的文档。

mattpocock/skills 系列|第 3 篇

本文内容以 1.2.3 版为准。文中的按席位计费流程依原始指令推演,不是实测输出。

先认识几个词

这五个 skill 都围绕着团队的工作跟踪工具运作。下面几个词会反复出现:

本文用词原文意思
工作跟踪工具issue tracker团队记录待办事项的地方,例如 GitHub Issues。每件事是一张卡片,可以贴标签、评论,也能标注先后顺序
规格spec说明一整项功能要做成什么样子的文档
工作单ticket从规格切出来、可以单独完成的一小项工作
一次对话session与 AI 从开始到结束的一段工作过程。AI 在一次对话中能处理的内容有上限,内容累积太多时,判断就会变得不够精准

五个 skill 各自补不同的缺口

一般的功能开发有一条主线:先通过访谈厘清需求,再开始实现。功能小到一次对话就能做完时,谈完直接实现即可。要分成好几次对话才做得完时,才会在中间加入 to-spec 与 to-tickets。前者把谈定的内容整理成规格,后者再把规格切成一张张工作单。ask-matt 的主流程也要求这两步接在需求访谈之后,并留在同一段对话里进行,让 AI 记得前面谈过的内容。

另外三个 skill 不在主线上。triage 处理别人送进来的工作,wayfinder 处理大到一次谈不完的工作,两者整理完后都会接回主线。to-questionnaire 则负责去找掌握答案的人。

眼前缺少什么使用的 skill留下什么
需求已经谈清楚,但还没写成正式规格to-spec工作跟踪工具里的一份规格
规格还没切成可以分开完成的工作to-tickets一组标明先后顺序的工作单
别人送来的反馈还没查证与分类triage分类、处理状态,以及给 AI 的交接说明
工作大到连该做哪些决定都列不完整wayfinder一张“地图”与多张待决定的“决策单”
关键答案在另一个人手上to-questionnaire一份交给对方填写的问卷

左侧把 to-spec、to-tickets、triage、wayfinder 与 to-questionnaire 五个按钮全部按下,右侧依信息缺口只亮起一条路,底部写着“这不是集章卡,不用五格盖满” 五个名称放在同一张清单里,不代表每次都要全部运行。

to-spec 只整理已经谈过的内容

to-spec 依据的是目前的对话内容,以及 AI 对现有代码的了解。它的第一条规则明确要求不要再访谈你,只整理已经讨论过的内容。因此,需求里若还有没谈定的问题,这时调用它也得不到答案,那些空白只会原封不动地留在规格里。

整理之前,AI 会先了解项目现状、沿用词汇表里的名称,并遵守过去留下的决策记录(ADR,上一篇介绍过)。接着它要决定“之后从哪里检查这个功能有没有做对”。原始规则倾向于越接近用户实际操作的位置越好,检查点也越少越好,最理想的情况是只有一个。这一步需要人工确认,AI 会先问你这些检查点是否符合预期。

你确认后,to-spec 才把规格发布到工作跟踪工具,并打上 ready-for-agent 标签,意思是“信息已经齐全,可以交给 AI 接手”。规格有固定的字段:要解决的问题、解决方案、用户故事、实现决定、测试决定、这次不处理的范围,以及补充说明。其中“用户故事”是一种描述需求的固定句型:“作为某种角色,我希望能做某件事,以便得到某种好处。”

规格里不写具体的文件位置或代码,因为程序一改,这些细节很快就会过时。唯一的例外是:先前做过的原型里,若有一小段内容比文字更能精确表达某项决定,才节选其中最关键的部分。

短小的工作不一定需要规格。如果整项功能能在这次对话里做完,主流程会直接进入实现。

to-spec 示例

假设团队已经确认两件事:成员禁用时,立即收回他的席位;本期账单不因此退款,减少的席位从下一期账单开始计算。to-spec 可以把对话整理成下面这段规格(节选):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
## 问题

工作区管理员不清楚禁用成员后,席位何时会释放出来,因此容易算错可用席位与账单金额。

## 用户故事

1. 作为工作区管理员,我希望禁用成员后立即看到可用席位增加,以便把席位改分配给其他成员。

## 实现决定

- 禁用成员时,立即收回他的席位。
- 本期账单不退款,减少的席位从下个计费周期开始反映在账单上。

## 测试决定

- 模拟管理员禁用一位成员,确认可用席位增加一席。
- 确认计费系统收到新的席位数量,并标注从下个计费周期生效。

## 不处理的范围

- 本次不处理按使用天数比例退款。

这份规格只收录已确认的答案。如果“从下一期账单开始计算”还没经过财务确认,to-spec 就不应该自行替团队写进去。这时要先用后面介绍的 to-questionnaire,把答案问回来。

to-tickets 让每张工作单都是一小段完整功能

to-tickets 可以接手一份规格、一份计划、一张现有的工作卡片,或直接使用目前的对话。它读完所有内容后,把工作切成一张张工作单。

切法有一个重点:每张工作单都要是“从头到尾都能运作”的一小段功能,而不是“只做其中一层”。软件功能通常分成好几层,例如保存数据的地方、处理规则的程序、用户看到的界面,以及检查功能的测试。原始规则把这种切法称为 tracer bullet,也就是曳光弹。夜间射击时,曳光弹会发光,让射手看清弹道并实时修正。同样地,先让一小段功能完整打通每一层,团队就能立刻看到方向对不对。只改数据或只改界面的工作单,都不符合这项规则。

左侧把分配席位拆成只改数据、规则、界面与测试的四张工作单;右侧以一张工作单打通界面、规则、数据与测试,完成后可单独验证 同一项功能要切成能独立完成的小段,而不是依技术层拆成互相等待的工作单。

原始规则替每张工作单设了两个可以检查的条件:第一,完成后能单独展示或验证;第二,工作量要能在一次全新的对话里做完。每张工作单也要列出“前置工作”,也就是开始前必须先完成的其他工作单;没有前置工作的工作单可以立刻开始。切分规则与前置关系都写在 to-tickets/SKILL.md。

AI 不会直接把第一版切法写出去。它会先列出每张工作单的标题、前置工作,以及完成后能做到什么,再请你检查:切得太粗还是太细?前置关系是否真的必要?有没有哪几张该合并或再拆开?你同意后,它才依项目的设置,把工作单写成项目文件夹里的文件,或创建在工作跟踪工具中。发布规则也禁止它顺手关闭或修改原本那张总需求卡片。

有一种工作是例外:牵连整个项目的机械式修改,例如替一个到处都在使用的字段改名。这种修改一动就会影响整个项目,没办法切成一段段能独立运作的功能。原始规则改用“先扩展、再收敛”(expand-contract)的做法:先让新旧写法同时存在,确保不会坏掉;再分批把各处换成新写法;最后确认没有地方还在用旧写法,才把它删除。

to-tickets 示例

同一份席位规格不会拆成“改数据”、“改代码”和“改界面”三张工作单。其中一张可以写成:

1
2
3
4
5
6
7
8
9
10
11
12
13
# 管理员可以把可用席位分配给成员

前置工作:显示工作区已购买与可用席位

## 完成后能做到什么

管理员在成员页面选任选其一个未使用的席位并完成分配后,该成员就能使用付费功能,页面上的可用席位也少一席。

## 验收条件

- [ ] 完成分配后,可用席位显示少一席。
- [ ] 被分配的成员立即能使用付费功能。
- [ ] 没有可用席位时,系统拒绝分配并说明原因。

这张工作单从数据保存到界面都要修改,但完成后就能单独展示。之后的“禁用成员并释放席位”会把它列为前置工作,因为系统要先能分配席位,才能验证收回席位的行为。

triage 接手别人送进来的工作

triage 原本是急诊的“分诊”,这里指整理不是你亲手创建的工作:用户反馈的问题、别人提出的功能需求;若项目有设置,也包括外部人士直接送来的代码修改(PR)。to-tickets 产生的工作单已经打上可以交给 AI 的标签,不需要再送去分类。

每个条目都会打上一个分类和一个状态。分类只有两种:bug 代表有东西坏了,enhancement 代表新功能或改进。状态则有五种:

状态意思
needs-triage等待维护者评估
needs-info等待报告者补充信息
ready-for-agent信息齐全,可以交给 AI 处理
ready-for-human需要由人处理
wontfix决定不处理

如果同一个条目出现互相矛盾的状态,triage 的状态规则要求先提出来询问维护者,再做其他事。

分类不能只看反馈的文字。AI 会先读完整个讨论帖,确认代码里是否早已有同样的功能,并查看过去被拒绝过的类似需求。接着它提出分类与状态的建议,然后停下来等维护者指示。之后它会依照反馈的步骤复现问题、确认反馈属实,必要时再追问细节。最后依结果处理:可以交给 AI 的,留下一份交接说明;需要人处理的,用同样格式写,并注明为什么不能交给 AI;信息不足的,列出已确认的事项和还需要报告者补充的问题;功能其实早就存在的,就指出它在哪里,然后关闭。完整处理顺序把查证、追问与更新状态分成不同步骤。

triage 示例

假设有用户送来一条反馈,内容只有一句“禁用成员后,可用席位没有增加”。AI 读完反馈、查过现有代码后,先向维护者提出分类建议。维护者同意后,它再依照反馈的描述操作,确认问题存在。整理后的结果可能如下:

字段内容
分类bug
状态ready-for-agent
查证结果禁用成员后,该成员已无法使用付费功能,但席位仍记在他名下;刷新页面后,可用席位依然没有增加
比对现有规则席位规格要求禁用后立即释放席位,项目中也没有推翻这条规则的决策记录
交接说明找出禁用成员时漏掉收回席位的环节并修正;完成后,禁用一位成员,可用席位应增加一席

如果查证后发现系统其实已经释放席位,只是界面没有更新,交接说明就应把范围缩小到界面显示。如果反馈没有说明使用哪一种方案、做了哪些操作,状态就应先改成 needs-info,请报告者补充,而不是猜测原因。

wayfinder 先处理还列不完整的决策

有些工作大到一次对话看不清全貌,连“需要做哪些决定”都还列不出来。wayfinder 的字面意思是“找路的人”。它会先在工作跟踪工具里创建一张“地图”,记下终点是什么、已经做了哪些决定、哪些地方还看不清楚,以及哪些事不在这次的范围内。已经能清楚说出来的问题,则各自开成一张“决策单”。

决策单完成时产出的是一项决定,不是做好的功能。wayfinder 的规则要求它默认只做规划,不动手实现。每次对话最多只解决一张决策单;唯一的例外是单纯查资料的决策单,可以同时交给多个 AI 分头查。答案写在该张决策单的评论里。决策单关闭后,地图上只加一行摘要与链接,细节仍留在决策单里。如果某个答案让原本看不清楚的地方变得明确,就再开一张新的决策单。

如果第一轮盘点就发现所有问题都很清楚,整件事也能在一次对话中谈完,就不需要地图,AI 会停下来问你打算怎么进行。等地图上的决定全部完成,流程会回到 to-spec,把分散在各张决策单的答案整理成一份规格,再交给 to-tickets。

wayfinder 示例

假设要把现有的“依成员人数计费”改成“依分配席位计费”,团队一开始可能还不知道要做哪些决定。这时可以先把目前看得见的部分写成地图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 席位计费转换地图

## 终点

所有现有工作区改用席位计费,转换期间不重复收费,也不中断付费功能。

## 备注

- 新工作区直接采用席位计费。
- 现有合同在续约前维持原价。

## 已做的决定

(目前还没有。每关闭一张决策单,就在这里加一行摘要与链接。)

## 还看不清楚的地方

- 现有成员要如何迁移成席位分配。
- 转换失败时,如何恢复原本的账单与使用权限。

## 不在这次范围内

- 不重新设计价格方案。

地图本身不列出还没解决的决策单,它们另外开在工作跟踪工具里,归在这张地图底下。这次可以先开出两张:“现有工作区要分几批转换,出问题时何时暂停”,以及“新旧计费并行期间,账单要以哪一套数字为准”。

第一张决策单解决后,原本列在“还看不清楚的地方”的“转换失败时如何恢复”,可能变得能写成明确的问题,例如“单一工作区转换失败时,在什么条件下要退回旧的计费方式”。这时 wayfinder 才把它开成新的决策单,并从“还看不清楚的地方”移除。它不会一开始就假装已经列出所有问题。

第一轮盘点时,地图记录终点与看不清楚的地方,已知问题另开决策单;解完分批转换的决策单后,才把转换失败时何时退回旧计费写成新决策单 决策单另外开在地图底下;一张决策单的答案,可能让下一个问题变得能具体提出。

to-questionnaire 去找掌握答案的人

有些问题查不到,也不该由正在对话的人决定。换个情况来看:假设财务负责人还没确认席位增减后要从哪一期开始计费。to-questionnaire 会把这类问题整理成一份问卷,让对方有空时填写,或在会议中一起填。

它只问你两件事:问卷要交给谁(对方的角色、专长,以及和你的关系),以及你需要带回哪些答案。它不会要求你代替对方回答专业问题。问完后,它会在目前的文件夹产生一份依主题命名的问卷文件,例如 to-questionnaire-seat-billing.md。

问卷会交代目的、背景与回答方式。问题依重要性排序,因为对方可能只会填一次;每题只问一件事,最后再留一题“还有什么我们没问到、但应该知道的?”答案收回来之后,才成为 grill-with-docs 或 to-spec 的素材,ask-matt 也把这两个流程列为问卷的后续去向。问卷本身不替项目做决定。

to-questionnaire 示例

若答案在财务负责人手上,产生的 to-questionnaire-seat-billing.md 可以包含:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# 席位变动的计费规则

**目的:** 确认席位增减从哪一期账单开始生效,让产品与计费系统采用同一套规则。

**发件人:** 产品负责人 **收件人:** 财务负责人

## 回答方式

请于本周五前回复,约需 10 分钟。每题选一个选项;选“其他”时,请补上生效时间与计算方式。不确定的题目请直接注明“不确定”,不必跳过。

## 月付方案

1. 添加席位后,何时开始收费?
   - 分配之时起,按剩余天数比例收费
   - 从下个计费周期开始收费
   - 其他:

2. 释放席位后,何时停止收费?
   - 释放之时起,按剩余天数比例退款
   - 本期不退款,从下个计费周期停止收费
   - 其他:

## 年付方案

3. 年付合同的席位增减,有哪些规则与月付不同?若完全相同,请填“相同”。

## 其他

4. 还有什么我们没问到、但应该知道的?

收件人填回答案后,团队才能把“本期不退款”这类结论写进规格。问卷列出选项只是为了方便回答,不代表团队已经倾向其中哪一个。

都会留下文档,但用途不同

五个 skill 都会留下文字。看产物接下来要交给谁,就能分辨它们的差别。

产物内容接下来交给谁
规格整项功能已确认的需求与决定to-tickets,或直接开始实现
工作单一次对话做得完的一小段完整功能实现(implement)
交接说明外部反馈的查证结果,以及接手所需的信息AI 或负责处理的人
决策单一个待决定的问题,以及最后的结论后续的决策单,或 to-spec
问卷项目缺少、需由特定对象补上的答案grill-with-docs 或 to-spec

规格与工作单都可能打上 ready-for-agent,但工作量不同:规格覆盖一整项功能,工作单只是其中一小段。功能大到一次对话做不完,才需要再切成工作单。

规划多一层,也多一轮人工确认

这套流程没有省掉人工确认,而是把确认放在文档写出去之前。

使用 to-spec 时,你要确认检查点;使用 to-tickets 时,你要确认切分的粗细与前置关系。triage 会先提出建议,再等维护者指示;to-questionnaire 则需要你说明收件人是谁、要带回什么答案。

wayfinder 花费的人力最多。它把一次谈不完的工作拆成许多决策单,而且每次对话通常只解决一张,这些时间都由参与决策的人付出。若问题本来就能在一次对话里列清楚,创建地图只会让工作跟踪工具多出一堆需要维护的条目。

先看信息缺在哪里

选择时,先看眼前的状况:

目前状况下一步可以跳过什么
需求已谈清楚,但要分好几次对话才做得完to-spec,接着 to-tickets不需要 wayfinder
需求已谈清楚,一次对话就做得完直接实现to-spec 与 to-tickets 都可跳过
收到别人送来、还没查证的反馈triage不必先写新规格
连该做哪些决定都列不出来wayfinder先不急着切工作单
某项决定需要特定的人提供答案to-questionnaire不让 AI 猜答案

这张表只决定现在从哪里开始。wayfinder 完成后会回到 to-spec;问卷收回后,答案也能带回需求讨论。主线以外的 skill 负责补齐缺口,补完之后再回到主线。

模拟场景:把按席位计费切成可开工的工作

以下没有实际运行这些 skill,因为它们会写入项目的工作跟踪工具或目前的文件夹。内容依 1.2.3 版的原始规则推演,实际结果会随项目内容、现有的决策记录与对话内容而不同。

延续上一篇的场景:CONTEXT.md 已定义计费席位、成员与席位分配,禁用、分配与计费时间点也都在对话中确认了。团队判断这项功能要分好几次对话才做得完,所以在同一段对话里调用:

1
$to-spec

AI 会先查看现有代码,再提出检查点。假设团队确认,最能一次检查整个功能的位置是“席位变动完成后,计费系统收到正确的席位数量”。AI 便把谈过的问题、解决方案、用户故事、实现与测试决定整理成规格,经你确认后发布。

规格创建后,仍在同一段对话里附上规格链接:

1
$to-tickets <规格链接>

AI 会先列出切分草案,例如:

工作单完成后能做到什么前置工作
显示工作区已购买与可用席位管理员能看到席位总数与剩余数量无
把可用席位分配给成员管理员完成分配后,成员能使用付费功能显示工作区已购买与可用席位
禁用成员并释放席位禁用后收回席位,计费系统收到新的席位数量把可用席位分配给成员

这时要检查三件事:每张工作单能否单独验证、是否一次全新的对话就做得完,以及前置关系是否真的必要。例如,“分配席位”的验收条件要看到可用席位少一席,所以确实得等“显示席位”先完成。你同意后,AI 才把工作单写进工作跟踪工具。这些工作单已经打上 ready-for-agent,不必再经过 triage。实现时,每张工作单各自开一次新的对话;工作单已写明所需信息,不必依赖先前的对话内容。

如果财务还没确认席位增减何时反映在账单上,就先用 to-questionnaire 向负责人取得答案,再回来完成规格。如果连转换期间要做哪些决定都无法一次列清楚,则改用 wayfinder 创建地图。缺口不同,起点就不同。

我会先找缺口,不会把五个都跑一遍

前面介绍的输入、产物与使用时机,都能在原始指令里查到。以下则是我的个人判断,原始资料并不能证明这套做法一定能节省时间。

我会先问自己:现在缺的是规格、可以开工的工作、对外部反馈的判断、大型工作的决策,还是另一个人才知道的答案?确定之后,再选一个 skill。

把五个 skill 全跑一遍,文档会变多,问题却不一定更清楚。triage 不需要处理自己刚切好的工作单;已经能列清楚问题的工作,也不需要 wayfinder。每次只补眼前的缺口,产出的文档才有明确的下一位使用者。

这项判断适用于通过工作跟踪工具交接工作,而且工作会跨好几次对话的团队项目。如果只是想在这次对话里完成一个小修改,直接实现即可。

先决定下一份文档要交给谁

需求谈完后,该从哪个 skill 开始?先看下一份文档要交给谁,以及目前缺的是哪一种信息。

需要一份完整的需求说明交给后续规划,就用 to-spec;需要让好几次新的对话各自开工,再接着用 to-tickets。别人送来的反馈交给 triage,列不完整的大型决策交给 wayfinder,只有别人知道的答案则用 to-questionnaire 去问。

回到按席位计费的场景,最小的下一步是留在同一段对话里运行 to-spec,确认检查点,再依工作量决定要不要切成工作单。

延伸阅读

  • to-spec:查看规格的固定字段、检查点的确认方式与发布规则。
  • to-tickets:核对工作单的切分规则、前置关系,以及两种工作单格式。
  • triage:了解别人送来的反馈如何经过分类、查证与状态转换。
  • wayfinder:查看地图、决策单、前置关系与逐张解决的流程。
  • to-questionnaire:了解问卷如何依收件人与所需答案安排问题。
本文由作者按照 CC BY 4.0 进行授权