提出人机结对的核心分工:你拥有目标和上下文,模型负责转录、枚举和初稿;给出了具体步骤,包括先用验收测试描述目标、要求计划而非代码等。
这个说法暗示的是两个平等的搭档,但实际上截然不同——真正有效的方法恰恰来自于认真对待这种差异,而不是假装差异不存在。
在人类结对编程中,driver 拿着键盘并掌握上下文,navigator 保持视角。而在这里,driver 速度快、不知疲倦、博闻强识,却对结果没有任何利害关系、没有上周的记忆、也不知道任何你没有展示给它的东西。你拥有所有上下文,却不动一根手指。
这种颠倒决定了分工。你拥有目标、验收标准、约束条件,以及关于何时停下来的判断权。它拥有转录、API 表面的回忆、列举各种情况,以及初稿。当事情变糟时,往往是因为你向上委托了——让它来决定"完成"意味着什么——或者向下囤积,把本来它能敲的字留在那里,自己一个字一个字地盯着。
先用一句话陈述验收标准。最好写成一个尚未通过的测试。"用同一个幂等键调用 issueInvoice 两次,只创建一个 invoice。"如果你写不出这句话,这场结对不会顺利,而现在发现这个问题代价为零。
问计划,不要代码。五条要点,说明它打算修改哪些文件。明确说:还不到写代码的时候。
纠正这个计划。这是人们跳过但却包含整个方法价值的步骤。见下方详解。
一次只做一个改动,小到可以读完。如果 diff 超过一屏,说明范围太大了——说出来然后拆开,而不是读得一塌糊涂。
自己跑测试。不是"看起来对不对",不是模型说"测试通过了"的报告。你的终端,你的眼睛,每次都这样。
每次 green 就提交。后续可以 squash 成小提交。提交就是 undo,而有便宜的 undo 才让第 5 步的停止规则成为可能。
纠正一个计划是四句阅读加一句回复——算它三十秒。同样的误解等它变成 300 行代码后再纠正,意味着读 diff、找出哪部分错了、解释、再读修订版:乐观估计也要二十分钟,而且可能漏掉一部分。
比例大约是四十比一,而且信息量是一样的。一场结对感觉顺畅高效还是陷入"不,不是这样"的痛苦循环,完全取决于纠正是发生在第 3 步还是第 5 步。
具体来说,计划中需要关注这些:它打算修改的文件中让你意外的(它误解了架构)、它没提到但你知道必须改的文件(它看不到这些——修复上下文,不是修复计划)、写着"更新测试"但测试本应驱动的步骤,以及任何模糊的、困难的部分。计划中的模糊是模型什么都没有、在拖延的信号。
有一个表述值得在每次结对中都占有一席之地:在你写任何东西之前,告诉我你需要知道什么是你现在不知道的。答案往往是缺失的约束,而提供它的代价远低于看它猜测。
"知道何时停止"是无用的建议。以下是可观察的事件;一旦触发,就停下来,git reset --hard 到上一个 green 提交,要么重新框定范围,要么自己来。
连续两次修复都没有让失败的测试移动。这和自动化循环中的无进展规则是同一条件,应用于人类驱动的结对时同理。两次失败的尝试意味着模型的问题模型是错的,从同样的理解出发第三次尝试也会失败。
你无法解释的修复。测试 green 了,但你不知道为什么。这不是成功;这是你代码库中一个无法解释的状态变更。要么用一句话讲清因果链,要么回退。
diff 在增长但测试持续 red。添加的东西在累积但失败没有移动,说明它在尝试各种东西。尝试是昂贵的,而且不会收敛。
它问你一个它本应已经知道的东西。"Invoice 类型长什么样?"——明明你给过它那个文件。这是上下文问题——文件被埋了、transcript 太长、或者结对已经跑偏了——再多的重新 prompt 也修复不了上下文问题。
第三次一致却没有行为改变。对你的纠正表现出热情接受,随后的代码却实质相同。模型没有办法发出"我不知道怎么做这个"的信号,而这,就是它不知道时的样子。
这些值得写下来的原因是沉没成本。在一个你估计 15 分钟但已经花了 25 分钟的任务上,继续做下去感觉离完成更近了,重新开始则感觉更远。实则不然:此后的预期时间取决于当前方法是否能工作,而那二十五分钟无论如何都回不来了。不过你获得的确实是真实的——你现在知道了失败模式、涉及的文件和错误答案的形状。带着这些知识回退并重新开始通常比继续更快,而且正因为你在每次 green 时都提交了,它才变得便宜。
话题切换时开新 session。transcript 携带着过时的前提——你已经改过的文件、你放弃的方法、不再成立的约束——而模型会继续尊重它们,这是长 session 越来越糟的机制之一。成本也是二次方的。
不要委托验收标准、安全边界或合并的决定。这三样东西出错代价高昂,而模型没有利害关系。
说出你尝试过并拒绝了的方案。没有这句话,你会被再次自信地提供同样的东西。
把 repo instruction 文件作为持久记忆。任何你在第三次结对时还要解释的东西,都应该放进那个每个 session 都会读的文件,而不是放在这个 transcript 里。
最后一句实在的话:这是一个方法,不是一个主张。它让结对不那么令人沮丧,让失败更早显现,这本身就值得拥有。它是否让你更快,取决于你处于哪类工作,而相关证据确实参差不齐——包括一项随机试验,其中经验丰富的开发者变慢了,同时却相信自己变快了。上述方法不会替你解决这个问题。它能做到的是:让它不工作的那个时刻在五分钟而不是五十分钟时到来。