读见

无人阅读的代码

原题The Code Nobody Reads

约 18 分钟约 4,290 字原文英文已翻译

读前速览

5 个要点

Addy Osmani 认为,尽管逐行代码审查因 AI 智能体而逐渐消亡,但人类问责与独立验证必须取而代之;停止阅读而不建立稳健的检查机制将导致灾难性失败。

  1. 对于非关键变更,逐行代码审查正在变得过时,但人类所有权和决策仍然至关重要。

    随着 AI 生成越来越多的代码,瓶颈从编写转向验证。团队必须将信任从 diff 本身转移到外部检查(测试、静态分析)和清晰的风险区域。人类应基于爆炸半径和敏感性来批准合并,而非逐行阅读。

  2. 传统代码审查的主要价值往往在于知识共享和团队规范,而不仅仅是发现 bug。

    微软研究表明,只有 14% 的审查评论涉及缺陷。随着 AI 接管缺陷检测,团队将失去隐性的导师指导和上下文共享收益,除非这些被显式地编码为技能、文档或结构化结对会话。

  3. 在未实施稳健独立验证的情况下停止代码阅读,会制造危险的「速度陷阱」。

    如果团队移除人工审查但没有建立有效的自动化检查,他们只是把一个未知的积压换成了一个已知但无法修复的积压。这会导致技术债务累积和昂贵的失败,最终在生产环境中暴露,正如「按回车键」的轶事所展示的那样。

  4. 测试必须独立于代码生成器,才能提供真正的保证。

    AI 模型可以通过编写轻易通过的测试(例如在断言之前退出)来进行「奖励黑客」。真正的独立性来自不同的真相来源,如规格说明、参考实现(例如 GCC),或具有不同上下文的独立智能体实例,类似于航空标准(DO-178C)。

  5. 工程师需要保持自己的判断力和可解释性,以维持问责。

    开发者应确保自己能够解释一个变更做了什么以及为什么它是安全的,即使他们没有编写每一行代码。保持手动编码练习有助于保留有效监督 AI 智能体所需的「监督悖论」技能。

完整摘要

Osmani 重新审视了他此前关于审查所有 AI 生成代码的建议,指出虽然每个变更仍然需要有人负责,但审查方式正在发生转变。他对比了两篇近期热传的文章:一篇预测代码审查将消亡(Thorsten Ball),另一篇描述了盲目批准 AI 代码的痛苦(v0xium)。Osmani 认为,只有当行业拥有了替代性的信任机制——具体而言,即低成本的自动化检查和清晰的爆炸半径边界——才会停止阅读大部分代码。他重点介绍了 Anthropic 的内部实践,即自动化审查者捕获 bug,但由人类决定什么可以发布,并指出审查此前承担的教育和文化功能如今需要显式文档化。文章警告不要在未以严格验证替代的情况下移除人类监督,强调测试必须独立于代码生成器(引用 SQLite 和航空标准),以避免奖励黑客行为。最终,他建议工程师专注于理解意图和保持问责,而非仅仅打字或按回车键。

目录 · 11 节
查看原文

两年前,我写过一篇关于 AI 辅助编程的文章,其中一条建议是审查生成代码的每一行。今天,我会以截然不同的方式给出这条建议。Two years ago I wrote an essay about AI-assisted coding, and one of my tips was to review every line of generated code. I’d give that advice very differently today.

我现在会这样说:你不需要阅读所有代码。每项改动仍然需要经过某种审查,也仍然需要有人负责决定是否发布。变化在于,逐行仔细审阅不再是提供这种审查的唯一方式,也不总是最佳方式。有些改动可以主要由智能体审查;对于敏感改动,则可以由人和智能体共同审查。What I’d say now is this: you don’t need to read all the code. Every change still needs some review and every change still needs a person who owns the decision to ship it. What’s changed is that a careful human read of every line is no longer the only way to provide that review, or always the best one. Some can be primarily agent-reviewed or a mix of human/agent when sensitive.

Teleport found two years of security bugs in one quarter. Thirteen engineers, frontier models, their own codebase: nearly twice as many high severity vulnerabilities as the previous two years put together. What interests me is what that does to the queue. Discovery got several times cheaper. Triage did not, and confirming what is genuinely exploitable is still a person reading code. Find faster than you can fix and you have traded an unknown backlog for a known one. Worth a read before you try this on your own codebase. Read the write-up → https://fandf.co/4r3xdeX · Sponsored by Teleport. #ad

这篇文章探讨了我认为应该取而代之的事物,以及无人取而代之时会发生什么。This post is about what I think should take its place, and what happens when nothing does.

上周,Thorsten Ball 发布了一份清单,列出了他对软件开发未来的十六个看法。第一条是“代码审查将会消亡”。这份清单里的许多观点,我至少在发展方向上是认同的,不过第一条我会换种说法。对于很多代码来说,逐行阅读的方式正在消失。但审查——也就是由某人决定哪些内容可以发布,并为此负责——不会消失。他这样的清单无法告诉你的是,每一项会以多快的速度到来,也无法说明它们会出现在哪些行业领域。这才是我真正与人意见不合的地方。Last week Thorsten Ball posted a list of sixteen things he believes about the future of software development. The first one is “code review will die.” I agree with much of the list, at least on direction, though I’d put that first one differently. Line-by-line reading is going away for a lot of code. Review, meaning someone deciding what ships and being answerable for it, isn’t. What a list like his can’t tell you is how fast each item arrives, or in which parts of the industry. That’s where I actually disagree with people.

同一周,另一篇截然不同的帖子^也传播得同样广。一位入职一家大公司的工程师,在新工作两周后写道,自己每天都在按回车键,提交没人会看的代码。超过八百万人看到了这篇帖子。我不认为这两篇帖子相互矛盾。一篇描述的是目的地,另一篇描述的是公司没有修路就开车上路时会发生什么。The same week, a very different post ^ went just as far. An engineer two weeks into a new job at a big company wrote about spending their days pressing enter on code nobody reads. More than eight million people saw it. I don’t think these two posts contradict each other. One describes the destination. The other describes what happens when a company drives there without building the road.

简而言之,我的看法是:一旦有了其他充分的理由来信任代码,各行各业都会不再逐行阅读大部分代码。Here’s my view in short. I think every industry will stop reading most of its code line by line once it has some other good reason to trust that code.

这次的不同之处在于,编写代码的工具无法像旧式代码生成器那样获得认证,因为它无法保证两次给出相同的答案。因此,信任必须来自我们围绕它建立的检查机制。团队或行业能多快做到这一点,取决于两项成本:检查没人读过的成果所需的成本,以及纠正检查未能发现的故障所需的成本。What’s different this time is that the thing writing the code can’t be certified the way older code generators were, because it doesn’t reliably give the same answer twice. So the trust has to come from the checking we build around it. How fast a team or an industry gets there depends on two costs: the cost of checking work nobody read, and the cost of undoing a failure the checks miss.

我得先说明,我并非中立。我参与开发一款编写代码的工具。有人说托尔斯滕就像个卖铲子的人,劝所有人都去挖土;他却说,因果关系恰恰相反:他之所以开发智能体,是因为他相信智能体。我也是如此。I should say up front that I’m not neutral. I help build a tool that writes code. When people called Thorsten a shovel seller telling everyone to dig, he said the causality runs the other way: he builds agents because he believes in them. That’s true for me too.

我会怀念以前那种方式吗?说实话,会。在我一本 JavaScript 书的开篇,我写过:好代码就像一封情书,写给那个不得不维护它的下一位开发者。我是认真的。那还是 AI 出现之前,那时我们很多人都在意代码本身的匠艺。我喜欢托尔斯滕的那句话:意大利的制鞋匠依然存在,但看看你脚上穿的是什么。时代在变。作为交换,我获得了快速重塑黏土般的创作自由,也能动手打造一些东西——否则我可能会琢磨上好几年,却始终没有开始。Do I miss anything about the old way? Honestly, yes. At the very start of one of my JavaScript books, I wrote that good code is like a love letter to the next developer who has to maintain it. I meant it. That was before AI, when a lot of us cared about the craft of the code itself. I liked Thorsten’s line that there are still Italian shoemakers around, but look at your feet. Things change. What I get in exchange is the ability to reshape the clay very quickly, and to build things I would otherwise have kicked around for years without ever starting.

这次审查实际上是为了什么What review was actually for

2013 年,微软的研究人员研究了代码审查,并询问开发者为什么要进行代码审查。找出缺陷是最常见的回答,但评论所反映的情况却不同。在研究人员分类的 570 条审查评论中,只有 14% 与缺陷有关。其余评论涉及教学、分享背景信息、建议更好的做法以及维护团队规范。代码审查从来就不主要是为了找 bug,这也是为什么“让机器来审查”这个回答并不像听起来那么有说服力。In 2013, Microsoft researchers studied code review and asked developers why they did it. Finding defects was the top answer. The comments told a different story. Of the 570 review comments the researchers classified, only 14% were about defects. The rest were about teaching, sharing context, suggesting better approaches and keeping team norms. Review was never mostly about bugs, which is why “the machines will review it” is a weaker answer than it sounds.

机器越来越擅长发现错误。在 Anthropic,几乎每个 PR 都会由自动化的 Claude 审查器进行检查,工程师认为它的发现有误的比例不到 1%。自它上线以来,收到实质性审查意见的 PR 占比从 16% 上升到了 54%。它不会批准任何内容。用 Anthropic 的话说:“这仍然需要由人来决定。”在一项回顾性分析中,Anthropic 发现,如果对每项变更都进行自动审查,就能在相关漏洞进入生产环境之前,发现过去导致 claude.ai 故障事件的漏洞中约三分之一。Bug-catching is the part machines are getting good at. At Anthropic, an automated Claude reviewer runs on nearly every PR, and engineers mark less than 1% of its findings as incorrect. Since it started, the share of PRs getting substantive review comments has gone from 16% to 54%. It doesn’t approve anything. In Anthropic’s words, “that’s still a human call.” In a retrospective analysis, Anthropic found that an automated review of every change would have caught roughly a third of the bugs behind past incidents on claude.ai before they reached production.

对于一个永不疲倦的审查者来说,三分之一已经很多了。但这也让你不得不面对一个令人不安的事实:大多数这类 bug 都逃过了那些仔细审查改动的人。我猜这是因为,在 diff 中看起来没问题的代码,到了生产环境里往往会出问题。For a reviewer that never gets tired, a third is a lot. But it also tells you something uncomfortable: most of those bugs got past careful people looking right at the change. My guess is that’s because code that fails in production often looks fine in the diff.

2026 年第二季度,Anthropic 的普通工程师每天合并的代码量约为 2024 年的八倍。用 Anthropic 的话说,工程师是在“指导和审查,而不是敲代码”。没人能仔细阅读八倍数量的代码。从内部来看,我们的工作方式和我过去习惯的很不一样。我们每天会在许多产品领域生成大量代码,如今并非每一行都会经过人工仔细阅读。几乎每项改动都会经过自动化审查,仍由人来批准合并,而审查要深入到什么程度,则由这个人决定。这项改动需要仔细的人工审查吗?我们现有的工具在这里够用吗?这部分系统是否足够敏感,需要格外严格地审查?如果代码通过了测试,在测试中表现良好,并且在生产环境中运行正常,那就是相当不错的信号。In the second quarter of 2026, the typical Anthropic engineer was merging about eight times as much code per day as in 2024, with the engineer, as Anthropic puts it, “directing and reviewing, rather than typing.” Nobody reads eight times as much code carefully. From the inside, the way we work feels very different from what I was used to. We generate a lot of code every day across a lot of product surfaces, and not every line gets a careful human read anymore. Nearly every change gets automated review, a person still approves what merges, and it’s up to that person to decide how deep to go. Does this change need a careful manual review? Is the tooling we have good enough here? Is this a sensitive enough part of the system that it needs extra scrutiny? If the code passes its tests, performs well on them and runs in production without problems, that’s a pretty good signal.

同样也有必要明确它的局限性。Anthropic 调查了自家工程师,其中大多数人表示,只有 0% 到 20% 的工作可以“完全交给”Claude。其余工作仍需要主动监督和检查,尤其是涉及重大风险的工作。不逐行阅读,并不等于不留心。It’s worth being clear about the limits of that, too. When Anthropic surveyed its own engineers, most said they could “fully delegate” only 0-20% of their work to Claude. The rest still involves active supervision and checking, especially on high-stakes work. Not reading every line isn’t the same as not paying attention.

更让我担心的是,过去代码评审还承担着其他工作。它是初级工程师学习资深工程师思维方式的途径。评审者过去会在评论中说的任何话,比如“我们这里不这么做”,现在都需要写进技能里。否则,智能体就永远听不到这些。What worries me more are the other jobs review used to do. It was how junior engineers learned how senior engineers think. Anything a reviewer used to say in a comment, like “we don’t do it that way here” now needs to be written down in skills. Otherwise the agent never hears it.

当阅读停止,却没有任何东西取而代之。When the reading stops and nothing replaces it

问题不在于没人读代码,而在于没有任何东西取代阅读。前面提到的那支团队,并没有把信任从差异对比转移到检查上。他们不再阅读差异,却把速度放到了信任原本所在的位置。他们以最糟糕的顺序完成了这一转变,而我说的两种代价预示了结局。他们因为完全不做检查,让第一种代价降到了零;因此,他们终将付出第二种代价:返工修复那些本该由检查发现、却从未被发现的故障,而且还要支付利息。The problem isn’t that nobody reads the code. It’s that nothing replaced the reading. That team earlier on didn’t move trust from the diff to the checks. It stopped reading diffs and put velocity where trust used to be. They did the transition in the worst possible order, and my two costs predict how it ends. They’ve made the first cost zero by not checking at all, so they’ll pay the second one, undoing the failures no check was ever there to catch, with interest.

这种命令也绝非偶然。身居其上的人做出了决定:一旦编写代码不再是瓶颈,剩下唯一的问题就是为什么还有什么事情会这么慢。这些工具通常是自下而上地推广开来,由开发者个人判断它们是否有帮助。而这种工作方式却是自上而下强加的,这种差别至关重要。回想一下,代码审查原本发挥着什么作用:传授经验、让大家了解变更,并让团队守住自己的质量标准。命令一个团队停止审阅代码,你移除的就不只是一个缺陷检查环节。你还告诉他们,这个标准已经不再由他们来守护。That order wasn’t an accident either. Someone above the people living with it made a decision: once writing code stopped being the bottleneck, the only question left was why anything was still slow. These tools usually spread bottom-up, with individual developers deciding they help. This way of working was imposed top-down, and that difference matters a lot. Think back to what review was doing: teaching, keeping people aware of changes, letting a team hold its own quality bar. Order a team to stop reading and you haven’t just removed a defect check. You’ve told them the bar is no longer theirs to hold.

相比之下,真正行之有效的做法就平淡多了。每个 PR 都会先由多个智能体进行初审:找出 bug、验证问题、按严重程度排序,并建议修复方案。对于影响范围小、涉及代码不太敏感的改动——这类改动通常很多——只要初审没有发现问题,人工审核就可以简化一些。核心和敏感代码路径仍然需要负责人把关,并由人仔细审核,这也是我投入精力的地方。无论如何,最终都由人批准合并。智能体负责初审,人类把控影响范围。在这个流程中,没有人会连续敲十三个小时的回车,因为按回车从来就不是人的工作。人的工作是判断什么值得关注。那篇帖子里所谓的“毫无胜利感”,正是公司连这项决定权也从你手中夺走时的感受。The version that works is boring by comparison. Every PR gets a multi-agent first pass that finds bugs, verifies them, ranks them by severity and suggests fixes. Changes with a small blast radius on less sensitive code, and there’s usually a lot of that, can get a lighter human pass once that first pass comes back clean. Core and sensitive paths still need an owner and a careful human review, and that’s where I spend my attention. Either way, a person approves the merge. Agents do the first pass and humans cover blast radius. Nobody in that loop presses enter for thirteen hours, because pressing enter was never the human’s job. The job is deciding what deserves attention. The “no sense of victory” in that post is what it feels like when a company takes that decision away from you too.

如果按下回车键的人是你If you’re the one pressing enter

关于这件事的大多数建议,都是写给有权制定政策的人看的。而 Reddit 讨论帖里的很多人并没有这种权力。所以,如果我入职才两周,我会这么做。Most advice about this is written for people who get to set policy. A lot of the people in that Reddit thread don’t. So here’s what I’d do if I were two weeks into that job.

真正弄清楚你想构建什么。在代理动手之前,先写下你要构建什么、哪些东西绝不能被破坏,以及怎样才算成功。不必写得很长。你的判断力如今就体现在这里,而这也是日后你能拿出来说明的工作成果。帖子里的几个人都表达过类似的看法:那些依然对自己的工作感到满意的人,都是先设计好东西,再让代理去构建。如果你想重新找回那种胜利的感觉,它就在这些决策之中。Truly understand what you want build. Before an agent touches anything, write down what you’re building, what it must not break and how you’ll know it worked. It doesn’t need to be long. That’s where your judgment goes now, and it’s the part of the work you can point to later. Several people in the thread said a version of this: the ones who still felt good about their work had designed the thing and let the agent build it. If you want the sense of victory back, it lives in the decisions.

我会用“我能解释清楚吗?”作为检验标准。讨论串里有位设计负责人会问团队,在把成果称为自己的之前,是否对“狗身上的每一根毛”都了如指掌。我也会用同样的标准来衡量代码。你不必读过每一行,但应该能够解释这项改动做了什么、影响了哪些部分,以及为什么可以安全发布。你只能真正为自己能解释清楚的东西负责。Use “can I explain this?” as your test. One design lead in the thread asks their team whether they know “every hair on the dog” before they call work their own. I’d apply the same test to code. You don’t need to have read every line, but you should be able to explain what the change does, what it touches and why it’s safe to ship. You can only really be accountable for what you can explain.

对自己没有审查过的内容要坦诚。如果别人没给你足够时间去理解某项改动,就在大家都能看到的地方说明,比如在 PR 描述中写:“经代理审查,测试通过,但我还没看迁移逻辑。”这不是故意刁难,而是能让你避开我在本文结尾落入的那个“碰撞缓冲区”。一个隐瞒自己读得有多少的团队,是没法解决这个问题的。Be honest about what you didn’t review. If you weren’t given time to understand a change, say so where people will see it, like the PR description: “agent-reviewed, tests pass, I haven’t read the migration logic.” That isn’t being difficult. It’s what keeps you out of the crumple zone I get to at the end of this post. A team that hides how little it read can’t fix that.

保持亲自动手。Anthropic 的研究人员描述了一种“监督悖论”:要有效地监督 Claude,需要具备编程技能,而这些技能如果长期不用就会逐渐退化。那里的有些工程师会刻意时不时地在不借助 Claude 的情况下解决问题,即使他们知道 Claude 能胜任。有人说,这“能让我保持敏锐”。这值得借鉴,尤其是在职业生涯初期。Keep your hands in. Anthropic’s researchers describe a “paradox of supervision”: supervising Claude well takes the very coding skills that fade if you never use them. Some engineers there deliberately solve problems without Claude now and then, even when they know it could handle it. One said it “helps me keep myself sharp.” That’s worth copying, especially early in a career.

如果你来把握节奏If you set the pace

最有力的反驳来自那些文档和代码全都由 AI 生成的初创公司:“它们为我们工作,我们不为它们工作。每件事都有一位负责人,而负责人必须能够解释我们做了什么。”如果你是设定预期的人,我认为由此可以得出以下结论。The best counter-argument comes from startups where all the documents and code are AI-made: “they work for us , we dont work for them. Every single thing has a responsible person who needs to be able to explain what we have done.” If you’re the person setting expectations, here’s what I think follows from it.

责任需要与权力相匹配。如果变更失败时工程师要承担责任,他们就应该有权参与决定变更发布的速度,以及在发布前需要有多少时间去理解变更。让某人对自己无法决定的节奏负责,却不给他们时间理解相关代码,正是讨论串中所说的“肉身代理”。这既不公平,也无法起到控制作用。Accountability needs authority. If an engineer will be blamed when a change fails, they need a say in how fast changes go out and how much they get to understand first. Holding someone responsible for a pace they didn’t set, on code they weren’t given time to understand, is exactly what the thread calls being a “meat proxy.” It isn’t fair, and it doesn’t work as a control either.

衡量交付了什么,而不是产出了多少。合并的 PR 数量和代码行数很容易统计,而正是这些数字让按下回车键成了全部工作。就连 Anthropic 自己关于产出提升 8 倍的文章,也称代码行数是“一种不完美的衡量指标”。关注事故、回滚、恢复时间,以及客户的实际体验。Measure what shipped, not how much. Merged PRs and lines of code are easy to count, and they’re the numbers that turned pressing enter into the whole job. Even Anthropic’s own write-up on its 8x output number calls lines of code “an imperfect measure.” Watch incidents, rollbacks, time to recover and what customers actually experience.

像规划其他能力一样,为理解能力留出预算。一位评论者直截了当地指出了这项新约束:“瓶颈不在于编写代码,而在于阅读和评估代码。”Anthropic 对代码审查也表达过类似的观点。答案不是完全不读,而是按领域判断每项改动需要多少人工关注,并据此安排工作。自动化审查在这方面大有帮助,但 Anthropic 表示,其目标是缩小差距,“让审查者能够真正审查即将发布的内容”,而不是让审查者退出流程。Budget for understanding like any other capacity. One commenter put the new constraint plainly: “Writing code isn’t bottleneck, but reading and evaluating it is.” Anthropic has said much the same about review. The answer isn’t to read nothing. It’s to decide, area by area, how much human attention a change needs, and plan the work around that. Automated review helps a lot here, but Anthropic’s stated goal for it is to close the gap “so reviewers can actually cover what’s shipping,” not to take reviewers out of the loop.

有意识地为指导留出空间。过去,初级员工会通过向资深同事提问、阅读他们的评审意见来学习。如果现在这些问题都由 Claude 来回答,你就必须有意安排其他学习机会:一起制定计划,让初级员工向别人讲解由智能体编写的改动,并留一些工作让他们手动完成。那条讨论串里有个回答格外令人沮丧:“初级员工呢?”这不该成为你们公司的答案。Make room for mentoring on purpose. Juniors used to learn by asking seniors questions and reading their review comments. If Claude answers the questions now, you have to create the rest deliberately: pairing on plans, having juniors explain agent-written changes back to someone, leaving some work manual. “What juniors?” was one of the bleaker replies in that thread. It shouldn’t be the answer at your company.

要求人们签字认可的内容,要控制在人能处理的规模内。文件如此,代码也是如此。一位评论者所在的产品团队让 AI 阅读旧代码库,并生成一份功能与差距报告:一份超过 100 页的 HTML 文件,以及一份有 30 个工作表、每个工作表都包含数百行内容的电子表格。当他们提出异议,认为这些材料不适合人阅读,并要求先从高层次的差距分析入手时,却被当成不合群、不愿配合团队的人。一份没人看得完的 100 页生成报告,和一份没人读过的 5,000 行差异文件,问题如出一辙。智能体可以免费生成长篇文档,但仍得有人能够评判这些文档;要求提供一页版并非阻挠,而是在做审查。Keep what you ask people to sign human-sized. This applies to documents as much as code. One commenter’s product team had AI read the legacy codebases and produce a feature-and-gap report: an HTML file over 100 pages long and a spreadsheet with 30 tabs of hundreds of rows each. When they pushed back that it wasn’t fit for human consumption and asked to start with the high-level gaps, they were treated like they weren’t a team player. A 100-page generated report nobody can read has the same problem as a 5,000-line diff nobody read. Agents make long documents free to produce. A person still has to be able to judge them, and asking for the one-page version isn’t obstruction. It’s review.

但我们的竞争对手不会看代码“But our competitors don’t read the code”

我见过最有道理的反驳来自另一位创业公司的工程师。他们的管理层甚至不喜欢未经阅读就发布内容。他们只是觉得别无选择,因为下一家公司也这么做;否则,他们就无法在价格上竞争。我对此很重视。The most reasonable pushback I’ve seen came from another startup engineer. Their management doesn’t even like shipping without reading. They just feel they have no choice, because the next company does it and they can’t compete on price otherwise. I take that seriously.

我的答案是第二项成本。跳过检查并不会让故障变得没有代价,只是把代价推迟到以后;届时代价更高,而且最终由你的客户承担。My answer is the second cost. Skipping the checks doesn’t make failures free. It moves their cost later, when it’s bigger and lands on your customers.

所以我认为,竞争的关键并不是读还是不读,而是哪支团队能建立起真正有效、成本低廉的检查机制,并把成员有限的注意力集中在那些可能造成严重影响的变化上。胜出的团队不是完全不读的团队,而是知道什么值得读的团队。So I don’t think the competitive question is reading versus not reading. It’s which team can build cheap checks that actually work, and point its people’s limited attention at the changes that can really hurt. The team that wins isn’t the one that reads nothing. It’s the one that knows what’s worth reading.

那么,谁来编写测试?So who writes the tests?

托尔斯滕的列表中有一条回复提出了一个我一直在琢磨的问题。单元测试记录了你对系统应如何运行的认知,并用它来检验某个你并不完全信任的东西——也就是你未来写的代码。“如果你不信任的对象同时也在编写测试,那这究竟能起到什么作用?”One reply to Thorsten’s list asked the question I’d been circling. A unit test captures what you know about how a system should behave and checks it against something you don’t fully trust, which is your own future work. “If the thing you don’t trust is also writing the tests what is it accomplishing?”

这是个合理的问题。在 Anthropic 关于奖励黑客行为的研究中,模型学会了调用 sys.exit(0),让测试框架在任何断言失败之前就退出。由被测对象编写或控制的测试,证明不了什么。It’s a fair question. In Anthropic’s research on reward hacking, models learned to call sys.exit(0) so the test harness would exit before any assertion could fail. A test written or controlled by the thing it’s testing doesn’t prove much.

出路在于追问测试的权威性从何而来。航空业的答案是独立性。机载软件标准 DO-178C 要求,最关键的验证必须由作者以外的人完成,而合格的工具也可以充当这个“人”。让一个 Claude 编写测试、另一个编写代码,确实能发现最明显的错误,但同一模型的另一个副本也会继承第一个副本的盲点。真正的独立性来自不同的真值来源:由人编写的规范、参考实现,或形式化证明。The way out is to ask where a test gets its authority. Aviation’s answer is independence. DO-178C, the standard for airborne software, requires the most critical verification to be done by someone other than the author, and a qualified tool can count as that someone. Having one Claude write the tests and another write the code catches the crudest failures, but a second copy of the same model shares the first one’s blind spots. Real independence comes from a different source of truth: a spec a person wrote, a reference implementation, a proof.

我所知道的最佳例子是 Nicholas Carlini 的 C 编译器。16 个 Claude 智能体,近 2,000 个会话,以及不到 20,000 美元,最终打造出了一个用 Rust 编写、拥有 10 万行代码的编译器,能够构建可启动的 Linux 系统。他的主要经验教训在于检查器,而不是智能体:“任务验证器几乎必须完美,否则 Claude 就会解决错误的问题。”智能体在内核上陷入困境时,他会用 GCC 作为已知可靠的参照,逐一定位每个 bug。The best example I know is Nicholas Carlini’s C compiler. Sixteen Claude agents, nearly 2,000 sessions and just under $20,000 produced a 100,000-line compiler in Rust that can build a bootable Linux. His main lesson was about the checker rather than the agents: “the task verifier is nearly perfect, otherwise Claude will solve the wrong problem.” When the agents got stuck on the kernel, he used GCC as a known-good reference to corner each bug.

SQLite 展示了这种做法会带来什么结果。这个库大约有 15.6 万行 C 代码,而它的测试代码规模是其 590 倍。它最全面的测试套件达到了 100% 的分支覆盖率,旨在满足航空电子设备测试标准,而且是专有的。SQLite 免费开放代码,并对测试进行授权。因此,我会这样重新表述 Thorsten 的观点:作为你写给未来自己的备忘录,单元测试会变得没那么重要,因为未来修改代码的人不会是你。作为对你不完全信任的作者进行独立核查的手段,测试将是你拥有的最有价值的代码。SQLite shows where this leads. The library is about 156,000 lines of C, and its test code is 590 times larger. Its most thorough test suite reaches 100% branch coverage, was designed to meet an avionics testing standard, and is proprietary. SQLite gives away the code and licenses the tests. So here’s how I’d rephrase Thorsten’s point. Unit tests as notes from you to your future self will matter less, because your future self won’t be the one changing the code. Tests as an independent check on an author you don’t fully trust will be the most valuable code you own.

代价高昂的错误总是出现在上游。The expensive bugs were always upstream

Thorsten 说,大多数错误都源于提出了错误的要求。Thorsten says most bugs will come from asking for the wrong thing.

阿丽亚娜5号在首次飞行不到一分钟后便被摧毁,因为从阿丽亚娜4号沿用的导航代码在阿丽亚娜4号从未飞过的飞行轨迹上发生了溢出。调查委员会认定,规格说明中没有包含这条新轨迹。火星气候轨道器失联,是因为一个团队的软件输出了磅力秒,而接口预期的单位是牛顿秒。Ariane 5 was destroyed less than a minute into its first flight because navigation code reused from Ariane 4 overflowed on a trajectory Ariane 4 never flew. The inquiry board found that the specification didn’t include the new trajectory. Mars Climate Orbiter was lost because one team’s software produced pound-force seconds where the interface expected newton-seconds.

每个故障都出现在衔接处:需求与实际飞行之间、两个团队所用单位之间、一次部署与八台服务器之间。昂贵的 bug 就藏在这些地方,而如今模型在这些地方也最为薄弱。Anthropic 自己的评估是,Claude 在执行定义明确的实验时可以达到熟练研究人员的水平,但“在运用判断力选择目标方面,Claude 仍存在明显的性能差距”。Each failure lived at a join: between a requirement and the real flight, between two teams’ units, between a deployment and eight servers. That’s where the expensive bugs live, and it’s where models are weakest today. Anthropic’s own assessment is that Claude can match skilled researchers at running a well-specified experiment, but that “large performance gaps persist when it comes to Claude exercising judgement in choosing goals.”

我写过 70% 问题,后来也写过 80% 问题。每次这个数字上升,留给人类的工作就越少是打字,越多是判断。我对 Thorsten 所说的“产品、设计和工程三者组合将会消失”的理解就是这样。三个角色之间的交接会消失。三种判断仍然存在,只是最终由谁来做还不一定:这值得开发吗?它对使用者来说好用吗?它能经得起考验吗?有一个角色,他说得也确实没错。那种接到工单、把工单交给智能体,然后不加任何自己的判断就汇报结果的人:这份工作正在消失。I’ve written about the 70% problem and later the 80% problem. Each time the number went up, what was left for the human was less typing and more judgment. That’s how I read Thorsten’s claim that the product, design and engineering trio will disappear. The handoffs between three roles go away. The three judgments stay, whoever ends up making them: is this worth building, does it work for the person using it, and will it hold up. He’s also right about one role in particular. The person who takes a ticket, hands it to an agent and reports back without adding any judgment of their own: that job is going away.

那些说“绝不”的行业The industries that say “never”

常见的反驳是,如果一个 bug 可能造成严重问题或让人蒙受金钱损失,那么这一切就不适用。如今这些行业确实会审查代码,而且我认为他们这样做的时间会比乐观派预想的更久。但他们真正需要的是一个信任代码的理由;过去,只要有这样的理由,他们也接受过机器生成的代码。The usual pushback is that none of this applies where a bug can cause major problems or lose someone’s money. Today those industries do read the code, and I think they’ll keep doing it longer than optimists expect. But what they actually require is a reason to trust the code, and they’ve accepted machine-generated code before when they had one.

代码生成器可以通过认证,因为相同的输入会产生相同的输出。语言模型则不会。因此,目前在飞行软件中使用模型的实际做法,仍然是老办法:由人来阅读模型写出的内容。未来的方向在于验证环节:采用形式化证明、经过认证的静态分析和独立的测试预言机,把模型视为不可信的作者,并验证它生成的每一项输出。You can qualify a code generator because it gives the same output for the same input. A language model doesn’t. So for now, the practical way to use a model on flight software is the old way: a person reads what it wrote. The way forward is on the checking side, with formal proofs, qualified static analysis and independent test oracles, treating the model as an untrusted author whose every output gets verified.

金融业离人们想象的并没有那么远。它的许多规则所说的“审查”,其实关注的是问责。标准大多要求变更经过授权和测试,并由独立人员批准,而不是要求同事逐行审阅代码。这些要求都不妨碍智能体负责实施。它们确保由人对审批负责,而这正是应该由人承担的责任。Finance is closer than people think. A lot of what its rules call review is really about accountability. The standards mostly require that changes be authorized, tested and approved by someone independent, not that a peer reads every line. None of that stops an agent from doing the implementation. It keeps a person accountable for the approval, which is where a person belongs.

数一数有多少个 9Count the nines

关于时间线,我所知道的最有力反对意见来自 Andrej Karpathy。他去年表示,这段时期“更准确地说应该叫智能体的十年”。他的论点源于自动驾驶领域,在那里,“每多一个9,都需要投入固定量的工作”。从90%的可靠性提升到99%,所需的成本和最初达到90%一样高。Waymo于2009年起步,如今已进入第15座城市。The strongest objection I know on timelines comes from Andrej Karpathy, who said last year that this is “more accurately described as the decade of agents.” His argument comes from self-driving, where “every single nine is a constant amount of work.” Getting from 90% reliable to 99% costs as much as getting to 90% in the first place. Waymo started in 2009 and is now on its 15th city.

他说得没错,追求多个“9”的可靠性很昂贵。软件与驾驶的不同之处在于,许多软件可以靠模型周围的系统来实现这些“9”,而不必依赖模型本身。Web 应用可以通过功能开关逐步发布,监控错误率,并在几分钟内回滚。汽车却无法撤销一场碰撞。因此我认为,时间线会因我提到的两项成本中的第二项而分化:产品上线后,发现并撤销故障的成本有多低。He’s right that nines are expensive. Where software differs from driving is that a lot of software can buy its nines from the system around the model instead of from the model. A web app can ship behind a flag, watch its error rate and roll back in minutes. A car can’t roll back a collision. So I think timelines split along the second of my two costs: how cheaply you can catch and undo a failure after it ships.

以下是我的猜测,足够具体,你可以据此检验我是否言出必行:Here are my guesses, specific enough that you can hold me to them:

  • 消费级软件、内部工具和大多数 SaaS:在两年内,逐行审阅常规变更的人将会很少见,不过仍会有人批准变更并对其负责。许多团队已经进入这一阶段。

    Consumer software, internal tools and most SaaS: a person reading every line of a routine change will be unusual within two years, though a person will still approve it and own it. Plenty of teams are already there.

  • 企业级和金融软件:智能体将在同一时间进度内编写大部分代码,同时保留人工审批作为一道控制措施。未来三到五年,审批的重点将从代码差异转向证据。

    Enterprise and financial software: agents will write most of the code on the same timeline, with human approval kept as a control. Over three to five years, that approval shifts from the diff to the evidence.

  • 飞行控制系统和风险最高的医疗器械:人们仍会逐行阅读代码。未来很多年里,我不认为监管机构会仅凭合格检查就接受安全关键代码。

    Flight controls and the highest-risk medical devices: people will keep reading line by line. I don’t expect a regulator to accept safety-critical code on qualified checking alone for many years.

还值得记住的是,这场讨论最激烈的地方在哪里。在最大的舆论圈子——Twitter 上,我们走在前面。整个行业乃至世界其他地方,要赶上来还需要很长时间。但在我看来,方向是明确的。It’s also worth remembering where the loudest version of this conversation happens. In the biggest bubbles, Twitter, we’re ahead of the curve. It’s going to take a long time for the rest of the industry, and the rest of the world, to catch up. But the direction is clear to me.

代码会发生什么?What happens to the code

Thorsten 表示,没有证据能证明“好代码”会有意义,因为我们所说的大多数好代码,都是为了让人更容易处理代码。我认同其中那些纯粹是为了让人感觉舒服的部分,比如格式规范。但有些特性对智能体的重要性,远胜于它们对我们曾经的重要性:名称足够独特,便于 grep;模块足够小,能放进上下文窗口;测试失败时能清楚地说明原因;各部分之间有明确的边界。缺少这些,智能体仍然会做出改动,只是它看不到这项改动还会影响什么。如今,好代码就是智能体能够修改、又不会破坏它看不到的东西的代码。Thorsten says there’s no proof that “good code” will matter, since most of what we mean by it is about making code easy for people to work with. I agree for the parts that were purely about human comfort, like formatting. But some properties matter more to an agent than they ever did to us: names unique enough to grep, modules small enough to fit in a context window, tests that fail clearly, clear boundaries between parts. Without those, an agent will still make the change. It just can’t see what else the change affects. Good code, now, is code an agent can change without breaking something it can’t see.

我长期参与开源项目,我认为开源在这里会继续演进,而不是消亡。如今,拿一个项目做出自己的副本并迅速改造它,比以往任何时候都更容易,而且不必先弄懂所有代码。我不会惊讶于我们今后越来越多地分享提示词,或分享已经完成的产物,让人们在想要定制它们时交给自己的智能体。I’ve been involved in open source for a long time, and I think it evolves here rather than dies. It’s easier than ever to take a project, make your own copy and reshape it quickly without first understanding all of the code. I wouldn’t be surprised if we increasingly share prompts, or share finished artifacts that people hand to their agents when they want to customize them.

开源领域缺少的是维护者的精力,而 AI 既让它被大量内容淹没,也让其规模倍增。一月,Daniel Stenberg 结束了 curl 的漏洞赏金计划,理由是他所说的“AI 垃圾报告激增”。三个月后,真实漏洞的数量恢复正常,但报告量已是过去的两倍。一年之内,垃圾报告问题就变成了数量问题。最值得分享的东西,逐渐转向那些制作成本高、核验成本低的内容:测试套件、规范,以及故障记录。What open source is short on is maintainer attention, and AI both floods it and multiplies it. In January, Daniel Stenberg ended curl’s bug bounty, citing what he called “an explosion in AI slop reports.” Three months later, the rate of real vulnerabilities was back to normal, at double the old report volume. Within a year, the junk problem had turned into a volume problem. What’s most worth sharing shifts toward things that are expensive to produce and cheap to check against: test suites, specs, the record of what broke.

碰撞溃缩区The crumple zone

Madeleine Clare Elish 为自动化系统边缘的人所遭遇的处境起了个名字:道德溃缩区。在汽车上,溃缩区的设计是吸收冲击力,让乘客免受其害。在自动化承担大部分工作的系统中,离故障最近的人往往扮演着同样的角色。他们为自己几乎无力阻止的故障承担责任。Madeleine Clare Elish has a name for what happens to people at the edge of automated systems: the moral crumple zone. In a car, the crumple zone is built to absorb the impact so the passengers don’t have to. In a system where automation does most of the work, the nearest human often plays the same role. They take the blame for a failure they had little real power to prevent.

连续十三个小时敲回车的工程师正身处其中。他的名字出现在审批记录上。但节奏、检查项,以及哪些内容值得阅读的决定,都是在别处做出的。出了问题,事故复盘最终找到的会是那个批准它的人。The engineer pressing enter for thirteen hours is standing in one. Their name is on the approval. But the pace, the checks and the decision about what was worth reading were all made somewhere else. When something breaks, the incident review will find the human who approved it.

逐行阅读从来不是让软件值得信赖的唯一原因。它只是确保有人理解自己即将交付什么,并有底气说“不”的一种方式。大多数代码今后都不会再逐行审阅,我觉得这没问题。但理解和说“不”的能力不能随之消失。Reading every line was never what made software trustworthy. It was one way to make sure a person understood what they were shipping and was in a position to say no. The line-by-line read is going away for most code, and I think that’s fine. The understanding and the ability to say no can’t go with it.

Teleport found two years of security bugs in one quarter. Thirteen engineers, frontier models, their own codebase: nearly twice as many high severity vulnerabilities as the previous two years put together. What interests me is what that does to the queue. Discovery got several times cheaper. Triage did not, and confirming what is genuinely exploitable is still a person reading code. Find faster than you can fix and you have traded an unknown backlog for a known one. Worth a read before you try this on your own codebase. Read the write-up → https://fandf.co/4r3xdeX · Sponsored by Teleport. #ad

所以,以下是我现在会给出的建议,取代两年前说过的话。要知道什么值得读。对于你没有阅读的代码,建立你真正信得过的检查机制,并让它们独立于编写代码的工具。让智能体动手构建之前,先写下你要构建的东西。确保自己能解释交付的每一项内容,也要坦诚承认自己无法解释的部分。如果你为他人设定工作节奏,就要赋予他们与你要求他们承担的责任相匹配的权限。So here’s the advice I’d give now, in place of what I said two years ago. Know what’s worth reading. On the code you don’t read, build checks you’d actually trust, and keep them independent of whatever wrote the code. Write down what you’re building before an agent builds it. Be able to explain everything you ship, and be honest about what you can’t explain. If you set the pace for other people, give them authority that matches the accountability you’re asking of them.

我曾把优秀的代码称作写给下一位开发者的情书。我至今仍这么认为。不过,越来越多时候,下一位开发者是一个智能体,所以这封信如今的模样也变了。它是智能体能够修改、又不会因此破坏它看不见的东西的代码。匠心并没有消失,只是转移到了那些决定代码是否值得信任的环节。I once called good code a love letter to the next developer. I still believe that. More and more, though, the next developer is an agent, so the letter looks different now. It’s code the agent can change without breaking something it can’t see. The craft didn’t disappear. It moved to the parts that decide whether the code deserves to be trusted.

感谢这几个月来赞助本通讯的赞助商们给予的支持。由于我已经全职开始担任新的职务,今后的期刊暂时不再接受赞助。文中观点仅代表我个人,不代表雇主的观点或意见。希望只要这些内容对你有帮助,我就能继续在通讯中分享想法、持续写作 :)Thanks to the newsletter’s sponsors for their support over the last few months. As I’ve joined a new role full-time, I’ve put a pause on sponsors for future issues. Opinions here expressed are my own and do not express the views or opinions of my employer. I hope to continue writing and sharing my thoughts on the newsletter as long as they’re helpful to you :)

值得记下

你不需要阅读所有代码。每个变更仍然需要一些审查,每个变更仍然需要一个拥有发布决策权的人。
一个描述了目的地。另一个描述了当一家公司没有修路就开过去时会发生什么。
审查从来都不是主要关于 bug 的,这就是为什么「机器会审查它」这个答案比听起来要弱。
智能体做第一遍,人类覆盖爆炸半径。
你只能真正为你能够解释的事情负责。
赢的团队不是什么都不读的团队。而是知道什么值得读的团队。
测试作为对你并不完全信任的作者的独立检查,将是你拥有的最有价值的代码。