AI 让代码迁移变快之后,质量保障反而更重要了

读 Anthropic 大规模代码迁移实践:当写代码变便宜,瓶颈转向工程控制

Posted by KL on July 18, 2026
ZH EN

AI 写代码的速度越快,工程师越不能只关注代码本身。真正稀缺的能力,正在从“写对每一行代码”转向“设计一套能持续生产正确代码的系统”:用规则约束生成、用小规模实验验证规则、用对抗性 Agent 主动找问题、用编译器和测试当裁判。这篇是我读 Anthropic《How Anthropic runs large-scale code migrations with Claude Code》后的整理与思考。

最近读了 Anthropic 发布的一篇文章:《How Anthropic runs large-scale code migrations with Claude Code》。

文章分享了他们如何利用 Claude Code 和多个 AI Agent,完成多次大型代码迁移。其中包括:

  • 在不到两周内,将 Bun 的大量代码从 Zig 迁移到 Rust,最终生成约 100 万行代码(共 1448 个文件);
  • 在合并前,让 Bun 原有测试套件在 CI 中达到 100% 通过;
  • 将一个内部 Python 项目在一个周末内迁移为约 16.5 万行 TypeScript;
  • 使用数百个 Agent、8 个阶段门禁、3 轮对抗性审查,并逐条对比新旧系统的输出结果。

文章篇幅不长,但里面关于规则制定、任务拆分、质量验证、对抗审查和成本控制的实践,信息密度非常高。

先说说我的个人感受

我自己做过多次中小型软件服务迁移,代码规模通常在几万行左右。

做过这类项目之后,会很清楚地意识到:代码迁移远远不是“把旧代码翻译成新代码”这么简单。

真正困难的问题通常包括:

  • 如何在产品持续迭代的过程中完成迁移?
  • 如何避免同一个新功能在旧系统和新系统中分别实现一遍?
  • 如何拆分迁移任务,让多个开发者能够并行工作?
  • 如何保证迁移后的系统不出现严重质量问题?
  • 如何判断新系统已经真正达到旧系统的功能完整度?

这些问题背后涉及的其实不是单纯的编码能力,而是项目管理、架构设计、任务拆解、测试计划和风险控制。

随着 AI 编程能力越来越强,代码迁移的速度确实可能获得数量级的提升。但与此同时,质量保障问题反而可能被进一步放大。

当 AI 可以在短时间内生成几万甚至几十万行代码时,人已经不可能逐个文件、逐个 Pull Request 地进行完整审查。

这时,工程师需要解决的问题就从:

AI 写的每一行代码是否正确?

转变为:

如何约束 AI 不跑偏? 如何建立客观的验证机制? 如何让错误能够被自动发现、分类和修复? 如何利用 AI 更好地完成新旧系统的对比测试?

普通工程师很少有机会参与百万行代码级别的语言迁移。Anthropic 这次公开的 Bun 迁移,仅按照 API 价格计算,就消耗了大约 16.5 万美元,使用了 59 亿个未缓存输入 Token 和 6.9 亿个输出 Token。

因此,这不仅是一篇产品宣传文章,也可以看作一份非常昂贵的大规模 AI 工程实验报告。

而且,里面确实有不少可以直接应用到日常开发工作的实践。

一、AI 改变的不是编码速度,而是迁移项目的经济模型

过去,大型语言迁移通常意味着持续数年的项目。

团队需要长期维护两套代码:

  • 旧系统继续承载线上业务;
  • 新系统不断补齐功能;
  • 新功能可能需要同时在两边开发;
  • 迁移到最后仍然可能只有 90% 的功能一致性。

如果迁移失败,团队得到的可能不是一个更好的系统,而是两套都需要维护的系统。

因此,过去只有非常严重的问题,才足以推动一次大型语言迁移,例如:

  • 原有语言生态逐渐衰退;
  • 长期存在内存安全问题;
  • 构建速度严重影响发布效率;
  • 某个架构瓶颈已经无法继续绕过。

AI Agent 改变了这个成本模型。

Anthropic 在文章中给出了一个很有意思的判断:

现在迁移失败的最坏结果,可能只是删除分支,然后重新再做一次。

这并不意味着代码迁移已经变得便宜。

Bun 的迁移按照 API 定价仍然花费约 16.5 万美元。但相比过去可能持续数年、消耗数百万美元工程资源的项目,试错成本已经显著降低。

值得一提的是,即便是这次成功的 Bun 迁移,合并后仍然出现了 19 个回归问题(目前已全部修复)。这恰好印证了本文的判断:迁移变快之后,回归和质量验证不是变得可有可无,而是变得更加关键。

因此,一些过去“不值得迁移”的问题,现在可能已经值得重新计算投入产出比。

例如,Anthropic 内部的一个 Python 工具,过去需要针对不同平台分别构建,每个平台大约 8 分钟,完整构建矩阵大约需要等待 30 分钟。迁移到 TypeScript 后,编译时间缩短到约两秒,启动速度提升了六倍,同时还可以下线一套独立的部署流程。

AI 不只是让迁移变快,也降低了企业重新评估技术债的门槛。

二、整篇文章最重要的一句话

Anthropic 在文章中提出了一个核心观点:

You don’t fix the code. You fix the process (loop) that produced the code.

翻译过来就是:

不要只修复代码,而要修复生成这些代码的流程(循环)。

这句话几乎可以概括整套 AI 迁移方法。

在传统开发中,当工程师发现一个 Bug,通常会修改对应的文件。

但在大规模 Agent 迁移中,如果几十个文件都出现了同一类错误,逐个修改文件并不能解决真正的问题。

真正需要修改的可能是:

  • 迁移规则不完整;
  • Prompt 中缺少约束;
  • 任务划分方式不合理;
  • 审查 Agent 没有覆盖某类风险;
  • 测试裁判无法识别某类错误;
  • 工作队列没有正确记录失败状态。

正确的做法不是让工程师手动修改几十个文件,而是:

  1. 找出产生这类错误的共同规则;
  2. 修改规则或工作流程;
  3. 重新生成受影响的代码;
  4. 再次通过测试和审查验证。

这也是 Agent 工程和传统编码最大的区别之一。

工程师的工作重点,开始从“直接生产代码”,转向“设计能够持续生产正确代码的系统”。

三、Anthropic 的大型代码迁移六步法

前置条件:先建立一个可靠的裁判

正式迁移之前,首先需要建立一个能够同时评价旧系统和新系统的“裁判”。

这个裁判可能是:

  • 自动化测试套件;
  • 编译器;
  • 新旧系统输出对比工具;
  • API 契约测试;
  • 真实业务场景回放;
  • 性能与资源使用基准测试。

一个好的裁判必须满足两个条件:

第一,它能够在旧系统上正常通过。

第二,当系统被故意破坏时,它必须能够发现问题。

文章中的说法很直接:

无法发现故障的裁判,就不是真正的裁判。

现实中,很多旧项目的测试依赖内部函数或语言特性,无法直接复用到新的语言中。

这时需要先对测试进行分类:

  • 哪些测试可以通过外部接口执行;
  • 哪些测试依赖内部实现;
  • 哪些测试需要改造成跨语言测试;
  • 改写后的测试是否削弱了原有断言。

如果没有完整测试套件,也不代表无法迁移。

Python 到 TypeScript 的项目只构建了七个真实业务场景,然后同时在新旧系统中执行,对每条命令的输出进行 Diff。

这里的关键不是一定要有多少测试,而是必须建立一个双方都认可的客观标准。

旧系统本身,就是新系统最重要的 Ground Truth。

第一步:建立规则手册、依赖图和差异清单

这是整个迁移过程中最重要、也最消耗工程师时间的阶段。

1. 规则手册

规则手册用于告诉所有迁移 Agent:

  • 类型应该如何转换;
  • 错误处理应该如何实现;
  • 内存和资源应该如何管理;
  • 日志、配置和依赖注入应该使用什么模式;
  • 哪些旧语言习惯不能直接复制;
  • 哪些架构必须保持一致;
  • 哪些部分允许重新设计。

如果迁移目标是保持原有结构,规则手册可能主要是一组语言和类型的映射规则。

如果迁移同时涉及架构重构,规则手册就更接近一份完整的设计文档。

它不是一个普通 Prompt,而是所有 Agent 必须遵守的工程规范。

2. 依赖图

大规模迁移需要高度并行。

但并行的前提是知道:

  • 哪些文件可以独立迁移;
  • 哪些模块必须一起处理;
  • 哪些底层依赖应该优先完成;
  • 哪些循环依赖需要提前拆解。

因此,Anthropic 会先利用确定性脚本分析代码依赖,再由 Agent 审查和修复依赖图。

这里有一个很重要的原则:

能用确定性程序完成的事情,不要完全交给模型猜测。

3. 差异清单

旧语言和新语言之间必然存在语义差异。例如:

  • Zig 到 Rust 的核心差异之一是内存所有权;
  • Python 到 TypeScript 的核心差异之一是接口和类型契约;
  • 动态语言中的隐式行为,在静态语言中必须被显式声明;
  • 旧系统允许的循环依赖,新系统可能无法编译。

这些无法通过简单语法替换解决的问题,需要提前放入差异清单。

规则手册定义默认做法,差异清单记录默认规则无法覆盖的情况。

第二步:先做一次可以丢弃的小规模实验

我认为这是整篇文章里最值得学习的实践之一。

Anthropic 不会在规则完成后立即迁移全部代码,而是先选择少量具有代表性的文件,进行一次小规模迁移实验。

Bun 的迁移中,他们安排:

  • 一个 Agent 严格按照规则手册迁移三个文件;
  • 一个 Agent 按照“资深 Rust 工程师”的方式迁移同样的文件;
  • 第三个 Agent 比较两份结果,并生成新的迁移规则。

仅仅通过这次实验,他们就提前发现了两个严重问题。

如果这些问题没有在小规模阶段暴露,而是直接扩散到全部 1448 个文件,后面的修复成本会非常高。

更加反直觉的是:

实验产生的代码应该直接丢弃。

因为这个阶段的目的不是完成迁移进度,而是验证迁移规则。

这和日常开发中的 Spike、PoC 或试点项目很像,但 AI 让这种实验的成本变得更低。

先用少量代码暴露规则问题,再大规模并行执行,比一开始追求迁移进度更可靠。

第三步:大规模并行迁移

规则经过验证后,才开始真正迁移全部代码。

Anthropic 使用的基本循环是:

Implement → Review → Fix 实现 → 审查 → 修复

多个实现 Agent 并行处理不同文件或模块。

为了控制成本,高吞吐量的实现工作可以交给较小、较便宜的模型;复杂规则设计、架构判断和代码审查,则交给能力更强的模型。

迁移队列由脚本管理,而不是依赖 Agent 自己记忆。例如:

  • 检查目标文件是否已经存在;
  • 自动计算还未迁移的文件;
  • 按照依赖关系切分任务;
  • 将任务分配给新的 Agent;
  • 失败后可以从磁盘状态继续执行。

这样设计后,迁移过程天然可以暂停和恢复。

Agent 无法确定如何迁移的地方,则统一标记:

// TODO(port): <reason>

之后,编译器错误、Smoke Test 崩溃和测试失败,会自动成为下一批修复任务。

队列不需要人工长期维护,因为失败本身就在不断生成新的任务。

第四步:编译,并按错误模式修复

代码完成初步迁移后,开始进入编译阶段。

这里需要根据项目特点决定编译器放在什么位置。

TypeScript 编译速度较快,可以放入每个 Agent 的执行循环。

Rust 大型项目的完整编译可能需要几分钟,因此 Bun 的迁移没有让每个 Agent 独立运行编译,而是由统一的编排脚本执行完整构建,再把错误列表分配给多个修复 Agent。

这个设计也体现了成本控制。如果每个 Agent 都重复执行完整构建,会浪费大量 CPU、时间、Token、上下文和 CI 资源。

因此,他们设置了一个统一的 Build Daemon。

只有这个进程可以重新构建程序。其他 Agent 只负责提交补丁,由 Build Daemon 对补丁进行批量合并、统一构建并重新执行相关测试。

它本质上是把最昂贵的操作集中管理,而不是让大量 Agent 重复执行。

第五步:运行 Smoke Test,按根因归类问题

通过编译不代表程序能够正常运行。接下来需要执行 Smoke Test,发现:

  • 启动失败;
  • Runtime Crash;
  • 配置加载错误;
  • 资源初始化问题;
  • 模块边界错误;
  • 外部依赖调用异常。

这里同样不能只看单个错误。

如果几十个崩溃来自同一个根因,就应该修改上游规则或架构,而不是让几十个 Agent 分别提交临时补丁。

Anthropic 的做法是先按根因对问题进行聚类,再由对抗性审查 Agent 检查问题分类和修复方案。

第六步:进行新旧系统行为对比

最后一步,是确认新旧系统的行为真正一致。

此时,新代码已经完成翻译、编译、Smoke Test 和基本问题修复。但要证明迁移成功,仍然需要对比真实行为。

Anthropic 会将测试任务拆分执行。每个失败测试由独立的修复 Agent 同时查看:

  • 旧代码;
  • 新代码;
  • 测试输入;
  • 实际输出;
  • 预期行为。

修复之后,再由对抗性审查 Agent 检查修改。

Python 到 TypeScript 的迁移,还使用七个真实使用场景分别调用两个系统,然后对输出逐项进行 Diff。

之后,Claude 又自动设计了一套端到端测试,连续四个晚上运行、修复并重新执行,从而发现了一些人工场景列表很难提前想到的边缘问题。

这也是我认为 AI 非常适合发挥能力的地方:

不是只让 AI 生成业务代码,而是让 AI:

  • 分析旧系统行为;
  • 生成对比测试;
  • 寻找边界场景;
  • 对失败结果进行分类;
  • 提出修复方案;
  • 再调用确定性工具进行验证。

四、最值得学习的四个工程实践

1. 人的时间应该前置投入

AI 可以快速生成代码,但迁移规则、架构边界和验证标准仍然需要工程师投入大量时间。

Anthropic 的结论是:

人工投入应该尽量前置。

最花费工程师时间的部分是:

  • 制定规则;
  • 识别语言和架构差异;
  • 建立测试裁判;
  • 设计任务队列;
  • 完成小规模压力测试。

一旦这些工作完成,后面的过程主要是让任务队列不断收敛。

这和很多人使用 Coding Agent 的习惯恰好相反。

很多人会先让 AI 大量生成代码,发现问题后再慢慢补规则。但对于大型任务,更合理的顺序是:

先花时间定义系统,再让 AI 快速执行。

2. 审查必须具有对抗性

文章中多次提到 Adversarial Review,也就是对抗性审查。

实现 Agent 的目标是完成任务。

审查 Agent 的目标不应该是帮助实现 Agent 证明自己正确,而应该主动寻找:

  • 违反规则的地方;
  • 隐含假设;
  • 未覆盖的边界条件;
  • 行为变化;
  • 类型和接口不一致;
  • 测试被弱化的问题;
  • 临时方案被当成最终实现的问题。

Anthropic 会让两个审查 Agent 在相互独立的上下文中检查同一份结果。如果两者意见不一致,再交给第三个 Agent 判断。

这类机制不只适合代码迁移,也很适合日常工作中的:架构设计评审、数据迁移、API 重构、数据库升级、框架升级、大型代码清理、安全审查、测试计划评审。

Agent 不应该全部扮演“协作者”。有些 Agent 应该被明确设计成怀疑者、反对者和破坏者。

3. 审查流程结果,而不是逐行审查代码

面对百万行 AI 生成代码,人不可能逐行审查。工程师真正应该关注的是:

  • 哪些错误反复出现;
  • 哪条规则产生了最多问题;
  • 哪类模块失败率最高;
  • 哪个阶段消耗最多 Token;
  • 哪些测试长期无法收敛;
  • 哪些 Agent 经常违反相同约束;
  • 哪些任务应该交给更强的模型;
  • 哪些判断可以改成确定性脚本。

也就是说,不再只审查代码,而是审查生成代码的 Loop。

这并不代表代码审查不重要,而是人的注意力应该集中在高风险代码和系统性问题上。普通、重复、大批量的代码,则更多依靠编译器、静态检查、测试、Diff、契约、对抗性 Agent 和自动化门禁。

4. 成本管理本身就是架构设计

文章很多地方都在讨论如何控制成本。例如:

  • 大批量实现使用较小模型;
  • 规则制定和最终审查使用较强模型;
  • 避免每个 Agent 重复执行昂贵构建;
  • 使用统一 Build Daemon 批量处理补丁;
  • 将编译器放在适合的位置;
  • 让任务可以暂停和恢复;
  • 只重新生成受规则变化影响的文件;
  • 把机械性判断交给脚本,而不是语言模型。

这说明在大规模 Agent 系统中,模型选择、任务队列、构建流程和验证机制已经不能分开考虑。

它们共同决定了:项目的完成速度、Token 成本、基础设施成本、错误收敛速度和最终质量。

AI Agent 的成本优化,不只是“换一个便宜模型”,而是重新设计整个执行流程。

五、这些实践如何应用到日常项目

大多数工程师不会迁移百万行代码,但这套方法仍然可以应用到普通开发中。

例如进行 Java 版本升级、Spring Boot 升级、数据库迁移、API 重构或前端框架迁移时,可以采用类似流程:

第一,先建立规则文件。 明确:哪些模式必须替换;哪些接口不能改变;哪些目录不允许修改;哪些兼容行为必须保留;哪些异常处理方式需要统一;什么情况必须停止并报告。

第二,建立新旧系统对比工具。 相同输入分别调用新旧系统,比较:返回值、错误码、日志、数据库变更、消息输出、性能、内存和资源使用。

第三,先做一次可丢弃实验。 选择几个典型模块进行迁移。不要急着保留代码,而是通过实验发现:规则是否完整;Agent 是否理解任务;测试是否能够发现错误;模块拆分是否合理;Prompt 是否存在歧义。

第四,让不同 Agent 扮演不同角色。 至少区分:实现 Agent、规则审查 Agent、代码审查 Agent、测试设计 Agent、行为对比 Agent、风险审查 Agent。

第五,修复产生错误的规则。 当多个模块出现相同问题时,不要逐个修改。先判断是否应该:修改规则、修改 Prompt、修改任务拆分、增加测试、增加静态检查、改变模型分工。

这可能才是大规模使用 Coding Agent 时最重要的思维变化。

写在最后

AI Agent 正在让一些过去风险极高、周期极长的工程项目重新变得可行。

但文章给我的最大启发,并不是“Claude 可以在两周内生成百万行代码”。

真正值得关注的是,Anthropic 如何围绕 AI 的不确定性,设计了一套完整的工程控制系统:

  • 用规则约束生成;
  • 用小规模实验验证规则;
  • 用多个 Agent 并行执行;
  • 用对抗性 Agent 主动寻找问题;
  • 用编译器、测试和 Diff 充当裁判;
  • 用统一任务队列保证流程可以恢复;
  • 用不同等级的模型控制成本;
  • 发现系统性问题后修改流程,而不是只修改代码。

AI 写代码的速度越快,工程师越不能只关注代码本身。

未来工程师更重要的能力,可能是:

设计约束、建立裁判、组织 Agent,并构建一个能够持续发现和修复错误的工程闭环。

对于正在使用 Claude Code、Codex、Cursor 或其他 Coding Agent 的工程师,我非常推荐阅读原文。即使暂时没有大型代码迁移需求,也可以看看 Anthropic 如何设计 Prompt、Rule、Review、Test 和 Agent Workflow。

这些方法不仅适用于语言迁移,对日常的软件重构、架构升级和复杂功能开发同样很有参考价值。

原文: How Anthropic runs large-scale code migrations with Claude Code(作者 / 版权归 Anthropic;本文为读后整理与个人思考)