本地先很绿。58/58,套件全过,我当时还想着这波稳了,至少不用在发布当晚渡劫。
然后 v2.9.1 发出去,冒烟测试,三个命令直接给我报 RESET is not defined。
你要知道,这种报错属于 bug 里最丢人的那一档——不是逻辑错了,是压根忘了把变量从单文件里带出来。AI 把代码拆到 lib/ 目录的时候,逻辑是原样复制的,但它漏掉了那些"隐式依赖":单文件里能直接访问的常量,拆出去以后就失去作用域了。我把 1920 行的入口文件拆到 410 行,以为自己在做架构优化,其实只是把炸药的线剪得分散了一点。
更妙的是后面的部分。我手动修完这三个,又写了 8 个回归测试,58/58 接着绿,接着发。直到某个版本我加了 ESLint 的 no-undef 规则——46 个未定义引用,分布在 7 个文件里,14 个命令坏了 7 个。
七,个,命,令。
而且有些错误只在特定标志、特定项目状态下才触发,几周内都不会有人察觉。也就是说,你完全可能在一个"全绿"的工具上跑两周,每天笑嘻嘻,然后在一个周五下午被一个偶发错误一波带走。
人类审查的问题就在这里。我重读了那些代码,心里想的是"嗯,这里看着没问题"——这就是我和 AI 共享的毛病:读代码的时候倾向于脑补它是对的。no-undef 不会脑补。它不累、不预设立场,机械地检查每个标识符是否有绑定,效率高得让人难堪。我第一次手动审查只找出 46 个里的 3 个,剩下 43 个都是规则跑出来的。
所以我现在有个习惯,凡是涉及代码提取的重构,默认隐式依赖已经坏了,直到工具证明它没坏。靠眼睛看不行,靠测试套件也不行——绿色测试套件证明不了任何没测过的东西,它只是一份"已验证路径的能力证明",不是健康证明。
(友情提示:如果你也经历过"全绿发布然后线上起火",评论区扣个同款,让我确认这不是我一个人的体质问题 🫠)
