跳转到内容

AI 审查

一次 AI 审查,就是针对一个处于打开状态的 pull request 运行一次预置的 pr_review 流水线。流水线会打开该 PR 的审查空间,派出多个审查智能体,在该空间的隔离检出中阅读 diff;每个审查者把自己的发现项以结构化 审查节点 的形式提交,随后由主导智能体汇总 成一份走查,最后由终结器计算出一个判定:Ship、Hold 或 Block。流水线绝不会 做的一件事是发布 —— 向 GitHub 发帖是一个单独的、需要人主动执行的步骤。

本页其余部分会解释各个组成部分,以及它们为什么被设计成这样。

PR 的审查上下文是一个消息空间 —— 模式为 review,类型为 pr —— 通过 审查空间关联 与这个 pull request 绑定。它的创建是幂等的:PR 页面、审查流水线和各个聊天界面 都通过同一条代码路径解析该 PR 唯一 的底层空间,因此,一个审查 PR 的模板和一个打开 该 PR 的人,永远不会落到两个不同的房间里、看着两份不同的检出。

该空间的隔离工作树中,PR 已检出至其 head ref。一个房间也意味着同一份检出:所有审查者 都在同一个空间里工作,而不是各自克隆一份工作区。

每个审查者都在这个空间里自己的具名流中发言,发现项是 review_node 消息,而不是普通的 散文式文字。最后在空间范围内汇总是有意为之 —— 若只根据某一条线程的发现项计算判定, 那就等于悄悄只对一个审查者下了判定。

该关联带有一条状态阶梯 —— requested → in progress → awaiting approval → completed —— 正是它决定 PR 评审标签页上的 发布到 GitHub 按钮能否使用。

审查的深入程度是一项工作区策略,共三个级别,在 设置 → 工作区 → 通用 中、 工作区策略 卡片上设置:

级别 派出的审查者 报告方式
light 仅工程师 只报告真正重要的内容
balanced 工程师、QA、架构师(默认) 常规的一遍检查
thorough 全部五个,包括安全和性能 不作任何降级

级别同时拨动两个旋钮:一是派出哪些审查者,这由流水线模板的 runWhen 状态门禁强制执行, 而不是靠提示词措辞 —— 提示词措辞可以被忽略,门禁不行;二是低于阈值的发现项呈现在哪里。 这两个旋钮都不会删除任何发现项:报告更少的级别,提交的发现项数量完全相同,只是把其余 部分归到一组。

安全和性能这两遍检查复用预置的架构师和工程师智能体,而不是引入新的智能体。其专长体现在 派发审查者时随附的任务说明里,而不是每个轴各用一个独立智能体 —— 每个轴一个智能体, 只会让每个工作区多出五行记录,却带不来任何额外能力。审查者的选择从不检查 diff 的语言 或领域。

审查节点:发现项是数据,而非散文

标题为“审查节点:发现项是数据,而非散文”的部分

用 add_review_node 提交的发现项会成为该 PR 上的一个 审查节点 —— 评审标签页渲染 的正是它,判定正是根据它计算出来的,而“发布到 GitHub”正是把它变成行内评论。只返回 散文式文字的审查者,会让流水线运行看起来成功了,而审查界面却空空如也;真正承重的是 提交这个动作。

每个节点包含:

字段 取值
类型 bug、suggestion、recommendation、question、ticket
优先级 P0(严重)→ P3(细枝末节)
分诊三元组 类别(security、stability、…)、严重程度、工作量
锚点 文件路径、起始行与结束行
修复承载 建议的替换行、可选的 diff、可选的修复提示词
置信度 一个 [0, 1] 分值
推理过程 在发现项之前写下的分析

有两个细节是有意为之。只有当审查者给出了确切的替换行时,才会提供一键 GitHub 建议 —— 从 unified diff 里推断替换行,出错时悄无声息,而把一次错误的推断一键提交,比根本不给 按钮更糟。另外,add_review_node 的 schema 把 reasoning 放在发现项之前,这样按 schema 顺序填充对象的模型会先写出分析。该字段是可选的:省略它并不会让节点被拒收。载荷格式不 正确的节点会直接消失,而不会污染审查结果。

节点会经历 open → consensus-ready → resolved 或 dismissed 的状态流转。中间 这一步是这套模型的核心:发现项只有在另一位审查者确认后才会升级,而智能体永远不能 确认自己提出的发现项。 MCP 工具 publish_review_to_github 和 RPC 的默认行为仍然只 发布经同行确认的发现项。而评审标签页的 发布到 GitHub 按钮则会发送所有仍然未解决的 发现项。

这条规则在三个相互独立的地方强制执行 —— 确认工具、终结器和发布器 —— 因此即使其中 任何一个的调用方有 bug,规则依然成立。所有状态变更都经由同一个服务处理,这正是状态 能够有意义的原因:在此之前,两条各自走一半的路径可能会对同一个发现项是否已解决给出 不一致的结论。

当审查者意见不一致时 —— 同一个文件和行、优先级相差两级或更多,或者一个称其为 bug 而另一个称其为 suggestion —— 这种分歧会显示在发现项列表上方。这正是审查者意见出现 分歧、而人的判断最有价值的地方。

驳回一个发现项还会向记忆域写入一条低置信度的软性抑制事实 —— 一次驳回只是一种偏好, 而不是一条规则。

审查计算这一遍会把 PR 中变更的文件按代码图划分为若干 队列:变更的文件映射到它们 触及的符号,符号再映射到相互连接的组件,队列则按影响半径排序。一个队列带有引导式阅读 顺序、图表和洞见,而不是一份平铺的文件列表。

有两条诚实性规则塑造了这一点。队列键由内容派生,并且在多次 push 之间保持稳定,因此 发现项和审查进度能挺过 rebase 或 force-push,而不会成为孤儿。另外,当仓库没有代码 索引时,分组会退回到按普通路径进行,并且会明确说明这一点 —— 这种退路绝不会伪装出 语义上的可信度。

除了审查者的发现项之外,一次审查还会累积 轴结果:六个轴,分为两类。

轴 类别 来源
correctness、security 由 token 驱动 审查者自己的发现项
testGap 由 token 驱动 审查者的发现项
visual、apiContract 确定性 无需消耗 token 即可算出
performance 确定性 仅有枚举 —— 产品中没有任何东西会计算出结果

一个轴的判定结果为 pass、warn、fail、partial 或 unavailable —— 只有 pass 或 warn 能通过门禁。fail、partial 与 unavailable 之间的区分是承重的:受门禁 约束的轴如果无法完成或根本无法运行,会拖住总体判定不放行,而不是让它通过。证据缺失 绝不会转化为门禁通过。

有些轴有意只作提示。由队列推导出的测试缺口轴看不到依赖注入或工厂的覆盖情况 —— 从它 的角度看,一个没有索引但测试套件很完备的仓库,和一个完全没有测试的仓库一模一样,因此 无论声称哪一种都是撒谎;它只出现在仪表板中,不参与门禁。由 token 驱动的那些轴只作提示, 因为发现项的优先级已经决定了判定,再凭它们施加门禁就是重复计数。

终结器在状态为 open 或 consensus-ready 的发现项上计算判定:

  • 任何置信度 ≥ 0.7 的 P0 发现项 → Block
  • 否则,任何 P0(低置信度)或任何 P1 → Hold
  • 否则 → Ship

该判定带有一个总体置信度,它由各个参与贡献的置信度的离散程度推导而来 —— 一致会提高它, 分歧会降低它。

主导(CEO)智能体的汇总是一遍编辑式整理,而不是重新罗列:手写一份发现项的第二副本, 恰恰是那种会逐渐偏离真实版本的东西。重复的发现项会被降级,而不是重复呈现 —— 多个 审查者被指派去看同一个 diff,他们的职责范围刻意重叠,因此同一个缺陷三次到达终结器, 恰恰说明系统在正常工作;而把它发布三次,则是系统把自己的架构泄漏进了读者的收件箱。 在重新审查时,发现项会被取指纹并与上一轮做 diff,因此浮现出来的是真正的增量。

最后,各个轴加入进来,而它们只会让判定变得 更 严重:受门禁约束且失败的轴会强制 给出 Block —— 它不会被发现项投票推翻 —— 而受门禁约束、无法完成的轴则至少会强制给出 Hold。

流水线有意不向 GitHub 发帖;发布由用户把关,因此一次审查绝不会重复发布。当你按下 发布到 GitHub 时:

  • 会提交一条 GitHub 审查。已经解决或已驳回的发现项会被跳过。该按钮会发布所有仍然 未解决的发现项(selection: all_open)。MCP 工具 publish_review_to_github 的默认 行为仍然是只发布经同行确认的发现项(consensus)。
  • 锚定到文件和行号的发现项会变成行内评论;其余的一切都归入摘要正文,每一项都带有 “— Control Center AI review”页脚,以便来源清楚明确。
  • 发布时会根据 PR 的 当前 diff 重新校验锚点。对已经被改写的代码留下评论,是审查者 可能留下的最破坏信任的做法;如果 GitHub 仍然拒绝某个行内锚点,整条审查会重新发送, 并把每一个发现项都归入正文,这样就不会有任何东西被悄悄丢弃。
  • Block 判定会以 REQUEST_CHANGES 提交;Hold 以 COMMENT 提交;Ship 则由 按钮以 APPROVE 提交(approve_on_ship: true)。除非你传入 approve_on_ship, 否则 MCP 工具会把 Ship 保留为 COMMENT。
  • 审查以服务器应用的标识发布。是谁按下的发布按钮会被记录下来,用于角色门禁和审计 日志;发布者并不是 GitHub 上的作者。

发布会声明 prPublish 动作类别,因此护栏卡点会像对待任何变更类操作一样对它施加 门禁 —— 它默认会弹出确认提示,并且在未连接任何审批人时以失败关闭的方式处理。 参见护栏。

审查智能体运行在 review 模式下:只读沙盒,以及一份精心筛选的工具允许列表,涵盖 发现项、评论、工单和同行评审 —— 但不允许任何变更操作。审查者无法修改它所批评的代码; 它可以附上一个建议的修复,由人来应用。当某个智能体仍试图动手时,该模式的拒绝消息会 告诉它先把审查定稿,再让用户基于已发布的摘要采取行动。