当 PR 看起来没问题,但你还是觉得不对劲

如果你已经用 AI 连续交付了几周以上,你大概认识这种感觉。

你打开一个 PR。代码够干净,命名也还过得去,测试也有。表面上看不出哪里明显坏了。可你还是会觉得哪里不太对。

也许 boundary 有点发虚。也许 contract 只是被默认存在,却没有被明确写出来。也许 happy path 覆盖了,但真正的业务规则还只活在某个人的脑子里。你能感觉到风险,却指不出哪一行代码是灾难源头。

这就是新的评审问题。

大多数团队还在用老流程来处理 AI 辅助编码:写 prompt,生成 diff,开 PR,再让资深工程师足够仔细地检查代码,试图抓出被破坏的 invariants、漏掉的 edge cases、架构漂移,以及藏起来的风险。

当几乎所有实现都是人手写出来时,这套模型说得通。可当一个模型已经能一口气生成实现、第一版测试套件、schema,甚至 contract scaffolding 时,它就没那么说得通了。

到了这一步,资深工程师再把注意力花在逐行代码评审上,就不再是杠杆最高的地方了。

真正的问题已经不再是:“这个函数看起来合理吗?”

真正的问题变成了:“在这个函数出现之前,我们有没有把正确的行为、boundary 和 invariant 定义清楚?”

这就是 AI 带来的工作流倒转。代码评审不会消失,但重心会往上游移动。在 AI 时代,代码评审会变成规格评审。

为什么这种转变的体感完全不同

很长一段时间里,大多数工程团队都把规格当成配角材料。

代码才是正片。doc comment 只是提示。ADR 是“有空再读”的上下文。schema 只是“做做校验”。Gherkin 文件则属于“如果有人愿意维护到最新,那当然很好”的附加品。

这套层级正在瓦解。

如果 LLM 能快速、反复地把规格变成实现产物,那规格就不再是次要材料。它会变成系统里其他东西被派生出来的源对象。

这也改变了错误在哪个环节最便宜、最容易被抓住。

如果规格含糊,模型完全可以把“错误的东西”实现得结构漂亮、井井有条。它会给你干净的代码、看起来像样的测试,以及一种虚假的安全感。即便是很强的代码评审,也还是可能错过真正的问题,因为 bug 不在语法里,bug 在意图里。

这正是当下既棘手又关键的原因。AI 让“看起来很像样”的输出变得更容易生产,也让你在自己到底要求了什么这件事上含糊其辞,变得危险得多。

如果规格精确、有边界,而且可测试,后面所有事情都会变简单。实现更简单,验证更简单,评审更简单,CI 也会更强。

所以,最有价值的人类评审工作,正在从手工审遍每一个分支,转向先把定义这些分支行为的那个工件收紧。

规格不是一份庞大的需求文档

一提到“规格”,很多人脑子里浮现的,都是那种臃肿到没人想写、六周后也没人相信的文档。

这里重要的不是那个东西。

在一套务实的 AI 辅助工作流里,所谓规格,就是任何能把预期行为定义得足够紧、足以拿来做生成和 enforcement 的工件。

它可以是:

  • 一份描述 boundary rule 的 Markdown ADR
  • 一个定义外部输入形状的 Zod schema
  • 一个带着明确 doc comment 的函数签名
  • 一个捕捉可观察行为的 Gherkin 场景
  • 一段写清 preconditions 和 postconditions 的 contract 块
  • 一个 reducer 模型,或者一张状态迁移表

这些都不需要很重。它们只需要足够清楚,让工具能据此做出有用的事。

这才是关键门槛。有用的规格不只是给人读得懂,还要能被 codebase 周围的系统拿来直接做事。

真正好的评审,会开始长成这个样子

在旧模型里,资深工程师主要把精力花在这些问题上:

  • 这个实现干不干净?
  • 作者有没有漏掉 edge case?
  • 这些测试够不够扎实?
  • 这个 import 有没有违反 boundary?

这些问题仍然重要,只是不再是杠杆最高的第一批问题。

在规格优先的工作流里,更有价值的问题会变成:

  • 这个 contract 本身到底对不对?
  • 这个 schema 定义的是真正的 boundary 吗?
  • 业务规则是否完整?
  • 这份 ADR 是否精确到足以被 enforcement?
  • 这些列出来的 properties,真的表达了系统的实际语义吗?

这些才是更好的评审问题,因为一个正确答案能同时改善多个工件。

你把一份含糊的 ADR 收紧一次,就能同时改善架构规则、实现指导和 CI enforcement。

你把一个薄弱的 schema 修正一次,就能同时改善运行时校验、type inference 和代码生成质量。

你把 contract 写得更尖锐一次,就能同时改善实现、测试,以及对 mutation 的抵抗力。

这就是杠杆差异。你不再逐个检查输出,而是在评审那个决定输出形状的东西。

为什么传统代码评审开始失灵

传统代码评审默认人类是主要作者,也默认评审者能从成品代码里逆向检查出一套人类思考过程的质量。

但在 AI 时代,这个前提每过一周都更站不住脚一点。

模型可以几秒钟写出五十行看起来像样的代码,再几秒钟写出另外五十行,然后再来五十行。如果你的整套流程还依赖评审者手工去抓出埋在这股代码洪流里的语义漂移,那么评审面扩张的速度会永远快过人类注意力。

这会形成一种糟糕的平衡:

  • 代码生成越来越快
  • diff 越来越大,或者出现得越来越频繁
  • 评审疲劳持续上升
  • 对语义正确性的信心不断下降
  • 团队开始拿 vibes、直觉,以及一句“looks good to me”来硬撑

这不是什么可扩展策略。这只是把累积风险排版得很好看而已。

更好的做法,是先减少你对主观评审的依赖。把更多语义塞进可评审、确定性的规格里,再让机器去检查代码是否仍然和这些语义对齐。

真正让这件事落地的是 CI

这种工作流倒转只有在规格和 enforcement 绑在一起时才成立。

否则你只是在给文档改名字,然后指望大家会突然更尊重它。

关键是让规格变成可操作的东西。

这意味着:

  • 架构决策能编译成 dependency rules
  • schema 定义出 runtime-safe、type-safe 的 boundaries
  • contracts 生成可执行的 checks
  • property 列表驱动测试生成
  • 关键语义变成 merge gates

一旦做到这一步,CI 就不再只是被动的 build system,而会变成让实现持续对齐意图的机制。

这也是为什么 living specifications 终于开始对普通团队变得现实。过去文档之所以会烂掉,是因为没人有时间靠手工把文字和代码一直同步下去。

AI 改写了编写和更新这些工件的成本结构,CI 则改写了对它们做 enforcement 的成本结构。

两者都要有。只有 AI 没有 enforcement,你得到的是精致的漂移。只有 enforcement 没有好规格,你得到的是僵硬的混乱。

硬护栏,软评审

这也是我越来越确信 Autotomy 这套哲学说对了的地方。

思路很简单:把不可协商的规则塞进 hard guards,再让人工评审去处理那些真正需要判断的部分。

也就是说,让 types、schema、contracts、dependency rules 和 deterministic checks 去处理那些已知的 failure modes。它们每次都会跑,不会累,不会因为 diff 排版得漂亮就分心,也不在乎代码来自 staff engineer 还是 language model。

这样一来,评审这一层会变得更小,也更好。

你不再把资深工程师的注意力浪费在系统本来就能自动拒掉的东西上,而是把它花在 tradeoffs、语义、interface 和架构上。你会问 boundary 对不对,contract 是否诚实,替换后的实现是否真的满足 interface,系统是变得更容易改,还是更难改。

最后这一点尤其重要。

规格优先工作流最健康的副作用之一,就是它会逼着你做出更干净的切点。只要一个 module 满足 contract、通过 checks,它就可以被替换;一旦这样想,你就不会再把每一份实现都当成圣物。你会开始为安全替换而设计,而不是为痛苦的保留而设计。

这变化很细,但它会改变团队处理增长的方式。codebase 不再像一团只能从内部小心修补的东西,而会更像一套接缝清晰、边界明确的系统。

这其实是资深工程师的好消息

这种变化不会让资深工程判断变得不值钱,反而会让它更聚焦,也更重要。

资深工程师最有价值的地方,不再是充当人肉语法 diff 引擎,而是出现在那些需要消解歧义、选定 invariants、塑造 interfaces、把 tradeoffs 摆到台面上的地方。

这意味着他们会把更多时间花在:

  • 写更精确的 ADR
  • 定义 contracts 和 schema
  • 评审语义变更,而不是风格细节
  • 决定哪些 properties 值得做 enforcement
  • 把架构变成能进入 merge gate 的规则

这才是对昂贵注意力更划算的用法。

机器很擅长把实现细节补齐。资深工程师依然更擅长决定:当系统承压、变化、扩张时,什么东西必须始终为真。

你不需要来一场庞大的流程 rewrite

这件事听起来常常比它实际大得多。

你不需要发起一场 formal methods 运动,不需要停止发版本,也不需要用流程把团队埋起来。

你只需要从一个很窄的变化开始:把某一类规格,当成一级评审工件来对待。

一条务实的顺序可以是:

  1. 在关键 boundary 上强制要求精确的 doc comment 和 schema
  2. 把 ADR 变更当成需要资深工程师评审的事项
  3. 从这些工件生成测试和 contracts
  4. 在 CI 里 enforcement 架构漂移和 contract 漂移
  5. 降低只谈 style 的 review comment 权重,把重点转到语义评审上

这就足以改变团队文化。

一旦团队亲身感受到更好的规格能减少下游评审的反复拉扯,这套模式就会开始自我强化。评审会更锋利,diff 没那么吓人,信任也会更高。

真正的战略变化

真正会在 AI 时代赢下来的团队,不会只是那些把代码生成得更快的团队。

它们会是那些把人类注意力挪到工作流里最窄、杠杆最高那一段的团队。

那一段,就是规格。

当规格成为主工件,代码就不再是唯一值得逐行评审的东西。它会变成一套更有纪律的系统所产出的其中一个结果。

这才是真正的变化。

实现依然重要,而且非常重要。但越来越多时候,最关键的评审决定发生在实现出现之前。

这也正是为什么,在 AI 时代,代码评审会变成规格评审。