一个月 3,000 个 PR:让代码不烂的不是更强的模型
有人一个月往生产推了 3,000 个 PR,回滚率还稳在 0.5%。她讲的是禁用什么、加什么 lint,以及七成 token 花在验证上。
指南7 min read
Lauren Tan 上个月往生产推了大约 3,000 个 PR,她的团队推了 11,000 个。数字本身没什么稀奇,稀奇的是配套的两件事:回滚率稳在 0.5% 左右,十月有 227 个人至少贡献过一个 PR,而这批代码里大部分在合并前没人读过。
她在 AI Engineer 的这场演讲叫《All Code Is Slop (Except Mine)》,标题是句玩笑,说的是每个工程师看别人生成的代码和看自己写的代码,用的是两套标准。玩笑底下那个判断要窄得多,也有用得多:让一个团队跑到这个速度的,不是更聪明的 agent,是一个大部分门都封死了的代码库。
先看这个数字经不经得起查
关于 AI 写代码的速度,吹牛不值钱,所以先看那些让这个数字难以造假的配套指标。
团队现在大约每天切一个稳定版。回滚率维持在 PR 总量的 0.5% 左右,按相对比例算,比 agent 进来之前还低。性能没有塌。启动变快,输入延迟变低,开新对话和切换对话都更顺。这些还都跑在一个 Electron 应用上,Tan 自己也说这条路有天花板,没打算把功劳全算给 agent。
变化最直观的地方是评审量。2024 年她走进办公室,当天要看的 PR 是同事写的三个。现在这个数字接近 300。没人能用看三个 diff 的注意力去看 300 个,这就是后面整套做法的起点:评审没法靠人加量,只能换成别的东西。
信任来自环境,不来自模型
Tan 把它画成一个倒金字塔,顺序比图形重要。
最底下是确定性的一层:API 设计与架构,重构,lint 规则与类型系统,编译器和测试,都在这里。往上一层是验证,运行时的和形式化的。最上面那层很窄,是 prose:规则文件,skill,AGENTS.md,也就是需要 agent 自己拿判断的东西。
这么排的理由很朴素。agent 的输出由输入决定,而代码库是它拿到的最大的那份输入。一个到处是临时绕法的代码库,等于在教下一个 agent:绕过去就是这里的规矩。她用园艺打比方,约束是水泥地基,新代码绕着地基长,杂草之所以蔓延,是因为没有东西挡它。
由此推出一条很硬的规则。每次纠正 agent,先问这件事能不能变成一条确定性检查,而不是往规则文件里再加一行。代码可复现,散文只是建议。
他们禁掉了什么
真正有信息量的是具体的几条禁令。
在为 Grok Bot 做的客户端框架 Dune 里,useEffect 在产品代码里被禁用,只允许出现在 Dune 自己的部分 API 内部。这个 hook 本身没毛病,问题在它需要分寸感才用得好,而 agent 恰恰没有分寸感。一条 lint 规则把整类错误一次性消掉,「再也不用在评审里抓这个」。
引用方向也这么管。顶层就两个目录,ElectronRenderer 和 ElectronMain,两边互相 import 会被依赖图分析器和 lint 拦下。这条来自他们看 agent 把主进程代码拖进渲染进程,拖出长任务和卡顿。
第三条会让很多人不舒服:Grok Bot 禁掉了 99% 的代码注释。她的理由是注释会过期,人早就不看了,而 agent 会很乐意用一条注释给「绕过去」找理由,而不是去修根因。她举的例子来自 Cursor:agent 大量使用命令式定时器,setTimeout、requestAnimationFrame、requestIdleCallback,拿来盖住 VS Code 命令式风格和 React 声明式风格之间的冲突。定时器越铺越多,垃圾回收上去了,界面开始卡,而 agent 还写了注释解释每一次绕过为什么合理。注释让这堆烂摊子看起来像是有意为之。
替代方案是报错信息写得很具体的 lint 规则,直接告诉 agent 去修根因。这么干够多次,待评审队列会自己空掉,agent 也就开始合并自己的 PR。
评审从看 diff 变成看证据
代码被约束到一定程度之后,问题就从「这个 diff 对不对」变成「这东西到底跑没跑通」。她的团队现在评审的是证据:录屏,截图,还有图,以及形式化验证的输出。
运行时的验证,说白就是给 agent 一个能自己跑起来的环境,再加上人会用的调试工具,比如 Chrome DevTools 协议。他们的 skill 里有一张「功能地图」,相当于从用户视角画的产品站点地图,这样「左边栏那个东西」能落到具体位置。驱动脚本外面又包了自定义 CLI,省 token,也能被测试。
形式化验证是最新加的一层,她讲得很谨慎。他们用 TLA+ 对跨设备、跨平台的推送通知这类流程做模型检查,用 Lean 证明自己写的虚拟化库的性质,专门用来排除闪烁和抖动。UI 的属性测试用的是一个叫 Bombadil 的库。她说形式化验证已经抓到过真 bug,但它不是银弹,只是环境里再加一层,还在试验。
预算的转移才是最值得抄的部分,哪怕你一行 TLA+ 都不会写。她引了另一位工程师的说法:半年前不敢信 agent,因为总有细微的 bug 混进来。现在她每天七成的 token 花在验证上。Tan 说自己也是这个比例。钱主要不是花在生成,是花在检查。
她的判断是这些技术没一样是新的。它们以前太贵,难写,难懂,也难维护,所以没人做。agent 把这部分成本压下来了,现在做测试反而划算。
账单在前,产能在后
最少被引用的是顺序那一段。
Tan 花了六个月,才走到「睡着也在推 PR」这一步。她的建议是先别急着建工厂:纠正 agent 的时候先去改代码库,先写一条 lint 规则挡住新增,再回头清理存量。原话很直接,如果你的内层循环本身在产垃圾,把这个循环自动化只会产出更多垃圾,代价以 token 的形式结算,而 token 不免费。
地基有了,外层循环才成立。现在每次发版,团队会拉起一个 agent 项目,让它像真人一样把整个应用跑一遍,找出 bug,为每个 bug 开修复 PR,然后自动合并。这一步之所以敢做,是因为 PR 默认就是好的,而这句话说的是代码库,不是模型。顺便说,这也是在演示 Tan 自己做的产品 Grok Bot,读的时候要打这个折扣。
那个不太好回答的问题
这场演讲真正的判断是:AI 辅助工程里的瓶颈不在模型有多强,而在你愿意把代码库里多少东西定为非法。
这件事比换个更强的模型难卖,因为它要求你先知道自己想要什么样的代码,而多数团队从来没把这件事写下来过。一条 lint 规则就是一个关于「该怎么写」的观点,精确到机器能执行。禁用 useEffect 不是技术决策,是一个带编译器的品味决策。
所以真正该问的是你现在哪些习惯愿意禁掉,以及禁掉之后第一周会坏在哪里。
更多硬核播客内容,来自 Podwise。


