
译者注:来源:Garry Tan 在 X 发布的文章;中文翻译供学习交流。
作者:Garry Tan(@garrytan)
过去一年,我一直在用 AI 写代码。不是只写提示词,而是在构建真正的软件。两个开源项目:GStack,让 AI 编程代理变得更好;GBrain,把你读过和写过的一切变成 AI 可以使用的、可搜索的知识库。两个项目加起来大约有 97 万行代码、665 个测试文件。基本上都是 Claude Code 和 Codex 在我的指导下写出来的(大多数时候我同时开着 15 个 Conductor 会话)。
上周,我在 72 小时内合并了 14 个 pull request。新增代码将近 29,000 行。每一个版本的测试都比前一个版本更充分。
这按理说是不可能的。速度和质量通常被认为必然互相取舍。快速发布,就会破坏东西;慢慢来,才能发布正确的东西。二选一。
现在你不必再二选一了。解锁这一点的关键,是 90% 的测试覆盖率——而 AI agent 让达到这个覆盖率的成本变成了“免费”。过去 50 年,这种级别的验证需要消耗太多人类意志力,难以长期维持。现在,agent 会在写代码的同时写测试。结果就是我所说的“复杂度棘轮”:一个只能变得更好、不会倒退的系统。
(这是关于用 AI 构建软件系列的第七篇:1 2 3 4 5 6)
过去的软件是脆弱的
50 年来,整个软件工程学科都围绕一个理念组织起来:防止错误,因为错误会带来灾难性后果。
你必须第一次就把代码写对。漏掉一个边界情况,生产环境就会崩溃。发布一次糟糕的数据库迁移,就会丢失客户数据。写了一个行为很微妙的函数,等唯一理解它的人离职后,就没人知道它为什么能工作。整个系统依赖人类足够小心,而人类并不小心。于是我们建立了复杂的流程——代码审查、预发布环境、QA 团队、发布列车——所有这些都是为了在错误到达用户之前把它们拦下来。
这在某种程度上有效。但很慢。而且它意味着任何软件系统的复杂度都有一个硬上限:一个团队能同时装在脑子里的东西的数量。
现在的软件变得有弹性了
我不是说可以粗糙。我说的是一种过去不可能实现的韧性。
当我说“模型已经到位”时,我的意思是 AI 编程代理——Claude、GPT、Codex,以及围绕它们成长起来的生态——现在已经可以阅读代码、理解上下文、诊断错误、编写修复。不是完美无缺。但已经足够好,以至于软件的错误模型发生了变化。
迁移失败了?Agent 会阅读错误信息,理解跨越 45 个版本的数据库 schema 历史,写出修复,并写出测试。文件同步在一百万个符号链接上卡死?Agent 会诊断出解析器超时,把它限制在 30 秒内,并带着测试发布修复。抽取流水线出现归因错误?跨模型评测会抓到它,提示词被迭代,数据库层加入强制约束。
对于大多数代码层面的错误——逻辑 bug、解析失败、边界情况破坏——agent 现在可以在下一轮对话中诊断并修复它们。这是真正的新变化。剩下那些仍然灾难性的错误,是会破坏状态的错误:针对生产数据的错误迁移、在被发现之前已经被利用的安全漏洞、无法撤回的隐私泄露。棘轮在这里也有帮助(好的测试能在生产环境之前抓住大多数这类问题),但真正的转变在于:代码库中的绝大多数错误都变成了可修复的那一类。
这是软件构建方式的一次相变。但它只有在你拥有棘轮时才有效。
Agent 复杂度棘轮
棘轮是一种只允许单方向运动的机制。套筒扳手会把螺栓往前拧,并防止它倒转。这就是这个比喻。
在由 agent 编写的软件中,每一次与 AI agent 的编码会话,都会给代码库增加三样东西:
测试,用来编码什么叫“正确”——每次有人修改代码时都会运行的自动化检查;如果修改破坏了某些东西,它们会大声失败。 文档,用来记录为什么做出这些决策——不只是代码做什么,还包括背后的推理和取舍。 评测结果,用来建立质量阈值——对输出质量进行结构化评估并给出分数,这样你就知道下一个版本是变好了还是变差了。
下一次 agent 在这个代码库上工作时,它会把这三样东西都加载进自己的上下文窗口(也就是 AI 可以看到并进行推理的文本)。它不能退化到测试套件之下——测试会失败。它不能忽视文档——文档就在上下文里。它不能交付低于评测基线的质量——分数已经被记录下来。
质量下限会随着每一轮提升。只能向前运动。这就是棘轮。
实际上是什么样子
我把它讲得具体一点。GBrain 是我正在构建的一个知识系统——它通过存储、索引和搜索一个人的笔记、会议、对话和研究,为 AI agent 提供长期记忆。你可以把它想象成一个你的 AI 助手真的可以阅读的“第二大脑”。
其中一个功能是“认识论抽取”(epistemological extraction):它会阅读数千页内容,提取出谁在什么时间、以多大置信度相信什么。例如:“Garry 认为比特币会涨到 30 万美元(置信度:0.45)。”“Jared 认为这家创业公司的留存很强(置信度:0.80)。”类似这样,但范围覆盖 28,000 页。
第一次抽取运行得到了 100,720 条主张。我使用跨模型评测来给质量打分——让 GPT-5.5 和 Claude 独立对输出评分。总体得分:6.8/10。
最大的问题是什么?我称之为“持有人混淆”(holder confusion)。拿这句话来说:“到 2027 年,AI 将取代 80% 的软件工程师。”谁持有这个信念?是写下这句话的人吗?是他们引用的某个人吗?还是系统的分析引擎从一段播客 transcript 中推断出来的?版本 1 在 35% 的情况下把这个区别搞错了。这很重要——如果你在构建一个追踪人们信念的系统,你必须知道是谁相信它。
于是,评测结果被写进了文档。六种具体失败模式被识别出来。版本 2 的提示词针对这六种失败模式逐一处理。权重四舍五入(置信度分数)在数据库层被强制执行——不再出现 0.74 这种虚假的精确度,因为 0.75 才是诚实的答案。17 个测试锁定了这个契约。
现在,未来任何版本的抽取功能,如果这 17 个测试不通过,就不能发布。没人需要记住为什么权重四舍五入很重要,也没人需要记住什么是“持有人混淆”。测试会记住。
质量下限永久提高了。这就是棘轮转动的一齿。
为什么大多数 Vibecoding 项目会死掉
“Vibecoding” 是 Andrej Karpathy 用来描述一种用 AI 写代码的方式:你用自然语言描述你想要什么,让模型生成代码。它很强大,也是我构建软件的方式。但根据我在 YC 申请和开源仓库中看到的情况,大多数跳过测试的 vibecoding 项目,一旦达到中等复杂度——几千行代码、几个相互作用的功能——就会开始崩塌。
它们跳过了棘轮。没有测试,没有文档,没有评测。Agent 增加了复杂度,但没有任何东西防止退化。每一个新功能都有可能破坏旧功能;没有测试,你只能等用户报告之后才知道。到 0.5 版本时,代码库已经变成一座鬼屋:每次改动都会打碎意想不到的东西。然后开发者写一篇博客,说 AI 编程不管用。
AI 编程本身没问题。他们只是没有构建棘轮。
你可以说,那种会写测试的人,本来也是会写出好架构的人。这个说法有道理。但棘轮机制关注的不是这个人,而是下一轮会发生什么。当一个新贡献者打开 PR,当模型版本发生变化,或者当你凌晨两点写代码、判断力下降时,测试都会抓住回归,不管这些测试是谁写的。棘轮在人类状态不佳时依然有效。这正是重点。
没有测试,改进就是一个充满噪声的过程——agent 试图让事情变好,但没有回归信号,好改动和坏改动同样不可见。有了密集的测试套件,你就在被测试的表面上拥有了一个棘轮:对于那些你已经编码进测试的行为,质量只能上升。那不是系统的全部,但已经覆盖了大部分系统。它足以让系统在高速前进时持续向前。
测试就是制度记忆
在传统软件公司里,制度记忆存在于人身上。那个知道为什么要有那层缓存的资深工程师。那个记得差点摧毁数据库的迁移事故的架构师。那个能解释计费系统里奇怪边界情况的技术负责人。
人会离开。他们会退休,会被挖走,会倦怠。当他们离开时,知识也跟着离开了。每家软件公司都经历过这样的场景:打开一个关键文件,看到一条注释写着 // DO NOT CHANGE THIS -- ask Dave,而 Dave 三年前就离职了。
Agent 的上下文窗口不会辞职。不会被挖走。不会忘记。当测试套件编码了“权重四舍五入必须使用 0.05 的增量”,而文档解释了“因为跨模型评测显示,虚假精确度会降低人们对置信度分数的信任”时,这些知识就是持久的。任何 agent、任何模型、任何时间,都可以加载这个上下文并理解这个约束。
测试是能够穿越员工流动而保存下来的制度记忆。对于一个人的项目,它们甚至更关键——因为它们是你唯一的制度记忆。
一切可被 harness 的东西都可被测试
棘轮不只适用于传统代码。它适用于任何计算机可以观察到的东西。
想想一个现代系统的各个层次。操作系统给你进程树、文件系统状态、网络 socket、cron 调度。终端给你每一次击键、每一行输出、每一个交互式提示。浏览器给你渲染后的页面、按钮状态、导航事件。API 给你可以解析和验证的结构化响应。而 AI agent 给你可观察的行为——它们说了什么,调用了哪些工具,以什么顺序做事,是否在行动前先询问。
所有这些都可以被 harness。只要能 harness,就能观察。只要能观察,就能断言。只要能断言,就能棘轮化。
这比传统单元测试的覆盖面大得多。让我举个例子。
GStack 是我的开源编程 agent 框架——GitHub 上有 93,000 颗星、701,000 行代码、46 个技能。其中一个核心功能是交互式计划审查:你让它审查你的架构,它会逐段走过计划,提出问题,探测边界情况,挑战你的假设。就像有一个真的会读代码的工程经理。
问题在于:Claude Code 有时会跳过整个交互部分。它会读取计划文件,一次性把所有发现倾倒出来,然后退出——连一个问题都不问用户。但审查的核心正是来回对话。跳过这一点,就失去了审查的意义。
这怎么测试?你无法用单元测试去测试“AI 是否进行了一场对话”。没有传统测试框架覆盖这种东西。
所以我使用 Bun 的 TTY 功能构建了一个测试 harness(PR #1354):它真的在伪终端里启动 Claude Code,给它喂入一个特定的 repo 场景,触发审查技能,然后实时观察终端输出。测试会观察 agent 是否在完成前提出了一个交互式问题。如果它只是倾倒发现然后退出,一个问题都没问,测试就失败。
这不是在测试代码。这是在测试一个 AI agent 是否遵守行为契约。在 TTY 层面。真的看着它工作。
棘轮式响应有三层:
技能指令中的 STOP gates——明确规则,要求“你必须在进入下一节之前询问用户”,并带有反合理化条款,把具体失败模式点名出来,让模型无法说服自己跳过去。 反捷径条款——“计划文件是交互式审查的输出,而不是它的替代品。”这一句话堵住了模型反复利用的那个漏洞。 Gate-tier floor tests——TTY harness 测试会在受控场景中启动 Claude Code,如果 agent 没有至少提出一个交互式问题,就失败。
现在,当 Anthropic 发布新模型版本,或者我修改一个技能提示词时,测试套件会抓住交互契约上的任何退化。Agent 不能悄悄停止提问。测试会观察终端并检查。
再看 PR #880,它发布了一个新的 OpenClaw 插件。测试不只是检查代码能否编译。它会从源码构建插件,在隔离 profile 中启动一个真实的 OpenClaw 实例,通过 CLI 安装插件,运行 plugins inspect 验证运行时已经加载它,设置配置 slot,验证配置,并运行 plugins doctor 确认诊断为零。一次跨越两个独立程序的完整端到端往返。359 行测试代码。这种测试,人类几乎不会手写,因为搭建过程太繁琐。Claude 大约五分钟就写好了。努力墙正在实时消失。
这个原则可以推广。你可以在 OS 层测试:迁移是否创建了正确的表,cron 任务是否触发,进程是否还活着。你可以在浏览器层测试:页面是否渲染,agent 是否正确填写了表单。你可以在 API 层测试:模型是否返回了符合正确 schema 的有效 JSON。你可以在行为层测试:agent 是否遵守了协议,是否在删除前询问,是否在被要求停止时停止。
整个技术栈都是可测试的。棘轮适用于所有这些层面。大多数人还没有意识到这一点,因为他们仍然把测试覆盖率理解为“我的函数是否返回了正确的数字”。真正的测试表面,是计算机能看到的一切。
90% 这个数字
那么,90% 的测试覆盖率到底能给你什么?
Capers Jones 研究了超过 10,000 个软件项目,并测量了缺陷移除效率(Defect Removal Efficiency,DRE)——也就是在 bug 到达用户之前被抓住的比例。他在《Applied Software Measurement》中的数据展示了一条非线性曲线:覆盖率低于 70% 时,DRE 大约在 65% 到 75% 之间。覆盖率达到 85% 到 95% 时,DRE 跳升到 92% 到 97%。这种关系不是线性的。在 85% 左右有一个曲线拐点,缺陷逃逸会急剧下降。
航空电子行业几十年前就搞清楚了这一点。DO-178C 是 FAA 针对飞行关键软件的标准,它要求 Level A 系统——也就是 bug 意味着飞机坠毁的系统——达到修改条件/判定覆盖(MC/DC)。单纯的分支覆盖会漏掉 10% 到 20% 的故障。MC/DC 比行覆盖更严格,可以达到超过 99% 的 DRE。他们强制这些要求,不是因为官僚喜欢文书工作。他们这样做,是因为数据显示:低于某些覆盖阈值时,关键缺陷逃逸的比例与“不杀人”这个目标不相容。
可靠性工程中的类比也很清楚。工厂使用一种叫 Six Sigma 的系统来衡量质量。思路是:统计每生产一百万个单位会出现多少缺陷,然后把它表达为一个“sigma 水平”——sigma 越高,缺陷越少。3-sigma 过程每百万个产品大约产生 67,000 个缺陷(相当糟糕)。4-sigma 过程大约产生 6,200 个(好十倍)。5-sigma 过程产生 233 个(又好 27 倍)。从 4 sigma 到 5 sigma 不是增量改进,而是相变。
测试覆盖率遵循同样的曲线。从 70% 到 90% 覆盖率,并不是好 30%。而是逃逸缺陷减少一个数量级。在 70% 覆盖率下漏掉的缺陷,藏在那 30% 未测试代码里。到了 90%,藏身之处缩小到 10%,而且大多数危险路径都被锁定。
现在,我也应该诚实说明研究还显示了什么。Mockus、Nagappan 和 Dinh-Trong 研究 Windows Vista 后发现,虽然覆盖率与更少的发布后缺陷相关,但达到 90% 以上覆盖率所需的努力会急剧上升。最后 20% 覆盖率所需的工作量,远远高于最初 70%。几十年来一直如此。这就是为什么大多数团队停在 70% 到 80%,然后称之为“足够好”。
但有件事变了:AI 编程代理不会感受到努力。
它们不会厌倦写第 14 个边界情况测试。不会在周五下午 5 点偷工减料。不会看着一个棘手的集成测试,然后想“我以后再回来做”。阻止人类团队停在 70% 的努力曲线,对 agent 不适用。你可以让 Claude 为一个模块中的每个边界情况写测试,它会开心、彻底、在凌晨两点、不抱怨地完成。过去让 90% 覆盖率对人类团队不切实际的残酷最后 20%,恰恰是 AI agent 最擅长的工作。
这才是真正的解锁点。不是 AI 让你写代码更快。很多人已经注意到了这一点。真正的解锁点是:AI 让你能够以过去成本过高、无法持续的级别进行验证。数据表明具有魔力的 90% 阈值,过去需要消耗太多人类意志力才能达到。现在,它是免费的。
关键区别就在这里。棘轮不是把行覆盖率当成虚荣指标。它关心的是那些编码了行为契约的测试——持有人混淆测试、权重四舍五入测试、交互式审查 gate。每个测试都锁定了一个具体学到的教训。覆盖率是一个代理指标,告诉你系统中有多少行为处于契约之下。在 90% 时,几乎每一次行为变化都会触发测试信号。Agent 要么通过(可以安全发布),要么打破某个测试(立刻被抓住)。
剩下的 10% 是集成点、基础设施管道,以及真正难以测试的边界情况。这没问题。90% 才是把混乱变成棘轮的东西。
过去,达到 90% 是英雄式努力。现在,它只是一个普通的星期二。这就是游戏规则的改变。
概念验证
我一开始是独自启动这两个项目的。现在它们已经不再是单人项目了。
GStack 现在有 37 位贡献者。v1.30 在一个版本中合并了 21 个社区 PR。GBrain 有 25 位贡献者。v0.31.1.1 在一个 PR 中落地了 22 个社区修复——认证流程、schema 引导、同步、隐私。
棘轮让这一切变得安全。每一个外部 PR 都必须通过现有测试套件。新贡献者不需要理解整个系统。他们只需要让测试通过。
上周的 GBrain 发布说明了这个故事:
v0.31.0:新增用于实时记忆的 facts 表,以及一个 dream consolidation 阶段,把短期记忆提升为长期知识。 v0.31.1:修复了 25 个 CLI 命令,这些命令之前会悄悄路由到一个空的本地数据库,而不是用户真实的大脑。 v0.31.1.1:在一个 PR 中修复了 22 个社区报告的问题。 v0.31.2:修复了代码同步在包含符号链接的大型 repo 上永久卡死的问题,方法是加入 30 秒超时。
每个版本发布时,测试都比上一个版本更多。Agent 在写代码的同时写测试。覆盖率不会滑落,因为维护它所需的努力已经不再是人类负担。
新的复杂度上限
软件的复杂度上限刚刚被大幅抬高。
过去,它受限于一个团队能把系统装进脑子里的能力。现在,它受限于一个人加上一群 agent:这些 agent 可以把完整代码库、schema 历史、测试套件和文档加载进上下文。
这是一个大得多的数字。而且随着上下文窗口变大、模型更擅长对代码进行推理,它还会继续增长。
任何不采用这种模式的软件公司——agent 加品味,加上一个只会上升的测试套件——在速度和质量上,已经落后于采用这种模式的一个人。
工具已经在这里。代码是开放的。测试就是棘轮。90% 覆盖率,每个 PR,无例外。
50 年来,90% 覆盖率是一种奢侈品,只属于航空电子和医疗设备——那些有预算用人类工时去撞努力墙的团队。AI agent 推倒了这堵墙。让软件可靠的覆盖率阈值不再昂贵。它只是一个设置。问题不再是你是否负担得起 90%。问题是:你是否负担得起没有 90%。
棘轮、技能,以及整个知识系统都在 GitHub 上开源并免费。去构建吧。
我的 MIT 许可开源项目:
GStack——让 Claude Code 显著变强。93K stars。免费。 GBrain——面向 AI agent 的你的第二大脑。14K stars。免费。
AI Explainer 系列:
Fat Skills, Fat Code, Thin Harness——架构 Resolvers——智能的路由表 The LOC Controversy——60 万行代码到底产出了什么 Naked Models Are Stupider——模型是引擎,不是汽车 The Skillify Manifesto——每个工作流都会变成可测试技能 Meta-Meta-Prompting——复合技能产生涌现能力 The Agent Complexity Ratchet——你正在读的这一篇
夜雨聆风