跳转至

你的AI代码越写越乱,他72小时合了14个PR——差距只在一个机制

Ch04.269 你的AI代码越写越乱,他72小时合了14个PR——差距只在一个机制

📊 Level ⭐⭐ | 9.1KB | entities/garry-tan-complexity-ratchet-90percent-testing-20260513.md

你的AI代码越写越乱,他72小时合了14个PR——差距只在一个机制

Garry Tan 上周发了一篇文章,我读完停了很久。 72小时,一个人,14个PR,近29,000行代码。每一次发布比上一次测试覆盖率更高,质量更好。不是快了但变差——是又快又更好。 我第一反应是:这不对。这违反了软件工程五十年来的基本常识。 Garry Tan是YCombinator的CEO,同时也是GStack(9.3万GitHub Star、70万行代码)和GBrain两个开源项目的创始人兼主要作者。几乎所有代码都是他用Claude Code和Codex写的,同时跑15个并行会话。他把这套能让AI写出的代码只进不退的机制叫做:复杂度棘轮。

相关实体

原文存档

深度分析

软件工程五十年来的核心焦虑是「防止出错」,因为「出错是灾难性的」——一次写坏的数据库迁移可能丢失客户数据,一个藏着微妙逻辑的函数可能在唯一懂它的工程师离职后成为无人能解的谜。这个焦虑催生了瀑布、敏捷、CI/CD、测试驱动开发一整套方法论,本质都是围绕同一个问题:怎么在人类意志力和注意力有限的前提下,建立一套足够可靠的防线来阻止错误到达用户?Garry Tan 的核心论点是,这个防守局面现在被 AI Agent 反转了——不是人在防守,是系统在防守,人不再需要持续输出意志力来维持质量底线。测试覆盖率从 70% 提升到 90%,缺陷逃逸率减少一个数量级,这不是渐进改善,是相变——和六西格玛里从 4σ 到 5σ 的跃升是同一类事件。

复杂度棘轮的本质是一个只允许单向运动的机械装置:每一次 AI 编程会话都会在代码库里留下测试(告诉下一个来的人什么叫「正确」)、文档(记录当时为什么这么决定、取舍是什么)和评估结果(给质量打分,能看出下一个版本是变好了还是滑下去了)。这三样东西构成了一份「有记忆的现场」。下次 Agent 处理这个代码库时,它面对的不是空白的起点——测试会失败(不能退化到套件以下)、文档就在眼前(不能无视约束)、评估分数都记着呢(不能把质量拉低到基准以下)。质量地板每一轮都在上升,单向前进。棘轮的意义在于它和人无关——当新的贡献者打开 PR,当模型版本迭代了,当你在凌晨两点判断力下降的时候,测试会无论如何抓住退化。

Garry Tan 在 GBrain 项目里展示了棘轮机制最真实的工作状态。认识论提取功能从 100,720 条观点的第一版(跨模型评分 6.8/10,存在 35% 的「持有者混淆」问题——分不清观点是原文作者说的、引用的还是系统推断的),到第二版针对性修复全部六个失败模式,到置信度取整规则被强制到数据库层(不再出现 0.74 这种假精确),到最后 17 条测试把这份契约锁住。这个过程的关键在于:没人需要记住「持有者混淆」是什么意思、为什么取整很重要——测试记得,任何 Agent、任何模型、任何时候都能加载这个上下文理解这个约束。测试是能熬过人员流动的机构记忆,对于单人项目来说这就是唯一的机构记忆。

文章里最反直觉的论断是「棘轮不只对传统代码有效,对任何计算机能观察到的东西都有效」。操作系统有进程树、文件系统状态、网络套接字;终端有每一次按键、每一行输出;浏览器有渲染后的页面、按钮状态、导航事件;AI Agent 有可观察的行为——它说了什么、调用了什么工具、按什么顺序做事。GStack 的交互式方案审查功能(让 AI 逐段审查架构、提问、质疑假设)面临的问题:Claude Code 有时会跳过交互部分,把所有发现一次性倒出来然后退出。这个行为无法用传统测试框架覆盖——「AI 有没有对话」不是代码层面的断言。但他用 Bun 的 TTY 功能搭了测试框架,把 Claude Code spawn 在伪终端里,实时监控输出,如果 Agent 没有在结束前发出交互式问题就失败。这是在终端层面「字面上盯着它工作」来测试 AI 行为契约——三层棘轮响应(技能指令强制停止门 + 反捷径条款 + 终端门槛测试)共同锁住了这个行为。

文章结尾 Garry Tan 本人其实也点出了这个论证最脆弱的地方:棘轮机制解决了退化问题,但没有解决方向问题。「每一家没有采纳这套模式的公司,已经在以比一个有这套工具的单独个人更慢的速度、更低的质量在发货」——这个结论成立的前提是「质量是可以被测试捕获的」。测试通过不等于变好了,也许测试只是让未覆盖的 10% 更难被发现,让整个系统看起来很健康但实际上在错误的方向上狂奔。「品味」被他用括号一笔带过,但那个括号里装的东西——地板在往正确的方向升这件事——比这篇文章讨论的所有工程机制都更难,也更重要。

实践启示

  • 把测试覆盖率目标定在 90%,这不是一个虚荣指标而是相变阈值:Capers Jones 的研究数据指向 85% 附近存在拐点,低于这个阈值缺陷逃逸率在 65-75%,高于这个阈值跳到 92-97%。从 70% 到 90% 不是提升了 30% 的质量,而是缺陷逃逸减少了一个数量级。航空电子的 DO-178C 标准也不是因为官僚主义才要求 99% 以上的 DRE,而是数据显示低于某个覆盖率阈值,关键缺陷会以与不出人命不兼容的速率逃逸。对于 AI 编程项目,这个阈值依然适用。

  • AI 编程必须和测试编写同步进行,不能分开「先写代码再补测试」:让人类团队止步在 70% 测试覆盖率的原因不是意愿,是意志力——写测试是枯燥的工作,边界情况一个一个过,烦了就跳过。AI Agent 不感受「努力」,不会在第 14 个边界情况测试时感到厌烦,不会盯着复杂集成测试想「以后再说」。达到 90% 曾经是一项英雄主义工程,现在是周二的日常工作。关键是把测试写作嵌入每次编程会话的工作流里,而不是事后再补。

  • 测试套件是唯一的机构记忆,单人项目尤其如此:知道为什么那个缓存层存在的资深工程师走了,技术负责人也走了,打开文件发现注释写着「千万别动这里——问 Dave」,Dave 三年前就离职了——每家软件公司都有过这种经历。Agent 的上下文窗口不会离职、不会被挖走、不会遗忘。测试套件里写的每一条约束(置信度取整必须用 0.05 步进、交互审查必须问用户至少一个问题)都是持久化的知识,任何 Agent、任何模型、任何时候都能加载这个上下文。

  • TTY harness 测试可以捕获 AI Agent 的行为契约:对于「AI 有没有遵守特定行为模式」这类需求——比如对话式 AI 必须问交互式问题、agent 必须先询问再行动——可以用操作系统提供的伪终端能力搭建测试框架,把 Agent 实际 spawn 进去,实时监控其输出,断言其行为是否符合契约。这突破了传统测试框架只测代码的边界,把「AI 行为」本身变成了可测试、可棘轮的对象。

  • 棘轮解决了「不退化」,但「方向正确」仍需要品味来保障:90% 覆盖率的棘轮机制是一个地板,而不是天花板。它确保每一次发布不比上一次差,但无法保证整体方向是对的。Garry Tan 把这个交给了「品味」,但实践中最难的部分恰恰在此:怎么知道系统在往正确的方向升?答案可能在于评估体系——不只是「有没有通过测试」,还要有「质量有没有变好」的评分机制,以及定期的人工审视来确认方向。