先看一次普通的合并请求
一名开发者提交了 26 个文件的改动:前端新增批量操作,后端增加一个异步接口,还顺手重构了日志。自动测试通过,lint 没有报错。审查者在半小时里留下四条评论:一个变量名不清楚,一处错误信息不统一,两处空值保护缺失。两天后,测试环境仍然发现了一个问题:异步任务在失败分支里没有释放锁,后续请求一直等待。
这类经历很容易导向两个相反的结论。有人会说,人工审查太慢,应该让 AI 全部接手;也有人会说,AI 连业务语义都不懂,代码审查只能依靠资深工程师。两种说法都把问题压扁了。真正需要回答的是:不同审查手段分别能看到什么证据,付出多少成本,在哪些条件下容易失效。
Code Review(CR) 是对代码改动进行判断和反馈的活动。它不等同于"找 Bug"。Google 的工程实践把设计、功能、复杂度、测试、命名、注释、风格和文档都列为审查对象;Bacchelli 与 Bird 对现代代码审查的研究还发现,开发者同时把知识传递和团队协作视为重要结果——这意味着审查不只是"发现缺陷",也是团队认知的同步机制。[1][2]
课程里会频繁出现 Merge Request(MR)。它是一份合并请求:开发者请团队把一个分支的改动合入目标分支。GitHub 常用 Pull Request(PR)这个名称。MR 不只是 diff 页面,还承载需求说明、提交记录、自动检查、讨论、批准和最终合并状态。AI CR 如果只拿到几行 diff,看到的只是这个协作对象的一小部分——这是后续所有上下文增强策略的出发点。
人工 CR 没有消失,但吞吐矛盾在加剧
现代代码审查的基本矛盾是:高质量判断需要上下文和注意力,研发流程却希望反馈更早、更快、更稳定。
人工审查擅长处理模糊目标。例如,"这个缓存会不会让结算金额过期""这个接口是否破坏了另一个团队的兼容承诺""为了赶发布日期暂时接受这段重复代码是否合理"。这些问题需要业务责任和风险取舍。审查者在判断代码时,同时也在判断团队愿意承担什么风险。
但同一个审查者也有注意力上限。小改动容易快速理解,大改动需要在多个文件、调用链和需求之间来回切换。等待审查拉长反馈周期;审查者忙于交付时,评论集中在容易看见的命名和格式;改动越晚被检查,返工时已经叠加的代码和测试就越多。
还有一类成本很容易被忽视:资深工程师不断重复解释已经稳定的规则。"错误日志必须记录原始 error""并发资源需要在所有退出路径释放""组件库已经处理空值,不要额外包一层""某目录只能调用领域服务,不能直接查存储"。前两条可能适合静态分析或 AI,后两条依赖仓库约定。关键不在于谁来执行,而在于:规则如果只存在于某个人的记忆里,审查吞吐就受这个人的时间限制。
所以本课程所说的"AI 替代人工"有严格边界:替代的是人工审查中的重复扫描、证据收集和第一轮反馈,不是替代代码所有者的责任。 准确的目标是让机器扩大覆盖,让人把注意力用在高风险和高语境判断上。
Code Review 的六个阶段
下面的演进不是一条所有团队都按年份经历的线性历史,也不是新阶段彻底淘汰旧阶段。成熟系统通常同时保留多种手段,只是把不同问题交给更合适的执行者。
flowchart LR A["人工逐行审查"] --> B["格式与规则自动化"] B --> C["远端 Diff AI 审查"] C --> D["本地仓库上下文审查"] D --> E["Harness 驱动审查"] E --> F["指标与反馈闭环"]
阶段一:人工逐行审查
最初的核心对象是补丁和讨论。人阅读改动,结合需求和经验给出评论。它的优点是判断弹性大,可以追问作者,也能处理架构取舍。缺点同样明显:结果依赖参与者时间、经验和注意力,重复规则消耗大量审查容量。
人工审查还承担教学功能。资深工程师指出一处错误时,可能顺便解释模块边界和历史原因。这个过程能传播知识,却难以规模化。把所有低级扫描都留给资深工程师,既昂贵,也会让真正需要讨论的设计问题淹没在评论列表里。
阶段二:格式、规则和静态分析自动化
lint、格式化器、类型检查、编译器、安全扫描和 静态分析 把一部分问题变成确定性判断。只要规则可编码、输入可获得,机器就能快速、稳定地执行。 例如未使用变量、危险 API、明显空指针路径、依赖漏洞或不符合格式规范的代码,都可能在提交前被拦截。
这一步的价值不是"工具比人聪明",而是让确定性问题不再占用人类注意力。它也是 Shift-Left 的典型实践:把质量检查提前到编码、提交或 MR 阶段,而不是等到集成测试或线上事故才发现。
规则工具的边界在于它必须提前知道要找什么。 某个函数虽然类型正确,却在业务上用了错误的 error 变量;某段并发代码虽然语法合法,却把锁释放放在了不完整的分支;某个建议虽然符合通用防御式编程,却违背了团队组件的推荐用法——这些问题需要比模式匹配更宽的语义判断。
阶段三:远端 Diff AI 审查
大语言模型让审查系统可以读自然语言与代码,给出解释性评论。最容易落地的形态是把 MR diff、少量规则和 Prompt 发给远端模型,再把结果写回 MR。它部署简单,能覆盖规则工具难以编码的问题,也能在很短时间内完成第一轮扫描。
CodeReviewer 这类研究把自动代码审查拆成代码改动质量估计、评论生成和代码修复三个任务。[4] 这个拆分很重要:发现问题、解释问题和产生可用修复不是同一种能力。 一个系统能生成流畅评论,不代表定位正确;能给出修复片段,也不代表修复符合仓库约束。
只看 diff 的 AI 审查经常遇到上下文缺口。调用函数的约定可能在另一个文件,类型定义可能由生成代码提供,需求约束可能写在任务系统,测试可能说明一个看似奇怪的分支是刻意设计。模型收到的信息不够时,仍可能给出语言流畅的建议。结果就是"看起来合理,实际上不适用"。 这是第 4 章采纳率诊断的核心起点。
阶段四:本地仓库上下文审查
下一步是让审查器进入真实工作区。它可以搜索符号、读取关联文件、查看测试、运行命令,再结合项目规则判断 diff。GitHub 的官方文档也把全项目上下文、自定义指令、仓库级说明、Agent skills 和 MCP 上下文作为提高审查相关性的手段。[5]
本地上下文减少了部分误报,却引入新的工程问题:模型该读哪些文件,如何避免把整个仓库塞进上下文,怎样限制命令权限,如何证明每个文件都检查过,任务失败后从哪里恢复。模型有了工具,只说明它"可以"行动,不说明它"必然"按完整流程行动。 这是第 6、7 章要深入讨论的核心矛盾。
阶段五:Harness 驱动审查
Harness 是包围模型的工程运行支架。它把一次大审查变成外部可控制的过程:服务端创建 Session,筛选文件并切分 Batch;Agent 只能领取当前任务;提交结果后由程序检查结构和工作量;状态机决定下一步是继续、重审、扩展检查还是汇总。
这里发生了一个关键转变。Prompt 仍然重要,但流程正确性不再完全寄托在模型"记住所有要求"。 批次、状态、下一步许可、重试和结果验证被写进代码与数据模型。模型负责擅长的语义分析,确定性程序负责计数、权限、状态与失败恢复。这是第 2 章要拆开讲的核心架构。
阶段六:指标与反馈闭环
系统上线后,问题从"能不能评论"变成"评论是否有用、漏掉多少、为何变差"。这要求记录开发者是否采纳、哪些建议被拒绝、测试后来发现哪些应召回问题、不同仓库和问题类型表现如何。反馈再进入规则、测试集、上下文策略和质量门。
BitsAI-CR 的工业实践使用规则检查、二次过滤、规则分类、反馈飞轮和评估指标,说明生产 AICR 往往是组合系统,而不是一次模型调用。[6] 课程不会照搬其公开数字,因为模型、团队、语言和统计口径都不同。我们关心的是工程结构:先检测,再验证,用反馈持续校准。 这是第 3 章要建立的度量体系和后续所有优化的前提。
为什么是今天:代码生成改变了输入规模
过去,代码产出速度在很大程度上受人工输入限制。AI 生码工具提高了创建和修改代码的速度,也让"一次改很多文件"变得更常见。代码写得更快,不会自动让需求更清楚、架构更一致或测试更充分。 审查入口因此承受更大的数量和速度压力。
如果生成端每小时产生多次改动,而审查仍等待少数资深工程师排队,质量系统会出现三个后果。第一,反馈变晚,错误在更多改动上叠加。第二,审查者会采用抽查或只看关键文件,覆盖难以稳定。第三,生码平台缺少一个可以程序化调用的质量门,生成结果只能直接进入测试或等待人工。
AI CR 的现实价值就在这里:它可以在提交前、本地工作区、MR 创建时或生码任务结束后立即运行,给出第一轮语义检查,并把高风险问题和证据交给人。远端服务化后,同一套能力还能被 CI、开发平台和其他生码 Agent 调用。 第 8 章会专门讨论服务化,当前只需记住:AICR 的调用方不再只有"正在看 MR 的人"。
这并不意味着评论越多越好。假设系统每次都报告几十个低价值问题,开发者会快速学会忽略它;假设系统只报告一两条极有把握的问题,采纳率可能很好,却漏掉大量真正缺陷。高质量 AICR 必须同时处理噪音与遗漏,这正是后续采纳率和召回率两条主线。
四类审查者怎样分工
用"AI 能不能审查代码"来提问太宽。更实用的做法是先看问题特征,再选择执行者。
| 问题特征 | 首选手段 | 原因 | 需要升级的条件 |
|---|---|---|---|
| 规则明确、可确定计算、无需业务语境 | lint / 编译 / 静态分析 | 快、稳定、可阻断,结果易复现 | 规则难表达或误报随上下文变化 |
| 需要跨少量文件理解代码意图,有清楚证据 | AI CR | 语义覆盖广,可解释并给出候选修复 | 涉及高风险、所有权或含糊业务取舍 |
| 需要需求、组织承诺、架构责任或风险接受 | 人工审查 | 人能承担决策责任并处理含糊目标 | 可先让 AI 收集证据和列出冲突点 |
| 既有可编码底线,又有上下文例外 | 组合审查 | 工具守底线,AI 查语境,人做终局判断 | 需要明确谁有阻断权和如何处理冲突 |
一个常见错误是把容易自动化的问题全部交给 AI。 例如格式、导入顺序和已知危险函数,本可由确定性工具快速判断,却被模型用自然语言重复评论。这样既增加成本,也让结果存在随机性。另一个错误是把高风险决策自动化:AI 说"没有问题"就允许涉及权限或资金的改动直接合并。 模型输出应该成为证据的一部分,而不是责任的替代物。
2025 年的一项研究尝试组合静态分析与 LLM,报告混合策略能改善评论的相关性与完整性。[7] Ericsson 的经验报告也采用 LLM 与静态程序分析的轻量组合,并让有经验开发者参与初步评估。[8] 这些公开证据与我们的工程判断一致:规则和模型不是竞争关系,它们覆盖不同的可判定空间。
从真实问题样本看"适合谁审"
下面的场景来自脱敏后的教学样本。它们不代表行业分布,也不用于计算生产指标。目的只是练习分工。
场景一:未使用变量
代码声明了变量却从未读取。编译器或 lint 可以确定判断,首选确定性工具。AI 再评论只会重复已有信号。人工一般无需参与,除非未使用代码暴露了更大的需求遗漏。
场景二:goroutine 中锁释放位置不完整
锁只在成功分支释放,错误分支提前返回。数据流分析可能发现,AI 也可以沿控制流解释后果。适合"静态分析 + AI"组合:前者提供稳定告警,后者解释并检查相邻代码是否存在约定。 若锁保护的是高风险共享状态,应由人确认修复。
场景三:日志记录了错误的 error 变量
当前分支检查 saveErr,日志却打印上一个步骤的 queryErr。类型系统通常不报错,局部语义却明显矛盾。AI 对这类跨几行的变量关系很有优势,也适合补充自定义静态规则。评论应包含具体变量和控制流证据,不能只说"错误处理可能有问题"——这种模糊评论本身就是采纳率杀手。
场景四:重复方法定义
如果语言或构建系统会直接报错,交给编译器;如果是不同文件中语义重复、导致维护分叉,AI 可搜索符号并提示。是否合并方法仍要看模块边界,可能需要人判断。
场景五:建议增加空值保护,但业务入口保证非空
这是一类典型拒绝评论。单看当前函数,防御式检查似乎合理;结合入口契约,它可能重复甚至隐藏上游错误。AI 只有读取契约、调用方或测试后才有资格判断。 证据仍冲突时,应交给代码所有者。
场景六:方法内部已经处理失败
AI 在调用处建议重复捕获,但被调用方法已转换错误并记录必要信息。这说明审查器只看了 diff,没追踪实现。 解决办法不是让 Prompt 更强硬,而是让系统提供符号搜索和相关文件上下文,并在提交评论前复核。
场景七:组件库推荐的写法看起来违反通用规则
通用规则要求显式传值,项目组件却约定缺省值触发受控行为。AI 若不知道组件文档,会把正确代码判为问题。 这类案例应沉淀为项目级规则或路径级说明。人工负责确认规则,AI 负责在后续审查中一致执行。
场景八:修复方向正确,建议代码不可用
AI 正确发现竞争条件,却给出会阻塞事件循环的修复。这里"发现"与"修复"必须分开评分。 评论可以保留问题证据,但修复建议要经过复核;高风险改动由人决定。
场景九:接口改变了权限边界
代码本身可以运行,测试也通过,但新接口把原本只在后台使用的能力暴露给普通用户。AI 可以追踪鉴权调用、列出缺失测试,却不能代表产品和安全负责人接受风险。 必须人工审查,并且适合设置强制审批规则。
场景十:命名不够清楚
AI 能快速指出含糊命名,但价值依赖团队语境。如果只是个人偏好,不应形成阻断评论;如果名称掩盖了单位、时区或状态语义,就可能导致真实缺陷。审查器应说明歧义如何影响阅读或调用,而不是只给一个替换词。
把十个场景放在一起可以看到,执行者不是按"简单/复杂"一刀切。选择标准至少包括:规则能否确定表达、需要多少上下文、错误后果、是否涉及责任决策、结果能否自动验证。
AI CR 的职责边界
一套健康的 AICR 系统应该明确三种权限。
建议权:AI 可以报告候选问题、证据、严重度和修复方向。大多数语义评论停留在这里。开发者可以采纳、拒绝或标记无法判断。
阻断权:只有规则清楚、误报经过校准、失败成本足够高的检查才适合阻断合并。阻断可以来自测试、静态分析或经过验证的 AI 质量门,但必须有申诉和人工覆盖路径。 否则系统会用"安全"名义制造不可解释的流程堵塞。
决策权:架构例外、业务风险、数据兼容、发布时间与技术债取舍属于责任主体。AI 可以准备材料,不能替负责人签字。GitHub 的官方 Code Review 文档也明确写道,Copilot 不保证发现 PR 中的所有问题,可能犯错,使用者应仔细验证反馈并补充人工审查。[5]
flowchart TD
I["候选问题"] --> D{"能否确定验证?"}
D -- "是" --> R{"规则成熟且误报可控?"}
R -- "是" --> G["自动检查,可配置阻断"]
R -- "否" --> S["AI 建议 + 人工确认"]
D -- "否" --> C{"是否涉及责任与风险接受?"}
C -- "是" --> H["人工决策,AI 提供证据"]
C -- "否" --> A["AI 分析,保留反馈入口"]边界还要体现在产品交互中。如果 AI 评论被当成普通审查意见,开发者可以讨论、解决和隐藏;如果系统允许一键应用修复,就应保留变更 diff 和测试结果;如果支持自动重审,就要避免重复提交已解决评论。官方产品已经暴露出这些工程细节:GitHub Copilot 的评论不计入必需批准,也不会直接阻止合并;它允许自定义仓库规则和反馈,并提示重审可能重复评论。[5]
Shift-Left 不是把所有门都移到最左边
Shift-Left 常被理解成"越早检查越好"。更准确的定义是:把能够在早期获得足够证据的检查提前。 格式、类型和局部语义可以在编辑器或提交前运行;依赖真实集成环境的行为仍应留给集成测试;需要线上流量才能判断的问题要依靠灰度和监控。
AICR 适合位于提交前和 MR 阶段,因为此时 diff、仓库和作者意图基本可得,修改成本又比测试后更低。它还可以成为生码任务的质量门:Agent 完成代码后先触发 AICR,处理高置信问题,再把代码交给人。但"左移"不能让同一个 AI 同时写代码、审自己、宣布通过并自动发布——生成者与评价者需要一定分离,关键状态要由外部系统维护。
这套思想在课程中被称为 CR Shift-Left。它不是一个单独模型,而是一组对象和流程:Session 保存一次审查,Batch 控制工作量,Issue 保存候选问题,状态机规定下一步,MCP 暴露领取任务与提交结果的工具,指标和记忆把反馈带回下一轮。第 2 章会沿一条真实请求逐站拆解。
本课程接下来怎样推进
第 1 章只建立了边界:人工、规则工具与 AI 各有职责;高质量不等于评论数量;AICR 必须同时面对噪音与遗漏。
第 2 章把模型放进一个可执行系统。你会看到 Prompt 为什么仍然必要,却不足以控制长流程;也会看到 Session、Batch、File、Issue、状态机、MCP 和 Agent 怎样交接。第 3 章先建立度量语言,定义采纳率、召回率与 F1,并揭示分母变化如何改变结论。这是后续所有优化的前提:没有稳定口径,"优化"很容易退化成展示几条漂亮评论。 随后四章分别诊断和改造采纳率、召回率,最后进入远端服务化。这条路线刻意把指标放在改造之前——也只有先分清 AI 和人的责任,后续的自动采纳、质量门和远端接入才不会扩大错误权限。
路线检查
回到章首的 26 文件 MR,可以这样分工:lint 处理格式和确定性规则;静态分析检查可编码的数据流与资源释放;AI 在仓库上下文中扫描错误变量、跨文件约定和候选风险;人工集中判断异步设计、业务契约和是否接受风险。测试环境发现的锁问题还应进入评估集,检查下一版 AICR 能否召回。
如果你面对一个新问题,可以依次问五个问题:它能否被确定性规则表达?需要哪些仓库或业务上下文?报告错误的成本是什么?谁有权接受风险?结果如何验证和回流? 能够回答这五问,就不会把"采用 AI"误写成"增加一次模型调用"。
参考文献
- Alberto Bacchelli, Christian Bird. Expectations, outcomes, and challenges of modern code review. ICSE, 2013.
- Google Engineering Practices. The Standard of Code Review;What to look for in a code review.
- Shane McIntosh 等. The impact of code review coverage and code review participation on software quality. MSR, 2014.
- Zhiyu Li 等. Automating Code Review Activities by Large-Scale Pre-training. ESEC/FSE, 2022.
- GitHub Docs. About GitHub Copilot code review.
- Tao Sun 等. BitsAI-CR: Automated Code Review via LLM in Practice. 2025.
- Imen Jaoua 等. Combining Large Language Models with Static Analyzers for Code Review Generation. MSR, 2025.
- Shweta Ramesh 等. Automated Code Review Using Large Language Models at Ericsson: An Experience Report. ICSME, 2025.