Claude Code 团队的代码评审:合并量翻倍,回滚率降了 40%

10 月 15 日,Anthropic 在 claude.dev 博客上发表了 Claude Code 团队的代码评审流程,作者是 Addy Osmani、Morgan Westlee Lunt 和 Qing Wang。文章给了一组结果:今年 6 月到 9 月,合入 Claude Code 代码库的 PR 数量翻了一倍多,需要回滚的比例下降了 40% 以上。Anthropic 此前说过,Claude Code 约 90% 的代码由 Claude 自己编写。这篇文章回答的是随之而来的问题:代码由 agent 大量产出之后,评审由谁做,出了问题由谁兜底。

本文先整理原文的流程和数据:PR 之前的自检、每个 PR 上的 AI 评审和安全评审、按风险分三档的人工审批、合并后的灰度与回滚,以及团队如何解决 agent 写、agent 审时陷入的循环。之后整理 Hacker News 讨论中的主要质疑(233 分、222 条评论),最后讨论其他团队应当按什么顺序借鉴。

这套流程最值得借鉴的地方不是「让 AI 审代码」,而是评审目标的改写。传统评审的隐含指标是「有没有人读过这段代码」,Anthropic 认为这个指标不准确,换成了两个可测量的量:每个 PR 消耗的人工时间(审批人数的中位数与 P95、人工评论数、PR 等人的时长),以及作为护栏的回滚率和事故率。人工时间降了而回滚率没升,才算真的省下了;如果回滚率上升,人工时间只是从评审阶段挪到了修复阶段。

这个改写也决定了借鉴的顺序。Anthropic 敢让低风险 PR 零人工合并,前提是下面垫着功能开关、内部员工先用、分渠道发布和每周值班这几层兜底。没有这些兜底,就先砍掉人工评审,等于拿掉护栏换速度。

6 月到 9 月的三组数字

原文给出的量化结果有三组,口径不同,需要分开看:

指标 变化 范围
每日合入变更数 5 月约 2,500 → 9 月 30,000 以上 Anthropic 主 monorepo
合入 PR 数 / 回滚比例 6--9 月 PR 数翻倍以上,回滚比例下降 40% 以上 Claude Code 代码库
收到实质性评审意见的 PR 占比 16% → 54% 内部 PR,Code Review 研究预览上线前后

第一组数字在 HN 上被大量误读。多位评论者质疑「一个终端工具一天怎么会有 3 万次改动」,但原文写明 3 万是整个 monorepo 的数字,Claude Code 是独立仓库,原文只说它「同样承受了很大压力」,没有给出日均变更量。

第三组数字说明的是 AI 评审的覆盖面:上线前只有 16% 的 PR 收到实质性意见,上线后是 54%。原文补充,超过 1,000 行的 PR 大多会收到问题报告,小 PR 大多直接通过。

从本地自检到合并后回滚的分层检查

原文把一次改动的路径拆成七层,核心思路是任何单层都会漏,靠层叠降低漏网概率,最后由快速回滚处理剩余部分。

PR 之前的自检。 大部分评审在 PR 创建之前就已发生。团队要求 Claude 运行测试、构建或对照设计稿截图,并展示输出,而不是只报告「做完了」;然后由一个 fresh context 的 subagent 审一遍 diff。Claude Code 的作者 Boris Cherny 估计,给 Claude 一个验证自身工作的手段,能让最终结果好两到三倍。

CLAUDE.md 与 REVIEW.md。 评审器反复报同一类问题时,团队不在评审环节逐个处理,而是回到源头修:写进 skill、加 lint 规则,或更新说明文件。CLAUDE.md 描述项目本身,每次评审都会加载,所以在大仓库里刻意保持简短。REVIEW.md 由代码 owner 编写,告诉评审器这一块代码里什么最重要。原文对好的 REVIEW.md 有具体描述:写明这个仓库里「失败」长什么样(文档的失败是「说了假话」,配置的失败是「路由错了」),限制 nit 数量,列出跳过的路径,要求以文件和行号为证据,摘要以问题数量开头。

每个 PR 上的 AI 评审。 多个 agent 并行找 bug,另一组 agent 对每条发现投票,票数足够才发出;纯风格、诊断和清理类意见直接丢弃,这些过滤规则在内部 PR 上做过 A/B 测试。留下的意见按严重程度排序,标记为 Important、Nit 或 Pre-existing,最后一类用于区分「这个 PR 之前就存在的 bug」,避免记在作者头上。每条意见必须处理:要么修复,要么写明理由后关闭。

可阻断合并的安全评审。 独立于 bug 评审单独运行。任一评审还有未关闭的发现,PR 就不能合并。

必过的 CI。 lint、类型检查、多平台测试、构建和打包。PR 模板要求填写「如何测试」和「如何回滚」,可以由 Claude 填,但必须由提出改动的人签字确认。

合并队列、功能开关和分渠道发布。 合并队列在最新 main 上重跑所有检查,防止两个各自通过的 PR 合在一起出错。新行为通常先放在开关后面给 Anthropic 员工使用,公开发布先进 latest 渠道,stable 渠道滞后跟进。

这里的开关指 feature flag。原文没有描述实现细节,业内的通行做法是:新功能合入主干时保留旧逻辑,代码用一个条件判断在新旧两条路径之间选择,判断依据是从服务端下发的开关值。开关可以按人群打开,先对内部员工,再逐步扩大到全部用户;新功能出问题时在后台关闭开关,客户端回到旧逻辑,不需要发新版本。开关只能保护放在它后面的新行为,公共代码的重构和没有加开关的改动,仍然要靠回滚并重新发版。

开关本身也有维护成本。用于灰度发布的开关,在全量稳定后应当连同旧逻辑一起删除,否则代码中的条件分支和需要测试的组合会持续累积。常见做法是建开关时登记负责人和过期日期,由开关平台列出长期全量开启的开关,或者用 Uber 开源的 Piranha 这类工具自动生成清理 PR。保留不删的旧路径并不安全:2012 年 Knight Capital 复用了一个废弃多年的开关,一台服务器漏装新代码,开关打开后执行了旧逻辑,45 分钟内亏损约 4.4 亿美元。用于紧急关停的运维开关(kill switch)是例外,会有意长期保留。

快速发现与回滚。 开关无需部署即可关闭,Claude Code 有每周轮换的 on-call,事故复盘会问「这个问题本该由哪一层拦住」。原文也承认一个缺口:目前还没有熔断机制,回滚率或事故率上升时不会自动收紧审批,工程师希望先有这个机制,再把更多代码放进零人工合并。

按风险分三档的人工审批

人工审批的人数由改动本身的风险决定:

风险 典型改动 需要的人工审批
低 文档、文案、仅内部可见的功能、开关后的增量改动 0 人(自动评审和安全检查全绿即可)
中 普通产品改动;缓存、自动更新、system prompt 等敏感区域 1 人
高 风险最高的代码,以及少数固定需要两人的路径 2 人

围绕这张表有五条配套规则,它们比表格本身更重要:

  1. 档位由改动决定,不由作者决定。 一个分类器读改动、定档位;第二个分类器单独判断「这个改动虽然档位低,是否仍需要人看」。owner 标记的敏感路径和所有 CI workflow 文件一律需要人。
  2. 轻量通道只对受信任作者开放。 只有仓库受信任名单上的作者(主要是 owner 团队)可以走低档位,其他人一律需要第二个人审批。
  3. agent 的批准不能顶替人。 自动评审可以放行低风险改动,但填不了任何一个「需要人」的名额。
  4. 谁驱动 agent,谁就是审批人之一。 agent 写的 PR,指挥 agent 的那个人算作必需的审批人之一,责任与亲手写代码相同。
  5. 批准只对具体的 commit 有效。 之后出现系统无法担保的新 commit(比如 agent 追加的推送、人工解决的合并冲突),需要重新批准。

评审收敛:59% 的旧问题与 50 轮循环

agent 写代码、agent 审代码,会出现一个人工评审时代不存在的问题:双方可以无限互相制造工作。原文记录了一个 CLI 的 PR,一夜之间经历了 50 多轮「评审---修复」,直到作者手动叫停。

团队用 git blame 分析评审器反复报告的问题,发现约 59% 指向第一轮评审时就已存在的代码。也就是说,评审器很少在新一轮里发现新 bug,而是每轮多挖出几个旧问题。噪声对 agent 作者的成本也更高:人可以几秒钟忽略一条 nit,agent 会去修,修完又是一个新 commit 和新一轮评审。

团队的改法有四条:三轮之后,评审器要求作者退一步重新考虑方案;前几轮之后只审新增 diff;报告 bug 的类别而非单行,让作者一次修掉所有同类实例;已经发过的意见不再重复。另外,评审 agent 每晚扫描存量代码,提前把旧 bug 清出来。

效果是:一轮评审修复即通过的比例从 65% 升到 78%,需要五轮以上的从 8.9% 降到 1.5%,平均评审轮数从 2.08 降到 1.32。团队现在把「通过所需轮数」和召回率一起跟踪,书面优先级是先抓真 bug,其次才是减少轮数。

用事故记录做评审器的 eval

评审器本身也在持续迭代,依据是一个由历史事故构成的 eval 集。团队收集了过去引发事故的 PR 及其后续修复和回滚,请熟悉对应代码的工程师逐个确认 bug 在哪里。评审器每天在这个集合上跑一遍,每次调整 prompt、工具或模型,都要在全集上重新打分,分数上升才保留。

噪声单独测量。每条评审意见按 PR 作者的处理方式归类:修了、说它错了、说是有意为之、认为无关紧要。团队还在已知干净的 PR 上跑评审器,统计它报出「可能诱导人做出有害修改」的问题的频率。召回率很容易靠多报来提高,这一步是为了给它加约束。

人保留的五类决定

原文的说法是,工程师的工作从读每一个 diff 转向机器不擅长的决定,具体有五类:这个东西该不该做(方向、品味和范围);高风险代码,如计费、自动更新和 CI workflow;会被他人照搬的架构;阅读证据,包括测试输出、执行过的命令及结果、截图和评审器的发现;以及对结果负责,无论代码是谁敲的。

关于「阅读证据」,原文给了一个具体标准:如果你说不出这些检查会漏掉什么,就应该要求一次真正的评审,而不是快速批准。

评审的另一项传统功能是在团队内传播代码知识。原文的回答是团队没有正式流程:没有人在脑子里维护 Claude Code 的完整模型,需要了解某一块时,让 Claude 针对那一块写一份讲解。团队的规范是「你合入的,你负责」,这条规范能运转,依赖的是改动小、一切可回滚、按影响范围设门槛、问题能通过遥测和内部使用快速暴露。

Hacker News 上的五个质疑

这篇文章在 HN 上得到 233 分、222 条评论。去掉针对公司本身的情绪化评论,有实质内容的质疑集中在五点:

合规要求。 有评论者指出,他们的 SOC 2 审计员明确要求所有代码上线前至少经过另一个人评审,而 Anthropic 的低风险档位允许 0 人审批、中风险档位的那一个人可以是作者本人。这套流程如何满足合规要求,原文没有说明。对需要 SOC 2 或类似审计的团队,这是照搬前必须先回答的问题。

安全发现可以自行关闭。 原文写明,处理误报的方式是「关闭讨论并写一条简短理由」。有评论者认为,对高危发现,误报判定仍应经过安全团队,否则回滚率下降的同时可能引入更多漏洞。原文链接的开源 Action claude-code-security-review,其 README 写明它「没有针对 prompt injection 攻击做加固,只应用于审查可信 PR」。用它做安全门禁时,外部贡献者的 PR 需要另外处理。

讲解文档和评审出自同一系统。 有评论者指出,让 Claude 写讲解来理解代码,等于把对 diff 的认知经过了同一个已经审过、批过这段代码的系统,读者无法借此独立判断一个复杂 diff。原文对团队知识传播的回答确实是全文最薄的一节。

指标被当成目标。 团队的目标写的是「每次改动的人工时间更少,回滚不比以前多」。有评论者引用古德哈特定律:回滚率和事故率一旦成为优化目标,就未必还能反映质量。用户感知到的回归(例如界面频繁变动)未必会体现为回滚或事故。

成本。 多位评论者提到,按 Anthropic 的用量跑多 agent 并行评审加投票验证,token 成本对普通公司未必可承受。原文没有给出每次评审的成本数据,Code Review 的文档只说明 Deep 档位「耗时最长、成本最高」。

前两点是流程设计上真实存在的边界,后三点更多是原文没有回答的问题,不构成对其数据的否定。

其他团队的借鉴顺序

原文最后给了一份完整的采用清单。结合上面的分析,更稳妥的顺序是自下而上:先建兜底层,再加自动评审,最后才减少人工审批。

阶段 先做什么 前提条件
1. 兜底 功能开关、一步回滚、分阶段发布;PR 模板加「如何测试 / 风险 / 如何回滚」 无
2. 自检 写一份简短的 CLAUDE.md 列出可运行的检查;本地跑 /code-review 和 /security-review,或用 fresh context 的 subagent 审 diff 无
3. 自动评审 先在一个仓库接入 AI 评审,用 REVIEW.md 调几周再推广;限制评审轮数,几轮后只审新 diff 阶段 1 已就位
4. 积累 eval 把事故和回滚整理成 eval 集,评审器每次改动都重新打分 有历史事故记录
5. 分档审批 写下风险档位,从严开始,按证据放宽;用 CODEOWNERS 和分支保护锁住认证、计费、CI、发布和安装器 阶段 1--4 已运行一段时间,且合规要求允许

第 5 阶段是原文最引人注意的部分,也是最不该先做的部分。Anthropic 自己的工程师都在要求先有熔断机制,再扩大零人工合并的范围。

原文链接:claude.dev/blog/solvin...

相关推荐
HjhIron1 小时前
从朴素RAG到Agentic RAG(二):基于LangGraph的混合检索、重排与闭环设计
ai编程
坊钰1 小时前
【LangGraph框架入门级】12. 人机交互:interrupt 中断与 Command 恢复
开发语言·数据库·python·人机交互·ai编程·langgraph
Solara1 小时前
一个标志位挂了 18 天不落地:它等的重启,2 天 14 小时后就完成了
人工智能·程序员·ai编程
SkyWalking中文站2 小时前
从模型输入到文件变更:追踪 AgentCore 上的 LangGraph Agent
langchain·aigc·ai编程
金銀銅鐵2 小时前
[Java] 用 GUI 展示 ArrayList 扩容的过程
java·后端·ai编程
NC 王炸3 小时前
AI 做的便签,换个浏览器就没了?加一个导出按钮,把数据带走
javascript·ai编程·数据备份·localstorage·txt导出
凯歌的博客15 小时前
DuckDB 是一款进程内的分析型数据库
数据库·ai编程
冬奇Lab15 小时前
每日一个开源项目(第238篇):Impeccable - 让每个 AI 编程工具都学会审美的设计引擎
人工智能·开源·claude