<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>Code Review on AI博士 万戈</title>
        <link>https://www.yesmiracle.net/tags/code-review/</link>
        <description>AI博士万戈的技术博客，聚焦 Agentic AI、AI Infra 与 Agent Security，分享 AI 基础设施与工程落地实践。</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <managingEditor>admin@yesmiracle.net (万戈)</managingEditor>
        <webMaster>admin@yesmiracle.net (万戈)</webMaster>
        <lastBuildDate>Sat, 24 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.yesmiracle.net/tags/code-review/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Claude Code 团队的代码审查方法：六层检查、按风险分级审批、一个审批只覆盖一个 commit</title>
        <link>https://www.yesmiracle.net/post/20261024-claude-code-review-six-layers/</link>
        <pubDate>Sat, 24 Oct 2026 00:00:00 +0000</pubDate>
        <author>admin@yesmiracle.net (万戈)</author>
        <guid>https://www.yesmiracle.net/post/20261024-claude-code-review-six-layers/</guid>
        <description>&lt;img src="https://www.yesmiracle.net/post/20261024-claude-code-review-six-layers/cover.svg" alt="Featured image of post Claude Code 团队的代码审查方法：六层检查、按风险分级审批、一个审批只覆盖一个 commit" /&gt;&lt;p&gt;Anthropic 的 Claude Code 团队在 10 月 15 日发了一篇工程博客，把自己团队怎么做代码审查讲了一遍。里面有一组数字值得先放在最前面：&lt;/p&gt;
&lt;p&gt;从 6 月到 9 月，合并进 Claude Code 代码库的 PR &lt;strong&gt;翻了一倍多&lt;/strong&gt;，而其中被迫回滚的比例&lt;strong&gt;降了 40% 以上&lt;/strong&gt;。同一时期，Anthropic 那个 monorepo 的日均落地变更数从 5 月的约 2,500 涨到 9 月的 &lt;strong&gt;30,000 以上&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;在变更量涨一个数量级的前提下把返工率压下去，这本身就是个反常结果。而它靠的是把「审查」这件事的骨架换掉，跟模型是不是更聪明关系不大。&lt;/p&gt;
&lt;h2 id=&#34;他们把人工时间拆成了两个账本&#34;&gt;他们把人工时间拆成了两个账本&lt;/h2&gt;
&lt;p&gt;这套流程里最容易被漏掉的一句判断，藏在它对「省时间」的定义里。&lt;/p&gt;
&lt;p&gt;团队把人工时间看成&lt;strong&gt;两笔账&lt;/strong&gt;：一笔是花在审查上的时间，另一笔是花在修复坏代码上的时间。原文的说法是，如果只砍第一笔，而第二笔跟着涨，那就没有省下人工时间，只是把它挪了个位置。&lt;/p&gt;
&lt;p&gt;于是 revert 率和事故率在这套流程里被当成&lt;strong&gt;护栏&lt;/strong&gt;来用，不再是事后的附带统计。他们真正在优化的目标写得很清楚：Claude Code 那几个仓库（CLI、桌面、Web、移动端）的多数 PR，最多只要一个「人在环里」，这个人甚至可以是作者本人，前提是回滚率和事故率不上升。&lt;/p&gt;
&lt;p&gt;度量方式也具体：每个 PR 的人工批准数（看中位数和第 95 百分位）、人工评论数、以及 PR 等一个人等了多久。三个指标一起看，才能区分「审查变快了」和「审查被跳过了」。&lt;/p&gt;
&lt;p&gt;这个双账本框架是我觉得这篇文里最值得抄走的部分。很多团队引 AI 审查时只看「平均审查时长下降」，而返工时间悄悄转移到另一个地方去了，账面上看不出来。&lt;/p&gt;
&lt;h2 id=&#34;六层每层的洞都在不同地方&#34;&gt;六层，每层的洞都在不同地方&lt;/h2&gt;
&lt;p&gt;他们给出的结构是一张六层图，从上到下依次是：验证、必需 CI、AI 审查、安全审查、人工批准、合并队列加特性开关。原文的比喻是每层都有洞，而洞的位置各不相同，漏过某一层的问题会被后面某一层接住，穿过所有层的才落到最底下的快速回滚。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;层&lt;/th&gt;
          &lt;th&gt;谁在跑&lt;/th&gt;
          &lt;th&gt;拦什么&lt;/th&gt;
          &lt;th&gt;关键设计&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;1 验证&lt;/td&gt;
          &lt;td&gt;作者（人或 Agent）&lt;/td&gt;
          &lt;td&gt;「做完了」其实是假的&lt;/td&gt;
          &lt;td&gt;给 Agent 一个能跑的东西（测试、构建、截图比对），要求它&lt;strong&gt;展示输出&lt;/strong&gt;而不是声称完成&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;2 AI 审查&lt;/td&gt;
          &lt;td&gt;每个 PR 必过&lt;/td&gt;
          &lt;td&gt;常规错误&lt;/td&gt;
          &lt;td&gt;读 diff 对比整个仓库和 PR 声明的意图；发现项先由多个 Agent 投票复核，只投真实的&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;3 安全审查&lt;/td&gt;
          &lt;td&gt;自动&lt;/td&gt;
          &lt;td&gt;安全问题&lt;/td&gt;
          &lt;td&gt;与第 2 层一样可以&lt;strong&gt;阻塞合并&lt;/strong&gt;：有未关闭的发现项就合不了&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;4 必需 CI&lt;/td&gt;
          &lt;td&gt;自动&lt;/td&gt;
          &lt;td&gt;平台兼容、类型、lint&lt;/td&gt;
          &lt;td&gt;一个 CLI PR 在有人看之前可能已经跑了几十个检查&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;5 人工批准&lt;/td&gt;
          &lt;td&gt;人&lt;/td&gt;
          &lt;td&gt;高风险判断&lt;/td&gt;
          &lt;td&gt;按变更风险分级，见下一节&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;6 合并队列 + 开关&lt;/td&gt;
          &lt;td&gt;自动&lt;/td&gt;
          &lt;td&gt;两两合并才炸的情况&lt;/td&gt;
          &lt;td&gt;合并队列把每个 PR 应用到 main 上重跑全部检查；新行为先给内部员工用&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;第一层里有个细节值得单独说。他们要求 Agent 展示可验证的输出，而不是汇报「已完成」。Boris Cherny（Claude Code 的作者）说这大概是拿到好结果最重要的一件事，他估的价值是最终效果变好两到三倍。这个习惯的落点是让「完成」这个词有证据。&lt;/p&gt;
&lt;p&gt;第二层的机制也值得拆开：发现项在交给人之前，&lt;strong&gt;先由另一组 Agent 投票&lt;/strong&gt;。几个 Agent 同时找 bug，然后另一组对每个发现项投票，票数够才发布出来。只涉及风格、诊断信息、清理类的发现项直接丢掉。他们还用自己仓库里的 PR 做过 A/B，确认这套过滤器值得留下。剩下的发现项按严重度排序，以行内评论的形式出现，并且标注为重要、小问题或&lt;strong&gt;先前就存在&lt;/strong&gt;——后面这个标签的意义是：一个不是这次变更引入的 bug，不该看起来像作者的锅。&lt;/p&gt;
&lt;h2 id=&#34;审批粒度缩到了单个-commit&#34;&gt;审批粒度缩到了单个 commit&lt;/h2&gt;
&lt;p&gt;第五层是整篇里最反直觉的部分。他们没有给「谁有权限批准」设计一套角色体系，而是让&lt;strong&gt;变更本身决定风险档位&lt;/strong&gt;。&lt;/p&gt;
&lt;table&gt;
  &lt;thead&gt;
      &lt;tr&gt;
          &lt;th&gt;风险档&lt;/th&gt;
          &lt;th&gt;例子&lt;/th&gt;
          &lt;th&gt;需要几个人批准&lt;/th&gt;
      &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
      &lt;tr&gt;
          &lt;td&gt;低&lt;/td&gt;
          &lt;td&gt;文档、文案、仅内部的功能、藏在开关后面的增量变更&lt;/td&gt;
          &lt;td&gt;自动审查与安全检查全绿后，&lt;strong&gt;不需要人&lt;/strong&gt;&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;中&lt;/td&gt;
          &lt;td&gt;常规产品变更，以及缓存、自动更新器、系统提示词这类敏感区域的改动&lt;/td&gt;
          &lt;td&gt;一个人&lt;/td&gt;
      &lt;/tr&gt;
      &lt;tr&gt;
          &lt;td&gt;高&lt;/td&gt;
          &lt;td&gt;风险最高的代码，加上一小撮「永远需要两个人」的路径&lt;/td&gt;
          &lt;td&gt;两个人&lt;/td&gt;
      &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;档位由分类器读变更内容来定，第二个分类器再单独判断「这次变更是否还需要额外一个人，哪怕它的档位说不需要」。有些路径永远需要人：代码所有者标为敏感的，以及任何 CI 工作流文件。&lt;/p&gt;
&lt;p&gt;配套还有三条规则，我认为是这套流程在制度上最硬的部分：&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;只有受信任的作者走轻量路径。&lt;/strong&gt; 只有在该仓库受信任名单上的人（基本就是拥有这个仓库的团队）才能免掉人工批准，其他人一律需要第二个人签字。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent 的批准永远不算人的批准。&lt;/strong&gt; 自动审查可以放行一个低风险变更，但它不能去填一个要求由人填的位子。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;谁下的提示词，谁对这个变更负责。&lt;/strong&gt; 一个由 Agent 写出来的 PR，下指令的那个人算作必需审查人之一，跟这些代码是他自己敲的没有区别。&lt;/p&gt;
&lt;p&gt;还有一条粒度上的规定：&lt;strong&gt;一个批准只覆盖一个具体的 commit&lt;/strong&gt;。如果之后落进了系统无法担保的新提交，比如 Agent 自己推的、或者有人手工解决冲突产生的合并，批准就得重新给一次。&lt;/p&gt;
&lt;p&gt;把这几条连起来看，审查的对象已经从「人」换成了「commit」。审批不再是一份持久的授权，而是对某个具体状态的一次性确认。这大概是「持续集成」在 Agent 时代的对应物：&lt;strong&gt;持续授权&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id=&#34;审查者自己也在被审查&#34;&gt;审查者自己也在被审查&lt;/h2&gt;
&lt;p&gt;第六层之后是这套流程里我觉得最有意思的部分：他们怎么让审查者本身变好。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;事故变成评测集。&lt;/strong&gt; 团队把历史上导致过事故的 PR 收集起来，连同当时的修复提交和回滚一起，让熟悉那段代码的工程师逐条确认 bug 是什么、在哪里。审查者每天对这套集合跑一遍，而每一次对审查者的改动，都要在这套集合上打分，分数涨了才留下。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;噪声用人的行为来量。&lt;/strong&gt; 想多抓 bug 很容易，代价是多报非 bug。他们不靠内部打分，而是把审查者留下的每条评论按 PR 上的人的反应归类：改了、说它错了、说这个行为是故意的、或者认为不重要。另外还会拿一批已知干净的 PR 跑审查者，统计它有多少次会让人做出有害改动。优先级写下来是：抓真 bug 排在减少审查轮次前面。&lt;/p&gt;
&lt;p&gt;这里有一句我认为值得所有做 AI 审查的人记下来：&lt;strong&gt;当作者是 Agent 时，噪声的代价更高。&lt;/strong&gt; 人可以在一秒内把一个小问题挥掉，Agent 会去修它，于是多一个提交、多一轮审查。&lt;/p&gt;
&lt;h2 id=&#34;真正没解决的是收敛问题&#34;&gt;真正没解决的是收敛问题&lt;/h2&gt;
&lt;p&gt;如果这篇文只讲六层和分级，那它是一份漂亮的流程说明。但团队自己写出了这套机制的失败模式，而且写得比外部批评更狠。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Agent 作者和 Agent 审查者可以互相喂活，无限期。&lt;/strong&gt; 有一个 CLI 的 PR，在一夜之间经过了五十多轮审查与修复，直到作者手动叫停。&lt;/p&gt;
&lt;p&gt;他们去查了审查者反复标记的那些代码是谁写的：用 git blame 追下去，&lt;strong&gt;约 59% 是在审查者第一轮时就已经在那里的代码&lt;/strong&gt;。也就是说，审查者很少发现新 bug，它每一轮多找出的是几个&lt;strong&gt;旧的&lt;/strong&gt; bug。&lt;/p&gt;
&lt;p&gt;更诚实的是，他们把责任归到了自己身上：团队习惯了默认跑好几轮，因为每一轮总能捞出点新东西。这在一次高风险变更上可能值，但在每个 PR 上都跑就不值了。&lt;/p&gt;
&lt;p&gt;对策有四条：&lt;strong&gt;三轮封顶&lt;/strong&gt;，超过三轮审查者会要求作者退回去重新考虑方案；前几轮之后只审查增量 diff；按 bug 类别标记，让作者一次修掉所有同类实例而不只是一行；以及已经发过的发现项不再重复。&lt;/p&gt;
&lt;p&gt;这一段是整篇里对我冲击最大的地方。人类代码审查的失败模式通常是漏看，而 Agent 审查 Agent 的失败模式是&lt;strong&gt;不收敛&lt;/strong&gt;：双方都有耐心、都能一直干活，于是这里缺的东西变成了终止条件。「多审几轮更安全」在这里是个错觉，边际收益在几轮之后变成了对历史债务的重复曝光。&lt;/p&gt;
&lt;p&gt;而且团队承认自己也没有全部解决：他们还没有「当回滚率或事故率上升时自动收紧审批」的熔断器，工程师们希望在更多代码走向零人工合并之前先把这东西做出来。&lt;/p&gt;
&lt;h2 id=&#34;被让出去的那一半职责&#34;&gt;被让出去的那一半职责&lt;/h2&gt;
&lt;p&gt;文章开头说代码审查干两件事，第二件是在团队内部建立共享理解和代码库认知。这一半在机器审查主导之后怎么办，文章到很后面才回答。&lt;/p&gt;
&lt;p&gt;给出的答案是几个偏文化的做法：有人会让 Claude 生成一个小产物，把要改的那部分代码可视化出来，用这个人自己喜欢的方式讲给他听；团队默认在开放的 Slack 频道里干活，于是别人在建什么你能看见。原文的论证是：一个一行的文案改动几乎教不会你什么，而一个即将修改的模块的讲解能教会你很多，所以后者比逐行读琐碎的 diff 更值。&lt;/p&gt;
&lt;p&gt;这个回答我持保留意见。它用一个&lt;strong&gt;由 AI 生成的产物&lt;/strong&gt;去补一个原本发生在&lt;strong&gt;人与人之间&lt;/strong&gt;的过程。讲解质量、提问与追问、以及「我知道隔壁组为什么这么设计」这类隐性知识的传递，是不是能被等价替代，文章没有给出证据。这是我认为这套流程里最值得观察的一个缺口。&lt;/p&gt;
&lt;h2 id=&#34;你合的你负责把回滚当成一等公民&#34;&gt;「你合的，你负责」：把回滚当成一等公民&lt;/h2&gt;
&lt;p&gt;六层之外还有一层不写在图里的东西，是团队对责任的处理方式。&lt;/p&gt;
&lt;p&gt;他们的默认规范是：你合入一个中小变更，之后它出了问题，通常由你来修。这条听起来像追责，但原文列出的几条前提把它的性质改了。变更都很小，所以好审、好查、好回滚；&lt;strong&gt;所有东西都可逆&lt;/strong&gt;，特性开关、revert 和分阶段发布能在几分钟内撤销大部分错误；影响面决定规格，贵的代码自然拿到更多人和更多检查；回归通过遥测和内部使用快速浮出水面；以及最关键的，这不算追责，负责修的人恰好掌握最多上下文，而事故复盘看的是系统而不是人。&lt;/p&gt;
&lt;p&gt;这一段解释了为什么前面那些自动层敢放开。流程之所以能把大部分阅读交给机器，是因为&lt;strong&gt;兜底成本被压得很低&lt;/strong&gt;：错了能几分钟撤掉，撤掉之后有人认领。如果回滚一次要半天、要开三个会，那自动放行就是不负责任。所以这套设计里，可逆性不是附属能力，它和审查层是同一个结构的两半。&lt;/p&gt;
&lt;p&gt;团队也写了「方向要变的时候怎么办」：Agent 让起一个事情变得很便宜，所以有些工作本来就不该落地。通常的做法是有人在频道里问一句为什么、指一个早先的决定、或者提一个更简单的路子，然后作者关掉或者改写那个 PR。因为代码写得快，关掉一个 PR 不觉得是损失。前提是这种不同方向要早说，而不是等到 PR 做完了再给一条阻塞性评论。&lt;/p&gt;
&lt;h2 id=&#34;能直接拿走的部分&#34;&gt;能直接拿走的部分&lt;/h2&gt;
&lt;p&gt;抛开 Anthropic 的规模，这套流程里有几件小事是可以明天就开始做的。&lt;/p&gt;
&lt;p&gt;在 PR 之前：给 Agent 一些它能跑的检查，写进一份简短的 &lt;code&gt;CLAUDE.md&lt;/code&gt;；用钩子跑格式化和 lint；本地先跑一遍 &lt;code&gt;/code-review&lt;/code&gt; 或 &lt;code&gt;/security-review&lt;/code&gt;；再加一份 &lt;code&gt;REVIEW.md&lt;/code&gt;，把反复出现的审查意见沉淀进去。&lt;/p&gt;
&lt;p&gt;在 PR 上：要求 CI；把「怎么测试的」和「怎么回滚」写进 PR 模板；先在一个仓库上加 AI 审查，调几周 &lt;code&gt;REVIEW.md&lt;/code&gt; 再铺开；让审查努力匹配风险，常规变更快过一遍，一个漏掉的 bug 很贵的路径上深查。&lt;/p&gt;
&lt;p&gt;关于 &lt;code&gt;REVIEW.md&lt;/code&gt; 的写法，原文给了一条很实用的标准：好的 &lt;code&gt;REVIEW.md&lt;/code&gt; 很短，它会写清在这个仓库里「失败长什么样」（文档仓库的失败是「它在撒谎」，配置仓库的失败是「它路由错了」），限制小问题的数量，列出该跳过的路径，并且要求证据给到文件和行号而不是从名字猜。它还会要求总结以数字开头，没什么可修的时候要明说。&lt;/p&gt;
&lt;h2 id=&#34;写在最后&#34;&gt;写在最后&lt;/h2&gt;
&lt;p&gt;我读完这篇的主要收获，是它把「AI 审查」这件事从工具选型问题变成了流程设计问题。杠杆落在六层怎么分、审批粒度切到多细、以及谁为 Agent 写的代码签字，而不是换一个更强的审查模型。其中「Agent 的批准永远不算人的批准」和「一个批准只覆盖一个 commit」这两条，是制度设计而不是技术设计，而它们恰好是最容易被抄漏的部分。&lt;/p&gt;
&lt;p&gt;另一面是，他们公开了自己流程的失败模式（五十轮不收敛、59% 是旧 bug、没有熔断器），这部分的价值我认为高于流程本身。一份把缺陷写出来的工程文，比一份只讲做法的工程文可信得多。&lt;/p&gt;
&lt;p&gt;相关阅读：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20261014-agent-fleet-operation-layer/&#34; &gt;《94 位顶级工程师，只有 8 位还在逐行读 Agent 的代码》&lt;/a&gt;：那篇讲的是这一层正在长成独立品类的市场判断，这篇拆的是审查机制本身的骨架，两篇不重叠。&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20261015-agent-scale-version-control-scion/&#34; &gt;《AI 一天合 3 万次代码，把 Git 逼到了极限》&lt;/a&gt;：同样的 30,000 次日均变更，那篇看的是版本控制系统的承受力，这篇看的是审查流程的重构。&lt;/li&gt;
&lt;li&gt;&lt;a class=&#34;link&#34; href=&#34;https://www.yesmiracle.net/post/20261021-litellm-supply-chain-attack-1070/&#34; &gt;《LiteLLM 又被投毒了》&lt;/a&gt;：这套六层挡的是常规错误和高风险变更，供应链投毒走的是另一条路，两篇一起看能看清「审查」和「供给链」是两个不同的防线。&lt;/li&gt;
&lt;/ul&gt;
</description>
        </item>
        
    </channel>
</rss>
