测试一直全绿,仓库却没人敢碰:编码智能体的验收不测“结构健康”
你的 CI 天天全绿,编码智能体提交的补丁全部通过测试,可仓库却越来越没人敢碰。这不是模型不会重构,而是任务描述和验收机制只奖励眼前的行为正确,没有把架构意图变成可验证的目标。这篇专题用四条递进的证据链讲清“局部成功如何系统性制造全局债”,并在结尾给出重新定义“完成”的具体方向。
1. 测试全过,就等于完成任务吗:验收面只看得到当前行为
资深开发者都认得一个身体经验:调试时在一堆分支里把自己搞丢的那一刻,会本能地说“该重构了”。开发者 Rodrigo Rosenfeld Rosas 把这段反射精确地写成“I'm lost, therefore it's time to refactor”,并称它一直是让长寿系统保持可维护的重要力量之一,因为它由人类局限触发:人一旦无法再跟上代码,信号就响了。但编码智能体没有工作记忆的瓶颈,它读得懂乱麻、追得上每个 caller,在没人完全理解的代码里也能自信地继续加分支。它从不迷路,于是这个信号再也不响。Rosas 的原句是“the agent never gets lost, so the signal never fires”。乱麻对 agent 本人不是问题,因为它的“完成”由验收判据定义,而你给的验收判据里没有“这代码变难懂了”这一项。RefactorReflex
更隐蔽的后果是连带发生的:自然检查点消失,人不再注意到代码漂移出自己的理解范围,团队恰恰因为不再理解代码而越来越信任 agent,这跟信任该有的方向正好相反。
现象背后是机制。1975 年英国经济学家 Charles Goodhart 在一篇货币政策文章里写下:Any observed statistical regularity will tend to collapse once pressure is placed upon it for control purposes. 任何被观察到的统计规律,一旦被施加控制压力就会趋于坍塌。流行转述“当指标成为目标,它就不再是好指标”是其 1997 年的版本,原句更准确:规律不是消失了,是被优化压力压垮了。翻译到工程语境:功能测试通过本来是“代码没问题”的经验规律,可一旦“测试通过”成为验收的唯一标准,成为被优化的指标,智能体就会在这个系统内优化自己的行为。绕过抽象、打最小补丁、把新逻辑硬塞进现有结构,是最大化测试通过率的最小代价路径,原来“代码保持可维护”的规律就是这么坍塌的。Goodhart
这不是假设,现行行业范式就是这么定义的。Princeton 团队 2023 年的 SWE-bench 把“真实 GitHub issue + 隐藏测试”立为编码智能体的标准任务形态:一个 issue 对应一个待解问题,模型拿到问题陈述和代码库,生成补丁,补丁被应用到仓库并运行隐藏测试,必须让失败的测试全部转绿才算 resolve,判定与参考解法无关,只看行为是否正确。发布时最强的 Claude 2 也只解决了不到 2% 的 issue,但真正重要的是它定义了什么叫做“完成”:测试全过,即完成。SWE-bench
把这条回路画出来,缺的那一块一眼可见:

图注:任务到验收的单向回路。智能体拿到请求生成补丁,补丁过功能测试,全过即通过验收,而“通过验收”又成为下一次生成时被优化的指标。回路里只有行为,没有结构;右上角注记是 Goodhart 1975 原句的缩写。Goodhart
所以“测试通过等于完成”是当前全行业默认的验收定义,而它观测的只有当前行为。复用、依赖方向、职责边界,全都不在验收面里。当行为正确成为最优策略时,绕过抽象不是偷懒,是理性。那么问题来了:智能体是不是因为给的上下文太少、看不懂需求,才只能打这种补丁?
2. 缺的不是上下文,是架构意图:真实请求里到底写了什么
成均馆大学的 RealSWE 团队把“需求里有什么”变成了可复现的测量。他们收集 718 条真实用户请求(来自公开交互数据集 SWE-chat),与 SWE-bench Verified/Pro 的 1229 条问题陈述对照,定义六类信息字段(问题陈述、期望行为、复现步骤、环境信息、动机、补充)和四维语言风格。结论令人不安:真实请求里有 88% 只包含问题陈述或问题陈述加少量补充,基准里这个比例只有 7%;真实请求 87% 是口语化的,基准 94% 是正式书面语;真实请求平均每条只含 1.4 个信息字段,基准是 2.9,64.2% 的真实请求干脆只有一个问题陈述字段。RealSWE
先看这张分布图,它是“基准与现实鸿沟”的第一眼证据:

图注:双面板分布图。(a) 是信息构成:真实请求(SWE-chat)集中在贫信息集合上,SWE-bench Verified 与 Pro 则信息密集;(b) 是语言风格四维对比:真实请求口语化、祈使语气为主,基准几乎全是正式陈述。两侧分布几乎不重叠。RealSWE
更关键的是哪些字段缺席。只有约 5% 的真实请求写明“期望行为”或“动机”(合并口径;字段级数据是期望行为出现率 5.4%、基准 73.5%,动机 8.9%、基准 96.1%)。这不是信息量问题,是需求意图问题:这两类字段要的正是“系统该表现出什么行为、用户为什么想要它”,是需求里最像设计意图的部分,而真实请求里它们几乎不出现。受控消融证明它们才是真正有价值的:缺陷修复任务里去掉“期望行为”字段,解决率平均下降 8 个百分点,是去掉环境、复现步骤等字段(平均只波动 1.8 个百分点)的四倍以上;功能请求里去掉“动机”字段,平均下降 3.4 个百分点,损失最大的模型降 7.1 个百分点(引言口径写作“最多提升 7 个百分点”)。换句话说,给 agent 再多的环境细节和复现步骤,不如告诉它“你希望这个系统最终长什么样”。RealSWE 的结论到此为止:它的分类法只涵盖六类信息字段和四维语言风格,并没有直接测量复用、依赖方向这类结构性属性,那是需要另找基准验证的更高层推断。RealSWE
缺口在请求内容而非任务难度,这一点 RealSWE 用 381 个任务族做了受控证明。每个任务族里的变体共享底层任务和 gold patch,只改信息构成与语言风格。把按真实分布重写的输入交给 7 个模型,平均解决率下降 6.4 个百分点,还改变了排名:MiMo V2.5 Pro 从第 4 升到第 2。同一个任务,换一种“真实的说法”,难度就变了;真实化后前四名模型的分差从 1.7 个百分点扩到 3.3 个百分点,排行榜排序都失真了。RealSWE 也自认评测是单轮的,迭代澄清能否缓解贫信息没有被测量,但当前的主流工作流恰恰大多是“一次描述,一次执行”。RealSWE
下面这张流水线图说明了这种受控性如何达成:

图注:RealSWE 的基准构造流水线。先定义信息分类法与语言维度,再应用到真实请求与基准、量化差距,然后基于测量结果把基准问题改写成多变量任务族,最后人工校验。双产出是固定配置的 RealSWE-bench 与可配置的 RealSWE-framework。RealSWE
所以从 RealSWE 能直接读出的结论,是真实请求常缺期望行为与动机这类需求意图。架构意图,也就是对“代码应该长成什么样”的设计期望:这段逻辑该复用哪个已有模块、依赖该朝哪个方向、哪部分职责归谁,是比这更高一层的缺口。连行为期望和动机都拿不到,agent 更无从推断长期的复用与依赖方向。但这一层目前还是推断,RealSWE 的分类法没有直接测过复用与依赖方向,它是否真的缺失、代价有多大,尚待专门检验结构的基准来回答。CODETASTE 里的 Open 轨可以看作这种缺口的极端形态,任务描述只有 38 个字符的笼统目标。它到底有多贵,正是下一章要量给我们的。
3. 结构能不能成为可验证目标:两台“预言机”的证据
先给“预言机”一个白话定义:评测里负责判定对错的裁判。功能预言机是跑测试的那位,结构预言机则是检查“这次改动有没有让仓库更难维护”的那位。UCR 的 NITR 基准给出了机制定义:21 个 C++ 探针(每个是一个小型多文件仓库场景加给 agent 的任务),覆盖 9 个可维护性维度(改动局部性、复用与仓库意识、职责分解、扩展结构、依赖控制等),每个探针打包两个裁判,判定规则是“功能测试通过且结构预言机通过”,两者都过才算 pass。结构预言机不是通用的语法风格打分,而是针对目标维度逐 case 编写的轻量检查,区分“维护化方案族”与“诱人捷径方案族”。NITR
下图就是这套机制的骨架:

图注:从 9 类仓库演化压力到诊断探针的三段流程。左端是 9 个可维护性压力,中间实例化为紧凑探针(starter code 加给 agent 的任务),右端打包成功能预言机与结构预言机两个裁判。图是流程示意,不含任何通过率数字。NITR
评测结果是对现行范式最干净的反例。483 次评测里,13.3%(64 次)功能测试全部通过、结构预言机却判失败,常规评测会把它们全部记成成功。维度之间的难度差异更大:依赖控制维度通过率只有 4.3%,职责分解 15.2%,而最容易的状态归属达到 58.7%,差了 13 倍。注意这些维度通过率是 NITR 内部的诊断性趋势,不是总体估计(有的维度只有两三个 case),但它指出的方向是明确的:架构性压力最难,而现有验收面根本看不见它。另外,NITR 的任务描述刻意不透露任何设计意图,agent 只能凭代码现状自行推断,恰好复现了第 2 章的信息缺口。NITR
CODETASTE 用不同赛道给出同向证据,它测的是显式重构指令的执行率。ETH SRI Lab 与 LogicStar.ai 的 CODETASTE 把 100 个真实的大型多文件重构(87 个仓库、6 种语言,平均每个任务要动约 91 个文件、2605 行)做成基准,定义了 Alignment = Pass × IFR 的双项验收:功能测试通过率乘以结构规则遵从率。静态规则把“重构意图”变成可自动判定的检查,additive 规则检查应引入的期望模式、reductive 规则检查应移除的不良模式。乘法是关键:照着规则改了但改坏了功能,不得分;功能全过但结构走样,同样不得分。这正好是把第 1 章缺失的结构项放回验收面的直接实现。CODETASTE
下面这条流水线展示了结构项如何进入验收流程:

图注:CODETASTE 的六步流水线:提交发现、任务描述、构建环境、静态规则生成、模型推理、评估。第 4 步把重构意图变成静态规则,第 6 步同时用“静态规则 + 测试套件”双评估,测试套件本身不含结构检查。结构项第一次作为独立验收项出现,这正是“验收面扩容”的直观表达,图中无任何结果数字。CODETASTE
两轨对比给出数量级证据。Instructed 轨给平均 1921 字符的详细重构说明,GPT-5.2 对齐率达到 69.6%;Open 轨只给 38 字符的笼统目标,最高只有 7.9%。最刺眼的分解在 Open 轨:GPT-5.2 功能通过率高达 87%,结构规则遵从率只有 10.6%,对齐率 7.9%。行为几乎全对,结构几乎全错。这就是“验收面没有结构项时,行为正确就是最优策略”的直接数字(v2 口径)。CODETASTE

图注:左右双栏结果对比。左栏是 Instructed 轨的多模型对比,详细指定时对齐率显著高于其余模型;右栏是 Open 轨的 Direct、Plan 与 Oracle Multiplan,方案生成与选择能拉高对齐率,但离人类重构选择仍很远。精确数值以论文正文为准。CODETASTE
结构健康可以做成可自动判定的验收项,这一点现在有机制、有反例、有数量级证据。但注意,这些评测都在看单次补丁。把时间拉长,一次次的“功能全过、结构失守”累积起来,仓库会变成什么样?
4. 把一次性补丁放回时间轴:代码如何在智能体手下变老
SlopCodeBench(UW-Madison 等团队)做的正是把评测搬上时间轴。协议设计刻意复刻“黑盒”的真实协作:任务展开为 36 个问题的 196 个 checkpoints,每个 checkpoint 只给 CLI/API 边界的规格,不规定内部结构、不给测试;agent 从空工作区起步,在自己的前序代码上扩展,没有上一轮对话上下文,必须从代码结构推断怎么改。一个 checkpoint 的错误架构选择,成为下一个 checkpoint 的地基。回归测试把前序要求带下去,一次错误可能清零后续所有 checkpoint。规格更新与评分都在外部进行、对 agent 隐藏(v2 口径)。SlopCodeBench
下图是该协议的全貌:

图注:任务在 checkpoints 之间展开,每一步 agent 在先前工作区上扩展以满足更新的规格(橙色),正确性、侵蚀与冗余由外部评分并对 agent 隐藏(灰色)。局部捷径不断复利:正确性下滑,侵蚀与冗余上升。SlopCodeBench
结果:没有任何一个模型端到端完成任何问题;最优模型(GPT 5.5)也只在 14.8% 的 checkpoints 上严格通过。结构侵蚀(复杂度向已经复杂的函数集中)出现在 77% 的轨迹上,冗余(重复与无意义代码膨胀)出现在 75.5% 的轨迹上。更早的 v1 口径是 80% 与 89.8%,v2 扩到 36/196 后数字略降,方向完全一致。需要澄清的是,该基准并不证明每一轮都全绿;它证明的是,在不约束内部结构的连续扩展中,功能失败与结构退化会共同累积,而不是“功能一直全对、只有结构在偷偷失守”的“全绿掩盖结构失守”画面。后者是第 3 章双预言机证据刻画的情形,也就是 NITR 里 13.3% 的评测功能测试全过、结构预言机却判失败;SlopCodeBench 看到的是更直接的一层,连功能正确性都在随轨迹下滑(回归测试把前序要求带下来,一次错误可以清零后续 checkpoint),功能与结构一并滑落。高复杂度函数的平均数量则从 3.6 涨到 23.7。评测只覆盖 Python 轨道,跨语言外推要谨慎。SlopCodeBench
退化快慢要有参照系。与 473 个真实 Python 仓库共 13667 个采样提交对比,agent 代码整体 2.3 倍更冗余、2.0 倍更侵蚀,冗余累积速度约为人类的 7 倍、侵蚀约 5 倍(论文原文 roughly 7x/5x 的表述)。473 个仓库里只有 18 个越过了 agent 的平均冗余水平。再看 2024 年前后同一批仓库自身的变化:人类代码也在变糟,与 agent 辅助普及后小幅上升的 slop 一致,但仍远低于 agent 单个 checkpoint 的累积速度。SlopCodeBench

图注:双面板折线图,上方是冗余、下方是侵蚀,随归一化轨迹进度变化,agent 与按 GitHub star 分档的 473 个人类仓库对比,含 95% 置信区间阴影。agent 的起点更高、斜率更陡,差距稳定。SlopCodeBench
这听起来像新病,其实是两个老问题在新生产方式下的形态。Parnas 在 1994 年的 ICSE 特邀报告里就说:Programs, like people, get old,程序像人一样变老。他把老化分成两类成因:一类是不改,产品所有者不修改它去满足变化的需求,程序一行没改也会因为不再符合期望而老化;另一类是乱改,不理解原设计概念的修改几乎必然使结构退化。两者叠加成 one-two punch,价值快速衰退。SlopCodeBench 的侵蚀对应“乱改”,冗余对应 Parnas 说的“变胖”:加功能最省事的方式就是加新代码。SoftwareAging
Cunningham 则在 1992 年给了债务语言:首次交付代码就像借债,少量债务能加速开发,前提是用一次 rewrite 及时偿还;危险发生在不偿还的时候,每一分钟花在不正确的代码上都在为这笔债务支付利息,整个工程组织可以被未巩固实现的债务压到停摆。今天 agent 每个 checkpoint 累积的结构侵蚀,就是自动生成的利息。他 2009 年还专门澄清过:技术债不是烂代码,而是带着不完整但诚实的理解发布代码,再用重构偿还。WyCash
单次验收全绿,掩盖的是时间轴上数倍于人类速度的退化。结构侵蚀和冗余在 agent 手下以这样的速度累积,那在提示里多加一句“保持代码整洁”,能止住吗?
5. 多提示一句“保持整洁”有用吗:代价清单与治理转向
提示层干预确实有价,但边际明显。CODETASTE 的 Plan 模式(先自拟方案再实施)把 GPT-5.2 在 Open 轨的对齐率从 7.9% 提到 15.1%,几乎翻倍;oracle 从多个自拟方案里选最接近人类重构的那个,能到 20.6%。但代价真实存在:补丁大约变大 2-3 倍(GPT-5.2 从 632 行涨到 1672 行),部分模型功能通过率最多下降 23 个百分点,其中 Qwen3 从 58 降到 35,GPT-5.2 则纹丝不动。更重要的信号是:即使是 oracle 选择,20.6% 依然远低于人类识别重构目标的能力,论文结论是“自主判断改什么”仍是当前真正的瓶颈(v2 口径)。CODETASTE
SlopCodeBench 的 anti-slop 实验给出互证:在提示里枚举应避免的繁冗与过度工程模式,初始冗余最多降约 35%、初始侵蚀最多降约 62%,但最关键的是退化速率完全不变,平均仍每 checkpoint 1.3 个百分点,每 checkpoint 成本还上涨约 12.1%,严格通过率平均下降约 2.4 个百分点。一句话:提示只移动了起点,没有改变斜率。泛泛要求“保持整洁”,治标不治本。SlopCodeBench
那解法是什么?普渡大学的 12 周真实案例给出一个方向:把结构失败转化为治理机制,而不是要求模型自觉。一名资深工程师用前沿 agent 构建生产系统,期间留下 88 条现场笔记、产出约 42 万行生产代码。注意这是单案例第一人称报告、作者明示不从单案例断言普适性,所以它提供的是机制示范而非统计证据。案例的核心主张是“代码廉价、判断昂贵”:生成式 AI 把软件工程从稀缺的实现努力转向充裕的廉价代码生产,中心问题变成如何组织架构、工具、证据与反馈回路,让 AI 中介的开发保持可检查、可纠正、可维护。作者把它归纳成 governance conversion 的循环:agent 化速度暴露失败;人区分局部缺陷与重复性结构失败;把结构失败编码成治理,概率性的 agent harness 与模板,或者确定性的静态分析、lint 与提交门禁;后续 agent 继承更窄更明确的行动空间;治理能力复合。CheapCode
这个循环在真实工作流里长这样:

图注:案例中的开发工作流。Subject(工程师本人)提供产品目标与治理更新;受治理的工程环境内,Agent 治理约束智能体行为,Product 治理在候选变更进入产物前过滤;产品洞察与失败反馈回 Subject,被转化为更强治理以维持开发速度。CheapCode
NITR 的双预言机早已证明结构项可以进验收,这个案例展示的正是它在真实生产中的落地形态:结构失败一旦可见,就能被组织化为持久机制。治理是组织行为,不是提示词。那么,把架构意图写进任务与验收,在团队流程里到底长什么样?
6. 把架构意图写进验收,重新定义“完成”
回到 Goodhart。1975 年的机制说的是:当“完成等于功能测试通过”成为唯一的优化压力,绕过抽象就是理性最短路径。但处方不是弃用指标,指标还能用,只是要换更诚实的。这一路见过的所有方案,本质都是同一件事:Alignment=Pass×IFR 把“行为正确”和“结构对齐”拆成两个可叠加的验收项,NITR 的结构预言机让结构健康可自动判定,SlopCodeBench 的退化斜率则提示需要时间轴上的账本。Goodhart
“时间轴上的账本”就是质量预算:把长期质量目标量化成可监控的额度,比如“高复杂度函数承载的复杂度占比不允许再涨”,超了就算欠债,必须有偿还机制。Cunningham 1992 年说债务要用 rewrite 及时偿还,当代的偿还机制不再靠事后自觉,而是写进任务与验收:迁移完整性检查要求跨模块的改动全量迁移,不允许用 compat shim 绕过几百处调用,持续质量预算则是超阈值即红灯。局部成功制造全局债的根源,就在于“完成”的定义里没有长期健康这一项。CODETASTE WyCash
团队级做法已有概念框架。Spec-Driven Development 那篇论文提出:把规格当作人-智能体之间的契约基质。每个非平凡变更先写一份被团队当作契约的书面规格,规格与代码一起版本化、一起走评审;制品从规格推导、带显式来源与可追溯性;规格与制品冲突时,规格是唯一事实源。规格由此承载 accountability(可问责)、verifiability(可验证)、transferability(可移交)三种能力,把 vibe coding 溶解掉的契约重新立起来。它区分技术 harness(模型周围的软件基础设施,瞬态,模型变强就折旧)与方法 harness(团队拥有的实践与制品,随时间升值),主张优先投资后者。注意这是基于灰色文献的概念分析,作者明示是“迈向共识的第一步而非验证过的理论”,不能当作实证结果。SDD
下面这张概念图就是“以规格为中心”的形态:

图注:概念对比示意:一侧是“无规格”路径,契约、协调与信任被迫从代码和对话历史中重建;另一侧是 SDD 路径,规格成为共享契约,产出可审计的证据与可扩展的信任。这是概念模型,不是实证结果,图中不含任何数据。SDD
全篇的论证可以这样收口:编码智能体的架构债首先是目标函数问题,不是能力问题。把架构意图写进任务描述(RealSWE 显示真实请求常缺期望行为和动机等需求意图;团队还需把更具体的架构意图显式写入任务),把结构预言机放进验收面(CODETASTE 与 NITR 证明它可测、可判),在时间轴上立起质量预算(SlopCodeBench 的退化斜率,正是 Cunningham 利息的账本化),在组织里建立把失败转化为治理的循环(12 周案例证明这可行)。做到这四件事,“完成”的定义才把长期健康纳入进来。到那时,测试全绿,才不用拿仓库没人敢碰来换。
参考文献
本专题引用的核心资料如下,建议深入学习时阅读原文:
- RealSWE: A Compositional Evaluation of Coding Agents under Realistic User Requests — arXiv:2608.27831
- CODETASTE: Can LLMs Generate Human-Level Code Refactorings? — arXiv:2603.04177
- Needle in the Repo (NITR): A Benchmark for Maintainability in AI-Generated Repository Edits — arXiv:2603.27745
- SlopCodeBench: Benchmarking How Coding Agents Degrade Over Long-Horizon Iterative Tasks — arXiv:2603.24755
- AI Agents and the Refactoring That Never Happens(Rodrigo Rosenfeld Rosas)— https://www.rosenfeld.page/articles/programming/2026_09_02_ai_agents_and_the_refactoring_that_never_happens/
- Goodhart's Law(Charles Goodhart, 1975 原句,经 Wikipedia 词条核实)— https://en.wikipedia.org/wiki/Goodhart%27s_law
- Software Aging(David Lorge Parnas, ICSE 1994)— DOI 10.1109/ICSE.1994.296790
- The WyCash Portfolio Management System(Ward Cunningham, OOPSLA 1992)— https://c2.com/doc/oopsla92.html
- SWE-bench: Can Language Models Resolve Real-World GitHub Issues? — arXiv:2310.06770
- Cheap Code, Costly Judgment: A Case Study on Governable Agentic Software Engineering — arXiv:2607.01087
- Spec-Driven Development for Agentic Software Engineering — arXiv:2609.00252