返回
Factory Research、Theo Luan · 2026 年 8 月 27 日 · 阅读时长 10 分钟
研究
分享
当智能体必须达到由它们亲自制定的完成标准时,它们将复杂程序重建到了接近原版的程度。
对于那些成功标准简洁、稳定的问题,模型已经非常擅长。过去一年中,数学和约束优化领域的许多进展都属于这一类——用机器验证悬而未决多年的 Erdős 问题证明 、在国际数学奥林匹克竞赛中达到金牌水平 ,以及为数十年前提出的组合数学问题找到新的界限 。搜索空间可能极其庞大,但最终结果可以作为一个整体来判断。
大型软件任务则不同。软件规格可以在语义上完整描述预期结果,却未必说明在宣布工作完成之前,必须运行什么、检查什么、比较什么。需求定义了哪些条件必须成立,但需求本身并不衡量工作是否真的实现了这些条件。
缺少这种衡量方式时,智能体会在工作过程中零散地自行构建一套。它会拆解任务,在产生各部分的上下文中分别验证它们,最终判断工作已经完成。每个局部判断都可能合情合理,但整体中仍有一些部分从未得到衡量。
目前,人类通过监督智能体来闭合这个循环:始终把握完整结果,并将智能体引导回这个目标。
我们想知道,模型能否自行闭合这个循环。
从零实现 gdal
为了验证这一点,我们在 24 个选自 ProgramBench 的任务和三个模型上,对比了单智能体运行与多角色运行。以 gdal 为例,我们要求 Droid 用两种方式从零重建它。两次运行中,Droid 都可以无限制地执行参考程序,但无法访问其源代码、测试或互联网。
gdal · 参考程序
gdal 是 GDAL 项目的命令行工具,也是地理空间数据处理的主力。它的数十个子命令背后承载着几十年积累的功能。
GDAL 自 1998 年开始开发,是全球大量地图软件——QGIS、ArcGIS、PostGIS——的底层基础,可以读取两百多种栅格和矢量格式,从卫星影像到航海图均涵盖其中。
C/C++ · 上游约 200 万行代码 · 约 60 万行可通过 CLI 触达
在单智能体模式下,Droid 自行实现、检查工作,并自行决定何时完成。它编写了 17,000 行 C++,复现了原程序 36% 的行为。代码质量扎实,常见路径也能正常工作,但程序的大部分功能仍然缺失。它既没有耗尽时间,也没有用完预算;它停下来,只是因为根据自己的判断,工作已经完成。
随后,我们把 Droid 组织成一个由不同角色组成的系统。在开始实现之前,其中一个角色先建立一套可执行的完成标准——由它自行描述重新实现必须具备哪些能力,以及什么证据能够证明这一点——后续实现必须达到这套标准。这次运行最终增长到 115,000 行代码,行为一致性达到 90%。
这次系统运行产出的是它自己的程序 :无论结构还是规模都与原版不同——代码量只是 GDAL 的一小部分,并按自己的方式组织。
这并非孤例。在全部 24 项任务中,同一个系统将 7-Zip 重建版本的一致性从 54% 提升到 95%,将 DuckDB 重建版本从 34% 提升到 80%。还有多个重建版本达到了 90% 以上的高位。
The frontier · best single agent vs best system, per task
single-agent frontiersystem frontier held by fable kimi sol opus
0 25 50 75 100 ffmpeg - single-agent frontier 10.7% - system frontier 40.3% (+29.6) +29.6 ffmpeg gromacs - single-agent frontier 15.1% - system frontier 30.6% (+15.6) +15.6 gromacs ctags - single-agent frontier 28.4% - system frontier 76.4% (+48.0) +48.0 ctags cppcheck - single-agent frontier 30.3% - system frontier 54.2% (+23.9) +23.9 cppcheck duckdb - single-agent frontier 34.2% - system frontier 80.0% (+45.9) +45.9 duckdb doxygen - single-agent frontier 37.5% - system frontier 60.7% (+23.2) +23.2 doxygen pandoc - single-agent frontier 39.5% - system frontier 84.2% (+44.7) +44.7 pandoc lnav - single-agent frontier 43.5% - system frontier 83.9% (+40.4) +40.4 lnav ast-grep - single-agent frontier 58.0% - system frontier 86.8% (+28.7) +28.7 ast-grep gdal - single-agent frontier 58.5% - system frontier 90.3% (+31.8) +31.8 gdal tree-sitter - single-agent frontier 61.9% - system frontier 90.9% (+29.1) +29.1 tree-sitter samtools - single-agent frontier 62.1% - system frontier 96.5% (+34.4) +34.4 samtools typst - single-agent frontier 67.2% - system frontier 78.0% (+10.8) +10.8 typst delta - single-agent frontier 68.0% - system frontier 91.4% (+23.4) +23.4 delta lazygit - single-agent frontier 69.6% - system frontier 93.2% (+23.6) +23.6 lazygit sox - single-agent frontier 70.5% - system frontier 99.5% (+29.0) +29.0 sox bedtools2 - single-agent frontier 75.2% - system frontier 98.2% (+23.0) +23.0 bedtools2 scc - single-agent frontier 78.0% - system frontier 88.4% (+10.3) +10.3 scc 7zip - single-agent frontier 78.2% - system frontier 94.9% (+16.7) +16.7 7zip svgbob - single-agent frontier 83.3% - system frontier 93.4% (+10.2) +10.2 svgbob solar - single-agent frontier 87.0% - system frontier 89.9% (+2.9) +2.9 solar peco - single-agent frontier 92.4% - system frontier 99.6% (+7.2) +7.2 peco stgit - single-agent frontier 93.3% - system frontier 96.9% (+3.6) +3.6 stgit proj - single-agent frontier 97.3% - system frontier 99.4% (+2.1) +2.1 proj ORDERED BY THE SINGLE-AGENT FRONTIER · HARDEST AT TOP One row per task. The ring is the single-agent frontier: the best any single agent has achieved on the task, every public leaderboard entry plus our own singles — every ring is dashed because on these 24 tasks our own singles hold all of them. The dot is the system frontier, colored by the model that holds it, and the number is what closing the loop added.
底层模型没有变化。但在必须达到自己制定的完成标准时,它复现出了远多于此前的程序行为。
为什么同一个智能体会过早停下
编程智能体通常会一边工作,一边验证自己的成果。它们实现一部分功能,编写或运行几项检查,查看输出,再决定是否继续。对于小型改动,这种方式效果很好:任务、实现和证据都能纳入同一个视野。
大型任务则必须拆解为功能、子系统和一轮轮连续推进的工作。当智能体处理每个部分时,也会同时决定什么样的证据算数,以及现有证据是否充分。这些检查会继承产生它们的那部分工作的范围。它们可以验证智能体想到并实现的一切,却会排除那些从未被智能体纳入表示的功能、交互或约束。
因此,智能体可能持续取得局部正确的进展,却在整体结果仍有大量缺失时停下。问题未必是它没有能力实现剩余部分,而是它从未建立过一份完整清单,说明还有什么尚未完成。
在工作开始前定义验证方式
要确立完整结果,仅有一份需求列表还不够。系统需要一份必须验证事项的清单、验证每一项的流程,以及这些流程目前能在待交付产物上通过的证据。
这套标准应当在实现将任务收窄为一个个工作项之前,从需求及相关事实来源中推导出来。它不必永远固定不变;系统可以在学习过程中增加、替换或完善检查。但完成标准不能悄然收缩成恰好包住现有实现的形状。
为什么人类很少这样做
将需求与证据分离并非新概念。安全关键项目会使用需求可追溯性以及独立的验证与确认;标准组织会发布多种实现都必须通过的一致性测试套件;产品团队也会编写验收测试。
真正少见的是为每个项目推导并维护一套全面的标准。一致性测试套件可以将成本分摊到多种实现上;而对于每一个应用、重写项目或迁移任务,产品团队都要重新承担这笔成本。因此,大多数团队会采用增量验证,并依靠代码审查、产品反馈和参与者的持续投入来维持对整体的把握。
智能体改变了这项权衡的两端。它们产出工作的速度可能超过人类检查的速度,使非正式监督成为瓶颈;但同样的能力也可以用于标准本身:盘点预期结果、构建检查,并在产物变化时反复运行。
ProgramBench 代表了一个要求极高的极限场景:参考程序虽然可用,但模型必须同时探索行为空间,并找出衡量它的方法。
ProgramBench
ProgramBench 是一个采用洁净室方法的软件工程基准。每项任务都提供一个参考程序、固定测试数据和部分文档。参考程序是一个黑盒 oracle:可以运行,但绝不允许读取、反编译或跟踪。
目标是从零开始复现参考程序可观察到的行为。每项任务都由一套隐藏的行为检查进行评估和评分。
衡量黑盒实现的完整性并不容易。任何单一行为都很容易验证,只要分别运行参考程序和候选程序即可;但整体却无法如此验证。随任务提供的文档只覆盖接口的一部分,程序其余行为必须自行探索。
于是便有三个问题:
前沿模型能否为一个大型、未知的程序构建自己的完整性衡量方式?
这种衡量方式能否在漫长的实现过程中持续发挥作用?
让实现对这套衡量方式负责,是否会产出更好的成果?
任务选择
我们根据当前排行榜的最高得分,选取了基准中最难的 24 项任务。
Task selection · all 200 tasks by best public score
selected the other 176
0 25 50 75 100 ← HARDER EASIER → ffmpeg - best public: 8.1% gromacs - best public: 10.4% pandoc - best public: 14.7% php-src - best public: 17.8% ctags - best public: 19.0% cppcheck - best public: 19.3% lnav - best public: 21.6% pueue - best public: 21.3% duckdb - best public: 22.9% ast-grep - best public: 32.7% proj - best public: 34.4% doxygen - best public: 34.5% gdal - best public: 39.0% samtools - best public: 39.0% ditaa - best public: 38.4% miller - best public: 38.9% chroma - best public: 41.7% typst - best public: 44.7% tree-sitter - best public: 46.5% scc - best public: 47.6% delta - best public: 47.7% quickjs - best public: 46.8% solar - best public: 48.1% stgit - best public: 48.7% bedtools2 - best public: 48.9% revive - best public: 48.3% yq - best public: 49.9% sox - best public: 51.6% svgbob - best public: 54.9% 7zip - best public: 56.6% go-critic - best public: 56.8% jsonschema - best public: 57.1% chafa - best public: 58.4% zk - best public: 59.7% crowbook - best public: 60.3% rumdl - best public: 61.2% xh - best public: 61.5% lazygit - best public: 63.4% argc - best public: 62.0% lightningcss - best public: 63.1% oranda - best public: 66.1% treemd - best public: 66.7% broot - best public: 67.1% marmite - best public: 68.6% bat - best public: 70.2% zstd - best public: 70.8% sqlite - best public: 71.6% tui-journal - best public: 72.3% tinycc - best public: 72.4% atlas - best public: 72.5% serpl - best public: 72.9% masscan - best public: 73.2% dropbear - best public: 74.4% genact - best public: 74.9% age - best public: 76.0% fselect - best public: 76.4% mdbook - best public: 76.5% hyperfine - best public: 77.0% angle-grinder - best public: 77.7% dep-tree - best public: 77.8% cheat - best public: 78.1% flamelens - best public: 78.5% calcurse - best public: 78.7% git-trim - best public: 79.0% skeema - best public: 79.7% caps-log - best public: 79.7% fx - best public: 79.9% gdu - best public: 80.0% dsq - best public: 80.3% direnv - best public: 80.9% datasurgeon - best public: 80.9% gittype - best public: 81.1% seqtk - best public: 81.4% dirble - best public: 81.5% xplr - best public: 81.6% svd2rust - best public: 81.6% parqeye - best public: 81.6% rhit - best public: 81.8% luajit - best public: 82.4% dstask - best public: 82.5% bat-go - best public: 82.7% srgn - best public: 83.0% gotests - best public: 83.3% dust - best public: 83.4% nsh - best public: 83.9% ripgrep - best public: 84.0% gomplate - best public: 84.1% trdsql - best public: 84.1% oha - best public: 84.6% xz - best public: 84.7% fzf - best public: 84.9% monolith - best public: 85.0% rust-sloth - best public: 85.0% onefetch - best public: 85.1% lua - best public: 85.1% ascii-image-converter - best public: 85.4% tig - best public: 85.5% pipr - best public: 86.6% pls - best public: 86.7% tokei - best public: 86.9% yj - best public: 87.1% xq - best public: 87.6% figlet - best public: 87.8% peco - best public: 89.6% lz4 - best public: 88.0% chamber - best public: 88.0% quinn - best public: 88.1% jp2a - best public: 88.1% run - best public: 88.2% codesnap - best public: 88.6% hwatch - best public: 88.7% the_silver_searcher - best public: 88.8% ov - best public: 89.4% amber - best public: 89.4% goimports-reviser - best public: 89.7% statix - best public: 89.8% jq - best public: 90.1% zoxide - best public: 90.2% pixterm - best public: 90.2% felix - best public: 90.2% hush - best public: 90.3% ninja - best public: 90.5% melody - best public: 90.5% tparse - best public: 90.8% tex-fmt - best public: 90.8% tailspin - best public: 91.5% diffr - best public: 91.7% hashcards - best public: 92.6% dupl - best public: 92.8% curlie - best public: 92.9% igrep - best public: 92.9% rustowl - best public: 93.0% hostctl - best public: 93.0% duc - best public: 93.0% i3-style - best public: 93.3% ripsecrets - best public: 93.5% json-tui - best public: 93.5% richgo - best public: 93.6% fd - best public: 93.9% xsv - best public: 94.1% gron - best public: 94.2% miniserve - best public: 94.2% handlr - best public: 94.2% pier - best public: 94.2% ethabi - best public: 94.5% walk - best public: 94.6% pastel - best public: 94.7% jplot - best public: 94.7% keifu - best public: 94.7% pigz - best public: 94.9% gowsdl - best public: 94.9% gping - best public: 95.0% errcheck - best public: 95.0% brotli - best public: 95.5% entr - best public: 95.6% git-graph - best public: 95.6% halite - best public: 95.6% hexyl - best public: 95.9% parallel-disk-usage - best public: 95.9% bartib - best public: 96.0% fblog - best public: 96.0% html-to-markdown - best public: 96.2% caesium-clt - best public: 96.2% tty-clock - best public: 96.4% fasttext - best public: 96.5% muffet - best public: 96.6% thokr - best public: 96.6% shellharden - best public: 96.7% rnr - best public: 96.7% kiro-editor - best public: 96.8% deadnix - best public: 96.8% hck - best public: 97.2% sd - best public: 97.4% dutree - best public: 97.5% nomino - best public: 97.8% dog - best public: 97.9% htmlq - best public: 98.0% grex - best public: 98.1% blake3 - best public: 98.1% xcp - best public: 98.1% elfcat - best public: 98.2% tuc - best public: 98.2% nnn - best public: 98.3% dua-cli - best public: 98.3% eureka - best public: 98.5% eva - best public: 98.7% jot - best public: 98.7% pingu - best public: 98.9% loop - best public: 98.9% go-mod-outdated - best public: 98.9% clog-cli - best public: 99.1% htop - best public: 99.4% code-minimap - best public: 99.4% bore - best public: 99.5% csview - best public: 99.7% ngrrram - best public: 99.7% wrapcheck - best public: 99.8% zip-password-finder - best public: 99.9% cmatrix - best public: 100.0% hex - best public: 100.0% median 41.9 · selected median 89.1 · the other 176 OFFICIAL METRIC · 0–100 Every dot is one of ProgramBench’s 200 tasks, placed at the best score any public leaderboard entry has achieved on it. The ink dots are the 24 selected tasks; hover any dot for its name.
这组任务由人工挑选,重点偏向当前最佳公开得分较低的项目。一些同属高难度的候选项(php-src、pueue、ditaa、quickjs、chroma、miller)在筛选过程中被移除,原因包括持续触发安全拦截、单智能体得分已经饱和,或分数取决于某个未记录的环境变量。
实验设计
对于每个入选任务和模型组,我们分别在两种条件下各运行一次实验。系统条件在不取代实现者日常开发循环的前提下,增加了一套独立的完成度衡量机制。
单智能体实验
系统实验
实现循环
智能体负责调查、实现、运行检查并判断自己的工作
实现者负责调查、实现、运行检查并判断自己的工作
完成标准
在构建候选程序的同一上下文中逐步形成
验证者在实现开始前构建一套独立的测量工具
独立测量
实验期间没有独立测量
验证者使用自己的测量工具评估连续迭代的候选程序
信息流
智能体可以看到所有检查及其结果
测量工具和原始结果由验证者保管;只有归类整理后的发现可以越过隔离墙
实验控制
智能体自行选择下一步行动以及何时停止
编排者裁定各项发现、下达指令,并决定何时交付
两种条件都从相同的任务脚手架和固定测试数据开始。在每个未使用替代模型的模型组中,单智能体和系统内三个角色都使用相同模型及相同推理级别。两种条件都可以无限制地执行参考程序,但都不能读取、反编译或跟踪它,不能查看基准测试,也不能访问互联网。Fable 因安全机制受阻后,有六个明确披露的 Fable 实验单元改用了 Opus。
实验一旦启动,全程不再有人类干预。两种实验并未匹配计算量;每次运行都会继续,直到单智能体或系统编排者决定交付。
每个单元格代表一次实验,而非多次重复运行的平均值。实验结束后,其最终候选程序会使用官方 pb-1.2.0 指标评分一次。
系统如何闭合循环
测量工具
完整的行为一致性无法直接衡量。程序可以接受近乎无穷无尽的输入、标志、文件格式、组合和错误条件。任何实际可行的验证策略,都必须对这个空间进行采样。
在我们的系统中,这份样本就是测量工具。实现开始前,验证者会考察参考程序,绘制其行为分布。随后,它会构建一组带权重的测试用例,以及判断候选程序输出所需的比较规则。我们只要求它给出测量工具的大致框架,其中的一切——哪些行为重要、如何赋予权重、什么算作证据——均由验证者决定。
以下是验证者为 gdal 构建的测量工具中的两个用例:
D('hillshade.combined', ['raster', 'hillshade', '--variant', 'combined', 'dem.tif', 'out.tif']),
D('contour.levels', ['raster', 'contour', '--levels', '120,150,180', 'dem.tif', 'out.geojson']),
每个用例描述一次调用,评分策略则说明如何判断结果:
Primary comparator: for every case, the runner executes oracle and candidate sequentially in the same absolute sandbox path (wiped between runs), same env, same fixture bytes and mtimes, and byte-compares four channels:
1. exit code
2. stdout bytes
3. stderr bytes
4. full work-tree delta: the set of files created/modified/deleted by the run, and the exact bytes of each (includes sidecars: .aux.xml, .ovr, .msk, shapefile companions, tile trees).
Byte identity is the default on every channel. A relaxation exists only as a named normalizer attached to specific cases, each carrying a license below.
验证者编写了数百个这样的用例,并在所有用例中只批准了两项宽松处理:一项用于屏蔽调试跟踪中的堆地址,另一项用于忽略文件头内嵌的日期;两者都附有证据,证明参考程序无法在这些位置产生稳定一致的字节。
外层循环
系统由三个角色构成:编排者、实现者和验证者。编排者同时向实现候选程序的实现者,以及使用测量工具评估候选程序的验证者分派任务。
验证者首先构建测量工具。实现开始后,循环如下:
编排者选择应当测量什么。
验证者测试当前候选程序并解释失败原因。
编排者判断哪些发现确有其事,以及下一步应开展什么工作。
实现者独立调查参考程序,并推进候选程序。
当测量工具不再能揭示连续版本候选程序之间有意义的差异时,编排者可以要求验证者扩展薄弱区域,或开始针对参考程序进行定向差分测试。
The system · three roles and the wall
THE WALL REFERENCE PROGRAM runnable, never readable both roles hold it and may query it without limit IMPLEMENTER writes the candidate never sees the instrument ORCHESTRATOR adjudicates each measurement decides what happens next VALIDATOR surveys the reference, measures the candidate clusters what fails THE INSTRUMENT a weighted sample of the reference cases, plus the rules for a match authored, held and run here directive candidate candidate measurement the last candidate ships HIDDEN SUITE · graded once, after the run samples the same behavior space Both roles are the same model at the same reasoning level, and both hold the reference program, so keeping the instrument on the measuring side costs no information — only a shortcut. The candidate and the findings cross the wall; the instrument does not. Grading happens once, outside the loop, and is the source of every score in this post.
隔离墙
在 ProgramBench 中,由于这些用例只是庞大行为空间中的一份样本,完成标准还需要一道额外边界。
这道边界在两个方向上都有效。验证者可以随着对参考程序了解的加深而扩展测量工具,但不能为了迁就候选程序碰巧已经实现的内容而削弱或修改它。实现者则永远不能编写或运行这套工具,也看不到其中的用例或原始输出:一旦稀疏样本变得可见,它就会成为优化目标;通过样本只能证明这些用例成立,而无法证明它们原本代表的整个空间都已覆盖。
验证者使用测量工具检查当前候选程序,并按根本原因对失败进行分组。编排者审查这些发现,排除噪声或无效测量,再将剩余问题转化为描述缺失功能、子系统或行为的指令。实现者收到指令后,会独立调查参考程序,并自行决定如何修改候选程序。
以下是 gdal 运行中一段指令的节选:
## 1. Stub frontier (dominant mass, ~60 verbs)
Ordered by measured weight (approximate case mass in brackets). Probe each against the oracle first, as always.
- vgrid: all 11 grid methods [14]
- mdim group on multidim VRT + classic-input pins [12]
- sozip: create / list / validate / optimize [11]
- DEM suite [~30]: contour [7], hillshade incl. variants [6], aspect [6], slope [4], viewshed [4], roughness, tpi, tri [1-3 each]
- rasterize [7], pixel-info [7], calc [7], mosaic [6] + stack, tile [5], footprint [5]
这份指令告诉实现者候选程序的薄弱之处,却不会泄露具体样本。
结果
我们使用三个前沿模型运行了实验:Fable 5、Kimi K3 和 GPT 5.6 Sol。
这里的每个分数都来自基准的隐藏测试套件——它是对同一行为空间的一份采样,而所有角色都从未见过。系统根据自己构建的测量工具取得的提升,同样迁移到了这套独立衡量机制上。
Results · single agent → system, one panel per model
Fable 5xhigh opus fallback median 56.7 → 89.3 gap closed 73% on the clock 8.5h → 96h
0 25 50 75 100 SINGLE AGENT one campaign run SYSTEM one campaign run peco single: official 92.4% (1123/1215) · raw 85.4% → peco system: official 99.6% (1210/1215) · raw 92.2% peco 92→ 100 sox single: official 70.5% (843/1196) · raw 69.3% — Opus substitute (fable safety-killed / compile-failed) → sox system: official 99.5% (1190/1196) · raw 97.0% — Opus substitute (fable safety-killed / compile-failed) sox (opus) 70→ 100 proj single: official 97.3% (5176/5319) · raw 72.4% → proj system: official 99.4% (5288/5319) · raw 74.0% proj 97→ 99 bedtools2 single: official 74.2% (781/1053) · raw 72.9% — Opus substitute (fable safety-killed / compile-failed) → bedtools2 system: official 98.2% (1034/1053) · raw 96.3% — Opus substitute (fable safety-killed / compile-failed) bedtools2 (opus) 74→ 98 stgit single: official 93.3% (1388/1488) · raw 89.7% → stgit system: official 96.9% (1442/1488) · raw 92.1% stgit 93→ 97 samtools single: official 62.1% (885/1425) · raw 53.7% — Opus substitute (fable safety-killed / compile-failed) → samtools system: official 96.5% (1375/1425) · raw 95.0% — Opus substitute (fable safety-killed / compile-failed) samtools (opus) 62→ 96 7zip single: official 54.4% (567/1043) · raw 53.5% → 7zip system: official 94.9% (990/1043) · raw 92.8% 7zip 54→ 95 svgbob single: official 83.3% (393/472) · raw 83.1% → svgbob system: official 93.4% (441/472) · raw 93.5% svgbob 83→ 93 lazygit single: official 46.4% (397/855) · raw 51.8% → lazygit system: official 93.2% (797/855) · raw 89.9% lazygit 46→ 93 delta single: official 68.0% (645/949) · raw 69.7% → delta system: official 91.4% (867/949) · raw 89.2% delta 68→ 91 tree-sitter single: official 55.4% (682/1232) · raw 63.8% — Opus substitute (fable safety-killed / compile-failed) → tree-sitter system: official 90.9% (1120/1232) · raw 90.7% — Opus substitute (fable safety-killed / compile-failed) tree-sitter (opus) 55→ 91 gdal single: official 35.8% (235/657) · raw 43.5% → gdal system: official 90.3% (593/657) · raw 89.8% gdal 36→ 90 scc single: official 72.6% (337/464) · raw 71.4% → scc system: official 88.4% (410/464) · raw 86.8% scc 73→ 88 ast-grep single: official 58.0% (509/877) · raw 57.8% → ast-grep system: official 86.8% (761/877) · raw 86.6% ast-grep 58→ 87 solar single: official 71.9% (1422/1978) · raw 76.6% → solar system: official 85.7% (1695/1978) · raw 88.1% solar 72→ 86 pandoc single: official 19.0% (991/5214) · raw 19.0% — Opus substitute (fable safety-killed / compile-failed) → pandoc system: official 84.2% (4389/5214) · raw 82.3% — Opus substitute (fable safety-killed / compile-failed) pandoc (opus) 19→ 84 lnav single: official 38.2% (378/989) · raw 34.2% → lnav system: official 83.9% (830/989) · raw 74.4% lnav 38→ 84 duckdb single: official 34.2% (1931/5649) · raw 23.0% → duckdb system: official 80.0% (4522/5649) · raw 55.6% duckdb 34→ 80 typst single: official 67.2% (1158/1724) · raw 67.4% → typst system: official 78.0% (1344/1724) · raw 77.5% typst 67→ 78 ctags single: official 14.3% (322/2258) · raw 17.7% → ctags system: official 76.4% (1726/2258) · raw 76.8% ctags 14→ 76 doxygen single: official 37.5% (86/229) · raw 41.0% → doxygen system: official 60.7% (139/229) · raw 62.1% doxygen 38→ 61 cppcheck single: official 30.3% (644/2126) · raw 30.6% → cppcheck system: official 54.2% (1152/2126) · raw 50.7% cppcheck 30→ 54 ffmpeg single: official 9.0% (273/3041) · raw 9.0% → ffmpeg system: official 40.3% (1225/3041) · raw 31.9% ffmpeg 9→ 40 gromacs single: official 13.9% (172/1234) · raw 13.1% — Opus substitute (fable safety-killed / compile-failed) → gromacs system: official 30.3% (374/1234) · raw 30.5% — Opus substitute (fable safety-killed / compile-failed) gromacs (opus) 14→ 30 Kimi K3high median 45.1 → 75.4 gap closed 42% on the clock 9.0h → 64h
0 25 50 75 100 SINGLE AGENT one campaign run SYSTEM one campaign run peco single: official 78.5% (954/1215) · raw 77.1% → peco system: official 98.3% (1195/1215) · raw 91.4% peco 79→ 98 bedtools2 single: official 75.2% (792/1053) · raw 73.2% → bedtools2 system: official 94.0% (990/1053) · raw 92.4% bedtools2 75→ 94 solar single: official 87.0% (1721/1978) · raw 88.5% → solar system: official 89.9% (1779/1978) · raw 91.3% solar 87→ 90 proj single: official 44.4% (2363/5319) · raw 33.1% → proj system: official 88.1% (4684/5319) · raw 65.5% proj 44→ 88 stgit single: official 37.0% (551/1488) · raw 33.9% → stgit system: official 87.7% (1305/1488) · raw 85.5% stgit 37→ 88 scc single: official 78.0% (362/464) · raw 76.5% → scc system: official 87.3% (405/464) · raw 85.5% scc 78→ 87 svgbob single: official 69.7% (329/472) · raw 69.6% → svgbob system: official 82.0% (387/472) · raw 81.9% svgbob 70→ 82 7zip single: official 76.3% (796/1043) · raw 75.0% → 7zip system: official 80.9% (844/1043) · raw 79.3% 7zip 76→ 81 typst single: official 66.5% (1147/1724) · raw 66.6% → typst system: official 77.5% (1336/1724) · raw 77.3% typst 67→ 77 sox single: official 51.8% (619/1196) · raw 51.4% → sox system: official 76.3% (913/1196) · raw 74.8% sox 52→ 76 lazygit single: official 43.2% (369/855) · raw 48.4% → lazygit system: official 74.4% (636/855) · raw 75.9% lazygit 43→ 74 tree-sitter single: official 45.7% (563/1232) · raw 56.3% → tree-sitter system: official 73.5% (906/1232) · raw 77.8% tree-sitter 46→ 74 gdal single: official 56.8% (373/657) · raw 65.5% → gdal system: official 71.5% (470/657) · raw 75.2% gdal 57→ 72 pandoc single: official 31.6% (1645/5214) · raw 31.1% → pandoc system: official 70.5% (3674/5214) · raw 68.8% pandoc 32→ 70 lnav single: official 18.2% (180/989) · raw 17.1% → lnav system: official 66.2% (655/989) · raw 57.8% lnav 18→ 66 ctags single: official 28.2% (636/2258) · raw 34.1% → ctags system: official 58.4% (1318/2258) · raw 60.8% ctags 28→ 58 duckdb single: official 31.1% (1756/5649) · raw 22.1% → duckdb system: official 41.2% (2328/5649) · raw 29.5% duckdb 31→ 41 doxygen single: official 35.4% (81/229) · raw 39.0% → doxygen system: official 36.7% (84/229) · raw 40.2% doxygen 35→ 37 gromacs single: official 15.1% (186/1234) · raw 14.1% → gromacs system: official 30.6% (378/1234) · raw 28.1% gromacs 15→ 31 ffmpeg single: official 8.7% (264/3041) · raw 8.3% → ffmpeg system: official 13.0% (395/3041) · raw 11.6% ffmpeg 9→ 13 eval timeout: cppcheck single: official 11.9% (253/2126) · raw 11.4% — evaluation timed out; score is a floor — graded 269/2126, 253 passed cppcheck system: official 4.1% (88/2126) · raw 5.8% eval timeout: ast-grep system: official 0.0% (0/877) · raw 0.0% — evaluation hung twice; 0 of 877 graded — no bound; delta system: official 13.1% (124/949) · raw 24.8% — evaluation timed out; score is a floor — graded 128/949, 124 passed ast-grep single: official 56.6% (496/877) · raw 56.6% delta single: official 50.0% (475/949) · raw 55.8% ast-grep 57 → eval timeout cppcheck eval timeout → 4 delta 50 → eval timeout GPT-5.6-solmax median 48.6 → 66.2 gap closed 25% on the clock 1.5h → 24h
0 25 50 75 100 SINGLE AGENT one campaign run SYSTEM one campaign run peco single: official 77.0% (935/1215) · raw 74.4% → peco system: official 95.5% (1160/1215) · raw 89.3% peco 77→ 95 7zip single: official 78.2% (816/1043) · raw 76.9% → 7zip system: official 93.6% (976/1043) · raw 91.6% 7zip 78→ 94 proj single: official 26.6% (1413/5319) · raw 19.9% → proj system: official 89.8% (4778/5319) · raw 66.9% proj 27→ 90 stgit single: official 77.5% (1154/1488) · raw 78.8% → stgit system: official 84.3% (1255/1488) · raw 86.0% stgit 78→ 84 bedtools2 single: official 75.2% (792/1053) · raw 73.7% → bedtools2 system: official 83.2% (876/1053) · raw 81.8% bedtools2 75→ 83 svgbob single: official 71.8% (339/472) · raw 71.7% → svgbob system: official 78.0% (368/472) · raw 78.1% svgbob 72→ 78 samtools single: official 43.7% (623/1425) · raw 38.8% → samtools system: official 74.2% (1057/1425) · raw 72.2% samtools 44→ 74 solar single: official 49.5% (979/1978) · raw 58.6% → solar system: official 74.0% (1463/1978) · raw 78.0% solar 49→ 74 lazygit single: official 69.6% (595/855) · raw 72.5% → lazygit system: official 72.3% (618/855) · raw 74.6% lazygit 70→ 72 scc single: official 66.6% (309/464) · raw 65.3% → scc system: official 71.5% (332/464) · raw 70.2% scc 67→ 72 sox single: official 48.6% (581/1196) · raw 48.1% → sox system: official 66.2% (792/1196) · raw 65.2% sox 49→ 66 ast-grep single: official 34.0% (298/877) · raw 34.4% → ast-grep system: official 64.2% (563/877) · raw 64.3% ast-grep 34→ 64 typst single: official 54.8% (945/1724) · raw 55.3% → typst system: official 62.1% (1071/1724) · raw 62.4% typst 55→ 62 pandoc single: official 39.5% (2060/5214) · raw 38.9% → pandoc system: official 59.0% (3074/5214) · raw 57.7% pandoc 40→ 59 tree-sitter single: official 61.9% (762/1232) · raw 68.0% → tree-sitter system: official 56.7% (699/1232) · raw 64.6% tree-sitter 62→ 57 ctags single: official 28.4% (642/2258) · raw 34.5% → ctags system: official 46.2% (1043/2258) · raw 50.1% ctags 28→ 46 doxygen single: official 37.5% (86/229) · raw 41.0% → doxygen system: official 38.9% (89/229) · raw 42.2% doxygen 38→ 39 duckdb single: official 29.7% (1678/5649) · raw 21.7% → duckdb system: official 29.4% (1662/5649) · raw 21.2% duckdb 30→ 29 lnav single: official 43.5% (430/989) · raw 38.6% → lnav system: official 20.6% (204/989) · raw 18.4% lnav 43→ 21 ffmpeg single: official 10.7% (325/3041) · raw 9.9% → ffmpeg system: official 17.1% (521/3041) · raw 27.6% ffmpeg 11→ 17 cppcheck single: official 4.8% (103/2126) · raw 6.9% → cppcheck system: official 6.8% (144/2126) · raw 8.6% cppcheck 5→ 7 eval timeout: delta single: official 13.2% (125/949) · raw 24.9% — evaluation timed out; score is a floor — graded 128/949, 125 passed eval timeout: delta system: official 13.3% (126/949) · raw 35.1% — evaluation timed out; score is a floor — graded 128/949, 126 passed delta eval timeout → eval timeout
每个面板对应一个模型,在相同的 24 项任务上运行两次:左侧为单智能体,右侧为完整系统。每条线代表一项任务,并落在基准隐藏测试套件给出的官方分数位置。得分下降的线以虚线绘制。少数实验单元完全没有分数,因为测试在评估过程中卡死,导致评分未能完成;它们被放在面板底部。左侧导轨按任务难度筛选任务,即每项任务的最佳公开分数,使用相同的 0–100 分制。
系统运行耗时更长、成本也高得多;以 gdal 为例,消耗的 credits 是 14 倍,实际耗时是 13 倍。但两种条件之间真正的区别并不是预算。每一次单智能体实验,都是因为智能体自行决定结束而终止。对于根本不会继续使用算力的智能体,增加计算资源毫无帮助。我们的方法改变的是对“何时完成”的判断,计算量的增加只是随之而来的结果。
每项任务、每个模型
每项任务、每个模型、每份运行记录:选择器可以按任一模型的系统得分排序;点击分数单元格可打开对应模型的页面及该次运行的时间线;点击任务名称可打开三个模型的对比;方向键则可在网格中移动。
方法说明
推理级别。 Fable 使用 xhigh,Kimi 使用 high,Sol 使用 max;同一模型的单智能体和系统内三个角色都统一采用该级别。
每个单元格只运行一次。 这里的每个数字都来自单次运行,没有通过重复实验取平均值,因此任何单元格都没有方差估计,这些数值也都不应被理解为均值。
正文重点数据。 开头部分的 gdal、7-Zip 和 DuckDB 数字均来自 Fable 5 的运行。
规模。 GDAL 上游约有 200 万行 C/C++ 代码(排除捆绑的第三方库后为 190 万行)。按任务配置,可通过 gdal CLI 触达的子集——11 个驱动程序,不含 GEOS——约为 60 万行。重建版本以 11.5 万行代码复现了这部分范围内 90% 的被测行为。
Opus 替代运行。 Fable 面板中有六个单元格使用 Opus,替代了因安全机制受阻而无法运行的 Fable;替代可能发生在单智能体或系统一侧,涉及 bedtools2、gromacs、pandoc、samtools、sox 和 tree-sitter。
覆盖范围。 144 个单元格中已有 141 个完成评分。剩余三个系统运行——Sol 上的 gdal 和 gromacs,以及 Kimi 上的 samtools——在发布前被中断且未重新运行,因此没有分数。
评分。 每个分数均采用隐藏测试套件的官方指标,固定使用 pb-1.2.0 版本,并以完全相同的方式计算单智能体和系统产物的得分。
结论
单智能体缺少的不是能力,而是完成标准。由同一个模型编写的一套独立标准,推动实现与参考程序在行为上达到远高于此前的一致性。
ProgramBench 让这套标准呈现出一种特定形态:从黑盒参考程序中恢复出来的一份行为清单及加权样本。
其他任务会从不同来源推导标准。产品任务可以依据用户认可的流程和设计;迁移任务则可以依据将被替换的系统。
真正能够推广到现实软件工作中的,是对一套外部、可执行完成标准的需要:它应当从预期结果中推导,在实现收窄注意力之前建立,并持续保持更新,直到工作真正达到标准。
我们正将这种结构融入下一代 Missions。
如需加入候补名单,请联系 Factory ,或联系你的 Factory 客户团队。