说实话我也不知道这套东西行不行。
我自己被AI编程折腾了挺久,从最早用Cursor,到后来重度依赖Claude Code,中间踩过的坑能填平一整个太平洋。有一段时间我甚至有点抗拒,因为那个感觉太熟悉了,你让AI改个东西,它咔咔咔给你一顿改,第一眼看好像没问题,再往下跑发现新bug,你让它修,它又给你改出新的,来回几次之后整个项目乱成一锅粥,最后你只能咬牙全部回退,自己重写。
这种「越改越烂」的体感,我相信每个深度用AI编程的人都遇到过。
我憋了挺久,一直想搞明白这到底是怎么回事。是AI太笨?是prompt写得不好?是模型不够强?后来我发现都不是,或者说,这些都是表象。
真正的答案是个数学问题。
而且一旦你看懂了这个数学问题,很多事就豁然开朗了,包括为什么要写CLAUDE.md,为什么要用worktree,为什么那些工程实践一个个都那么「反直觉」地严格。它们不是玄学,是在解同一个方程。
今天我就把这套我自己总结的框架掏出来。不一定对,我自己也还在摸索,你凑合看。
我先抛个公式,别怕,很简单。
假设AI每一步出错的概率是p,连续做N步的任务,整体成功率是多少?
不是1-p,是(1-p)的N次方。
每一步的成功是相乘的关系,不是相加。
这就很要命了。我们直觉上觉得「每步90%成功率已经很高了啊」,但你是连乘的。假设p等于10%,也就是每步成功率90%,听着不错吧???
N等于10步,成功率0.9的10次方,大概是60%。N等于30步,21%。N等于50步,7.7%。
50步的任务,每步都九成把握,最后只有不到8%的概率一次过。
你看明白了吗,这玩意不是线性下降,是指数崩塌。步数一长,不管你单步多准,整体都会塌。
而且每一步的p还不一样。改个配置文件的p很小,做个架构调整的p很大。指令清晰的时候p小,信息过载的时候p大。更要命的是,前面的错误会传导到后面,前面错了后面基本就是错上加错,pᵢ会被前序的失败顶上去。同时这个p还会因为环境漂移,项目架构变了模块新增了文档没同步,整体往上爬。
所以我后来想明白一件事,AI编程的所有问题,说到底都在跟这个连乘公式搏斗。你要么把p降下来,要么把N降下来,要么承认p降不到0于是控制失败的成本,要么对抗p随时间漂移。
我把它们叫四大职能。
降低pᵢ,让单次更准。降低N,让步骤更少。降低失败成本,让失败可回滚。自我演化,对抗pᵢ漂移。
我们一个个聊。
先说降低pᵢ,这是最直觉的一个,就是让每一步更准。
但这里有个反直觉的点。降低pᵢ不是靠「让AI更聪明」,是靠「把判断变成约束」。AI最不擅长的是判断,最不会出错的是执行明确的规则。所以降低pᵢ的核心动作,是把那些需要AI判断的地方,要么变成它不用判断的约束,要么变成能被立刻检测出来的检查。
我自己的体感,这一块分三个时机,执行前、执行中、执行后。
执行前最大的坑,是目标太模糊。「加个验证」「修个bug」,这种话你跟人说都得再确认半天,跟AI说AI就只能猜。猜错的概率有多高你想想看。
所以我后来强制自己把模糊目标翻译成可验证目标。「加验证」变成「先写一组针对非法输入的测试,然后让测试通过」。这样AI就没有理解歧义的空间了,做完了你跑一下测试就知道对没对。
做多步任务也是,先让它列个计划,每一步后面跟一个「怎么验证这一步做对了」。没有计划的时候,AI是一边走一边决策,走偏了你要到最后才发现,回退起来代价巨大。有计划,每步有验证标准,偏了立马能抓住。
这里其实有个很关键的认知,做和检查应该是一个原子操作,不是先做完再检查。你把检查能力前置、强化,pᵢ本身就降下来了,因为AI在做的过程中就知道边界在哪。还有一个细节,要给AI一个明确的停止条件,DONE就是做完了,BLOCKED是卡住了,NEEDS_CONTEXT是需要更多信息,别让它收一个「差不多做完了」的尾,「差不多做完了」不是个合法状态,那是任务实际没完成你还得跟在屁股后面追。
执行中的坑更多,而且都是那种「顺手」的坑。
AI特别喜欢顺手干点别的。你让它改A,它顺手把B也优化了一下,顺手把注释整理了,顺手把格式调了。每一个「顺手」都是在往diff里塞你没要求的东西,塞着塞着,真正的改动就被淹没了,审查的时候你根本注意不到它在哪偷偷引入了一个bug。
所以有一条铁律,不要顺手改相邻代码、注释、格式。每一行改动都得能追溯到你的原始请求。
还有一类坑是它特别爱「预防性设计」。你只让它做一个一次性的小功能,它给你抽出来三层抽象,建了几个接口,留了一堆扩展点。这玩意不是帮你,是在给你埋雷。不必要的抽象会让后面的步骤pᵢ全部上升,因为代码更绕了,AI要理解的路径更多了。
200行能写完的东西如果它给你写成50行你就让它重写,别心疼。
警告也是。lint的警告、类型检查的警告、编译器的警告,AI特别容易忽略它们觉得「无所谓」。但你放任警告堆积,真正的问题就会被淹没,等到哪天一个关键警告被淹在一堆无所谓的警告里,bug就漏过去了。不留警告,每一个都修。
注释掉的代码直接删。别留着觉得「万一以后用得上」。注释掉的代码依然是上下文,AI读着读着可能就基于这段死代码做决策了,这是实打实的污染。替换而不是废弃,旧实现该删就删干净,别留着加一层兼容shim,两条路径比一条路径更容易出错。
执行后就是验证。这块我必须强调一个事,bug修复一定要附带一个能捕获这个bug的测试。没测试等于没做完,因为未来某次修改它可能又把同一个bug引回来,没有回归测试你根本不知道。
而且测试本身要有效。怎么验证测试有效?先故意把代码改坏,确认测试会失败,再把代码改回来。如果你改坏了测试还过,那这个测试什么都没测到,是废的。
测行为别测实现,测边界别只测happy path,mock只mock外部边界别mock内部逻辑。这几条随便一条破了,测试就变成安慰剂,比没测试还坑。提交之前再重读一遍自己的改动,AI是一步步堆出来的代码,很容易堆出不必要的复杂度,重读一眼常常能揪出来。
接下来说降低N,这个其实跟降低pᵢ同等重要,因为N也是指数项。
很多人没意识到,N不只包括「往前走的步骤」,还包括「搜索的步骤」「沟通的步骤」「回退的步骤」。把这些都算上,一个看着不复杂的任务,N可能大得吓人。
降低N最猛的一招,是skill。skill这个东西说到底就是把一个多步决策的流程封装成单次调用,直接把N压到1。
你想想看,没有skill的时候,AI做一个事要经历什么,理解需求、搜索相关代码、制定方案、逐步实现、再验证,每一步都有pᵢ,N也大。有了skill,预制好的流程一调用,中间所有决策点全跳过。这就是为什么重复做的事情一定要封装成skill,做两次是偶然,做第三次就该封装了,手动流程每次都得让AI重新决策一遍,N从k降成1,这笔账怎么算都划算。
搜依赖也有讲究,按标准库、热门库、自写这个顺序来。标准库和热门库是调接口,几行代码的事,自写是设计加实现加测试,代码量翻几十倍。代码量少出错面就小,N也短。加依赖之前先查一下当前稳定版本,别从记忆里假设,模型训练数据有时滞,你脑子里那个版本号可能早就过时了,用过时版本API不兼容,又是一通折腾。
实现一个功能之前,先去看看项目里类似功能是怎么做的,照着已有的模式来。自己从头设计加实现加调试,跟参照已有模式微调,差的步骤数不是一个量级。AI自己设计的东西你还得多审几遍,照着抄的几乎不用审。
搜索代码也别瞎搜。搜代码结构用AST级别的工具,搜字面量用文本工具,用错了误匹配一堆,得反复搜,N白白涨上去。大文件先grep定位行号,再读目标范围,别从头到尾重读整个文件。
沟通也要省。跟人协作用文件名加行号引用,别说「那个函数大概在前面」,直接甩src/auth.py第42行,对方一步到位。还有,连续性任务的回复以「下一步动作」结尾,别回顾总结。回顾不产生任何进展,纯粹浪费回合。
第三个,降低失败成本。这一块我个人觉得是四个里最被低估的。
为什么?因为前两个是「努力让事情做对」,这一个的前提是「事情一定会做错」。pᵢ降不到0,失败必然发生,那关键就不在「会不会失败」,而在「失败的时候代价多大」。
失败成本等于不可逆程度乘以影响范围乘以修复时间。这三个维度每一个都能砍。
不可逆程度,最简单的,每改一步就git提交,一条commit只做一件事。这样任意一步炸了,你能精准回退到上一步,而不是整个人类文明回退到「我把文件备份到桌面那个文件夹里」的状态。破坏性操作必须确认,rm -rf、git reset --hard、DROP TABLE、kubectl delete这种,执行前一定停下来问一下,因为这种操作一旦走错,成本是无限大。能用trash别用rm,误删了还能从回收站捞回来,不可逆直接降成可逆。
影响范围,并行跑多个子Agent的时候,每个都要用独立的worktree,谁也别踩谁的脚,一个炸了不连累其他。别直接推main,用feature分支,分支失败跟主干没关系,影响范围归零。
修复时间,这一条我深有体会。AI连续两次修正还是错的时候,别再让它改第三次。在错误的基础上堆叠修补只会越改越乱,你会陷入那种「再改一次就好了」的执念,其实越改越远。回退到上一个已知正确的提交点,重新来。放弃沉没成本才是最快的修复。
最后一个,自我演化,这个最玄,但也最长期。
pᵢ不是恒定的。它会随时间漂移,往上涨。原因有两个,一个是规则本身过时了,一个是上下文被污染了。
规则过时好理解。你项目架构调整了,模块换位置了,但CLAUDE.md里写的还是老路径。AI照着老规则走,基于错误前提开发,pᵢ直接上去。所以有个原则,发现规则跟代码实际情况矛盾的时候,别闷头遵循,主动报告。你这一报告,过时的规则就暴露出来了,才能被修。
写新规则进memory的时候,记得把被它纠正的旧规则标记成过时。不然新旧两条矛盾的规则同时躺在那儿,下次会话AI又懵了,pᵢ又上去。
上下文污染更隐蔽。死代码、注释掉的代码、废弃的方案、文档里写了但实际没实现的功能,这些东西都是污染。AI读上下文的时候没法区分「这是现在的」「这是过去的」,它把所有信息都当当前选项,基于过时信息做决策,pᵢ上升。
所以注释掉的代码删掉,废弃的方案别留档,文档跟代码不一致就同步更新,一个会话只干一个任务范围的事,干完就结束或者压缩,过时的计划文件随手删。这些都是在保持上下文新鲜。
聊到这儿得说一个区分,软规则和硬规则。
CLAUDE.md、AGENTS.md里写的那些,是软规则,靠上下文引导AI的偏好,能降低pᵢ,但降不到0,因为AI还是可能不听。hooks、CI、linter这些是硬规则,直接从工程上把某些错误路径堵死,pᵢ直接等于0。
选哪个的原则很简单。能被工具检测的错误,上硬规则。只能靠判断力避免的错误,留软规则。高危又能检测的,软硬双保险。
而且这个比例是会演进的。项目初期CLAUDE.md里写满软规则,大部分靠AI自觉。成熟之后,可检测的软规则一个个升级成硬规则,CLAUDE.md只剩判断力类的那点东西。人的注意力投资方向也跟着变,从写软规则,到配硬规则,最后只维护硬规则加少量判断力。
写到最后我聊点形而上的。
人其实一直在跟这个连乘公式搏斗,只不过以前不自觉。
飞机驾驶舱为什么有checklist?因为飞行任务N很大,每一步pᵢ不能高,靠人记忆会出错,checklist就是把这些高pᵢ步骤固化成pᵢ等于0的硬规则。医院手术前为什么要数纱布?同理。工厂流水线为什么要SOP?同理。三权分立为什么是三权不是一权?因为权力集中pᵢ太高,分立是降低单点失败的成本。
人类文明搞出的所有制度、流程、规范,拆开看都在做这四件事,降pᵢ、降N、控失败成本、自我演化。AI编程这个新场景,不过是把这个古老的问题又搬出来重解了一遍。
而且有个趋势我觉得挺重要。Harness这四大职能的终极目标,不是让AI更强,是减少完成单位任务所需的人的注意力。
人的注意力是稀缺的,一个人同时只能盯一个Agent的输出,盯久了还会疲劳,疲劳了审查质量就下降,pᵢ反弹。每次人工干预都是成本。
所以你看这个演进路径。现在我们是逐条审批逐次纠偏,注意力消耗很高,人盯单Agent。近期会变成调度者,管多个Agent,关注调度和结果不管过程。远期就是目标定义者和约束设计者,只在关键节点介入。
核心不是不需要人,是人的注意力从「消耗在每次操作上」转向「投资在约束和规则上」。你今天花一小时写一条CLAUDE.md规则或者配一个hook,省下来的是未来无数次的人工干预。
这才是这套框架真正划算的地方。短期看是给自己找麻烦,长期看是把自己从无穷无尽的纠偏里解放出来。
我也不知道这套东西你用不用得上,反正我是真这么想的,也真这么在用。哪天你要是也被AI改到崩溃,回过头来看看这四个字,降低pᵢ,降低N,降低失败成本,自我演化,没准能帮你从那个坑里爬出来。
以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧,如果想第一时间收到推送,也可以给我个星标⭐~谢谢你看我的文章,我们,下次再见。
夜雨聆风