AI 现在可以编写功能。

然后 AI 可以编写测试。

然后 AI 可以打开拉取请求。

然后 AI 可以审查拉取请求。

然后 AI 可以修复审查意见。

最后,开发者点击:

批准。

这个工作流听起来极其高效。

它也引出了一个非常令人不安的问题:

如果 AI 编写代码、AI 审查代码,那么人类究竟在验证什么?

这已不再是理论。

GitHub 表示,Copilot 代码审查现在占 GitHub 上超过五分之一的代码审查,其审查系统可以探索仓库上下文、检查大型拉取请求、审查机器人编写的 PR,并在更改后重新检查自己的发现。

这可能非常有用。

但前提是我们必须清楚人类审查者仍然负责什么。

因为:

AI 审查 AI 生成的代码,与独立验证不是一回事。


新的开发循环

越来越多的 工作流 现在看起来是这样的:

Requirement
   ↓
AI generates implementation
   ↓
AI generates tests
   ↓
AI opens pull request
   ↓
AI reviews pull request
   ↓
AI fixes findings
   ↓
Human approves

纸面上看,这很棒。

一切都已:

  • 实现
  • 测试
  • 审查
  • 修复

那么留给开发者的是什么?

实际上,有很多。

因为上述每一步都可能共享同一个误解。


最大的风险:共享假设

想象一下需求是:

只有当支付成功捕获时,用户才应收到退款。

AI 将其误解为:

只要存在支付记录,用户就可以收到退款。

然后 AI 编写实现。

接着它编写测试。

测试使用相同的解释。

然后一个 AI 审查者检查代码。

它看到:

  • 结构清晰
  • 测试通过
  • 类型正确
  • 合理的错误处理

一切看起来都很好。

但需求仍然是错的。

流水线变成了:

Wrong assumption
      ↓
Correct implementation of wrong assumption
      ↓
Correct tests for wrong assumption
      ↓
Correct review of wrong implementation
      ↓
Green CI

这就是为什么通过测试和正面的 AI 审查还不够。

它们可以验证一致性。

它们无法保证最初的理解是正确的。


AI 可以在不理解你真实意图的情况下审查代码

这正是人类判断仍然重要的地方。

AI 审查者通常可以检测到:

  • 明显的 bug
  • 空值处理
  • 不安全的模式
  • 缺失的验证
  • 可疑的逻辑
  • 不一致的命名
  • 重复的代码
  • 测试缺口

这很有价值。

GitHub 一直在扩展 Copilot 代码审查,加入更深入的仓库探索、严重性级别和更强的智能体审查能力。

但你的实际产品意图可能并不存在于代码库中。

它可能存在于:

  • 与客户的对话中
  • 产品会议中
  • 支持工单中
  • 法律要求中
  • 业务规则中
  • 未记录的边缘情况中
  • 六个月前做出的一个决定中

模型可能永远看不到这些上下文。

即使你提供了它,它仍然可能误解。

这意味着人工审查者必须验证比语法更深层的东西。


开发者应首先验证需求

第一个问题不应该是:

“这段代码好吗?”

而应该是:

“它解决的是正确的问题吗?”

在审查实现之前,先问:

  • 最初的需求是什么?
  • 用户实际应该看到什么行为?
  • 哪些业务规则重要?
  • 什么情况绝不应该发生?
  • AI 做了哪些假设?
  • 这些假设正确吗?

这就是需求验证。

它可能成为 AI 辅助开发中开发者最重要的技能之一。


如果 AI 从同一个提示词写出测试,测试就不是独立的

这是另一个微妙的问题。

假设你给 AI:

构建一个密码重置流程。

AI 写好了这个功能。

然后你说:

写测试。

这些测试往往基于 AI 在实现时使用的同一套心智模型。

所以如果模型忘记了一个重要需求,测试可能也会忘记。

你得到的是:

Implementation assumption
          ↓
Test assumption
          ↓
Both agree
          ↓
Tests pass

那不是独立验证。

那是附和。

而附和并不等同于正确。


让测试去挑战实现

更好的做法是改变测试生成步骤的角色。

不要:

Write tests for this implementation.

试试:

Act as a skeptical QA engineer.

Do not assume the implementation is correct.

Based on the requirement, identify:
- failure cases
- abuse cases
- race conditions
- boundary cases
- invalid states
- unexpected user behavior

Then write tests that try to break the implementation.

这样就在以下两者之间创造了更多分离:

创造者

和

批评者

这仍然是 AI 审查 AI。

但至少你在改变目标。


人工审查者应该审视决策

AI 非常擅长检查代码。

人类应该花更多时间审视决策。

例如:

不要问:

这个函数正确吗?

而要问:

这个函数为什么会存在这里?

不要问:

这个 API 返回的类型对吗?

而要问:

这个端点到底应不应该被允许执行这个操作?

不要问:

这个查询高效吗?

而要问:

这个数据一开始就应该以这种方式查询吗?

不要问:

测试通过了吗?

而要问:

我们测试的是业务真正需要的行为吗?

这正是开发者能创造最大价值的地方。


架构仍然需要人类的关注

AI 审查者可以捕捉到许多局部问题。

但架构往往涉及整个系统的权衡取舍。

一个 AI 生成的功能可能引入:

  • 另一个服务
  • 另一个队列
  • 另一张数据库表
  • 另一个缓存
  • 另一个依赖
  • 另一层抽象

每一个单独看可能都合理。

合在一起,它们可能让系统变得更糟。

这就是为什么人类审查者应该问:

这个改动让系统更容易理解还是更难理解?

这个问题往往比每一行是否在技术上正确更重要。


警惕“AI 共识循环”

我认为团队应该主动避免的一种模式是:

AI writes code
↓
AI reviewer suggests change
↓
AI author accepts
↓
AI reviewer approves
↓
Human sees green check
↓
Merge

那个循环中的一切可能都来自具有相似假设的模型。

这个过程看起来经过了充分审查。

但各步骤之间的独立性可能很弱。

我把它称为:

AI 共识循环

这个系统制造出了经过验证的表象,因为多个阶段都表示同意。

但这些阶段可能并非真正独立。

这才是关键的危险所在。


绿色勾选可能制造虚假的信心

开发者被训练去信任这样的信号:

测试通过

Lint 通过

类型检查通过

AI 审查通过

安全扫描通过

这些信号很有用。

但它们可能制造出一种危险的感觉:

“一切都是绿的,所以这一定安全。”

未必如此。

一条全绿的流水线告诉你:

系统通过了你选择运行的检查。

它不会告诉你:

你选择了正确的检查。

这一区别比以往任何时候都更重要。


一份实用的人类审查清单

当 AI 写代码、AI 审查代码时,我认为开发者至少应该核实以下 7 件事。

1. 核实需求

问:

这真的解决了用户或业务所要求的问题吗?

而不是:

代码是否与提示词相符?

这是两个不同的问题。


2. 核实假设

问 AI:

List every assumption this implementation makes about:

- user behavior
- data
- permissions
- APIs
- infrastructure
- ordering
- timing

然后手动审查它们。

隐藏的假设会导致大量生产环境 bug。


3. 核实失败模式

问:

  • 如果网络失败会发生什么?
  • 如果数据库写入部分成功会发生什么?
  • 如果请求被重复会发生什么?
  • 如果外部 API 超时会发生什么?
  • 如果两个请求同时发生会发生什么?
  • 如果输入在技术上有效但出乎意料会发生什么?

正常路径的代码很容易写。

生产环境的故障都发生在正常路径之外。


4. 验证影响范围

如果这个变更失败了,什么会出问题?

一个组件?

一个客户?

所有客户?

支付?

认证?

数据完整性?

触及关键路径的变更比小的 UI 变更更值得人工关注。


5. 验证架构

问:

  • AI 是否添加了新的抽象?
  • 是否引入了另一个依赖?
  • 是否重复了现有功能?
  • 是否绕过了现有的架构边界?
  • 是否让系统更难推理?

正确的代码仍然可能造成糟糕的架构。


6. 验证测试

不要只读测试是否通过。

要读它们实际测试了什么。

问:

如果需求是错的,这些测试会发现吗?

如果答案是否定的,你需要更好的测试。


7. 验证你能解释这个变更

这是我的最后一条规则。

如果有人问:

“为什么这样实现?”

你的回答应该比这个更好:

“智能体生成的,Copilot 批准了。”

如果你无法解释这个变更,你就还没准备好对它负责。


为不同角色使用不同的智能体

一个有用的模式是刻意分离角色。

例如:

智能体 1 —— 实现者

Implement the requirement using the existing architecture.

智能体 2 —— 对抗性审查者

Assume this implementation contains subtle bugs.

Try to find:
- incorrect assumptions
- security problems
- failure modes
- race conditions
- architectural problems

智能体 3 —— 测试设计者

Ignore the existing tests.

Design tests directly from the original requirement.

人类

验证:

这三者是否都正确理解了实际问题?

多个智能体不能替代人工审查。

但角色分离可以减少简单的附和循环。


同时审查需求和 diff

一个实用的习惯很有帮助。

不要只看着代码审查 pull request。

把原始需求放在旁边。

对于每一个重要变更,比较:

Requirement
     ↕
Implementation
     ↕
Tests

这三者应该一致。

如果只有:

Implementation ↔ Tests

一致,你可能仍然有一个经过完美测试的错误功能。


在让 AI 修复之前先让它解释

假设 AI 审查者发现了一个问题。

避免立刻点击:

应用建议

而是问:

Explain:

1. Why this is a problem.
2. What real-world failure it could cause.
3. What assumptions the current implementation makes.
4. Why your proposed change fixes it.
5. What new risks your fix introduces.

现在你是在审查推理,而不只是接受另一个生成的 diff。

这有助于保持责任感。


AI 审查应该增加人类杠杆,而不是移除人类判断

我不是在反对 AI 代码审查。

恰恰相反。

AI 审查可以非常有用。

它可以捕捉人类遗漏的问题。

它可以减少重复性的审查工作。

它可以快速检查大型变更。

它可以帮助团队把注意力集中在重要的地方。

但目标应该是:

AI checks mechanics
+
Human checks meaning

不是:

AI writes
+
AI tests
+
AI reviews
+
Human clicks approve

第二种工作流可能很快。

但最终,开发者不过是自动化流水线中的最后一个按钮。

而这很危险。


人的角色正在向上提升一个层级

开发者的价值正在逐渐转移。

花在以下事项上的时间可能减少:

敲写语法

花在以下事项上的时间可能增加:

理解需求

设计系统

质疑假设

验证行为

评估风险

调试故障

做出权衡

承担责任

这并非软件工程的消失。

而是软件工程变得更关乎判断力。


我现在批准 AI 代码前会问的问题

我过去会问:

“这段代码看起来正确吗?”

现在我认为更好的问题是:

“在这个循环中,我知道哪些 AI 系统可能不知道的东西?”

也许是:

  • 客户意图
  • 历史背景
  • 生产环境行为
  • 未记录的依赖
  • 组织约束
  • 过往事故
  • 业务规则

这些缺失的上下文可能是审查中最重要的部分。


最后一点思考

我们正迅速接近这样一种工作流:AI 能够:

编写代码

编写测试

审查代码

修复审查意见

甚至可能:

合并并部署它

这并不会让人工验证变得不那么重要。

它改变的是人类需要验证的内容。

开发者的工作越来越不是检查每个分号是否正确。

而是要问:

我们构建的是正确的东西吗?

假设正确吗?

我们理解它可能如何失败吗?

我们能解释为什么存在这个设计吗?

我们愿意承担后果吗?

因为如果 AI 编写代码、AI 审查代码,开发者能提供的最有价值的东西,是这两个系统都不会自动保证的:

独立判断。

AI 可以审查实现。

开发者仍然必须审查现实。