2025 年 5 月,GitHub Copilot Coding Agent(CCA)正式发布的同一天,Stephen Toub 和 .NET 团队就把它接入了 dotnet/runtime。这是 .NET 最核心的代码库,涵盖垃圾回收器、JIT 编译器、AOT 工具链和数百个基础库,跨越 C#、C++、汇编等多种语言,运行在 Windows、Linux、macOS、iOS、Android 和 WebAssembly 上。如果这里出了问题,数百万开发者和客户都会感受到。
十个月后,有了足够多的数据来讲清楚一件事:AI 编码智能体在一个世界级复杂生产代码库里,到底能做什么、做不好什么。

总体数据
从 2025 年 5 月 19 日到 2026 年 3 月 22 日,dotnet/runtime 的 PR 构成如下:
| 来源 | PR 数 | 占比 | 合并 | 关闭 | 成功率 |
|---|---|---|---|---|---|
| 微软员工 | 3,082 | 50% | 2,556 | 377 | 87.1% |
| 社区贡献 | 1,411 | 23% | 1,029 | 262 | 79.7% |
| CCA | 878 | 14% | 535 | 253 | 67.9% |
| Bot(如 dependabot) | 810 | 13% | 666 | 109 | 85.9% |
| 合计 | 6,181 | 4,786 | 1,001 | 82.7% |
CCA 的 67.9% 成功率乍看低于人类,但这两个群体面临的任务完全不同:人类倾向于做复杂的判断类工作,CCA 被分配的是更有边界的具体任务。更直接的质量信号是回滚率:535 个合并的 CCA PR 中,3 个被回滚(0.6%);非 CCA 的 4,251 个合并 PR 中,33 个被回滚(0.8%)。样本量不够下结论,但至少没有红旗。
扩展到 .NET 团队的 7 个代码库,CCA 总计提交 2,963 个 PR,1,885 个合并(68.6% 成功率),净增约 27.1 万行代码。
成功率如何从 41.7% 爬升到 71%
按月看 dotnet/runtime 的 CCA 成功率:
| 月份 | PR 数 | 当月成功率 | 累计成功率 |
|---|---|---|---|
| 2025-05 | 24 | 41.7% | 41.7% |
| 2025-06 | 13 | 69.2% | 51.4% |
| 2025-10 | 86 | 58.8% | 59.2% |
| 2025-12 | 87 | 72.4% | 64.4% |
| 2026-01 | 182 | 71.2% | 66.6% |
| 2026-02 | 196 | 69.7% | 67.4% |
| 2026-03* | 140 | 72.1% | 67.9% |
这条增长曲线背后的故事是学习:学会分配什么任务、如何写指令、如何迭代。
为什么 Instructions 比模型更重要
dotnet/runtime 最初没有 .github/copilot-instructions.md,也没有配置防火墙规则。CCA 的沙箱环境默认屏蔽大部分外部资源,连 NuGet 包都下载不了。结果是 CCA 在写它无法编译、无法测试的代码,早期 5 月的成功率只有 41.7%。
修复很简单:配置防火墙放行包源,写 copilot-instructions.md 告诉 CCA 怎么构建仓库。
修复前:38.1% 成功率。修复后:69%。
提升来自更好的准备,而不是更好的模型。此后团队持续迭代这份指令文件,每次修改都编码了新的经验教训:明确构建命令、说明测试规范、解释架构边界、标注运行环境的平台限制。
好的指令文件应该包含:
- 具体的构建命令(而不是让 CCA 猜)
- 测试约定(如不要 assert 精确的异常消息,因为消息可能本地化)
- 禁止使用
InternalsVisibleTo(会形成内部 API 契约,制约重构) - 环境限制(CCA 运行在 Linux,无法测试 Windows 特定代码)
生日派对实验:从手机分配 20 个 Issue
成为转折点的是 2025 年 10 月一个周六。Stephen Toub 在陪孩子参加生日派对,趁孩子们玩耍的空档,用手机浏览 dotnet/runtime 的积压 Issue,开始向 Copilot 分配任务。一个小时内分配了 20 多个。到当天傍晚,22 个 PR 已经可以审查。
三个典型案例:
线程安全修复(PR #120619):System.Text.Json 的 JsonObject.InitializeDictionary 有线程安全问题。CCA 验证了假设、实现了修复、添加了回归测试。整个审查花了约 10 分钟。这是 CCA 最擅长的场景:有清晰描述的 Bug,有大致的修复思路。
主动关闭的 PR(PR #120638):Issue 建议把一种本来能正常解析的正则语法改为拒绝。CCA 正确实现了改动,但审查它修改的测试时发现:那些测试记录的是刻意设计的行为,原语法是故意支持的。PR 被关闭。但 CCA 做了本该人工完成的调查工作,节省了几个小时。
调试胜利(PR #120622):非回溯正则引擎中一个关于空捕获组和换行符的隐蔽 Bug。手动调试可能需要一天。CCA 找到了问题,提交了一行修复加测试。审查花了五分钟。
BCrypt 挣扎(PR #120633):不是每件事都顺利。涉及 Windows BCrypt 的 PR 经过 20+ 次提交,因为 CCA 无法在 Windows 上测试,最终被关闭。这个案例说明:CCA 在需要跨平台架构判断的问题上会遇到麻烦。
飞机上开 9 个 PR
2026 年 1 月 6 日,Stephen 搭飞机去雷蒙德,没带笔记本,只有手机。在飞行途中,他用手机向 CCA 分配任务,飞机落地时,9 个 PR 已经开好:
| PR | 内容 | 结果 |
|---|---|---|
| #122944 | BufferedStream 大缓冲区整数溢出修复 | 已合并 |
| #122945 | TarReader 回归测试 | 已合并,+226 行测试 |
| #122947 | Directory.GetFiles 性能优化 | 已合并 |
| #122950 | System.Text.Json 支持 byref 参数构造函数 | 已合并,+8,359 行 |
| #122952 | HashSet.UnionWith 性能优化 | 已合并 |
| #122953 | 移除 112 个文件中的废弃预处理器常量 | 已合并 |
| #122959 | 正则编译器优化移植 | 已合并 |
| #122951 | Baggage 编码修复 | 已关闭 |
| #122956 | ConcurrentBag 实验性改动 | 已关闭 |
7 个合并,2 个关闭。这改变了”严肃的软件工程只能发生在什么地方”的认知。
但这里有个隐患:一个人在几小时内可以生成 9 个复杂 PR,但这些 PR 需要审查。每个 PR 至少 30-60 分钟的认真审查,意味着迅速积累了 5-9 小时的审查工作压在团队成员身上。生产的瓶颈从实现转移到了审查。
擅长什么、不擅长什么
按任务类型的成功率:
| 类型 | PR 数 | 成功率 |
|---|---|---|
| 代码清理/删除 | 77 | 84.7% |
| 写测试 | 99 | 75.6% |
| 重构 | 86 | 69.7% |
| Bug 修复 | 317 | 69.4% |
| 文档 | 52 | 68.1% |
| 版本升级 | 44 | 67.4% |
| 功能开发 | 131 | 64.5% |
| 性能优化 | 46 | 54.5% |
规律清晰:任务越机械、范围越明确,成功率越高。
擅长的领域:
- 清理和删除(84.7%):删废弃代码、清理死分支。任务明确,无需创造性判断。
- 写测试(75.6%):分析代码、识别未覆盖路径、生成测试用例。但注意:CCA 倾向于量大于质,初稿往往需要剪枝;更危险的是,它可能写出验证错误行为的测试,把 Bug 编码成预期结果。
- 具体的 Bug 修复(69.4%):清晰的复现步骤 + 明确的期望行为 = CCA 可以一次成功。关键是”清晰描述”。
挣扎的领域:
- 原生代码(C++):CCA 只能在 Linux 上运行,无法测试 Windows 特定代码。内存管理、所有权语义、平台特定宏,错误频率更高。
- 性能优化(54.5%):CCA 可以实现明确描述的 SIMD 优化,但无法自主进行性能分析、运行和解读 Benchmark。为此团队创建了一个自定义技能,让 CCA 学会调用 EgorBot 在专用硬件上跑 BenchmarkDotNet 并分析结果。
自主程度如何
合并的 CCA PR 平均有 6.9 个提交,但拆解看:
- 初始自主提交(人类介入前):平均 2.7 个,中位数 2 个
- 反馈后迭代提交:平均 4.1 个
62% 的合并 PR 在初始阶段只有 2 个提交(setup commit + 一次代码提交)。29.9% 的 PR 在收到第一个人类评论后不需要任何新提交,即 CCA 的初始方案被直接接受。
有无人类直接往 CCA 分支推提交的成功率差异很大:
| 类型 | PR 数 | 成功率 |
|---|---|---|
| 有人类直接推送代码 | 396 | 86.2% |
| 无人类直接推送代码 | 482 | 55.1% |
这说明 CCA 是力量倍增器,而不是替代者。
积压清理效果
在 464 个关联到 Issue 的 CCA PR 中,Issue 的年龄分布很有意思:
- 当天:38.8%
- 2 年以上:20.0%(最老的 Issue 可追溯到 9 年前)
平均 Issue 年龄 382 天(12.6 个月)。那些被推迟了几年的 Issue,CCA 不需要争抢优先级,只要有人指向它。
绿地 vs 棕地代码库
dotnet/runtime(数十年历史,数百万行)vs modelcontextprotocol/csharp-sdk(2025 年春全新项目)的对比:
| 指标 | dotnet/runtime | mcp/csharp-sdk |
|---|---|---|
| 成功率 | 67.9% | 77.3% |
| 合并平均提交数 | 6.9 | 5.2 |
| 人类直接推送率 | 45.1% | 32.6% |
| 合并中位时间(小时) | 50.0 | 17.4 |
| 每百行审查评论数 | 3.73 | 0.37 |
代码库越新、越自包含,CCA 能做到的越好。历史包袱越重,需要的人工介入越多。
给工程师的建议
1. 把 CCA 当成结对编程的搭档 你是高级开发,CCA 是有无限耐心但判断力有限的实习生。你提供方向和质量把控,CCA 提供实现带宽。
2. 好任务的特征
- 问题描述清晰,最好有复现步骤
- 有现成的测试模式可以参考
- 不需要深层架构决策
- 不涉及 CCA 无法测试的平台特定代码
3. 迭代是预期行为,不是异常 不要期望一次成功。建立清晰、具体、可执行的反馈是工作流的一部分。
4. 警惕懒惰倾向 CCA 倾向于满足最小请求而不主动推断更广的目标。“在整个代码库中搜索所有类似模式并统一修改”需要你明确说出来。
5. Instructions 是你最重要的杠杆
每一次你在代码审查中纠正 CCA 的问题,考虑:能否把这条经验写进 .github/copilot-instructions.md?这样同样的错误就不需要教第二次。
6. 关闭的 PR 不等于失败 CCA 用于探索可行性、暴露隐藏复杂度、让设计讨论有具体代码可以反应——这些价值不体现在合并率上。253 个关闭的 CCA PR 中,44% 是因为超过仓库 30 天无活动限制而自动关闭,只有 16% 是因为方向根本错误。
结语
十个月、878 个 PR,一个核心结论:准备比模型更重要。
从没有 Instructions 文件时的 38.1% 到有了之后的 69%,这个提升来自更好的准备,不是更好的 AI。每一个写进指令文件的经验教训,都会在所有后续 PR 上产生复利。
与此同时,.NET 团队核心成员的工作方式已经发生了真实转变:从亲自实现者变成了审查者和引导者。在某些仓库中,CCA 在近期已占据了 Stephen 个人贡献 PR 的 70-95%。总贡献量没有下降,反而上升了——减少的是机械实现的时间,增加的是架构设计、深度审查和真正需要人类判断的工作。