| name | long-horizon-spec |
| description | 在动手执行一个"长任务/大改动"之前,先和用户一起把任务的边界、目标、可验证的验收标准谈清楚,写成一份自洽的 SPEC.md,规范定义完整后才开始执行。这是一个"协作式 Plan Mode":先润色用户的意图,用 AskUserQuestion 反向访谈补齐缺口,给出可运行的 check(测试/构建/截图对比),再放行实现。无论用户是否说"先规划",只要任务是多步骤、跨多个文件、需要数小时自主推进、涉及迁移/重构/从零搭功能/调研,或者用户给了一个含糊的大目标("帮我做一个 X"、"重构 Y"、"把这个项目搭起来"、"迁移到 Z"),都应主动使用本 skill 先立规范、再执行,避免 Claude 埋头解决一个错的问题。小到一句话能描述清楚的改动(改 typo、加日志、重命名)不要用本 skill,直接做。 |
长任务:先立规范,再执行(协作式 Plan Mode)
为什么需要这个 skill
当模型能自己读文件、跑命令、连续干上几个小时,瓶颈就不再是"会不会写代码",而是有没有在做对的事。一个含糊的大任务直接开干,最常见的结局是:Claude 给出一份"看起来做完了"的实现,却解决了一个错的问题,或者漏掉了边界情况——也就是官方说的 trust-then-verify gap(信任但没法验证的缺口)。
这个 skill 的职责是在执行前装一道闸门:把任务的边界、目标、可运行的验收标准和用户一起谈清楚、落成 SPEC.md,然后才放行。前期把需求说清楚,比盯着模型一行行写代码值钱得多。
核心信条只有一句:能验证它,才能交付它;验证不了,就别开始。
什么时候用、什么时候别用
先做一个判断,别让规范本身变成负担:
- 该用:多步骤、跨多个文件、需要长时间自主推进;迁移/重构/从零搭功能/调研类;或者用户给的目标含糊、范围不清、你对要改的代码不熟。
- 别用:一句话能描述清楚 diff 的小改动(改 typo、加一行日志、重命名变量)。这类直接做,硬套流程只会拖慢。
判断不准时,用一句话问用户:"这个我想先花几分钟把范围和验收标准对齐再开干,还是你要我直接上?"
完整流程
下面六步是一条有先后、且第 5 步是硬闸门的链路。不要跳过访谈直接写 SPEC,也不要在用户确认 SPEC 之前开始改代码。
第 1 步 · 对齐意图,顺手润色 prompt
先复述你对任务的理解,并把用户那句原始诉求润色成一个更精确的任务描述——指明涉及哪些文件/模块、约束是什么、参考哪个现有模式。这一步本身就在帮用户想清楚,也让后面的访谈更有的放矢。
把"模糊版"和"精确版"并排给用户看,例如:
- 模糊:"帮我加个登录"
- 精确:"在
src/auth/ 下新增 Google OAuth 登录,复用现有的 session 机制(参考 HotDogWidget 那套模式),不引入新的鉴权库;回调处理要有测试。"
让用户确认或修正这个精确版,它是后续访谈和 SPEC 的起点。
第 2 步 · 先探索(只读,不改)
进入只读式探索:读相关文件、git 历史、现有模式,搞清楚现状。这一步只看不改。 目的是让 SPEC 建立在代码真实状况上,而不是凭空想象。
如果探索会读很多文件,用 subagent 去探索、只把结论带回来,避免把主对话的 context 撑爆(context 是最稀缺的资源,填满了模型就开始"忘事")。
第 3 步 · 反向访谈用户(AskUserQuestion)
这是把"缺口"逼出来的关键一步。不要假设你已经懂了——用 AskUserQuestion 反过来采访用户,专挑那些用户可能没想到、但会决定成败的硬骨头。
宁可多问,也要问透。 一个没问清楚就开干的长任务,返工的代价远大于多聊几轮的代价。把"少打扰用户"这个念头压下去——在这个阶段,把问题问全比让用户少点几下重要得多。围绕这几类,每一类都要覆盖到:
- 边界 / 范围:什么算这次要做的,什么明确不做(out of scope)?
- 目标 / 成功长什么样:做完之后,用什么现象判断"成了"?
- 技术取舍:用哪个方案、哪个库、要不要兼容旧逻辑?
- 边界情况:超时、并发、空数据、权限、失败回滚……哪些必须处理?
- 验收标准:用什么可运行的 check 来证明它对(见第 4 步,这条最重要,必须问到)?
怎么"问透"——用多轮访谈,而不是一次问完。 AskUserQuestion 每次调用最多放 4 个问题、每个问题 2–4 个选项,这是硬上限。所以正确姿势是分多轮:
- 每一轮聚焦一两个主题(比如这轮只谈"范围+取舍",下一轮谈"边界情况+验收"),把这个主题挖到底。
- 用户的回答常常会暴露新的未知——顺着追问下去,再开一轮,直到没有新的缺口冒出来。
- 不要因为"已经问了一轮"就急着收尾。问题问完的标准不是轮数够了,而是你已经能想象出一份没有歧义、可以照着实现的 SPEC。 达不到这个标准,就再开一轮。
别问显而易见的问题,把每一轮都花在用户没想清楚的地方。
如果当前环境没有 AskUserQuestion 工具,就用普通提问代替,但仍然一次聚焦一组、等用户回答再继续,并保持同样的"多轮问透"原则。
第 4 步 · 定义可运行的验收标准(本 skill 的核心)
模型会在"看起来做完了"的时候停下,而"看起来"恰恰是最危险的信号。所以每个 SPEC 都必须配一个能产出通过 / 失败信号的 check,让 Claude 自己干活、跑检查、读结果、再改,直到通过——这个循环才能自己闭环,你才敢放手。
check 是任何 Claude 能在对话里读到结果的东西:
- 一套测试(最常见、最硬)
- 一个构建/编译的退出码或 linter
- 一段把输出和 fixture/设计稿做 diff 的脚本
- 一张截图和设计稿对比
把验收标准写成具体、可执行的形式,而不是空话。对比:
- 空话:"实现一个校验邮箱的函数"
- 可验收:"写
validateEmail;示例用例:user@example.com→true,invalid→false,user@.com→false;实现后跑测试,全绿才算完成。"
并且要求 Claude 拿证据说话——把跑了什么命令、返回了什么、测试输出、截图摆出来,而不是嘴上说"我跑过了"。审证据比你亲自重跑一遍快得多,也是你没盯着那段执行时唯一能信的依据。
如果环境支持 /goal,把这个 check 设成 /goal 的完成条件:每轮由一个独立评估器复核,没达成就继续干。但要清楚它的局限——评估器只看 Claude 在对话里摆出来的证据,不会自己跑命令;条件写松了、或 Claude 只是嘴上说跑过了,照样可能误判通过。所以验收标准要写得客观、可机器判定。
第 5 步 · 落成 SPEC.md,并作为硬闸门让用户确认
把前面谈定的内容写进项目根目录的 SPEC.md,模板见 assets/spec-template.md(用 Read 读取后套用)。一份好 SPEC 必须自洽:
- 点名涉及的文件和接口
- 明确写出不做什么(out of scope)
- 以一个端到端的验证步骤收尾,能证明功能确实跑通
写完后,把 SPEC.md 交给用户,并停下来等明确放行。这是一道硬闸门,不是礼节性的知会:
"SPEC 写好了,范围、目标、验收标准都在里面。请审一遍——确认无误就回我一句明确的『确认 / 开始 / go』,我才会动手;要改的地方现在提。"
闸门规则,严格执行:
- 没有拿到用户明确的放行信号("确认""可以""开始"之类),一个字的代码都不许改。 沉默不算放行,"嗯""看着不错"这类含糊回应也不算——拿不准就再确认一次。
- 用户提了修改意见,就改 SPEC、再交回去等下一次放行,不要一边改一边偷偷开干。
- 在等待期间,你能做的只有"继续完善 SPEC / 回答用户对 SPEC 的疑问",不包括任何写入、执行、改文件的动作。
这道闸门就是这个 skill 存在的全部意义——宁可多停一次,也不让"想清楚"被"急着动手"绕过去。 一旦放行,立刻进入第 6 步。
第 6 步 · 拍板执行路径与自主引擎,然后执行
用户确认 SPEC 后,开干前还有两个拍板:第一个决定谁来执行,第二个决定它能自主跑多远、何时收手。
拍板 ① · 这是不是一个"实验型任务"?(决定执行路径) 如果任务的本质是"反复试→量→比,直到某个指标达标/打过基线"——比如性能优化、kernel/编译器调优、模型或训练/RL 调参、查询或数据管线提速、需要交叉验证的调研——那它不是一次性生成,而是一个长实验系统。这种任务不要在这里手写执行,而是交给 engineering-loop(或用 kda 起完整三件套),并把 SPEC 的"验收标准"小节直接映射成它的 Task Contract:
| SPEC.md 字段 | → Task Contract 字段 |
|---|
| 验收标准 · 怎么跑(命令) | correctness + validation command |
| 验收标准 · 目标指标/判据 | target metric + evaluation command |
| 当前基线是什么(实验型才填) | immutable baseline + provenance |
| 多好算赢(实验型才填) | promotion criteria |
| 端到端验证步骤 | 整体 definition of done |
因为这份 SPEC 是人工放行过的,它锁定的"成功"正是 engineering-loop 最需要的反漂移锚——交接是无损的,照着上表填进 docs/contract.md 即可。两点别搞混:① SPEC 是给人看的"做什么/何为成",engineering-loop 内部的 draft.md→plan.md 是"这一轮具体怎么试",二者嵌套不重复,别写两份冗余计划;② 前面那套多轮人工访谈只在立项时做一次,绝不要塞进每一轮迭代里,否则毁掉循环的自主性。
拍板 ② · 挂哪个自主引擎?(显式决定"自主到什么程度")
Skill 本身不会让执行自主循环——模型默认只在单个 turn 内自主干活,到"看起来做完了"就停,而"看起来"正是最危险的信号。要让它持续干到 SPEC 的验收标准客观达标才收手,必须显式挂一个引擎。这个选择不要替用户默默做掉:用 AskUserQuestion 把选项摆出来(附上你按任务形状给的推荐),让用户拍板。
| 引擎 | 终止判定 | 适合 |
|---|
| 不挂引擎(默认) | 模型自己觉得做完,人来验收 | 短任务、用户打算盯着干 |
/goal "<验收条件>" | 每 turn 结束由独立小模型读"条件+本轮对话"判达成与否,没达成自动续 | 串行长任务、想跨 turn 无人值守;条件必须客观可判 |
| Stop hook | 你的脚本真的跑 check,不通过就不许这轮结束(连挡 8 次后强制收手) | 有硬性可跑的 check、要确定性闸门 |
| Dynamic Workflow | 编排脚本里的真循环(while/loop-until-dry)+ 并行 subagents | 大迁移/全库审计/并行候选搜索;实验型任务可把 engineering-loop 写成脚本跑 |
接线规则:终止条件不要重新发明。 就用 SPEC"验收标准"小节那条可运行的 check(实验型任务则用 promotion criteria),原样填进所选引擎。这正是前面人工闸门的回报——人锁死了"何为成",机器才敢放手循环。两个注意:
- 挂
/goal 时记住它的局限:评估器只看对话里摆出来的证据、不会自己跑命令。所以条件要写成可核对的形式("跑了哪条命令、看到什么输出"),并要求执行方每轮把真实输出摆进对话,否则"嘴上说跑过了"也可能被判通过。
- 引擎越自主,第 6 步末尾那道对抗式复查越不能省——无人值守跑完的结果,交付前必须有独立 context 对着 SPEC 验一遍。
然后执行。普通任务(搭功能/迁移/重构/写脚本等一次性任务)就地执行:
- 如果探索/访谈已经让主对话的 context 很满,建议开一个干净的新会话来执行,让它专注实现、并以 SPEC.md 为唯一参照。干净的 context 表现更好。
- 执行时严格对着 SPEC 走,跑第 4 步定义的 check,没过就改到过。
- 交付前加一道对抗式复查:让一个全新 context 的 subagent 只看 diff 和 SPEC,逐条核对"每条需求是否实现、列出的边界情况是否有测试、有没有改到 scope 之外的东西",只报影响正确性或违反需求的 gap,不报风格偏好。(可直接用
/code-review。)
注意别过度:一个被要求"找问题"的复查者总能找出点什么,别为每条都加抽象层和防御代码。只追那些真影响正确性或既定需求的。
几个要主动规避的坑
- trust-then-verify gap:实现看着像模像样,却没处理边界。解法就是第 4 步——没有能验证的 check,就别交付。
- 无尽探索:让 Claude "调研一下"却不限定范围,它会读几百个文件把 context 填满。解法:把探索范围切窄,或丢给 subagent。
- 一锅烩会话:在同一个会话里穿插无关任务,context 被噪声污染。解法:无关任务之间
/clear。
- 反复纠偏:同一个问题纠正两次还不对,说明 context 已经被失败的尝试污染了。解法:
/clear,带着学到的东西重写一个更精确的 prompt。
规则是起点,不是教条
这套流程在多数长任务上好用,但不是铁律。有时该让 context 一直攒着,因为你正啃一个复杂问题、那段历史很重要;有时任务本就是探索性的,跳过规划直接上反而对;有时一句含糊的提示恰恰是对的,你想先看看 Claude 怎么理解再决定要不要框住它。
留心什么管用:Claude 干得漂亮时,回想你怎么写的 prompt、给了哪些 context、用的哪个模式;它卡壳时,反思是不是提示太空、任务一口吃不下。慢慢长出那种没有指南能教的直觉——什么时候该说细、什么时候该留白,什么时候该立规范、什么时候该放它去探索。