@tvykruta:我在 Microsoft 和 Google 从事 C 和 C++ 工作多年,审查过数千次代码变更。我亲眼见证过优秀工程师如何……
摘要
一位拥有 Microsoft 和 Google C/C++ 经验的工程师,在真实 PR 上开展了 12 次 AI 代码审查实验,发现:不带任何共享上下文的全新审查 agent 能发现多得多的缺陷;要发现逻辑 bug,执行代码(而不只是阅读)是必不可少的;而模型的选择对性价比的影响,远大于对绝对能力的影响。
查看缓存全文
缓存时间: 2026/10/03 19:03
我在 Microsoft 和 Google 用 C 和 C++ 工作了多年,审阅过成千上万次代码变更。我见过优秀的工程师因为评审者草草扫过代码、点批准然后去吃午饭,而发布糟糕的代码。
现在 AI 写代码的速度是以前的 200 倍。那谁来审这些代码?
如果你在每一次代码变更发布之前没有严格执行三名工程师的代码评审,你根本没有资格构建软件。
开玩笑的。这个说法昨天还是对的。
今天我要回答的问题是:AI 能不能审查 AI 生成的代码?然后我会告诉你如何在每次审查不到一美元的情况下,获得一次出色的、资深水平的、不遗漏细节的审查。
收藏这篇。完整的 REVIEW.md 在下面第一条评论中,直接可以粘贴使用。
结果让我大吃一惊
1/ 我让写这段代码的 AI 会话审查它自己的工作。它只发现了 23 个问题中的 3 个,并且建议合并。然后我在同一个模型上启动了一个全新的智能体,它对写代码这件事没有任何记忆,只给了它 diff。它发现了 23 个中的 17 个。
2/ 只读代码的评审者在功能 PR 中发现了 8 个逻辑错误中的零个。每一个逻辑错误都是由运行了代码的评审者发现的。
3/ 给评审者的指令中添加一条规则,使其从发现 8 个逻辑错误中的 4 个提升到发现 7 个,外加一个之前没人发现的。同一个模型,成本从 $0.72 变成 $0.74,速度快了 27%。
4/ 最贵的模型并不是最划算的选择。Opus 在两个 PR 上的表现与 Fable 持平或更好,而价格只有大约三分之一:每次审查不到 $1 vs. 超过 $2。
5/ 第二天,一个全新的评审智能体在一个有 272 个测试通过、CI 全绿的 PR 中发现了 4 个阻塞性 bug。
6/ “始终获取代码评审“这条指令被写入了智能体的配置中,但这个智能体在第一个 PR 上就跳过了它。
这是一次令人难以置信的解锁。再也不会有 bug 趁着绿色对勾溜进代码库了。
以下是我如何得出这些结论的。
实验设置
• 2 个来自生产代码库的真实 PR。一个是 75 个文件的重构,另一个是 23 个文件的功能开发。 • 共 12 次评审:4 次由已经拥有该工作上下文的 AI 会话完成,8 次由全新的智能体完成(它们只拥有 diff、仓库和一个规则文件)。 • 3 个模型:Fable 5.1、Opus 5.5、Sonnet 5.5。 • 我亲自重新运行了每一个报告的缺陷,分别在 PR 上和当前主干上,以区分仍然存在的 bug 和已被修复的 bug。 • 成本是根据每个评审者的 token 数量按 API 列表价格估算的,没有缓存折扣,所以成本偏高。
然后我把它用到了一个真实的功能开发上。案例研究如下。
- 盲点在于上下文,而不在于作者身份。
在重构 PR 上: • 写代码的会话审查自己的工作(Fable):只发现了 23 个问题中的 3 个 • 一个全新的 Fable 智能体,对该工作没有任何记忆:发现了 23 个中的 17 个 • 一个全新的 Opus 智能体:发现了 23 个中的 18 个
在功能 PR 上,由三天前的另一个会话编写: • 一个没有编写代码但在该仓库中工作了一天的 Fable 会话:发现了 8 个逻辑错误中的 0 个 • 全新的 Fable、Opus 和 Sonnet 智能体:各自发现了 8 个中的 2 到 4 个
功能 PR 的评审者并没有写代码,但仍然什么也没找到。与写代码者共享心智模型的评审者会继承写代码者的盲点,无论代码是谁写的。
- 读代码能发现风格问题。运行代码才能发现 bug。
每一个逻辑错误都来自一个评审者:它搭建了一个临时数据库,用自己选择的输入调用被修改的代码,并观察返回了什么。那个已经有上下文的会话什么也没运行。它只是读了代码,没有发现任何逻辑错误。
功能 PR 上的 8 个逻辑错误没有一个能仅从 diff 文本中看出。一旦你运行代码,每一个都是显而易见的。
- 对于已有上下文的评审者,规则文件几乎没用。
给它一份书面的检查清单,每个 PR 只增加了一个发现。发现的逻辑错误:仍然是零。用同一份文件,全新的 Fable 和 Opus 智能体在每个 PR 上发现了 13 到 18 个问题。检查清单无法修复一个已经相信代码是正确的评审者。
- 问题出在评审者的工作顺序上。
表现最好的全新评审者仍然遗漏了半数逻辑错误,所以我拉出了它完整的工具调用日志,一步一步地进行了分析。
它打开过它所遗漏的全部三个错误背后的函数,并且理解了每一个函数。但它是在阅读了实现代码之后才编写测试输入的,所以每个输入都遵循了实现代码自身的假设。它的边界情况只是代码已经处理过的情况的变体。
代码实际上已经自己写了考卷,然后自己通过了考试。
修复方法只有一条规则:“在阅读实现代码之前写下你的测试输入。然后运行它们。” 同一个模型,同一个 PR:召回率从 8 个中的 4 个提升到 8 个中的 7 个,外加一个之前没人发现的 bug,多花了两美分。
- 模型很重要,但不如流程重要。
Opus 5.5:每次审查 $0.72 到 $0.93,8 到 11 分钟。它在两个 PR 上都发现了最多的问题:在全面性和成本之间达到了最佳平衡。
Fable 5.1:$2.11 到 $2.73,大约是 Opus 的 3 倍。在每个 PR 上都发现了一个其他人没抓到的 bug,但在测试全绿时跳过了与基础分支的比较。
Sonnet 5.5:$0.14 到 $0.21。每个发现最便宜,但它在相同输入上先发现了 8 个中的 2 个,然后发现了 4 个。这种运行间的波动才是真正的成本。
两个最强的评审者在 20 个发现中只有 10 个是重合的。
一个令人惊讶的案例研究:一个真实功能的端到端评审
一个智能体构建了一个真实功能:37 个文件,5000 多行代码,272 个测试通过,CI 全绿。它没有经过评审就推送了代码。
我让它进行了评审。
11 个重大 bug。一个全新的 Opus 评审者发现了 11 个阻塞性 bug,外加几十个小问题。每一个都隐藏在绿色对勾后面。
8 次评审,6 轮修复。每个循环都是:评审 → 修复 → 再评审: • 功能本身:4 个阻塞问题 → 修复 → 通过,但修复破坏了一个过滤器 → 修复 → 通过。这是 3 次评审。 • 强制评审的工具:4 个阻塞问题 → 修复 → 又出现 2 个 → 修复 → 又出现 1 个 → 修复 → 通过 → 小修复 → 通过。这是 5 次评审。
全部在 40 分钟内完成,每次审查不到一美元。
如果没有评审,以下内容将会发布: • 新功能的每个页面都会在 2 月 29 日崩溃。 • 用户会看到被标记为不属于他们的高级类别的记录。 • 当用户更改筛选条件时,列表会显示过期数据。 • 一个精心构造的链接可以将隐藏的收件人插入用户发送的邮件中。 • 评审门禁并没有真正强制执行评审:它检查了错误的仓库,并让真正的推送通过了。 • 更糟糕的是,安装它会默默地关闭每个提交上已经运行的所有安全检查。 • 一个数据库文件会被提交到仓库中。
这个案例教会了我:
1/ 272 个通过的测试对这些 bug 什么都没说明。其中没有任何一个有对应的测试。
2/ 第一次批准并不是终点。一个 bug 的修复创建了另一个 bug,只有第二次评审才发现了它。
3/ 强制执行评审的工具需要 3 轮修改才能正常工作。要审查门禁本身,而不仅仅是代码。
AI 代码评审的最佳实践
1/ 始终启动一个全新的智能体,它对写代码这件事没有任何记忆。只给它 diff、仓库和 REVIEW.md。在同一个模型上,这使召回率从 23 个中的 3 个提升到 23 个中的 17 个。
2/ 让它运行代码,而不仅仅是阅读代码。阅读发现了零个逻辑错误;每个逻辑错误都是通过运行代码发现的。
3/ 让它在阅读实现代码之前写下测试输入。这条规则用两美分的额外成本将召回率从 8 个中的 4 个提升到 8 个中的 7 个。
4/ 每次都把测试结果与基础分支进行比较,即使一切全绿。
5/ 重新评审每一个修复提交。修复会创建 bug。
6/ 默认使用 Opus。对于业务规则、阈值和门禁,添加一个使用不同模型的第二个评审者。两个最强的评审者只有一半的发现是重合的。
7/ 用门禁来强制执行评审,而不是用提示词。使用 git pre-push 钩子:没有通过该确切提交的已批准评审,就不能推送。对规则本身的修改同样需要被评审。
8/ 让它按名称报告每一条设计原则:关注点分离、意图式编程、封装性、高内聚、低耦合。未提及的原则意味着这次评审是不完整的。
9/ 检查诚实性,而不仅仅是代码风格。未知就是未知。UI 绝不能凭空捏造数据。
10/ 要求一个明确的结论(APPROVE 或 CHANGES),并以“到目前为止发现了 K 个中的 N 个“的形式报告发现。bug 池永远不可能完整。
完整的 REVIEW.md 在下面的评论中。将其粘贴到你的仓库中,并将你的评审智能体指向它。
REVIEW.md:AI 代码评审规则。将其粘贴到你的仓库中。
-
谁来评审 • 评审者是一个没有编写过代码的全新智能体。它只会得到:diff、仓库、这个文件。 • 编写者的自我评审只是检查清单式的过一遍,不能算真正的评审。 • 默认模型:Opus。高风险变更(业务规则、阈值、评分、定价、校验门禁)需要在不同模型上使用第二个评审者。 • 每个修复提交都需要自己的评审。修复会创建 bug。
-
如何评审:执行,而不仅仅是阅读 • 在阅读实现代码之前,写下你将要测试的输入。在阅读代码之后写的输入会呈现代码的形状,从而错过代码所错过的东西。 • 在临时环境中使用这些输入运行被修改的代码。尽可能在真实数据的副本上进行只读探测。 • 每次都要将测试结果与基础提交进行比较,包括当头提交全绿时。
-
需要探测什么 • 输入的每一种替代形式,包括将其中两种组合起来的形式。 • 每一个单位,以及完全没有单位的输入。 • 一个输入中的两个或更多实体,按每一种顺序。 • 变更后的枚举、状态或常量的每一个消费者。 • 每一个原因或错误代码,追溯到用户实际看到的消息。 • 存储、计算或渲染同一事实的每一个位置(服务端和客户端)。它们是否仍然一致? • 边界情况:空、一个、正好在阈值上、超过上限。 • 日期:闰日、年界、时区。
-
诚实性 • 未知就是未知。UI 绝不能凭空编造、猜测或默默解析它没有的数据。 • 每一个标签都必须对它所显示的每一条记录都是真实的。
-
设计原则(对每一条都要报告) 对每一条:OK,或违反并附上 file:line。 • 关注点分离 • 意图式编程 • 封装性 • 高内聚 • 低耦合 阻塞问题:一个领域有两个所有者、重复的逻辑、模板或 UI 代码中的业务逻辑。 未提及的原则 = 一次不完整的评审。
-
门禁和工具 • 用它应该拒绝的输入攻击每一个新的检查、钩子或门禁,包括那些措辞不同以规避它的输入。 • 优先使用平台原语(例如 git pre-push),而不是巧妙地解析命令。 • 确认每一个豁免仍然指向存在的事物,并且没有豁免可以用来偷偷放行代码。 • 安装钩子绝不能禁用已有的钩子。 • 对规则本身的修改永远不能免于评审。
-
文档和重构 • 在任何查找替换或移动操作之后,重新阅读每一个编辑过的句子并问自己:这句话还是真的吗? • 有日期的文档保持其原有的路径和事实。
-
报告 • 发现分为 BLOCKING(阻塞)或 NIT(小问题)。阻塞问题必须修复;小问题是可选的。 • 每个发现都要附带复现步骤:输入、预期结果、实际结果。 • 报告“到目前为止发现了 K 个中的 N 个“。bug 池永远不可能完整。 • 通过的测试不是证据。要说明你执行了什么。 • 结尾必须恰好一行:VERDICT: APPROVE 或 VERDICT: CHANGES
这里有一个彩蛋。规则文件对我昨天写的那些 C++ 模式实施了更严格的合规要求:
附加材料:为了更强的合规性,请实施这种智能体代码评审:
是的。起初我发现不同的模型发现不同的缺陷这件事非常令人不安
更令人惊讶的是,Sonnet 对同一个 diff 运行多次会发现不同的缺陷。
一旦你检查了智能体的日志——原因就变得非常清楚,而且不再令人不安了。
和人类一样,LLM 必须决定深入研究哪些函数和文件。这是一个简单但极其庞大、复杂的决策树/搜索空间。这些决定是合理的、可以辩护的,即使结果看起来完全不相关。
我们构建的不是在宇宙飞船上运行的软件,所以我们不需要 100% 的覆盖率。
复杂的 bug 几乎总是架构糟糕的代码库导致的。
内聚性差、关注点分离不良。bug 不是根本原因,而是症状。
架构正确的系统不可能藏着复杂的 bug。
写好设计文档,并在开始实现之前评审它们。
我们的“肉计算机“速度太慢、IQ 太低,而且每天需要睡 8.0 小时。不可接受的瓶颈。
没有阻塞性问题,只是复盘。
我对我的 AI 代码 100% 进行 AI 代码评审,到目前为止 100% 的评审都发现了真实的缺陷。
永远不晚开始一次重大的重构。我在大规模重置方面取得了很大的成功。
Scott Bain——我听过最传奇的关于核设施重构的故事来源。
他的课程是我上过的最好的课程。
相似文章
@rohanpaul_ai:卡内基梅隆大学和微软的一篇新论文发现,表现最好的 AI 代码审查工具在其前 5 条评…中发现了 71.9% 的已知漏洞
卡内基梅隆大学和微软推出了 CRBugBench,一个包含 1,800 项代码审查任务的基准测试,发现表现最好的 AI 代码审查工具(claude-opus-5)在其前 5 条评论中能指出 71.9% 的已知错误——仍不足以取代人工审查者。
Agentic Code Review(15分钟阅读)
分析AI编码代理如何将瓶颈从编写代码转移到审查代码,数据显示代码变更量增加861%,缺陷率上升,使得代码审查成为软件工程中最具杠杆效应的技能。
我让58个AI代理互相审查代码561次——发现它们的盲点
一个实验性竞技场,AI代理互相审查代码,揭示了双峰分数分布、对安全代码更严厉审查等模式。作者分享了114次提交、561次审查的发现。
@svpino: 如果你还在人工审查100%的AI生成代码,那你的速度就不够快。这根本不可能。审查…
该推文认为手动审查所有AI生成代码会造成瓶颈,并附带了一个链接,指向一种更好的方法。
@RayFernando1337: 导致用户流失的错误几乎从不出现在差异对比中,只有当你停止审查代码时才能真正捕捉到它们……
一位开发者分享了在Cursor中使用Opus 4.8 Max Thinking模型与子代理框架的工作流,并介绍了一个包含可安装技能文件的GitHub仓库,其中包含一个名为'running-bug-review-board'的技能,可进行实时QA测试。