clarify-requirements:第一份正式文件出现之前,先把话谈完
这是 skill 深挖系列的第一篇。前面两个系列——五层约束、五个阶段 ——讲的是系统结构;这个系列逐个拆构成系统的 21 份 skill,每篇只讲一份:它为什么存在,具体怎么干。母篇是《从能跑到可交付:一套前端 AI 协作系统的设计笔记 》。我用的系统是开源的 frontend-harness-cli ,文中所有规则都能在仓库里找到对应实现。
第一份 skill 是澄清链的开头。澄清链一共六份——clarify-requirements、write-prd、write-quality-vision、write-tech-design、write-dev-plan、write-acceptance-criteria——依次把一句话需求变成需求文档、品质愿景、技术方案、开发计划和验收标准。链条的第一环不产出其中任何一份文件。它只产出一样东西:一份被用户逐字确认过的澄清摘要。
“加个导出功能”,它就真只加了个导出
先看一个具体的场景。
你说:给订单列表加个导出功能。AI 二十分钟交活:一个导出按钮,点下去下载一个 CSV,内容是当前页的二十条订单。
它没有做错任何事——你说的每个字它都执行了。问题在于你没说的那些字:你想要的是按筛选条件导出全部结果,不是当前页;财务要的是 Excel 不是 CSV;订单里有手机号和地址,导出该不该脱敏、谁有权限点这个按钮,你没提,它也没问。等你验收时逐条说出这些,它逐条改——每一轮返工都比上一轮贵,因为字段、权限、文件格式全缠在已有的实现上。
这类返工的共同点是:缺的不是能力,是问题。 上面每一个没说清的点,在动手之前问一句只要几秒钟;动手之后发现,每一个都要连着代码一起改。这份 skill 存在的理由,就是把“问”这件事从随缘变成流程:它是澄清阶段里由规划者执行的第一份 skill,专门负责提问,在任何正式文件存在之前。
这份 skill 是什么:链条的第一环
它的触发方式很机械:harness next <功能名> 返回 clarify,或者一次重规划冒出了只有用户能回答的问题,就轮到它。已有一份确认过的摘要时跳过——summary.md 里写着 confirmed-by-user: yes 且 open-questions: 0 的功能,直接去 write-prd。
它对自己的定位,原文说得很直白:
和用户把功能谈透,直到没有任何会改变设计的问题悬而未决——然后、也只有那时,才写正式文件。“先写全套 PRD,再用提问去补”正是本 skill 要阻止的顺序。
注意它的产出边界。它不写 prd.md,不写技术方案,不写评分表——那些是后面五份 skill 的活。它产出的全部东西放在一个草稿区目录里(.harness/tasks/<功能>/clarification/),一共四份:
questions.md——问过的问题批次,带编号;answers.md——用户的回答,用用户自己的原话,每条标着对应的问题编号;summary.md——澄清摘要,最后由用户确认;quality-expectations.md——品质期待模块的回答(下面单独讲)。
回答为什么要原话落盘?因为这条链后面全是转手:摘要要交给 write-prd 编成正式需求,需求要交给实现和评测。每一手转述都会漂移一点——“导出要脱敏”在转述里很容易变成“导出注意隐私”,再转一手就没了。原话是唯一不会漂移的版本。答案文件在这里不只是记录,是防漂移的锚。
它怎么干:先读,再问,一次问全
流程五步,顺序是钉死的。
第一步,读上下文。 先读项目总览(.harness/overview/ 下的产品与技术两份文件,不存在就先建只含标题的骨架)、仓库 README、这次需求会碰到的代码。目的写得很实在:先搞清已经有什么,不要问仓库能回答的问题。问用户“现在用的什么框架”,而答案就躺在 package.json 里——这种问题每问一个,用户对后面真问题的耐心就少一分。
第二步,一次问全。 第一轮提问就覆盖全部十一个模块:
- 目标与成功指标;
- 用户、角色与权限;
- 主路径;
- 异常与边界路径;
- 数据对象与字段口径;
- 集成与接口边界;
- 非功能约束(性能、安全、可访问性、浏览器);
- 范围外——明确不做什么;
- 验收口径;
- 预算与停止策略(大循环跑几轮、稳定通过要几次、交付门禁用哪些命令);
- 品质期待与参照(下一节单独讲)。
外加一项单独强调的:技术栈。明确确认“沿用仓库现有的”还是引入新框架新库,绝不默默选型。
提问的形式也有纪律:能做成选择题就做选择题,把最可能的答案放在第一个,并且说明每个选项会改变什么。不是“你想要 A 还是 B”,是“选 A 导出当前页,选 B 按筛选导出全部,B 要多一个后端接口”。用户不是在填表,是在做一连串看得见后果的决定。
第三步,转达,不代答。 执行这份 skill 的往往是子 agent,它接触不到用户:把问题批次交回主 agent,然后停下。这里有一条很硬的规则:调度方的 prompt 里写“这条已决定”“视为已澄清”“默认用 X”,都不算用户的回答——照样要问。 这条规则防的是 AI 协作里一种很常见的事故:上游为了推进度,把自己的猜测包装成用户的决定,下游照着猜测一路做到验收。答案只能有一个来源,就是用户本人。
第四步,把缺口清零。 每收到一批回答,就列一遍还剩下哪些未决问题,追问,直到“会改变设计的未决问题”数量为零。注意定语——不是所有好奇都值得问,是会改变设计的问题清零。这一份 skill 的停止条件是一个可以数的数:open-questions: 0。
第五步,确认摘要。 把 summary.md 写出来,请用户就这份文字确认。原文特意补了一句:对别的事情说“好”,不算确认。摘要的结尾必须是两行固定格式:
confirmed-by-user: yes (<日期>, "<用户确认时的原话>")
open-questions: 0
连同确认时用户的原话一起记。为什么抠到这个程度?因为这份摘要是下游所有文件的出生证:以后任何一份文件和用户意图对不上,回查的终点就是这两行。确认必须能定位到“谁、在哪天、对着哪份文字、说了什么”。
第十一个模块:品质期待也要问出来
十一个模块里,前十个是常规的需求访谈,第十一个是这份 skill 自己的发明:品质期待。它问的不是功能,是“做到什么程度算好”:
- 层级:A,能用的 MVP;B,精打磨,视觉与交互都讲究;C,生产级,还要管性能、安全、可访问性。
- 排序:正确性、视觉品质、交互、性能、代码质量、安全,哪个最重要,排出来。
- 参照:哪个产品、页面、截图“做对了”——并且具体对在哪。
- 反面参照:绝对不要像什么。
- 红线:一出现就不可接受的问题,比如文字被截断、点击没有反馈、两个页面的数字对不上。
为什么这件事要塞进需求访谈、还要排进第一轮?因为品质期待是后面所有判断的地基:write-quality-vision 要把它编成可核对的品质愿景,评测阶段拿它当锚点打分。如果澄清时没人问,用户默认的是 C 级,模型默认交付的是 A 级,验收时才发现两人说的“做好”根本不是一回事——这种分歧没法靠改代码解决,它是预期管理事故。
还有一条小规则很见功力:用户给不出参照时,提供两三个具体方向让用户挑,提问者自己绝不替用户选。参照决定的是品味,品味没有正确答案,只有用户的答案。
设计一:为什么是访谈,不是表单
完全可以把十一个模块做成一张表单发给用户填。为什么绕道访谈?
因为表单不会追问。用户在“异常路径”一栏写“导出失败时提示一下”,表单收下了;访谈会接着问:提示之后用户能做什么——重试、还是换个格式再导?失败的任务留不留记录?真实需求里的大部分信息,是在回答的回答里才浮出来的,第一轮答案往往只是把问题照亮。
另一个原因是提问的形态本身在传递信息。选择题加“每个选项改变什么”,等于把设计空间摊开给用户看:很多用户不是没想清楚,是不知道这里有得选。表单假设用户已经知道所有问题存在;访谈负责让问题先存在。
设计二:草稿区和正式文件,为什么必须分家
这份 skill 有一条看起来过分严厉的禁令:用户确认之前,prd.md、vision.md、tech-design.md、tasks.json、rubric.json、e2e-cases.json 一份都不许创建——草稿也不行。能写的只有草稿区那四份文件。
理由原文只有一句,但很准:
草稿会靠惯性变成契约。
一份写好的 PRD 草稿摆在那里,后面每个角色都会不由自主地以它为准——推翻一份成文的东西,心理成本远高于在一张白纸上改主意。于是“先写个大概、回头再修”的 PRD,修的那一步永远不会发生,它直接以草稿状态成为合同。把正式文件的创建推迟到确认之后,等于保证:用户确认的那一刻,世界上还不存在任何和摘要竞争权威的文本。
这也是它和 write-prd 的分工线:clarify-requirements 负责谈拢,write-prd 负责成文。谈拢之前不成文,成文必须以谈拢的摘要为唯一输入。
设计三:自带 PRD 时,它只补缺口
有一种情况这份 skill 会切换模式:用户不是从一句话开始的,是带着一份成稿 PRD 来的(状态文件里标着 prd.source: "imported",prd.md 已经躺在功能目录里)。
这时访谈缩减成只补缺口:
- 先读
prd.md,它已经回答的问题一律不重问——包括十一个模块里它覆盖到的部分; - 只问三类事:PRD 没定的决策、PRD 内部自相矛盾的地方、以及 PRD 对品质期待没有任何可核对表述时的品质问题;
- 导入时内核如果报告了编号缺口,规划者把缺失的
REQ-n编号原地补进prd.md——不改写用户的措辞,不重编已有的编号。
最后一条值得停一下。补编号听起来是编辑工作,为什么只许补、不许顺手润色?因为这份 PRD 是用户的资产,不是这份 skill 的草稿:措辞一改,原作者的意图就可能漂掉,而且漂得无声无息。编号是给下游用的索引,补上就够了。
模式切换之后,终点不变:summary.md 在这个模式下负责确认这份导入的 PRD——引用文件、列出补掉的缺口、结尾同样是 confirmed-by-user 与 open-questions: 0 两行;下一个 skill 仍是 write-prd,只是走它的仅规范化模式。
它为什么停在这里
把这份 skill 的边界收一下。
它只保证一件事:在写第一份正式文件之前,所有会改变设计的问题都问过了,用户对着一份摘要点了头。 它保证不了用户答得对——用户完全可以确认一份事后看是错的方向,访谈能消除的是“没说清”,不是“想错了”。它也保证不了摘要被正确地变成合同——那是下一份 skill 的活。
还有一条它刻意不做的:它不替用户决定任何事。转达不代答、参照只给选项不代选、技术栈不默默定——这份 skill 里所有看起来“效率低”的规则,都是在防同一件事:AI 在用户缺席时,先斩后奏地把空白填上自己的默认值。填错一个,后面五个阶段全是在错误地基上盖楼。
下一篇 write-prd:一份确认过的摘要,怎么变成带编号、可被逐条核对的正式 prd.md——以及为什么编号一旦定下,连它自己都不许重编。