先规划,后写码:开写之前,先把「完成」拆成能逐条验的清单
Skill 逐篇系列前面讲的都是绑在某个阶段上的 skill——澄清链在澄清阶段用,implement-task 在实现阶段用。从这篇起是通用组:七份不绑阶段的 skill,任何任务、任何时候都能单独拿出来用。第一份是 plan-before-code,管的是一件听起来最不像"技术"的事:**动手之前先规划。**母篇是《从能跑到可交付:一套前端 AI 协作系统的设计笔记
》,我用的系统是开源的 frontend-harness-cli
,这份 skill 在仓库的 templates/skills/plan-before-code/ 里。
十秒就开写,三百行后撞墙
先看一个具体的场景。
你说:给订单列表加一个导出功能。AI 几乎没有停顿就开始写:导出按钮、格式选择弹窗、生成 CSV 的工具函数、进度条——写得很顺,三百行出去了。
然后它撞墙了:导出需要用户的权限字段,接口没返回;导出的列要按财务的模板来,模板长什么样没人给过它;导出的是当前页还是全部,它自己选了全部,结果数据量大到要走异步任务。它前面写的三百行,有一半建在不存在的数据和没做过的决定上。
你让它总结一下计划,它能补出一份——听起来头头是道,但和已经写下的代码对不上:计划里说"先校验权限",代码里根本没有这一步。这份计划不是写在代码前面的,它是照着代码编出来的。 编出来的计划什么都证明不了,因为它不可能和代码不一致——它就是从代码倒推出来的。
这份 skill 的开头第一句就是针对这个场景的:不要从一句模糊的话开始(“Never start from a vague sentence”)。它要堵住的正是"十秒开写":在写第一行代码之前,先把"做到什么样才算完成"谈清楚,写成一份第三方能逐条验证的清单。
这份 skill 是什么:不绑阶段的规划纪律
先说它和澄清链的关系,不然容易混。
澄清阶段里有一整条链在做规划:访谈、写 PRD、写开发计划(write-dev-plan),那是功能规模的、嵌在状态机里的重型流程。但现实里大量任务不在这条流水线上:你临时让 AI 改一个页面、加一个小功能、修一处牵涉多文件的毛病——没有澄清阶段,没有规划者角色,只有一个上下文和一句话需求。
plan-before-code 是把同一条纪律抽出来,做成任何人(或任何 AI)在任何任务上都能独立执行的轻量版:一份计划,七个步骤,不依赖内核、不依赖其他文件。它自己的适用和不适用写得很明确:
该用的时候:新功能、新页面、新流程;需求只有一句话、藏着真实决策(“加个设置页"“让结账更快点”);改动牵涉多个文件、组件或数据源;以及一个很诚实的触发条件——你发现自己正要写代码,而验收标准只存在于自己脑子里。
该跳过的时候:一行能改完的修复、纯改名、用户已经给全了可测规格的改动。为一行修复写七步计划,那不叫纪律,叫仪式——这个区别后面还会回来。
怎么干:七步,从一句话目标到逐条判据
这份 skill 的流程是七步,每步都有明确产出,不是"想一想"这种没法查的东西:
第一步,一句话复述目标。 谁做什么、做完之后对他有什么不同。产出是一句话,用户能点头、也能纠正。这句话的作用是把"我以为你要的"摆到桌面上——理解错了,在这一步纠正只要十秒。
第二步,列出未知项。 拿着需求逐项扫缺的决策:空状态长什么样、出错怎么处理、权限怎么判、数据从哪来、边界情况有哪些。产出是一份编号的问题清单。
第三步,未知项逐个解决或写成假设。 会改变设计的去问用户;其余的写成明确假设,记在计划旁边。产出是:每一个未知项,要么有了答案,要么以假设的形式躺在纸上——没有第三种状态。
第四步,拆成功能点(FP)。 把功能拆成一条条功能点,每条固定用这个格式:输入 -> 动作 -> 校验 -> 结果。skill 里给的例子是:「FP-1:用户输入非空标题 -> 点击添加 -> 标题去空格并校验 -> 条目出现在列表里且输入框清空。」产出是一份编号清单,每条都能独立测试。
第五步,写明非目标。 这次改动明确不做什么,产出是一份范围外清单,而且要求至少写一条。
第六步,逐条定义"完成”。 每个 FP 分别说清怎么验:一个测试、一个手动步骤、一个可见结果。产出是每个 FP 一条完成判据——不是一句笼统的"能跑就行"。
第七步,动手前确认。 只要有承重假设(某个假设塌了整个设计就得改),就把计划先给用户看,然后停住。确认过的计划存到团队放计划的地方:文件、issue 或 PR 描述都行。
七步走完的样子,skill 的完成判据说得很死:计划存在之前,没有写任何代码;每个 FP 都能由没写这段代码的人回答"过 / 不过"。
设计一:功能点写行为,不写任务
第四步有一条最容易被违反、也最关键的禁令:不许把功能点写成实现任务。
- ❌「创建组件 X」「加一个 hook Y」——这是任务,描述的是你的活;
- ✅「用户输入非空标题 -> 点击添加 -> …… -> 条目出现在列表里」——这是功能点,描述的是可观察的行为。
区别在哪?任务只能由干活的人自评:组件建出来了,任务就算"完成",至于用户点下去有没有反应,任务里没写。功能点则把验收权交出去了:任何人——用户、测试、另一个 AI——打开页面照着做一遍,就能判过或不过。
这条禁令背后是一个老问题:自述不可信。 五个阶段那组文章里反复出现同一个结构——开发者不能自评、评测要换新鲜上下文——根源都在这里。功能点写成行为,就是在规划这一步先把"谁来判、拿什么判"定死,不给后面的自评留门。
设计二:未知项只有两个出口,问,或者写成假设
需求永远是缺信息的。空状态文案是什么、没权限时是隐藏还是置灰、接口失败重试几次——一句话需求里不会有这些。但代码里必须有:程序运行到那一行,总得做点什么。
所以未知项不会消失,只会换一种形态出现:要么在规划时被问出来或写成假设,要么在写代码时被执行者悄悄发明出来。 skill 的反模式里专门列了这一条:悄悄发明缺失的需求——规格没提,就自己挑一个错误码、一段空状态文案、一条权限规则,而不是去问或记为假设。
悄悄发明为什么危险?因为它伪装成"已经定了"。后面读代码的人——包括验收的人——看到一段处理空状态的代码,会默认这是需求,没人会去追问"这个文案是谁定的"。而写成假设就不一样:假设躺在计划旁边,字面上就是"这是我猜的",用户确认计划时一眼能看见,验收时也能拿它对账。同样是猜,写下来的猜可以被纠正,没写下来的猜会变成事实。
这也是第三步"解决或假设"为什么不许有第三种状态:未知项要么升级成答案,要么降级成留痕的假设。悬在中间的,最后都会从代码里冒出来,还找不到是谁拍的板。
设计三:计划写在代码前面,而且写完要回来对
回到开头的场景:事后补的计划为什么不算数?
因为计划的价值全在顺序上。计划写在代码前面,它是一个预测:我打算碰哪些文件、先做什么、每步怎么验。预测可以错——做到一半发现数据不存在,计划第三步的前提塌了——这时 skill 要求的是停下来改计划、把新发现写进去,而不是闷头把代码改完再把计划修得和代码一样。计划和现实不一致,本身就是最有价值的信号:它说明你对这个系统的理解有一处是错的,而这个错误现在只要改一行字,攒到交付时要改一下午。
反过来,和代码写在同一条消息里的"计划"不算计划。那只是叙述:模型一边写一边解释自己在写什么,解释永远和代码一致,因为它不需要提前承诺任何东西。承诺的标志是可证伪——计划里写了"FP-3 用现有的权限字段判断",打开接口一看没有这个字段,计划当场被证伪。这种"当场被打脸"的可能性,正是计划和叙述的分界线。
还有最后一个反模式,针对的是把计划当仪式:计划写得漂漂亮亮,然后写的是另一套东西,还从不拿结果回来对。计划写完不回来对,等于没有计划——只有第七步确认和做完逐条对 FP,才让这张纸有约束力。仪式化的计划比没计划更坏,因为它让人误以为规划这一步已经做过了。
设计四:和 write-dev-plan 是同一件事,两个尺度
读过澄清链的人会问:write-dev-plan 已经把 PRD 拆成任务了,这份 skill 是不是重复?
不是。两者是同一条纪律的两个尺度:
write-dev-plan在功能尺度上工作:输入是已经确认的 PRD 和技术设计,产出是任务清单,嵌在状态机里,服务于多角色流水线;plan-before-code在任务尺度上工作:输入是一句人话,产出是一张 FP 清单,独立运行,服务于任何一次具体的动手。
它们共享同一个内核:把"完成"提前定义成可逐条验证的条目,把未知项逼到纸面上,把非目标写出来。区别只在重量。流水线里的功能值得起一整条澄清链;临时改一个页面不值得,但"先写清单再动手"这条纪律本身不该因为任务小就豁免——小任务漂移起来,一样能漂掉一下午。
这也是把这份 skill 放在通用组的原因:它不依赖状态机是否存在。没有 Harness 的项目、没有澄清阶段的随手任务,都能直接拿它用——一份计划,七步,仅此而已。
这一份管不了什么
把边界说清。
第一,它管不了计划本身对不对。目标句复述错了、FP 拆漏了一个关键行为、假设猜反了——计划写得再规范,也可能是一份规范地错了的计划。它保证的是"错得可见":错误躺在纸上,用户确认时、验收对账时都有机会抓住;它不保证错误不存在。
第二,它管不了执行走样。计划和代码不一致,靠的是做完逐条对 FP 这一步人工(或评测)去抓;这份 skill 只负责把可对账的账本生产出来,不负责对账本身——对账是verification-before-completion 那份 skill 的事,后面会讲。
第三,它有明确的不适用区:一行修复、纯改名、规格已完整的改动,跳过是正确行为,不是偷懒。对小改动滥用流程,最后的结果是大家对所有流程都阳奉阴违——纪律的信用是会被仪式耗光的。
下一篇讲 context-map:规划之前还有一步——先搞清楚这块代码在整个系统里是什么位置、牵动谁。计划解决"要做什么",地图解决"在哪里做、会碰到谁"。