AI 写代码越来越快之后,我给合并流程加了一道闸

37 阅读7分钟

最近一段时间,我写代码的方式发生了很大变化。

以前一个功能需要自己逐个文件修改,现在很多时候只要把需求交给编码工具,它就能一次改完十几个甚至几十个文件。

速度确实快了。

但代码生成结束以后,新的问题也出现了:这些改动到底能不能合并?

文件少的时候,我还能从头到尾看一遍。改动一旦变大,Review 很容易变成快速浏览。接口看起来对,类型也能对上,测试可能还能通过,但一些真正危险的问题往往藏在更深的地方:

  • 权限校验少了一层;
  • 状态更新顺序不对;
  • 金额字段用了浮点数;
  • 某个失败分支没有回滚;
  • 调用了一个实际上并不存在的 API;
  • 从另一个模块复制来的代码,没有适配当前业务;
  • 需求要求修改三条链路,最终只实现了其中两条。

这些问题并不一定是语法错误,编译器和普通的静态检查也不一定能发现。

我试过直接让模型做 Code Review。

结果通常有两个极端。

一种是给出很多建议,从变量命名、注释、函数长度一路说到架构设计。看起来很认真,但真正会影响合并的内容并不多。

另一种是模型检查了很久,最后告诉我“没有发现明显问题”。但我无法确认它究竟审完了没有,有没有因为上下文太大跳过文件,或者在中间已经超时。

对代码审查工具来说,漏报当然是问题,但另一个同样现实的问题是噪音。

如果一个工具每次都输出二三十条意见,其中大部分不需要处理,用不了几次,开发者就会开始忽略它。最后即使真正危险的问题出现,也很容易淹没在一堆普通建议中。

所以我做了 ReviewGate。

它的定位不是替代测试,也不是替代人工 Review,而是在代码合并之前增加一道质量闸口。

它只优先回答一个问题:

这次改动里,有没有值得暂停合并、先检查清楚的问题?

不追求把所有问题都说一遍

ReviewGate 默认从几个维度并行检查改动:

  • 安全问题;
  • 逻辑和边界条件;
  • 性能问题;
  • AI 生成代码里常见的错误假设;
  • 项目自己的业务规则。

纯命名、格式和普通代码风格默认不检查。

不是因为这些完全不重要,而是它们更适合交给 linter、formatter 或团队规范。质量闸口如果被格式问题占满,真正危险的问题反而不容易被看见。

不同维度发现的问题会先合并去重,再交给独立的 Judge 重新验证。

高置信问题才会进入必须处理的区域,中低置信结果默认折叠。需要的时候仍然可以展开查看,但不会让它们直接阻塞合并。

最终只有三种结果:

  • BLOCK:发现了高置信问题,建议先处理;
  • WARN:存在风险,或者审查没有完整完成;
  • PASS:没有发现达到闸口阈值的问题。

这里我特意处理了一种情况:没有审完,不等于没有问题。

如果发生超时、上下文过大、部分任务失败,ReviewGate 不会给出 PASS,而是降级为 WARN。

我宁愿它保守地说“这次没有完整审完”,也不希望它在不确定的情况下告诉开发者“可以合并”。

业务规则比通用规范更重要

通用模型可以判断 SQL 注入、空值、错误处理和并发问题,但它并不知道每个项目自己的规则。

例如:

  • 金额必须使用整数分;
  • 用户资源访问必须校验 owner_id
  • 已完成订单不能再次取消;
  • 库存扣减必须和订单状态更新放在同一个事务;
  • 管理员权限不能通过前端传入的角色字段判断。

这些规则通常散落在文档、代码和团队成员的经验里。

ReviewGate 可以把它们直接写进项目配置:

[business]
rules = [
  "金额字段必须使用整数分,禁止使用 float",
  "用户级资源访问必须校验 owner_id",
  "已完成订单禁止回退到待支付状态",
]

之后每次 Review 都会检查这些规则。

对我来说,这部分比检查命名风格更有价值。因为真正容易造成线上事故的,往往不是代码写得不够漂亮,而是业务约束在某次改动中被绕过去了。

除了看代码,还可以检查需求有没有真正做完

缺陷审查只能判断代码本身有没有明显问题,但还有一类情况很难只靠 diff 判断:

需求写了五项,代码到底实现了几项?

ReviewGate 支持把需求文档、设计说明或者验收标准一起传进去:

reviewgate review \
  --from main \
  --to HEAD \
  --intent docs/requirement.md

它会先把需求拆成一条条验收标准,然后逐项检查:

  • 已满足;
  • 缺失;
  • 破坏了原有行为;
  • 实现与要求不一致;
  • 尚未核对。

如果有验收项没有检查完,同样不会直接给 PASS。

这对一次修改很多文件的任务比较有用,尤其是使用编码 Agent 完成功能时。代码可能写得没有明显错误,但实现范围未必完整。

误报不能只靠“下次忽略”

做 Review 工具绕不开误报。

模型换了,提示词变了,代码行号移动了,同一个问题可能反复出现。如果每次都让开发者重新判断,使用成本会越来越高。

ReviewGate 会给每条发现生成稳定指纹。

确认某条是误报后,可以把指纹写进仓库里的 .reviewgate/ignore

# 这里是常量拼接,不存在注入风险,已人工确认
a3f2c1b09d4e

这个记录可以和代码一起提交,全队共享。

以后再次遇到同一问题,它不会继续阻塞,但仍然会以过滤状态保留,需要审计时可以重新展开。

我不太喜欢完全静默地删除结果。因为规则可能会变化,过去的判断也可能需要重新检查。折叠比彻底消失更稳妥。

它应该是一道闸,而不是另一个聊天窗口

ReviewGate 目前主要以 CLI 和 GitHub Action 运行。

在本地仓库里可以直接执行:

reviewgate review

检查当前分支相对主分支的改动:

reviewgate review --from main --to HEAD

在 CI 中,可以让高置信问题直接阻止合并:

reviewgate review --fail-on block

它不绑定具体模型,可以使用 OpenAI 兼容接口或 Anthropic 接口,也可以接 DeepSeek、Kimi、GLM、通义以及其他兼容服务。

我更希望它成为开发流程的一部分,而不是每次都要打开一个页面、复制代码、等待一段对话,再人工整理结果。

这个项目不解决什么

ReviewGate 不会替你证明代码一定正确。

它也不应该用来替代:

  • 单元测试;
  • 集成测试;
  • 静态分析;
  • 安全扫描;
  • 人工代码审查;
  • 上线后的监控和回滚机制。

它做的是这些工具之间仍然缺少的一层:

在改动准备合并时,基于本次 diff、周边代码、项目规则和需求意图,优先找出值得停下来检查的问题。

尤其是在 AI 大量参与编码以后,代码产出速度已经不再是唯一瓶颈。

接下来更麻烦的问题可能是:

我们生成了越来越多代码,但有没有足够可靠的方法决定,哪些代码可以进入主分支?

ReviewGate 是我对这个问题的一次尝试。

项目目前已经开源,支持 macOS、Linux 和 Windows,可以作为本地 CLI 使用,也可以接入 GitHub Actions。

它还远没有做到覆盖所有情况,但核心链路已经可以用于真实项目。我也在持续补充真实 PR、大改动、多语言代码和意图评审的测试记录。

仓库:

github.com/dengmengmia…

有兴趣可以拿自己的真实改动跑一下。

比起 Star,我现在更需要的是具体反馈:它找出的哪些问题确实有价值,哪些属于误报,哪些真正危险的问题它没有发现。