
3 月 28 日上午,我让 Codex 审一个自己写的 Python CLI,从 7:49 审到 10:18,一共 10 轮。每轮用的都是同一句 prompt:review代码,模块拆分不合理,单体大文件,圈复杂度高。
第 4 轮时我问它,为什么每轮都能找到新问题。它说每次重构都重新划了模块边界,新接缝会暴露旧问题。我当时接受了这个解释,后来写《我让 AI 审了自己的代码,审了 10 轮》也是这么写的。
10 月 15 日,Claude Code 团队在 claude.dev 博客上讲了他们怎么做代码审查。一个 CLI 的 PR 审了改、改了审,一夜跑了五十多轮,最后是作者叫停的。他们对 reviewer 反复标出的东西跑了 git blame,约 59% 落在 reviewer 第一次看时就已经在的代码上。他们的结论是 reviewer 很少找到新 bug,每轮都在旧代码里又多翻出几个。
我回去翻那 10 轮的记录。第 7 轮拆的 config_store.py,前 6 轮没碰过。第 8 轮发现三个 formatter 各写了一遍查询摘要,当时我在那篇里写的原因是前几轮只盯着大文件,没看跨文件的重复。这两处用“结构在演化”都解释不通:一个文件没人动过,一处重复是没往那儿看。
再看那句 prompt。“模块拆分不合理,单体大文件,圈复杂度高”,三个结论我先替它下了,它要做的只是把证据找出来。拆到第 9 轮,它报的是 where/cond 解析在 command 层和 service 层各写了一份。照这句 prompt 的标准,仓库里总能挑出一个比别处大一点、绕一点的地方。
systematicls 3 月发过一篇讲 agentic engineering 的长文,在讲 sycophancy(讨好用户)的那节里写:你说 “Find me a bug”,它就会给你找一个,哪怕得自己造。我那句 prompt 是同一种问法,只是把“bug”换成了“拆分不合理”。
PR 作者也是 agent 的话,麻烦更大。Claude Code 团队那篇写,人看到一条 nit 几秒就放过去,agent 会去改,改完多一个 commit,又触发一轮审查。我那 10 轮里改代码的也是 Codex。第 1 轮它为了兼容测试写了个时区钩子,第 2 轮拆文件时踩上去,210 个测试挂了 1 个,报 RecursionError,又得先修它。
Claude Code 团队后来给重审加了几条规则,我最想照搬的是第一条:审到第三轮,reviewer 停下来,请作者退一步重新考虑方案。另外几条是前几轮之后只看新 diff,同类问题一次标完,贴过的不再贴。
规则上线前后,内部 PR 平均审几次能通过,从 2.08 降到 1.32,要审五轮及以上的 PR 从 8.9% 降到 1.5%。这组数在文中一张图里,没给统计时间段和样本量,我只把它当方向看。文中写明的优先级是先抓真 bug,再减轮数,还会把 reviewer 放到已知没问题的 PR 上跑,数它有多少次会让人去做有害的修改。
我打算把派活那句换成 systematicls 给的中性写法:沿着每个组件的逻辑走一遍,报告所有发现。按那篇的说法,这样问出来的东西有时是 bug,有时只是一段代码怎么运行的说明。
Claude Code 团队还提到,写得好的 REVIEW.md 会要求总结先写数量,没东西可修就直说,每条问题给文件和行号做证据。我会在 prompt 末尾加一行:第一行写发现了几个问题,没有就写 0,再逐条列出文件和行号。

轮数我还没想清楚该卡在哪。他们定的是三轮,zhu327 在 Pi 上做 loop 时也规定单次循环最多 3 轮聚焦修复,超过就暂停报告。我打算先按三轮来,第三轮后把剩下的问题分成两堆:这几轮改动带出来的,和第一轮就在的。第一轮就在的那堆不再让它接着修,回去改 prompt 重审。
这套改法我还没拿那个 CLI 重跑过,10 轮能压到几轮,现在说不准。