2026 · 软件工程 · 一篇 4 页的实测
我们习惯了“让 agent 记住教训”这套说法:踩过的坑写进说明书,下次就不会再踩。这篇论文把它拿到实验台上量了一遍,结果比想象中难看。
现在的“自我进化”只做到了一半:它会写下提案,但不知道提案有没有用。缺的不是动手能力,是验收能力。
研究对象是一个叫 /retro 的技能:让编码助手在干完活之后,回头看一遍自己刚才的整个过程,然后提出几条“下次应该怎么改”的建议。这里的“改”不是改模型,而是改它工作时的外挂配置——比如一份项目说明书、一个提交前自动跑的检查脚本、一份“哪些测试本来就会挂”的清单。
这套设计的关键在于:它不看“建议写得好不好”,只看“行为有没有变”。
按“改什么”分类,最常见的不是写规矩,而是加自动检查:
再看“为什么提”:125 条里有 101 条能对应到那次会话里真实发生的事——比如它真的试了 pytest,然后发现没装。这部分是扎实的。
19 条和会话里发生了什么无关,属于“凭常识觉得应该这样”。其中 18 条是代码风格检查。原因很直白:/retro 自己的指令里写着,“仓库既没有提交前检查、也没有 CI 检查”就算一条发现。
也就是说,工具把自己的偏好,包装成了经验。它不是在总结你踩的坑,是在推销它认为的好习惯。
还有个细节:38 条“自动检查”里,只有 9 条在任务环境里真能跑起来报错。28 条需要的工具根本没装,或者因为任务过程里压根没有提交动作,那个钩子从未被触发过。写下来的防线,大部分是纸做的。
13 次复测里,7 次真的复现了要防的那个问题,才算有效数据。每次 10 个会话:左边 5 个是原配置,右边 5 个是改过的配置。一个实心点代表“又犯了”。
前三格是 7 次有效复测的分布;第四格是另外挑无关任务做的对照实验,用来检查改动会不会凭空制造工作。
看出规律了吗:凡是“清单正好写中了后来遇到的那几个失败”,就 0 次;凡是“后来遇到的是清单外的失败”,就一次没少。改动本身没错,是它的适用范围太窄。
同样写进说明书,两种东西的命运完全不同:
一直成立
“测试跑 bin/test,没装 pytest。”
换个 bug 还是这个仓库,这句话依然对。5 次里 5 次犯,改完 0 次。这是唯一稳赢的一类。
很快过期
“这 3 个测试挂了,因为 docutils 版本不对。”
换个 bug、换批测试,这份清单就不适用了。更糟的是它会被当成权威——清单外的失败,一律判定为“我自己改坏的”。
那个对照实验最能说明问题:一份不完整的清单,让 4 个会话在根本不需要验证的任务上,跑去做了它本来要避免的基线对比。原本 0 次,改完 4 次。规则没消除工作,它制造了工作。
SymPy 那条最有代表性——同一份建议里写了两行:第一行“测试用 bin/test”,第二行“结束前跑一遍代码风格检查”。前半句是收益,后半句是纯成本。结果所有会话都跑了风格检查,中位耗时从 88 秒涨到 156 秒。建议天生喜欢打包,评测却应该拆开看。
作者写得挺克制,但作为读者得知道这份证据有多重:
这篇本质上是在给所有“让 AI 记住教训”的做法做体检。落成四条能直接用的:
“测试命令是 bin/test”能活很久;“这三个测试挂了”下个月就是错的,而且错得有害。
把收益和成本焊在一起,测出来永远是负的。风格检查那句就是活教材。
目标问题真的出现了吗 → 规则被读到了吗 → 动作真的变了吗。只做到第二关,是最常见的假阳性:文件躺在上下文里,人该干嘛还干嘛。
19 条凭常识的建议,18 条是风格检查,一条都没证明有用。想加可以,别叫它“经验”。
作者的落点也是这个:自我进化真正缺的不是“生成改动”,而是“判断改动有没有用、并且敢于把没用的删掉”。没有这一环,长期积累的结果大概是——说明书越来越长,行为越来越像没改过。