上一篇我们把需求拆成了五个槽位,目标是把“代码必须选一条路,而你没指定”的那些分叉点收回来,自己决定。但那说的是 决定发生在哪一层,还没说 决定发生在什么时候。

同一个决定,在你动手之前做,和它已经写完代码之后再做,代价差得很远。计划就是把这个时间点往前挪的东西。这一篇讲四件事:计划里该写清什么、怎么读才能发现它搞错了你的项目、哪些任务值得先规划,以及结果不对时该退回计划还是就地打补丁。

一、计划改变的不是它有多聪明,而是任务的性质

不要求计划时,模型在一轮里要同时干完七件事:理解需求、翻你的代码库、定方案、权衡取舍、拆成步骤、执行、验证。前三件属于“想清楚要做什么”,后两件属于“把它做出来”,它们被压在同一次生成里,用的还是同一份上下文。

先要一份计划,等于把“想清楚”单独拎出来做一轮。执行那一轮面对的任务就从“自己想明白要做什么”变成“按这份计划实现”。前者是生成,后者是核对——而模型在核对上通常比在凭空生成上更可靠。这一点和第一篇讲的“正确性由谁定义”是同一回事,只是这里把定义提前了。

更实际的一点是审查成本。一份计划通常只有十几行到几十行文字,读它、改它、推翻它都很便宜;而一份已经改好的 diff,你要在别人的错误判断之上重建意图,再逐行判断对错。计划里那句话写错了,你改一句话就行;同样的判断错误落进代码,就得先拆掉它。

二、让“先看再动”变成工具的约束

有的工具把这个流程做成了一个具体的状态,通常叫 Plan Mode(计划模式)。在 Cursor 和 Claude Code 里,它都是一个只读状态:模型可以读文件、搜代码库、跑只读命令,但在你批准之前不能改你的源码 12。

它的流程大致固定:先提问澄清需求,再研究代码库,然后产出一份可以编辑的计划,你改完再点执行 1。在 Claude Code 里用 Shift+Tab 循环到 plan 模式,或者在单条消息前加 /plan,也可以用 claude --permission-mode plan 直接以这个模式启动;计划出来时按 Ctrl+G 可以在编辑器里直接改,改完再批准 2。

为什么“只读”这件事本身重要?不是因为模型会乱改,而是因为计划要能被审,前提就是它在被审之前不能执行。否则它会一边告诉你打算这么做,一边已经做完了——你审的就不是计划,而是既成事实。

三、一份能被审的计划,至少要写清四件事

继续用上一篇那个压缩脚本的例子。假设你要给它加一个“按 EXIF 拍摄日期重命名”的功能,一份值得读的计划应该包含:

第一,改哪些文件、每个文件和为什么。 这是唯一你能直接对着自己项目核对的字段。Cursor 的计划会给出文件路径和代码引用 1;Claude Code 那边的建议是点名要改的文件、工作的顺序,以及拿什么测试证明它对了——标准是“一个没看过这场对话的同事,光看这份计划就能把改动做出来” 4。

第二,顺序和依赖。 哪一步必须排在哪一步前面。比如必须先改读取日期的那层,再改输出文件名的逻辑,顺序颠倒会把中间状态写成错的。

第三,每一步做完,怎么知道它是对的。 不是“实现完成”,而是“跑 python compress.py --rename,output/ 里的文件名变成 2024-03-11_143022.jpg 这种形式”。

第四,它当成真的那些前提。 这是最容易被跳过、也最值钱的一条。计划里凡是出现“复用现有的 read_exif 函数”“这里已经是异步调用”“配置从 settings.py 读”这类句子,那都不是设计意见,而是它对你项目现状的 断言。断言有真假,而假断言后面所有的步骤都会歪。

四、怎么读:审它对项目的断言,而不是审步骤

读计划时最容易犯的错,是问“这些步骤听起来合理吗”。步骤几乎总是听起来合理的——不合理的那部分恰恰是你不知道的东西。你要问的是另一个问题:它关于我这个仓库的每一句话,是真的吗?

具体看四处 3:

  • 它点名要改的文件,是不是你自己也会点名的那几个?还是名字很像、其实猜的?
  • 有没有一个人扫一眼就能看出的依赖被它跳过了?
  • 后面某一步,是不是假设了前面某一步从没做过的事?
  • 它提到的“现有函数”“现有字段”,真的存在吗?打不开文件确认一下,比批准之后再发现便宜得多。

有两个动作很值得养成。批准之前至少改一行,哪怕只是删掉一个你并不需要的步骤——因为要删,你就得先读完 3。以及 直接追问三个问题:这个改动可能弄坏什么?哪一步风险最高?你还考虑过哪些做法但放弃了?4 最后这个问题的答案,往往是计划里最没有写出来的部分,而它经常正好是你本来想说的话。

五、什么时候值得先规划,什么时候不值得

Cursor 的文档列了四类最值得用的场景:有多个合理方案的复杂功能、改动跨多个文件或系统、需求不清得先探索才知道范围、以及你想先评审架构决策 1。

但更好用的判断只有一句:动手之前,你说得出这次要改哪几个文件吗?

说得出,计划多半只是在复述你已经做过的决定,同样这点时间花在直接点名文件、把完成标准写进需求里更划算。说不出,那正是该规划的理由——不是因为你不知道怎么组织工作,而是因为你还不知道这件事有多大 3。

反过来,这几类不值得:改错别字、升版本号、改一行配置、你已经做过很多次的小改动;以及调试场景——这时候目标是发现哪里坏了,而不是执行一个已知的改动。这类任务反馈快、错了也好退,多一轮规划只是纯开销 5。

六、结果不对时:退回计划,还是就地打补丁

这是计划最容易失效的地方,而且失败的方式很隐蔽。

当它做出来的东西不像你要的,最省事的做法显然是再补一句:“把 XX 改一下。”每次补丁看起来都比重跑一遍便宜。但它真正的成本不在这一次:每一个补丁都在改一份计划从来没有描述过的代码。三轮之后,计划和你实际在跑的东西已经不一致——你失去了原本用来核对的那个基准,而且后面每一轮都在为同一个错前提付利息 3。

所以先分清是哪一种不对:

绘制中

方向错了,就退回计划。Cursor 官方给的建议正是这个:与其用追加提示去修一个跑到一半的 agent,不如回退改动、把计划写得更具体、再跑一遍——通常更快,结果也更干净 1。而且在你写新提示词之前,先看一遍已批准的那份计划,出问题的地方往往正是计划含糊的地方,要补的是计划里的一句话,不是一条更聪明的提示词 3。

方向对、只是局部现实和计划不一样,就不该硬推计划。比如代码库里已经有一套自己的命名或错误处理方式,而计划里写的是另一种;这时候让代码来纠正计划,先去看那处写法再决定 6。但调整完要把计划同步更新掉,别让计划和代码各说各话 4。

收尾:三句自检

下次计划摆在面前时,问自己三件事:

  1. 它点名的文件,是不是我自己会点的那几个?
  2. 里面每一句“现有的……”,我真的见过吗?
  3. 结果不对时,我是先回去看计划,还是先去改代码?

先要计划的价值不在于计划写得漂亮,而在于它把错误从“已经写进代码”提前到了“还写在纸上”。