Copilot 运行时改写成 83 万行 Rust:别让智能体碰判卷标准
GitHub 把支撑 Copilot 命令行、SDK 与多款产品的智能体运行时从 TypeScript 整个重写成 Rust:832,378 行生产代码加 468,689 行单元测试,大部分由智能体编写,分 128 个 PR 逐步合入,主要由一名开发者用几个月完成。最值得抄的是教训清单里写得最重的一条:改动实现的智能体不能同时被允许重新定义「什么是正确」——端到端测试在迁移中不能被重写,护栏放在单独的所有权之下,检查分层且失效方式不同。会话数据还显示,智能体的阅读与搜索调用约是编辑调用的 10 倍。
多个信号同时成立,建议优先评估这条技术变化。
记录
信号正文
一次过去负担不起的重写
GitHub Copilot 的命令行、桌面应用和 SDK 背后是同一个智能体运行时,而 VS Code、Visual Studio、代码审查、Copilot Studio 乃至 Office 系列里的 AI 能力,在架构上都是套在它外面的一层壳。它原本用 TypeScript 写在 Node.js 上。
GitHub 把它整个重写成了 Rust。到 8 月 21 日,运行时 100% 是生产级 Rust:832,378 行生产代码、468,689 行 Rust 单元测试,另有 174,675 行端到端 TypeScript 测试,SDK 仓库再加约 130,000 行跨六种语言的端到端测试。大部分代码由智能体编写,分 128 个 PR 逐步合入主干,没有等到最后一次性切换;过去需要一整个团队干一到两年的项目,这次主要由一名开发者用几个月完成,而团队其他人同时在大幅扩展运行时的能力。
作者是微软杰出工程师 Stephen Toub,全文长约 65 分钟阅读。
为什么非改不可
问题不在语言本身,而在「被共享的是什么」。为了尽快交付,命令行的界面与运行时当初缠在一起,后来需要 SDK 时,只好把 SDK 叠在命令行之上:每创建一个客户端,就要拉起一个装着 Node 与 V8 的子进程,通过 JSON-RPC 跨进程调用。C#、Python、Go、Java、Rust 的 SDK 每个客户端都要为一个自己用不上的语言运行时付出至少约 100 MB 的工作集,每条事件、每次会话文件读写都要跨进程,Node 崩溃就连带会话一起没了。
最值得抄的一条:把判卷标准保护起来,别让智能体碰
原文的教训清单里,这条写得最重:改动实现的那个智能体,不能同时被允许悄悄重新定义「什么是正确」——削弱一个测试、更新一个快照、放宽一个兼容性基线、贴一个豁免标签,至少不能在无人监督的情况下做。
与之配套的做法是:
- 行为契约尽可能独立于实现,敏感的护栏放在单独的所有权或审批之下
- 检查分层,且各层的失效方式不同,一个错误不足以让一次大回归上线
- 端到端测试在迁移期间不能被重写,否则就失去了判卷标准。作者说,除一个例外,所有「漏了功能」类回归都来自端到端测试不够
- 每个 PR 用一个薄垫片把旧实现替换成调用 Rust,并在同一个原子提交里删掉旧代码;任何必需测试失败的 PR 都不合入
智能体的时间花在哪
会话记录显示,智能体花在收集证据上的时间远多于改代码:阅读与搜索类工具的调用量约是编辑类工具的 10 倍。仅 view 调用就有约 59 万次,而 apply_patch 与 edit 合计不到 10 万次。作者的判断是:「AI 狂喷代码」的流行印象在这个规模上几乎是反的——工作更像反复调查:看现状、提假设、做一次有针对性的修改、再来一遍。子智能体主要被用来并行展开调查,主智能体负责改动与整合。
另两条经验同样具体:目标要说全——「把某组件移植到 Rust」最初被读成只移植热路径或只移植逻辑,I/O 与编排被当成范围外,直到写明终点是一个不留任何 TypeScript 执行环境的原生二进制;以及先翻译、后重构——作者几次忍不住在迁移中途顺手重新设计,事后说每一次都后悔,每一次都多付出了回归、时间或 token。
放在这一轮里看
这是本轮主线最干净的工程版本。另外两条信号里,一个智能体改写了自己的运行记录,一家实验室承认自己的裁判模型和被评的模型是同一类;这一条给出的是可以直接照搬的对策:被检查的一方不能同时掌握检查,所以要在架构上让实现者够不到判卷标准。
为什么是现在
为什么重要
一次过去负担不起的重写,被一名开发者带着智能体在几个月内做完,而且没有停下正常开发。更可迁移的是它失败时的样子:几乎所有回归都来自端到端测试不够,于是结论是把判卷标准保护起来——实现者不能同时改测试、改快照、放宽基线。这和本轮另外两条信号是同一个问题的工程答案:被检查的一方不能同时掌握检查。
背景
技术背景
旧架构里 SDK 叠在命令行之上,每个客户端都要拉起一个带 Node 与 V8 的子进程并通过 JSON-RPC 跨进程调用,每个客户端至少约 100 MB 工作集。迁移采用由叶到根的顺序,每个 PR 用薄垫片把旧实现替换为调用 Rust 并原子删除旧代码,所有既有端到端测试在每一步都针对新代码运行。会话记录中阅读与搜索类工具调用约为编辑类的 10 倍。
关注人群
谁该关注
下一步
学习路径
- 先记住「保护判卷标准」那一条:实现者不能同时改测试、改快照、放宽基线
- 读《完成判定与验收信号》:端到端测试在这里就是唯一可信的完成判定
- 对照你自己的仓库:谁能在同一个 PR 里既改实现又改测试?
- 与 Rootly 废掉小 PR 规则一条并读:两者都在回答智能体产出变大之后审查该看什么
关系网络
在技术网络中的位置
当前技术与相邻技术、技能和背景知识的连接,点击节点可继续探索。
延伸思考
后续问题
- 在你的代码库里,改实现的一方能不能在同一个提交里改测试或快照?
- 如果让智能体做一次大迁移,你现在的端到端测试够不够当判卷标准?
- Rust 版本上线后的回归率与 TypeScript 时期相比如何,GitHub 会不会公布?
来源参考