某公司从单条prompt发展出包含6个专业agent和验证器的完整Code Review体系,详细披露了各阶段踩坑与解决思路。
Claude Code 评审在我们公司始于 GitHub workflow 中的一个 prompt,五个月后它变成了一份 playbook、六个专业 agent 和一个验证器——任何无法证明的发现都会被丢弃。这两者之间的几乎每一步都是对某个出错之处的回应:规则还在调整阶段的误报、针对 pull request 从未触及的代码的发现、依赖模型情绪的严重程度,以及当我们一次性给它太多规则时一个凭空编造问题的评审者。
这就是规则是如何演变的,以及每次改动修复了什么。
Claude Code 现在已有自己的评审功能。Anthropic 的托管 Code Review 目前处于研究预览阶段,面向 Team 和 Enterprise 计划,通过 Claude GitHub App 运行:多个 agent 并行查找不同类别的问题,一个验证步骤过滤掉误报,发现以 Important、Nit 或 Pre-existing 标签的内联评论形式到达。它永远不会 approve 或 block 一个 pull request,你通过 REVIEW.md 文件来调优它。在本地,/code-review 对你的分支做同样的事。
我们保留了自己的评审流程,因为我们已经有一套定制化的流程。内置评审默认查找正确性 bug;我们的则强制执行一份成文的架构规范、为每个发现引用规则,并对 pull request 投票。如果你想要一双检查 bug 的额外眼睛,从那里开始;如果你想要用裁决来执行文档化的规则,你需要自己的 playbook。
第一个版本在 4 月 20 日上线。一个 workflow 监听包含 "@claude" 和 "review" 的 pull request 评论,然后用包含三个任务的 prompt 运行 Claude Code。
对于我们分层模块中的文件(routers、services、repositories 和 DTOs),它读取每层的架构规则文档,将任何违规视为阻塞性的。
其他所有内容获得一次通用评审,明确不应用分层规则。
它按文件对发现进行分组,每个发现包含严重程度(BLOCKING、WARNING 或 SUGGESTION)、位置、问题和具体修复方案。
这个结构在之后的每个版本中都保留了下来;触发条件则没有。在规则还在调整的阶段它产生了误报,所以只在有人提出请求时才运行。
5 月 12 日到 15 日之间,workflow 四次更改。
它在每个 pull request 上运行——打开时、每次新 push 时、以及重新打开时。
它提交一个真正的 GitHub review:如果有任何 blocking 发现则 request changes,否则 approve。
它跳过 draft pull request,直到它们被标记为 ready for review。
它跳过长期存在的项目分支,否则每个中间 push 都会触发一次评审。
那一周的教训:当评审者开始投票时,噪音不再是烦扰,而变成了成本。一个错误的 "request changes" 会阻塞一个同事。之后的一切都关乎精确性。
下一次重写引入了三个理念,它们至今仍是系统的骨架。
按路径加载规则,而非一次性全部加载。评审者列出改动的文件,然后只读取那些路径所需的规则文档:只有 router 改动时才读取 router 规则,以此类推。一次加载所有规则会导致幻觉:评审者报告了不存在的违规。
只评审改动的行。prompt 增加了一句我们从未删除的话:只评审改动或新增的行,绝不标记已有代码。没有这句话,一个旧文件中的单行修复可能会返回二十个关于多年前编写的代码的发现。
严重程度按定义而非判断。严重程度部分的标题是"严格套用,不做主观判断"。BLOCKING 意味着分层规则违规、正确性 bug、安全问题或数据丢失风险。WARNING 意味着架构正确但仍有风险。SUGGESTION 意味着风格或命名问题但不违反任何规则。
5 月 18 日,规则从 workflow 和 CLAUDE.md 中移出,合并到单个 docs/review.md。GitHub Action 和本地 /review 命令都遵循同一份文件,因此 push 前在本地评审应用的是与 pull request 相同的规则。
请求基准分支。本地评审时,询问工作将合并到哪个分支,而不是假设 main。
跳过数据文件。SQL、CSV 和 JSON 文件被排除在外;将迁移和 fixtures 作为代码评审会产生无人能执行的发现。
每个发现都要引用规则。BLOCKING 必须引用架构规则文件及章节,WARNING 引用 CLAUDE.md 中的风格规则。SUGGESTION 用于没有任何规则覆盖的内容。
绝不用风格规则 block 遗留代码。风格规则在任何地方最高只到 WARNING。
将严重程度与引用绑定改变了评审的性质。一个发现要么指向团队一致同意的规则,要么是一个作者可以忽略的建议。
5 月 19 日,单个评审者变成了一个协调者——本身不评审任何内容。它将每个改动的文件路由到拥有它的专业评审者,并行运行它们并汇总结果。
每个专业评审者只读取自己的规则文档,因此被四个专业评审者评审的 service 文件不会收到同一个发现四次。它们都以一种固定格式返回发现,附上逐字引用的违规代码。
验证器是我会最先复制的 Claude Code 评审 agent。对于每个发现,它检查四件事,任何一项失败则拒绝该发现:
引用的文件存在。
引用的代码出现在引用行号的五行范围内。
该行是在此 diff 中新增或改动的。
引用的规则章节存在,且与发现所声称的内容一致。
它的指令以整个设计背后的原则开头:误报的危害远大于漏报。它不能重新评级严重程度或自行添加发现,被拒绝的发现被静默丢弃。
9 月我们添加了第六个评审者,专门负责数据库性能,因为我们最昂贵的生产问题是在开发环境快速但在规模上缓慢的查询。它 block 循环内的查询、N+1 访问关联字段,以及存在批量写入时的逐行写入,并对无界获取和在 Python 而非数据库中完成的聚合发出警告。当某个模式是刻意为之的,用 # db-perf: allow 注释加原因来抑制该发现。
有两个决定值得注意。数据库性能发现也可以 block 遗留代码,这是"绝不用风格规则 block 遗留"规则的唯一一个刻意的例外,因为循环中的查询无论在哪里成本都一样。另外,workflow 文件完全没有改动:添加一个专业评审者意味着一份规则文档、一个 agent 定义和路由表中的一行。
从输出格式和严重程度定义开始。它们在每个版本中都保留了下来;触发条件和架构则没有。
让每个发现引用一条规则。这将关于品味的争论转化为关于规则是否正确的对话。
绝不标记已有代码。没有什么比这更快摧毁对自动化评审者的信任。
在发布前验证。检查引用、行号、diff 和规则的第二轮通过成本远低于一个错误的 "request changes"。
这关联到 AI 编码 agent 的六个反馈循环:评审阶段只有在发现足够精确可以采取行动时才能改进下一次变更,而且它防止了为什么生成的测试会漏掉 bug 这个问题的发生。
Claude Code PR 评审能自动在每个 pull request 上运行吗?
能。它通过 Anthropic 官方 action 在 GitHub Actions 中运行,由 pull request 事件或 "@claude" 评论触发。
Claude Code review skill、command 或 agent:我应该用哪个?
它们配合使用:斜杠命令作为本地入口点,子 agent 让每个评审者持有一套规则,skill 用于可复用的流程。要将我们的打包为 skill,把步骤放在 SKILL.md 中,规则文档和发现格式放在旁边,并把专业评审者和验证器作为子 agent。如何创建 Claude Skills 讲解了结构。
它能取代人工评审吗?
不能。当规则被写下来并被引用时,它能可靠地捕捉规则违规——这占人工评审者大部分时间——但在判断一个变更是否是正确的变更方面较弱。每个 pull request 仍需要人工 approval。另外,评审工作量也是头条数字所掩盖的成本:90% 的 agent PR 合并率仍然可能描述的是一个薄弱的工作流程。
我们今天运行的系统并不聪明。它是一份 playbook、一个路由表、少数几个各知一套规则的评审者,以及一个拒绝任何无法证明之物的验证器。每个组件的存在都是因为更简单的版本在特定方式下失败了,如果你现在从头开始,可以跳过大部分那些失败。
playbook 本身(移除我们公司特定的规则后)在这里:一你可以复制的 Claude Code 评审模板。
Originally published on nulltensor.com.