跳到主要内容

AI 作为 CI/CD 门禁:智能体可以和无法可靠拦截的内容

· 阅读需 11 分钟
Tian Pan
Software Engineer

一个 AI 审查器拦截了一个合并(merge)。一名开发者盯着失败的检查,点击“查看详情”,扫视了三段样板文字,然后在没有阅读实际发现的情况下提交了一个“强制推送异常”(force-push exception)。在不到一周的时间里,团队中的每一位工程师都在潜意识里认为 AI 门禁只是背景噪音——是需要被忽略的,而不是需要去参与处理的。

这是大多数构建 AI CI/CD 门禁的团队实际交付的结果,即便底层模型在技术上是有能力的。问题不在于 AI 是否能审查代码,而在于你要求它拦截什么,以及你期望在它拦截时发生什么。

要正确构建这种架构,需要明确三件事:首先,AI 智能体究竟能可靠地捕捉到什么;其次,在压力之下,门禁的信任模型实际上是什么样的;最后,如何防止工具在处理真实流量时信噪比崩溃。

AI 门禁真正擅长捕捉的内容

基准测试显示,召回率在 36% 到 82% 之间(取决于具体工具),但这些数字掩盖了一个重要事实:性能在不同问题类别之间非常不均衡。AI 代码审查擅长处理机械的、基于模式的和局部作用域的问题。

风格和一致性违规是最可靠的类别。AI 可以检测整个变更文件中的格式不一致、重复代码块、过于复杂的函数,以及像基本类型迷恋(primitive obsession)这样的结构性反模式。无需显式编写规则——模型就能从周围的代码库中推断出惯用模式。

API 误用是另一个强项。在将新端点与现有端点进行比较时,AI 可以可靠地发现缺失的授权中间件、已弃用的 API 调用、损坏的身份验证模式,以及在其他类似代码处理了错误但此处却缺失的情况。这类检查需要跨文件的语义上下文,而基于规则的 Linter 很难处理这一点。

常见安全问题是 AI 明显优于静态分析的地方。受控实验显示,基于 LLM 的检测器在 SQL 注入上的召回率达到 95%(而静态分析为 32%),在命令注入上为 83%(而静态分析为 24%)。这种差距源于语义理解:AI 能够识别出即使经过多次中间转换(这些转换会让模式匹配失效),源自用户输入的变量仍然是危险的。

**文档偏差(Documentation drift)**是一个被团队低估的类别。当修改后的代码与相邻的文档注释不一致时,AI 可以在作者仍然拥有上下文时标记出这种不一致。这种检查的成本很低,而回报是稳定的。

所有这些的共同点是在有限范围内进行模式识别——单个文件、单个函数签名或众所周知的漏洞类别。当问题类型超出这个范围时,性能会大幅下降。

AI 无法可靠拦截的内容

这些失败是可以预见的,而假装它们不存在正是导致团队构建出无法信任的门禁的原因。

架构决策是无法触及的。新的抽象是否符合长期系统设计,将服务耦合到特定数据存储是否是正确的权衡,数据模型的选择是否会在 10 倍规模时带来痛苦——这些都无法从 Diff 中评估。AI 缺乏资深审查者所具备的关于你的系统模型、组织的债务承受能力以及产品路线图的认知。

业务逻辑正确性是最昂贵的缺口。一个 PR 可以通过所有语法和语义检查,但实现的却是完全错误的东西。对 2,000 多个 PR 的分析发现,在 AI 编程采用率翻倍的同一时期,每个 Pull Request 的事故增加了 23.5%。交付的代码更多了,但业务逻辑缺陷却溜了进来,因为 AI 审查无法验证代码是否解决了正确的问题。

新型安全漏洞需要当前模型处理得不好的过程间分析(interprocedural analysis)。AI 无法可靠地确定一个变量是否在复杂的调用图中包含用户控制的数据,也无法模拟特定于应用程序的信任边界。它能很好地捕捉已知类别的漏洞,但对于零日漏洞(Zero-days)和特定上下文的漏洞利用,效果较差。

性能权衡需要理解 Diff 中未编码的约束:预期的数据量、现有的热点、SLA 预算。AI 会标记它识别为反模式的 O(n²) 循环,但它不会告诉你该循环是在 10 条记录的数据集上运行,还是在 1,000 万条记录上运行。

实用的规则是:如果正确评估一个问题需要了解代码存在的原因、谁在使用它,或者它位于哪个系统内部,那么该检查属于人工审查员,而不是门禁。

真正稳固的信任模型

行之有效的模式是双层门禁:将“强制拦截(hard blocks)”预留给少数高置信度的关键问题,而其他所有内容都作为“建议性评论”呈现,不阻塞合并。

强制拦截在流水线级别应该是不可绕过的。这意味着在检查通过之前,合并按钮是禁用的,而不仅仅是发布一个警告。将此类类别保留给满足以下条件的少数问题:

  1. 分类准确率高(误报率低于 5%)
  2. 严重性明确(安全漏洞、数据丢失风险)
  3. 修复方案足够明确,开发者无需审查员即可理解如何解决

该集合之外的所有内容都应作为 PR 评论出现——可审查、可操作并链接到相关行——但不阻塞。开发者可以处理它、忽略它或标记它以进行讨论,而不会造成需要变通方案的流水线故障。

团队通过这种方式避免的失败模式是“狼来了”(cry wolf)效应。一旦门禁产生了几次不必要的阻塞发布的误报,工程师们就会学会忽略它。当你对工具进行微调时,这种习得性的忽略并不会消失。声誉受损是持久的。

从仅建议模式开始。运行 30 天。衡量可操作警报率——即开发者采取行动的评论比例。如果该比例高于 30%,你就拥有了一个值得拦截的信噪比。如果低于这个比例,你就是在训练你的团队去忽略它。

集成架构

在流水线中的哪个位置放置关卡,与你要求它检查的内容同样重要。

最有效的模式是具有不同范围的三个层级:

IDE 层(推送前):在编写代码时进行实时语义分析,可以在修复成本最低时发现问题。开发人员已经在思考这些代码。延迟容忍度很高——在编辑器中,两秒钟的内联建议是可以接受的。

CLI 层(推送前):在分支推送前运行的本地审查可以发现那些需要文件上下文但不需要完整 PR 差异的问题。开发人员可以有选择地运行它,或者通过 git hook 强制执行。

PR 层 (CI/CD):正式关卡针对完整的拉取请求运行,可以访问完整的差异、CI 上下文和整个代码库。这是做出阻断决定的地方。

将所有内容都放在 PR 层是一个常见的错误。它使延迟最大化(仅在推送后才有反馈),使成本最大化(每次 PR 都要进行 LLM 推理),并产生一种“截止日期前审查”的动态,此时开发人员对实质性反馈的接受度最低。将检测前移可以降低成本并增加开发人员参与的机会。

在 PR 层,将 AI 审查检查与现有的关卡(代码覆盖率、静态分析、安全扫描)并列,作为独立的必选状态检查。每个检查都有自己的通过/失败标准。这使 AI 关卡的信任度与机械关卡的信任度分开——AI 检查的误报不会波及到对覆盖率关卡的怀疑。

对于规模化团队,对每次提交进行完整的 LLM 分析是昂贵的。两种可行的方法是:分层分析(对发往 main 分支的 PR 进行完整审查,对功能分支进行轻量级审查)和针对性分析(仅针对已知能产生高质量信号的变更类别文件运行 LLM,如身份验证、支付、数据访问层)。

橡皮图章失效模式

橡皮图章是指当关卡在技术上正常运行,但负责审查其输出的人员已经不再阅读它时产生的结果。

其机制很简单:高频、低上下文的批准请求训练人类默认选择批准。一项研究发现,在一个智能体系统请求批准仅三天后,批准率就达到了 99.7%——这比系统可能赢得该信任水平的速度还要快。警报内容变得不再重要,批准的动作变成了条件反射。

对于代码审查关卡,橡皮图章通常是因为:

  • 关卡在每个 PR 中产生的发现过多(开发人员的认知预算在触及真实问题前已耗尽)
  • 发现的描述是抽象的而非可操作的(开发人员不知道该做什么,默认忽略)
  • 关卡有明显的误报历史(开发人员假设任何发现可能都是错误的)
  • 关卡在开发人员认为非关键的问题上阻断合并(开发人员学会了“修复”AI 意味着绕过它)

早期检测这一点的最重要指标是评论确认率:AI 审查评论中,有多少比例导致了代码更改或保留代码现状的记录决策。在提交质量下降之前,确认率的下降就是橡皮图章现象正在滋生的信号。

缓解措施:

  • 将每个 PR 的发现数量限制在符合人类审查带宽的阈值内(10–15 条实质性评论,而不是 80 条)
  • 提供带有明确上下文的发现:哪一行、什么模式、为什么重要、修复方案是什么
  • 在视觉和结构上区分建议性发现和关键性发现,以便开发人员知道哪些需要处理,哪些只需了解
  • 长期跟踪接受率,并在其降至 30% 以下时调整阈值

最关键的决定

问题不在于“我们能否添加一个 AI 关卡?”,而在于“我们要在哪些目前未被发现的问题上阻断合并?”大多数团队的答案分为三类:

  1. 静态分析或 linter 已经捕获的内容(不要替换,而是叠加)
  2. 需要人类判断来评估的内容(不要自动化)
  3. 一个狭窄的中间地带:基于规则的工具漏掉的语义问题,这些问题足够可复现从而值得信任,并且足够具体从而可操作

这个中间地带是 AI 关卡合适的初始范围。它比大多数团队预期的要小,这就是为什么从建议模式开始并在阻断前进行测量,是产生一个让开发人员视为信号而非阻力的关卡的唯一架构。

成功实现这一点的团队并不是那些相信基准测试数字的团队。他们是在自己的代码库上测量了误报率,将其调整到开发人员可以容忍的水平,并在赢得阻断权限所需的信任之前,抵制住了扩大范围的诱惑。

References:Let's stay in touch and Follow me for more thoughts and updates