AI生成的PR有一个共同特征:太干净了。格式完美、注释详尽、总结自信。恰恰因为这份精致,它需要一套不同的审查方式——打磨过的表面,底下藏着每次都一样的失效模式。

打开网易新闻 查看精彩图片

把十分钟拆成五段,每段盯一件事。

第0到2分钟:它动了不该动的东西吗?

先打开文件列表,别急着看diff。智能体以范围蔓延出名:重排没碰过的文件、顺手"修"相邻代码、为一个辅助函数引入新依赖。如果PR改到了任务范围之外的文件,这应该是你提出的第一个问题,而不是第一次批准。

第2到4分钟:它给自己写的测试

智能体写的是能通过的测试,不是能保护的测试。要查三点:

  • 测试断言的是行为还是实现?逐行镜像代码的测试会永远通过,什么也抓不住。
  • 边界用例是真的吗?空输入、null、权限失败、超时,还是把顺利路径重复了三遍?
  • 代码写错时这个测试会失败吗?在脑子里改坏逻辑,如果测试照样通过,它就是装饰品。

第4到6分钟:错误处理与不顺利的路径

这是AI代码最稳定地表现不佳的地方。留意裸的except和空catch块、被吞掉只记日志却从不暴露的错误、没有退避也没有次数上限的重试、把堆栈或内部信息泄露给用户的报错。问一句:"这东西失败时会发生什么?"如果你读代码答不上来,值班工程师也答不上来。

第6到8分钟:安全基础

智能体不会用对抗视角思考。扫一遍:字符串拼接构造的SQL或查询、缺失的授权检查(认证不等于授权)、代码或日志或错误信息里的密钥与令牌、过度宽松的输入绑定。不需要完整审计,把OWASP前十的直觉用上两分钟就够。

第8到10分钟:你会这么写吗?

不是风格问题,是判断问题。它选了简单做法还是聪明做法?为一个单次使用加了抽象层?重复了三个文件外已经存在的东西?智能体优化的是完成任务,不是代码库的未来。这是你的活,也是最难学、但一旦认得那个味道就最省时间的一步。

该自动化的部分

上面所有机械性的检查都该放进CI,而不是占你的十分钟:范围检查,票单区域外的文件被改动且无说明就失败;对AI生成的PR跑测试变异分数,门槛该比人类PR更高而不是更低;密钥扫描;针对团队反复见到的错误处理模式加lint规则。

把描述和diff对一遍

上面的清单审的是代码。从十分钟里拿出一点,审PR对代码讲的那个故事——AI写的描述流畅、自信,偶尔是虚构的。

  • "为X加了测试":打开测试文件,数断言。智能体经常描述它打算写的测试。
  • 重构标注"无行为变化":抽查一个被移动内容的调用点。只改名的重构是安全的;改名又调了条件的重构,是穿着马甲的行为变化。
  • "处理了错误情况":在diff里找到那个错误情况。如果处理方式只是一行日志,描述和代码就不一致,而最终上线的是代码。

这不是偏执,是校准。描述和代码出自同一个生成过程,带着同样的自信和同样的盲区。信任它的程度,应该等同于信任一个只扫了一眼的人写的总结。

当方法本身错了

最难审的AI PR,是每一行单看都没问题、整体却错了的那种。智能体加了一个两个文件夹外已经存在的工具;在控制器里解决了你架构上该在服务层解决的问题;在代码库已统一的状态管理方案旁边引入了第二套模式。

逐行审查会让这些蒙混过关,因为每一行都站得住。挡住它的是第0到2分钟那份文件列表,外加一个问题:"如果这是新来的同事写的,我会告诉他这段代码该放哪?"如果答案是"不在这",这次审查就是一次改道,而不是逐行修改。尽早、具体地要求换方法,点名该遵循的既有模式。智能体对结构性反馈接受得很好,这是它们几乎从不会收到的反馈,因为审查者默认去评论具体的行。

还有一个相关的信号藏在提交历史里。一个叫"实现功能"的巨大提交对智能体来说很正常,对审查毫无用处;一串小提交、每个只做一件事,才是可审的。你改不掉智能体的习惯,但可以在上下文文件里立规矩:小提交、说明原因的提交信息、同一提交里不放无关改动。审查质量有一部分取决于审查者拿到的是什么,塑造输入比硬扛一个糟糕的输入便宜得多。

心态的转变

审人类代码,你问"这是对的吗"。审AI代码,要问"它没考虑到什么"。打字的是智能体,审查才是工程。