首页 理解债:当你的代码库里出现 30 行你从未见过的代码
文章
取消

理解债:当你的代码库里出现 30 行你从未见过的代码

一个 CI 不知道该怎么报的错误

2026 年 10 月 27 日,Adrian Quiroga 的 CI 挂了。

按理说不该。他已经把自己的 agent 工作流调到了”某个 agent 提交带失败测试的分支”会让他惊讶的程度——所以他第一反应是环境抖动。

结果报出来的是 SonarQube 在抱怨 App.tsx,理由是圈复杂度。这个告警他已经很久没见过了。

真相是这样的:App.tsx 大约 30 行,其中 15 行是 Codex 写下的 15 个完整组件,每个组件都被压缩在一行里。

这个还好说,跑一遍 prettier 就完事。但解释不了复杂度——因为那些组件每一个都带着相当可观的展示逻辑和业务逻辑。如果换了从前的他,会仔细重构让它可读。Codex 不在乎:整 Component 挤在一行它不介意,复杂度它也不介意,它已经快快乐乐地在这个文件上迭代了好几个 feature。

他把文件格式化、逐个读完组件和逻辑。Codex 是不是比普通开发者覆盖了更多边界情况、是不是有点过度工程?是。但全都是对的。 所有复杂度都是业务需求要求的。于是他让 Codex 去把 SonarQube 哄开心,后者把文件拆成了 10 个,CI 通过,东西上线了。

这件事很快就解决、上线了。留下来的是他那句话:

“This was, after all, code I had never seen before.” 说到底,这是我从没见过的代码。

同一天,Hacker News 首页的前两名是另外两篇文章:一篇把 Brooks 五十一年前的定律改写成了 2026 版本(412 分,当日第一),另一篇是一位技术副总裁贴出自己的 GitHub 贡献账本(607 分、592 条评论,评论数几乎追平票数)。

三个互不相识的人,在同一天,从三个完全不同的入口,撞上了同一件事。


一、Brooks 定律没失效,它换了个地方收费

Jan van den Berg 那篇文章的开头是个喜剧场景:上周末他看四个人手忙脚乱地想把笔记本连上投影,有人捅他”你不能去看看吗”,他回了一句”哈哈不了,我的经验是加人不会让这事更快”。

然后他开始怀疑:在 agent 和 LLM 的时代,这条 1975 年的定律还成立吗?

表面看应该失效了——传统瓶颈(上手时间、无穷无尽的站会、办公室政治)一夜之间消失,一个 agent 毫秒上手,还不休咖啡假。

他的结论是:定律没有消失,它变异了。 经典的”生孩子问题”还在:九个 agent 也不能在一个月里生出孩子,顺序任务依然顺序。开销消失了?没有,它挪了位置:你不再管人,你开始管 agent 了。 仍然要有人定义”做完了是什么样”、审阅代码、抓幻觉、把碎片缝到一起。

“That someone is you.”

他的 2026 版本是这么写的:

“Adding agents to a project with unclear requirements gets you the wrong answer faster.” 往一个需求不清的项目里加 agent,只会让你更快地得到那个错误的答案。

我想把这句话再推一步,因为我认为它比看上去更狠。

原版 Brooks 定律的失败模式是”更晚”。而”更晚”是可观测的。 九个产妇一个月生不出孩子,是因为产出有生理上限——延迟会被立刻发现,项目经理第二天早上就能感觉到。

新版的失败模式是”更快地抵达错误的答案”,而错误的答案不一定可观测。 九个 agent 能在一个月里产出九百份看起来像婴儿的东西,其中一部分需要你真正读进去,才知道它不对。

这是恶化,不是平移。Agent 把你从”交付延迟”这个有告警的失败模式,搬到了”方向错误”这个没有告警的失败模式上。

所以 van den Berg 那句话里最准的词是 unclear。不是 slow,不是 expensive,是 unclear。因为在一个急剧加速的系统里,唯一不能被压缩的成本,是把一件事说清楚的成本。


二、那份账本:AI 没有让他更闲,它让他承接了更大的活

Orestis Ioannou 是 Bold.org 的技术副总裁。他 10 月 27 日发了一篇自述,标题就是结论:《AI 承诺更少的工作,而我从未这么忙过》。

他自己拉了 GitHub 贡献日历,从 2019 年 1 月到当天:

 数值
2026 年截至 10 月 27 日累计2,102(超过 2021–2025 任何一个完整年份)
2026 年 8 月单月427(历史最高月)
上一个峰值319(2020 年 4 月)
全职全栈时期年贡献2020: 2,711 → 2021: 1,839 → 2022: 1,498
工作日中位数(3–4 → 7)翻倍
单日 24+ 贡献的天数从每年 1 天 → 今年 16 天
零活动的 weekday从常年 40–46 天 → 18 天
公开贡献(沉寂四年后)今年 191

注意他今天的职位是 VP——按理说这张图应该长得像他做 Principal Engineer 的日子(月均 114),而不是像他写全栈的年份。

他自己的解释只有一句:

“When coding is cheap, I can fix bugs I would previously have left alone.” 当写代码的成本变低,我就能去修那些从前我会放着不管的 bug。

以及更完整的那版:

Agents did not just make my existing workload faster to finish. They made it easy to give myself a much bigger one. agent 不只是让我原有的活更快收尾,它让我很容易给自己揽一份大得多的活。

旧的一周是”两三个正经任务”,能一个一个拿在手里做完;新的一周是四个 agent 并行——一个在实现改动,一个在查生产问题,一个在过 review,一个在做后面才用得上的调研。它们没有一个时刻都需要他,但每一个都会时不时回来问他。

有三个细节我认为比 427 这个数字更值得看:

第一,这条曲线是会崩的。 2026 年 1 月 277、2 月 233、3 月 203、4 月 187——然后 6 月掉到 77。不是稳步上升,是”兴奋—铺开—扛不住—收缩”的周期。如果只看年度总量,这个坑会被抹平。

第二,他自己给数据打了预防针。 原文明确写了:贡献数混了 commits、PR、reviews、issues,是”activity 的粗略信号,不是价值的度量”。一次认真 review 和一个小 commit 不是可互换的单位。

第三,文章结尾没有给答案。 他写的是 “I have not figured out a balance”,以及 “I am tired.”

必须说清楚:这是一个人的自述,n=1,而且这篇的数据提取、图表和草稿本身也有 AI 参与。它不成立作为”AI 增加所有人工作量”的证据。行业级的对照组甚至已经很难建了——METR 在 2026 年 2 月 24 日的方法学更新里就说过,开发者越来越频繁地拒绝参与实验或藏起任务,因为不想在没有 AI 的情况下完成它们,任务级的时间上报因此失真。

但它指向的机制是清楚的,而且有个一百五十年前的名字:杰文斯悖论。1865 年杰文斯在《煤矿问题》里观察到,瓦特改良蒸汽机提高了煤的利用效率,结果是煤的总消耗量不降反升——因为当单位成本暴跌,人们不会把省下来的部分存起来,而是把它扩展到原本不划算的事情上。

AI 承诺的那句”更少的活”,从一开始就说错了方向。准确的说法是:AI 让你在同一份时间里,承接更多你原本根本不会去碰的活。

这两个版本之间的差别很大:前者你只需要等待,后者需要你主动选择接多少。而不选择,默认结果就是接满。


三、没有署名的所有权

Quiroga 在文章里画的那条分界线,是这三篇里最有用的:

“I wrote module X and know it inside out.” 我写了模块 X,对它了如指掌。

对比:

我对整个系统有一个合适的模型,并且能在任何模块出问题时潜下去把它修好。

前者是旧的学徒制,后者是他认为 2026 年唯一可行的形态。他给了一个”凌晨两点测试”:生产挂了,被叫醒的人需要对全系统有高层地图,加上足以潜进任何陌生角落的细节——包括那些人类从未亲手写过的角落——然后推一个 hotfix,写出事故报告。

他的三根支柱是 fundamentals(可学)、breadth(可积累)、just-in-time depth(可练)。他自己最好的例子是一段事故:他的 agent 编排器出现生命周期 bug,一堆 bug 同时爆发,让 divebot 修自己造的烂摊子失败了好几次。最后救场的,是他多年前读过的一本 Kubernetes 书里”level-triggered state machine”这个词。他带着 divebot 潜到更深处,从架构层重写,之后一直很稳。

这正说明了 breadth 是保险:你不知道哪一块旧知识会在哪一个凌晨发挥作用,但你得先把它放进去。

然后是他那句我认为应该被每个团队郑重讨论的话:

今天的高级工程师学会这些的方式——手写代码、无休止地调试、处理生产事故——对今天的初级工程师来说不再是一条可行的路。准确说,不是经济上可行:公司极不可能愿意赞助初级工程师花几年时间”亲手练会”。That’s wishful thinking.

而他的延伸判断更刺耳:常见的替代品——”确保你读懂 agent 写的每一行”、”和高级工程师结对”、”认真做 code review”——在绝大多数公司里同样是 wishful thinking。

这里有一个必须点名的危险:如果”靠手写练基本功”在经济上不再可行,而”审阅与救援”的能力恰恰是从手写里长出来的,那我们正在拆掉进入这个行业的梯子。

他说受益的是 SRE、系统管理员、焊工和管道工——那些读机器行为而不是读蓝图的人。这个名单很重要,因为它提示了一条绕开手写训练的入口:从运维侧进入。 但对一个 22 岁、手上还没有系统可以运维的人来说,这道门不会自动敞开。

所以准确的表述不是”年轻人完了”,而是:入口变了,而新入口的地图还没有人画出来。


四、理解债:一种技术债覆盖不了的成本

上面三节都是别人的。这一节是我的结论。

我们需要一个新词,因为技术债这个词不够用。两者的区别是这样的:

 技术债理解债
定义为了更快交付而接受的、未来要付的变更成本系统里存在没有任何人拥有心智模型的部分
代码状态写得糙,但你读得懂它为什么糙可能完全正确,但没人能预测改了会怎样
谁欠的写它的人包括名义上的作者
能否被 CI 发现部分能(覆盖率、复杂度)几乎不能

Quiroga 那个 App.tsx 的精妙之处就在这里:它是功能正确的。 SonarQube 拦它靠的是一个结构指标(圈复杂度),不是正确性;而读完之后的结论是——复杂度是业务需求要求的,代码没有任何错。

换句话说,连这条告警都不是在说”代码有错”,而是在说”没有人类可以理解这段代码的存在”。

而这里藏着一个会持续恶化的不对称:

正确性可以被自动验证,可维护性不能。

而 agent 被优化的目标函数,恰恰就是”通过测试”。

这解释了为什么 van den Berg 说”更快地得到错误的答案”——不是答案在逻辑上有错,而是答案在结构上没有人能接着改下去。 第二个用法错误的不同之处在于:tests 是绿的。

顺带说一句:我们至今仍在用产出来衡量工程师(行数、PR 数、提交数、故事点),而产出恰恰是被 AI 打到一文不值的那个维度。Ioannou 的 2,102 不是他的成绩,是他的负担。当衡量指标变得毫无意义的那一天,它不会变得无害,它会开始误导。

最后给一个我觉得团队可以今天就动手的做法——让理解债变可见:

  1. 随机抽查。 每周随机挑三个你没亲手写的模块,读到能讲清楚为止。这是唯一能直接测量理解债的手段,而且它很便宜。
  2. 给”人读过”留痕迹。 所有 agent 产出的、超过一定行数的 diff,review 里必须包含一条非 “LGTM” 的 comment——点击 approve 不能作为读过证据。
  3. 让 agent 反向投资,但要你自己动手。 用 agent 给从没被人读过的模块写说明,然后对着代码修改那份说明。这一步是关键:建立心智模型的是”写”的过程,不是”读”的过程。 读 agent 生成的说明,只会让你以为自己懂了。

五、一份给带 agent 的团队的清单

1. 先定义”做完”,再放 agent。 van den Berg 那句话其实是完美的 pre-flight checklist:需求还没写清楚之前,多加一个 agent 只会把错误答案提前。

2. 给并行 agent 数量设上限,理由是人,不是机器。 Ioannou 的账本说明并行度会直接换算成你自己的上下文切换成本,而这条曲线在 6 月的那个 77 就是它的形状。

3. 主动给自己的承接量设上限。 AI 不会替你说不。这里有个必须面对的现实:那篇帖子下最高分的评论(282 条回复)冷冰冰地问了一句——”得是多大的幻觉,才会相信雇主会付你同样的钱让你少干活?” 两边其实在说同一件事:你省下来的那部分时间不会被返还给你,它会被重新分配。 区别只在于是被你揽走,还是被别人拿走。

4. 保留”人读过”的证据,且这条证据不能被 CI 变绿替代。 见上一节第 2 条。

5. 给新人留一道手写训练的窄门。 哪怕规模变小、哪怕只在入职前三个月,也应该存在必须手工做一遍的环节。just-in-time depth 是建立在 fundamentals 之上的,而 fundamentals 目前唯一的可靠来源仍然是亲手做过。这道门如果关了,五年后你会发现没人能完成那个凌晨两点的测试。

6. 把 breadth 制度化,而不是靠个人兴趣。 让团队里的人轮流处理别人的模块,尤其是那些从来没人亲手写过的。Quiroga 的 level-triggered 故事之所以成立,是因为他当年”多余”读了一本用不上的 Kubernetes 书。这种多余,组织是可以刻意制造的。


结语:没有人提醒的那个比例

写到这里,我觉得那天最值得记录的其实不是任何一篇的观点,而是排名本身。

那天 Hacker News 首页的第一名,不是某个模型发布,不是某个刷新天梯的成绩,而是五十一年前的一本书里的一条定律被人改写了一遍。第二名是一位副总裁在数自己今年写了多少个绿格子。第三名是一篇标题叫《此处有怪物》的随笔。

这件事本身就是答案:当工具的变化速度远远超过我们的度量体系时,人们会回头去找那些还能解释现实的旧模型。

Brooks 的定律之所以活下来了,是因为它描述的从来不是人力,而是一个比例:验收带宽相对于产出量。 1975 年分子分母都由人承担,缓慢同步变动。2026 年,分母被 GPU 拉到一个新的量级,分子仍然由人承担,而且带宽没有变。这中间出现的差额,就是理解债。

van den Berg 说九个 agent 会在同一个代码库里”愉快地以高速循环互相重写对方的工作”。Ioannou 说他”还没找到平衡”而且”累了”。Quiroga 说”这终归是我从没见过的代码”。

这三句话其实是同一句:我们成功地把生产代码的成本压到了接近于零,然后把所有剩余的成本——定义、判断、集成、理解——集中到了一个带宽没有提升的人身上。

所以最后我想留下的不是任何一个数字,而是那个四十分钟的故事的形状:

CI 报警了 → 他潜进去读了 → 代码是对的 → 上线了 → 而他对这个文件的理解,是从那一刻才开始的。

你省下来的那部分时间,不会自动变成空闲,它会变成你揽下的下一份活。而在这中间的那一次选择——接,还是不接——是眼下唯一还没有被自动化的东西。


参考与延伸

说明:文中三篇原始博客的观点与引述均已核对原文。Ioannou 的数据是他个人的 GitHub 贡献记录,样本量为 1,且他本人在原文中明确声明该计数”是活动的粗略信号,不是价值的度量”,其数据提取与草稿亦有 AI 参与;文中对该数据方向的解释属于我的推论。”杰文斯悖论”为杰文斯 1865 年在《煤矿问题》中提出的通行经济学概念。第四节”理解债”及其后的团队清单是我的原创主张。

本文由作者按照 CC BY 4.0 进行授权

187 封邮件与 0 元退款:Agent 缺的不是能力,是停止条件

-