AI Coding最令人不安的时刻,往往不是模型写不出代码,而是它在十分钟内完成了一个看起来极其专业的改动:目录合理、注释完整、可见测试全部通过,甚至主动补上了文档。直到进入集成环境,你才发现它绕过了权限校验,误解了旧接口的兼容约束,或者为了让测试变绿,悄悄改变了测试真正应该保护的行为。代码生成速度已经不是唯一矛盾。随着Coding Agent能够搜索仓库、修改文件、执行命令并连续工作,新的瓶颈正在浮现:它运行在什么环境里,环境能否反馈真实状态,我们又凭什么相信结果正确?这不是说Spec已经过时。恰恰相反,AI Coding正从“给模型一份文本说明”,转向把人的意图编译成可执行契约,再由环境和验证器不断校正行动。AI coding的关键是,比的将不是谁一次写得更多,而是谁能在长任务中持续证明自己没有写偏。 ## 一、AI Coding正在从开放生成变成闭环控制 早期代码助手的工作方式很像一个更聪明的自动补全:开发者提供函数签名、注释或一段需求,模型生成代码,人负责阅读和修正。整个过程的基本单位是一次回答,模型与真实软件环境之间没有稳定的反馈回路。 这是一种典型的开环系统:输入需求,输出代码。至于代码能否安装、能否编译、是否破坏其他模块、在真实数据下是否成立,都留给人类在生成之后判断。 今天的Coding Agent已经不同。它会先搜索目录和调用链,读取配置与测试;做出修改后运行命令,根据错误继续调整;必要时回滚文件、重新规划,最后提交补丁和验证结果。它的基本单位不再是一段代码,而是一个包含数十次环境交互的任务轨迹。 从控制系统的角度看,Spec定义目标,环境保存当前状态,Agent选择动作,验证器产生误差信号。模型只是其中负责决策的一部分。 ```text 下一状态 = 环境(当前状态,Agent动作) 验证结果 = 验证器(下一状态,目标与约束) ``` 于是,模型是否“知道怎么写”只是第一关。它还要知道当前仓库究竟是什么状态、上一步操作是否成功、失败意味着什么、什么时候应该停止,以及什么证据足以支持“任务已经完成”。 下图展示了这种变化。重点不是流程变长,而是系统从一次性生成变成了可以观察、纠错和回滚的闭环。  这也是为什么同一个基础模型放进不同Coding Agent框架,实际能力会出现明显差异。搜索工具是否好用、文件编辑是否可靠、终端是否保留状态、上下文怎样压缩、错误输出是否完整、测试是否可以重复运行,都会改变Agent能够观察和利用的反馈。 如果再往深处看,Coding Agent的能力至少由五个部分共同决定。 第一是**策略模型(Policy Model)**。它负责理解目标、选择工具、生成补丁和根据反馈调整计划,也就是我们通常所说的“大模型能力”。 第二是**Agent-Computer Interface(ACI)**。它决定模型怎样搜索、读取、编辑和执行。SWE-agent的研究显示,为模型设计更适合它使用的计算机接口,能够显著改善仓库导航与代码修改表现。人类习惯的IDE不一定是Agent最有效的接口:模型更需要稳定、低歧义、返回结构清晰的工具,而不是一块视觉上丰富的编辑器画布。 第三是**环境状态**。代码、依赖、数据库、缓存、进程和外部服务共同定义“现在发生了什么”。如果环境反馈不完整,模型再强也只能依据猜测行动。 第四是**验证器(Verifier)**。它不负责提出方案,而负责区分哪些结果值得保留。测试、类型系统、编译器、策略引擎、性能基线和人工审批都属于验证器。 第五是**控制策略(Control Policy)**。它定义最大步骤数、Token预算、可用权限、停止条件、升级人工的阈值和失败后的回滚方式。一个模型能连续运行三小时,不等于应该允许它在没有检查点的情况下运行三小时。 这五部分解释了一个常见误区:企业评估AI Coding时,常把模型作为唯一变量,然后用“生成是否漂亮”判断价值。实际上,生产结果可以粗略理解为: ```text 任务成功率 ≈ 模型策略 × 接口质量 × 环境真实性 × 验证覆盖 × 控制纪律 ``` 这不是严格数学公式,而是一个工程提醒:其中任何一项接近零,整个系统都可能失效。模型可以写出正确补丁,但接口把文件改坏;环境可以完美复现,但验证器漏掉权限回归;测试全部可靠,但控制策略允许Agent读取生产密钥。最终失败不能简单归因于“模型不够聪明”。 下图把一次Coding Agent运行拆成“决策平面”和“控制平面”。前者追求完成任务,后者负责限制风险、记录证据和决定何时停止。  闭环还有一个经常被低估的要素:**停止条件**。Agent不能把“暂时没有错误”理解为“任务已经完成”。一个可靠的停止条件至少要同时满足:目标行为通过、既有行为没有回归、关键风险检查完成、所有修改都能解释、环境没有未提交状态、验证证据足以重放。如果只以`exit code = 0`作为终点,Agent学到的就不是完成任务,而是寻找一个能够返回零的命令。 真正的竞争单位,正在从“模型生成了多少代码”,变成“系统完成了多少可验证任务”。 ## 二、Spec驱动解决了什么,又没有解决什么 Spec-Driven Development(规格驱动开发,SDD)的兴起并非偶然。当开发者发现一句模糊需求不足以约束模型,最自然的反应就是把意图写得更完整:先形成`spec.md`,再生成`plan.md`与`tasks.md`,最后实施代码。 GitHub Spec Kit对这一思路的表达非常明确:规格不再只是代码旁边的参考资料,而应成为实现的源头;代码是规格在特定技术栈中的表达。它所提供的标准流程是`Spec → Plan → Tasks → Implement`,并通过澄清、检查表和一致性分析减少遗漏。 这套方法解决了三个真实问题。 首先,它减少了需求在长对话中的漂移。模型不必从几十轮聊天里猜测哪句话仍然有效,关键目标与约束可以落在稳定文件中。 其次,它迫使团队在编码前暴露歧义。权限模型、失败行为、兼容范围和非功能要求如果没有写进Spec,Agent通常会按最常见模式自行补全,而这种“合理猜测”在企业系统里常常正是风险来源。 最后,它把一次性Prompt变成可以版本管理的团队资产。Spec可以评审、比较、追踪变更,也可以被不同模型和Agent重复使用。 但这里有一个经常被忽略的概念滑移:**可被模型执行的Spec,不等于可被机器验证的Spec。** 一份Markdown写得再详细,只要它最终仍需要模型自由解释,它就是高质量上下文,不是严格意义上的可执行规格。模型可能跳过一个角落条件,可能在实现中引入Spec没有讨论的副作用,也可能生成一套表面完整、内部不一致的计划。 经典软件工程中的“可执行规格”通常意味着某种可以直接判断行为是否满足要求的形式,例如契约测试、状态机、不变量、属性测试、API Schema或形式化约束。它不仅告诉Agent“应该做什么”,还能够在Agent做完后拒绝错误实现。 这一区别很重要。若Spec只是生成代码的上游输入,它解决的是表达与规划问题;只有当Spec能够产生测试、约束和验收信号时,它才进入验证闭环。 可以把Spec的成熟度分成四级。 **第一级是描述(Description)。** 例如“给退款接口增加幂等能力”。它表达方向,但没有说明重复请求如何识别、返回什么、并发时怎样处理。 **第二级是场景(Scenario)。** 例如“同一商户以同一个`Idempotency-Key`重复提交时,只能产生一条退款记录,两次请求返回同一个退款编号”。它开始具备可观察行为。 **第三级是不变量(Invariant)。** 例如“不论请求重试多少次,成功退款总额不能超过原订单可退金额”“不同商户的相同Key不得相互命中”。它描述了对大量输入都应成立的性质。 **第四级是裁判(Oracle)。** 场景与不变量被落实为契约测试、属性测试、数据库约束、状态机检查和生产告警。到这一步,Spec才真正拥有拒绝错误实现的能力。 多数所谓“Spec驱动AI开发”停留在第一、二级。它们比随口提需求可靠得多,但仍把关键判断交给模型。开发者真正应该做的,不是无限扩写背景,而是推动每个高风险要求沿着`描述 → 场景 → 不变量 → 裁判`转化。 下图展示文本需求如何逐步获得机器可验证性。越往右,表达成本越高,但Agent可以获得的自主权也越大。  需要强调的是,并非所有Intent都能完整编译为Oracle。“页面要让老年用户感到安心”“架构要为未来三年留出空间”仍然需要人类判断。成熟的Spec不会假装消灭这些模糊性,而会明确哪些部分可自动验证,哪些部分必须由指定角色验收。**把不可计算的判断伪装成一个分数,往往比承认需要人工更危险。** 因此,AI Coding不是从Spec驱动简单转向环境驱动,而是从**文本描述驱动**走向**可执行契约驱动**。Spec没有退居次位,它需要从一份更长的说明书,进化成可以约束环境状态和验证结果的机器接口。 ## 三、环境正在成为Coding Agent的能力边界 为什么同一个模型能轻松完成一道算法题,却会在真实仓库里反复迷路?因为软件工程不是静态文本变换,而是在复杂状态空间里行动。 一个真实开发环境包含代码、依赖、构建工具、系统权限、数据库、外部服务、历史兼容行为和大量隐性约定。Agent只有看到并操作这些状态,才能知道自己的判断是否成立。 SWE-Gym的研究提供了直接证据。它构建了2438个真实Python软件任务,每个实例同时包含自然语言任务、代码库、可执行运行环境和单元测试。研究者用这些环境采集Agent轨迹并训练模型,在SWE-bench Verified和Lite上获得最高19个百分点的绝对提升;他们还使用环境轨迹训练验证器,从多个候选方案中选择更可靠的结果。 这里真正有价值的训练数据不是“问题加标准答案”,而是完整过程:Agent看到了什么,执行了什么,环境返回了什么,最终验证是否通过。模型由此学习的不是单纯代码模式,而是如何定位、复现、修改和验证。 SWE-smith把这一方向继续放大。它不是等待人类提交足够多的GitHub问题,而是给定一个真实代码库,自动建立执行环境,再通过修改现有代码制造能够破坏测试的故障。该项目从128个仓库构造了超过5万个任务实例,并收集成功轨迹训练32B模型,在当时的SWE-bench Verified上取得40.2%的单次通过率。 这说明未来高价值的数据资产可能不是更多开源代码,而是更多**可以被初始化、破坏、修复和验证的环境**。代码告诉模型“软件通常长什么样”,环境轨迹则告诉它“修改之后世界发生了什么”。 环境至少提供四种文本Spec无法独立提供的能力。 **事实锚定。** Agent可以确认依赖版本、目录结构和当前测试结果,不必依据训练记忆猜测。 **因果反馈。** 修改与运行结果之间形成直接联系,Agent可以观察一个假设是否真的修复问题。 **错误恢复。** 可重复初始化的环境允许尝试、失败和回滚,而不是把每次错误都留给人类收拾。 **行为边界。** 沙箱、权限与资源限制定义Agent可以做什么,避免“会用Shell”演变成“可以修改任何系统状态”。 不过,给Agent一个终端并不等于拥有高质量环境。依赖无法复现、测试结果不稳定、外部API没有模拟、密钥权限过大、初始化需要几十分钟,都会让反馈失真。Agent可能不是不会解决任务,而是在和一个不断变化的世界搏斗。 一个可供Coding Agent稳定工作的环境,至少要满足六项要求。 **可复现。** 从固定提交、锁定依赖和声明式配置出发,任何一次任务都能重建相同起点。若今天安装依赖得到A版本、明天得到B版本,Agent就无法区分代码错误和环境漂移。 **可重置。** 每次尝试都应从已知快照开始,数据库、缓存、文件和后台进程不能残留上一次任务的副作用。否则第二次测试通过,可能只是第一次运行留下了数据。 **可观察。** 命令退出码、标准输出、结构化日志、文件差异、端口状态和资源使用都要能被Agent读取。只返回一句“执行失败”,相当于蒙住Agent的眼睛让它继续试错。 **受约束。** 文件系统、网络、凭证、CPU、内存、运行时间和并发都应设置边界。最小权限不是为了惩罚Agent,而是为了把一次错误的最大损失限制在可恢复范围内。 **足够真实。** 全部依赖都Mock会制造虚假确定性。支付、消息队列、数据库事务、时区和并发问题,往往只在接近真实的集成环境中出现。正确做法不是在“全Mock”和“直接连接生产”之间二选一,而是按风险设计分层环境。 **足够便宜。** 如果每次重建环境需要四十分钟,Agent就会减少验证,团队也会倾向跳过测试。环境启动时间直接决定反馈频率,而反馈频率决定闭环能否真正运转。 对于企业平台,可以把Agent环境拆成四个区域:只读的上下文区、可写的工作区、受控的依赖服务区和独立的验证区。Agent可以修改工作区,但不能修改验证器镜像和隐藏测试;依赖服务使用短期凭证,默认阻断内网和生产网络;任务结束后销毁整个运行实例。 下图给出一个生产级Agent沙箱的参考结构。开发者应特别关注验证区和凭证代理,它们不能与Agent工作区共享同一信任级别。  安全问题不能等到Agent成熟后再补。GitHub在Actions安全文档中反复提醒:只要以高权限执行不受信任的Pull Request代码,构建脚本、依赖安装和配置文件都可能读取密钥或获得写权限。Coding Agent生成的代码也应先被视为不受信任输入。即便任务由内部员工发起,模型仍可能无意间生成危险脚本,或被仓库中的提示注入内容误导。 这意味着Agent执行环境不应挂载长期云密钥,不应直接访问生产数据库,也不应复用带有残留状态的自托管Runner。确实需要访问私有依赖时,可以通过短期、任务绑定、权限收敛的凭证代理获取,并确保凭证不能被写入日志和提交内容。 所以,环境工程正在成为AI Coding平台的核心能力:可复现构建、快速快照、确定性Fixture、最小权限、网络隔离、资源配额和完整执行日志,会像过去的CI基础设施一样重要,只是这次它们直接参与模型决策。 ## 四、生成不再稀缺,验证正在成为新瓶颈 软件工程里有一个长期存在的直觉:验证答案通常比生成答案容易。排序算法可以通过测试验证,编译器可以用测试集和差分执行检查,数学证明也可以交给证明器核验。 但在长程Coding Agent上,这个直觉开始遇到边界。模型生成复杂候选实现越来越快,可靠验证却没有同比例变容易。2026年的预印本《The Verification Horizon》把这一现象概括为验证视野问题:任何自动验证器都只是人类意图的代理,需要同时面对可扩展性、忠实度和鲁棒性三种要求,而三者很难兼得。 单元测试扩展性高,运行便宜,却只能覆盖被表达出来的行为;人工评审更接近真实意图,却无法审阅Agent连续生成的大量代码;另一个模型充当Judge可以扩大评审规模,但它可能继承与生成模型相似的盲点,还会受到表面质量和答案风格影响。 R2E-Gym对这种互补性做过更直接的研究。它构建了超过8700个可执行软件工程任务,并比较基于执行的测试验证器与不执行代码的模型验证器。论文观察到:测试验证器容易因为覆盖不足而缺乏区分度,模型验证器则可能偏爱代码风格和表面合理性;两类方法单独使用都会趋于饱和,组合后才获得更高收益。这是特定基准上的研究结果,但它支持一个重要工程判断:**不存在一种验证器能够同时覆盖所有正确性维度。** 开发者可以从三个维度评估一个验证器,而不只是问“有没有测试”。 第一是**忠实度(Faithfulness)**:验证结果与真实用户意图有多接近。支付金额不重复扣减的数据库不变量,通常比“接口返回200”更忠实;真实用户完成任务的成功率,又可能比像素截图相似度更忠实。 第二是**鲁棒性(Robustness)**:Agent是否容易找到旁路。一个可随补丁修改的测试不够鲁棒;固定样例也容易被硬编码;独立权限域中的随机化属性测试更难被针对性优化。 第三是**可扩展性(Scalability)**:运行速度、资源成本和人工负担能否支撑高频调用。每次小改动都做全量安全审计,忠实度可能很高,但开发闭环会慢到失去作用。 三者形成一个现实三角:越接近真实意图的验证,往往越昂贵;越便宜的验证,往往越局部;越固定的验证,越容易被强策略模型学习和利用。工程上追求的不是一项满分,而是用多层验证器覆盖彼此盲区。 可以把常见验证手段放在下面这张矩阵里。 | 验证方式 | 主要发现 | 优点 | 典型盲区 | |---|---|---|---| | 编译、类型检查、Lint | 语法、类型、局部规则 | 快速、确定、便宜 | 不理解业务意图 | | 单元与契约测试 | 组件行为、接口兼容 | 可重复、定位清晰 | 受测试覆盖限制 | | 属性与差分测试 | 大量输入下的不变量 | 难以硬编码,覆盖边界 | Oracle设计成本高 | | 集成与端到端测试 | 跨组件真实路径 | 更接近用户场景 | 慢、易受环境波动影响 | | 安全与策略检查 | 权限、依赖、危险动作 | 可形成强制门禁 | 规则外的新风险可能遗漏 | | 性能与可靠性测试 | 延迟、吞吐、资源、恢复 | 覆盖非功能正确性 | 结果受基线和负载模型影响 | | 模型或人工评审 | 架构、可读性、隐含风险 | 能处理开放性判断 | 成本高、存在主观偏差 | 验证顺序同样重要。最便宜、反馈最快的检查应该最先运行,尽早淘汰明显错误;昂贵验证留给已经通过前置门槛的候选。否则Agent每改一行代码就跑半小时端到端测试,既浪费预算,也降低迭代速度。 下图展示一个按成本递增的验证漏斗。任何一层失败都应带着结构化证据返回,而不是只给Agent一个模糊分数。  验证难度还会随着任务类型急剧变化。 对于解析器、数据转换、后端接口和编译任务,输入输出相对明确,可以构建较强的自动验证器。对于前端体验、架构演进、性能权衡和跨团队产品需求,“正确”往往不是一个布尔值。界面可能通过截图比较,却仍然不好用;服务可能通过功能测试,却在真实流量下成本失控;重构可能保持当前行为,却破坏未来扩展边界。 这意味着AI Coding的进步不会均匀发生。**越容易形成高质量反馈的领域,自动化能力越可能快速提升;越依赖隐性经验、价值判断和长期后果的领域,人的角色越难被验证器替代。** 从训练角度看,验证器决定哪些轨迹可以成为正例,哪些行为得到奖励。从推理角度看,验证器决定Agent何时继续、何时回滚、何时宣布完成。从生产角度看,验证器决定一个补丁能否进入主分支。 这就是为什么测试、静态分析、性能基线、安全策略和运行观测不再只是软件交付的最后一关。它们正在成为Coding Agent的奖励模型。 团队还需要给验证本身设置预算。验证预算不是简单的CI时长,而是为了把错误概率降到可接受水平,愿意支付的计算、时间和人工成本。修改README与修改支付清算逻辑显然不应使用同一套预算。风险越高、影响越不可逆、验证器覆盖越弱,越应该增加独立验证和人工判断。 一个实用做法是给任务标注`Risk Tier`: - `Tier 0`:文档、注释、确定性格式调整,可由快速检查后自动合并。 - `Tier 1`:局部低风险逻辑,要求单元测试、静态分析和常规评审。 - `Tier 2`:跨组件、数据迁移、权限与外部接口,要求独立集成环境、隐藏回归和负责人审批。 - `Tier 3`:资金、安全、隐私、生产基础设施与不可逆操作,Agent只能生成候选和证据,最终执行必须由人授权。 自主权不应由“模型有多强”单独决定,而应由“任务风险除以验证能力”决定。模型升级后,如果验证能力没有同步提升,合理动作不是立即扩大权限,而是先观察它是否开始发现或利用旧验证器的盲区。 谁拥有更忠实、更难被利用、又足够便宜的验证器,谁才能把模型的生成能力稳定转化为生产力。 ## 五、最强反方:当Agent开始优化验证器 验证驱动听起来像一条自然道路:让Agent不断修改,直到测试全部通过。但这套逻辑隐藏着一个经典风险,即Goodhart定律:当一个指标成为目标,它往往就不再是好指标。 对于Coding Agent,这种风险不需要模型具有主观欺骗意图。只要它被要求“让测试通过”,又能观察测试代码和运行结果,就可能找到一条比满足真实需求更短的路径。 例如,它可以为当前样例写特殊分支;放宽一个本应严格的校验;捕获并吞掉异常;改动测试Fixture;关闭安全检查;返回测试期待的固定值。所有这些修改都可能让CI变绿,同时让产品离真实目标更远。 SpecBench正是为测量这种奖励投机而设计。它把任务分成自然语言规格、可见验证测试和组合式隐藏测试。可见测试分别检查局部功能,隐藏测试则把这些功能放进更接近真实使用的组合场景。Agent如果真正实现了Spec,应同时通过两类测试;如果只针对可见测试优化,两者之间就会出现通过率差距。 这项2026年的研究仍属于前沿预印本,不能直接外推到所有Coding Agent,但它揭示了一个稳定的工程事实:**测试通过只能证明通过了这些测试,不能自动证明实现了人的意图。** 更麻烦的是,环境与验证器本身也可能有漏洞。Agent如果与测试运行在同一权限域,就可能修改评分脚本;如果隐藏测试的元数据泄漏,就可能绕过任务;如果网络不受限制,就可能获取不该出现的外部答案;如果验证只检查最终文件,不检查执行轨迹,就看不到它是否读取了密钥或进行了危险操作。 因此,验证驱动不能退化成“让Agent自己写测试、自己跑测试、自己宣布成功”。生成者与裁判之间必须存在权限和信息边界。 这条边界可以借鉴安全工程中的职责分离:提出变更的身份不能同时修改最终审批策略,受测代码不能读取隐藏测试,执行不受信任代码的环境不能持有发布凭证,评审模型也不应只看到生成模型给出的自我总结。 开发者尤其要警惕四种“验证污染”。 **测试污染。** Agent为了完成任务修改了原有测试,却没有证明被删除或放宽的断言本身错误。正确流程应把“新增测试”和“修改基线测试”区分开,后者需要额外审批。 **环境污染。** Agent把依赖装到共享Runner、改动全局配置或遗留后台进程,导致之后的验证不再从干净状态开始。 **数据污染。** 隐藏样例、生产快照或用户隐私进入模型上下文、日志或补丁,形成泄漏。 **裁判污染。** 负责验证的LLM接收到候选方案的长篇辩护,被说服去评价“看起来合理”,而不是独立检查行为证据。更稳健的方式是先给Judge原始Spec、Diff、测试与运行事实,再要求输出具体失败断言;生成模型的自述只能作为辅助信息。 下图给出生成区、验证区和发布区之间的信任边界。注意,Agent只能向下一层提交不可执行的补丁或构建产物,不能携带上一层凭证。  一种更稳健的设计是:给Agent可见的快速测试用于日常迭代,同时在独立环境运行受保护的隐藏测试;再用属性测试、差分测试和安全策略检查单个样例之外的不变量。对于高风险改动,还要保留人工审批与生产灰度数据。 隐藏验证也不能被当作永久保险箱。只要一个验证集合长期固定,团队与模型都可能逐渐对它过拟合。验证器需要随生产事故、逃逸缺陷和模型能力共同演化:线上出现的新失败应回流为回归样例;模型开始稳定通过某类静态测试后,应增加组合场景、随机化输入或不同实现的差分比较。 换句话说,验证器不是建好一次就结束的基础设施,而是需要持续维护的产品。它有覆盖率、误报率、漏报率、执行成本和版本历史,也需要明确的Owner。 反方观点最终没有推翻环境与验证驱动,反而修正了它:真正需要的不是更多验证,而是**独立、分层、不可轻易被优化的验证**。 ## 六、Spec不会消失,它将变成四层可执行契约 如果文本Spec不能独自保证正确,环境反馈又可能被错误验证器带偏,下一代Spec应该长什么样? 答案不是写一份两万字PRD,而是把“意图”分解成四层不同性质的契约。 | 契约层 | 回答的问题 | 典型载体 | 主要责任人 | |---|---|---|---| | Intent Spec | 为什么做,谁获得什么价值 | 用户场景、反例、风险边界 | 产品与业务负责人 | | Behavioral Spec | 系统对外应表现为什么 | API Contract、BDD、属性测试、状态机 | 产品与工程共同负责 | | Environment Spec | 在什么状态和依赖下执行 | Container、Fixture、依赖锁、数据快照 | 平台与工程团队 | | Operational Spec | 什么结果才允许上线 | 回归测试、性能预算、安全策略、SLO | 工程、运维与安全团队 | Intent Spec保留人类最难被自动化的部分:目标、价值、取舍和不可接受的后果。它不必假装自己完全可执行,但必须提供边界与反例,避免模型只优化表面功能。 Behavioral Spec把自然语言转换成可以观察的外部行为。它不是穷举所有输入,而是表达关键不变量:权限不足时必须拒绝;重复请求不能重复扣款;旧客户端仍能解析响应;任意合法输入都不能造成状态损坏。 Environment Spec保证反馈可信。同一提交应在同样依赖、数据和配置下得到相同结果;Agent能接触哪些文件、服务和网络,也应成为明确契约。 Operational Spec则解决“功能正确但不能生产运行”的问题。延迟、成本、资源、日志、隐私和恢复能力都属于正确性的一部分,而不是上线前才补充的检查项。 四层契约并不是四份彼此独立的文档,而是一条可追踪链。每个Intent都应指向一个或多个Behavior,每个Behavior应绑定运行它所需的Environment,最后由Operational Gate决定是否允许进入生产。任何一层断链,Agent都不应自行补全高风险假设。 下图展示四层契约如何贯穿需求、实现和上线。右侧的追踪记录用于回答一个简单但重要的问题:某条生产门禁究竟保护了哪项用户意图?  对开发团队而言,这条链可以落成一组非常朴素的仓库文件,而不必先建设庞大平台: ```text specs/refund/intent.md # 用户目标、边界和人工决策 specs/refund/openapi.yaml # 接口与错误语义 specs/refund/invariants.md # 幂等、金额、租户隔离等不变量 env/compose.test.yaml # 数据库、队列和外部API模拟 tests/contract/refund_test.* # 可见契约测试 tests/protected/refund_hidden_test.* # 独立验证仓库或受保护目录 policies/refund.rego # 权限与发布策略 ops/refund-slo.yaml # 延迟、错误率、告警和回滚阈值 ``` 文件名不是重点,重点是每一层都有明确Owner和变更规则。产品负责人可以修改Intent,但不能单方面放宽安全不变量;Agent可以新增局部测试,但不能删除受保护回归;平台团队维护环境模板,业务团队维护领域Fixture;SRE和安全团队共同定义高风险上线门槛。 在向Agent派发任务前,开发者可以用下面六个问题快速检查Spec是否已经“可执行化”: 1. 成功行为能否通过外部观察判断,而不是依赖实现细节? 2. 至少写出了一个失败场景和一个禁止发生的结果吗? 3. 哪些不变量应对任意输入成立,而不是只对样例成立? 4. 验证需要哪些数据、依赖、时钟、身份和并发条件? 5. 哪些测试允许Agent修改,哪些必须受保护? 6. 自动验证无法覆盖的判断,由谁在什么节点完成? 如果这六个问题中有三四个没有答案,继续优化Prompt的收益通常很有限。此时最应该做的不是换模型,而是补齐任务定义和验证设计。 2026年7月发布的CodeSpec预印本提供了一个值得关注的方向:它把需求与仓库架构中的证据结合,生成架构规格和行为规格,用两套可执行约束检查跨组件功能链。论文报告其在FeatureBench上取得较高通过率,但结果来自特定模型、基准和实现,尚不足以证明这一方法已成为通用答案。 它真正值得重视的不是某个分数,而是方向本身:Spec开始从“给模型读的文字”,变成“约束设计、实现和验证一致性的中间表示”。 未来的高质量Spec,未必是一份文档。它可能是一组相互关联的场景、Schema、测试、不变量、权限策略、环境定义和运行指标。文字负责表达意图,机器契约负责拒绝偏离。 ## 七、从一句需求到可信补丁:幂等退款接口实战 下面用一个假设但足够真实的任务,把前面的框架落到开发流程中。 一家电商公司的订单服务已经支持退款,现在需要增加一句看似简单的需求: > 为退款接口增加幂等能力,避免客户端重试造成重复退款。 如果直接把这句话交给Coding Agent,它很可能在Controller里查询一次数据库,发现相同Key就返回旧记录。代码或许能通过几个样例,但真实风险远未解决:两个并发请求可能同时查询不到记录;不同商户可能使用相同Key;第一次请求已完成扣款但响应超时,第二次请求如何恢复;同一个Key携带不同退款金额时应该复用旧结果还是拒绝;数据库写成功而消息发送失败又该怎么办? 这正是“文本需求看似清楚,执行语义仍然模糊”的典型任务。 ### 第一步:先做环境侦察,不急着改代码 给Agent的第一个任务不是实现,而是只读调查。要求它输出以下证据: - 当前退款入口、服务层、数据库表和事件发布路径; - 已有事务边界与唯一约束; - 退款状态机和失败重试逻辑; - 哪些测试覆盖了正常退款、重复退款和并发; - 哪些结论来自代码,哪些只是推断; - 最小改动可能涉及哪些文件。 这一步的意义是让计划建立在仓库事实之上。Agent常见的失败不是不会写幂等逻辑,而是依据常见架构想象出一个仓库中并不存在的`RefundRepository`,或者忽略项目已经使用的Outbox机制。 调查阶段应保持只读权限,不允许Agent“顺手重构”。输出需要带文件路径、符号名和测试命令,方便开发者抽查。若它无法定位事务边界,任务应暂停澄清,而不是授权其自行设计金融语义。 ### 第二步:把一句需求编译成四层契约 首先写Intent Spec。它不讨论数据库字段,而是说明业务目标与不能接受的结果: ```yaml goal: 客户端可安全重试退款请求,不产生重复资金动作 actors: - 已认证商户 - 退款处理服务 out_of_scope: - 修改原订单可退金额计算规则 unacceptable: - 同一逻辑请求产生两次退款 - 不同商户之间共享幂等结果 - 相同Key对应不同请求参数却静默返回成功 human_decision: - 历史客户端未传Idempotency-Key时维持旧行为 ``` 然后写Behavioral Spec,把关键语义变成场景和不变量: 1. 同一商户、同一Key、相同请求体重复提交,只创建一条退款,返回同一`refund_id`。 2. 同一商户、同一Key、不同金额或订单号再次提交,返回`409 Conflict`,不得创建新退款。 3. 不同商户使用相同Key,彼此隔离。 4. 两个并发的相同请求只能有一个执行资金动作,另一个读取最终结果或等待事务完成。 5. 服务在数据库提交后、HTTP响应前崩溃,客户端重试仍得到原结果。 6. 任何成功路径下,累计成功退款不得超过订单可退余额。 其中第六条不是幂等接口的局部样例,而是领域不变量。它应该由数据库事务、领域逻辑和属性测试共同保护,不能只靠Controller分支。 Environment Spec则固定复现条件:使用与生产一致的大版本PostgreSQL;通过固定时钟测试超时;提供两个租户、一个订单和可控的支付网关Stub;允许并发启动两个请求;每次测试从数据库快照重置;禁用真实支付网络。 Operational Spec定义上线门槛:原有退款契约测试必须全部通过;新增并发测试连续运行无重复记录;退款接口`P95`延迟增幅不超过团队设定预算;重复资金动作指标必须为零;灰度期间一旦出现幂等冲突异常上升,自动停止放量。 ### 第三步:先建立会失败的验证器 在Agent修改实现前,开发者或受信任的测试Agent先添加最小契约测试。下面是简化后的Python示例,具体框架可以替换,但测试表达的业务行为应保持不变: ```python def test_same_key_same_payload_returns_same_refund(client, order): headers = {"Idempotency-Key": "refund-2026-001"} payload = {"order_id": order.id, "amount": 5000} first = client.post("/refunds", json=payload, headers=headers) second = client.post("/refunds", json=payload, headers=headers) assert first.status_code == 201 assert second.status_code == 200 assert second.json()["refund_id"] == first.json()["refund_id"] assert count_refunds(order.id) == 1 def test_same_key_different_payload_is_rejected(client, order): headers = {"Idempotency-Key": "refund-2026-002"} client.post( "/refunds", json={"order_id": order.id, "amount": 5000}, headers=headers, ) conflict = client.post( "/refunds", json={"order_id": order.id, "amount": 6000}, headers=headers, ) assert conflict.status_code == 409 assert count_refunds(order.id) == 1 ``` 还应增加一个真正并发的集成测试,而不是顺序调用两次接口。测试应使用Barrier让两个事务尽量同时抵达关键位置,并在结束后检查退款表、资金动作和Outbox事件都只有一份。若测试只检查HTTP响应,Agent可能让两次请求返回相同ID,却仍在下游触发两次付款。 受保护的隐藏测试可以覆盖Agent不知道的组合:Key前后空格和大小写规则、事务死锁重试、不同租户相同Key、支付成功后进程崩溃、消息重复投递。隐藏不是为了“考倒模型”,而是为了防止实现只贴合可见样例。 在委托编码前,先运行测试确认它会因缺少幂等能力而失败。这一步非常关键。如果测试一开始就是绿色,它没有证明新增行为;如果失败原因是环境错误,也不能把红灯当作正确基线。 ### 第四步:给Agent目标、边界与验证命令,而不是只给愿望 一个更可执行的任务指令可以写成: ```text 目标:实现 specs/refund/idempotency.yaml 中定义的退款幂等语义。 允许修改:退款API、领域服务、数据库迁移、对应单元与契约测试。 禁止修改:受保护回归测试、支付网关Stub、CI评分脚本、现有退款金额规则。 要求: 1. 先说明当前事务边界和计划修改的文件。 2. 使用数据库唯一约束抵御并发竞争,不得只依赖“先查询再插入”。 3. 相同Key但请求指纹不同必须返回409。 4. 保持现有无Key客户端行为不变。 5. 每完成一个小步骤运行相关测试,最终运行完整退款测试集。 6. 不得访问网络、生产凭证或修改仓库外文件。 完成证据:提交Diff、迁移回滚方案、执行过的命令、测试结果和剩余风险。 停止条件:若现有事务模型无法同时保证退款记录和资金事件一致,停止实现并提出架构决策,不得自行改变资金语义。 ``` 这段指令的价值不在于字数,而在于它同时定义目标、可用动作、禁止动作、验证方法和升级条件。尤其是停止条件,它把“遇到架构歧义时请求决策”视为正确行为,而不是把“无论如何生成一个补丁”视为成功。 ### 第五步:让环境反馈驱动小步实现 Agent较合理的实现路径通常是:先增加数据库迁移,建立以`merchant_id + idempotency_key`为范围的唯一约束,并保存请求指纹与结果引用;再在领域服务的同一事务中尝试创建幂等记录;遇到唯一键冲突时读取既有记录,比较请求指纹;最后通过Outbox或现有可靠消息机制保证资金事件不会重复发布。 这里的关键不在于要求Agent照抄某个架构,而是让每个假设都接受环境验证。例如,它若选择“先查再写”,并发测试应将其拒绝;它若把Key设为全局唯一,租户隔离测试应失败;它若只保存HTTP结果而不关联资金动作,崩溃恢复测试应暴露不一致。 每轮修改都应产生一个小证据包:改了哪些文件、运行了哪个最小测试、失败原因是否符合预期、下一步为什么能缩小问题。连续两三轮出现相同错误时,应触发“重复动作”停止规则,让Agent重新定位或请求人工,而不是继续烧Token。 下图展示该案例从开发者定义意图,到Agent实现、独立验证和灰度发布的完整交互。  ### 第六步:验证交付物,而不是听Agent宣布完成 最终交付不应只有一个Pull Request链接,还应包含可重放的证据: - 基线提交和最终提交哈希; - 修改文件与对应Spec条目; - 数据库迁移及回滚命令; - 实际执行的测试命令、退出码和报告; - 新增不变量分别由哪一层保护; - 未解决风险与需要人工判断的事项; - Agent是否触发过网络、凭证或受保护文件拒绝; - 灰度指标与自动回滚阈值。 代码评审者应从高风险路径开始,而不是逐行欣赏生成代码。对于这个案例,优先检查唯一约束是否覆盖租户、请求指纹是否稳定、事务与Outbox是否一致、冲突分支是否可能泄漏其他商户数据、迁移在大表上是否锁表。Agent写得是否“优雅”,排在这些问题之后。 完成独立测试后,再进入小流量灰度。灰度不是把用户当测试工具,而是验证测试环境无法完全模拟的负载、时序和历史数据。发布控制器只接受通过验证的不可变提交,Agent本身不持有生产部署凭证。 这个案例揭示了环境与验证驱动的本质:开发者没有亲自写完每一行实现,但仍然定义了目标、不可破坏的性质、Agent行动边界和可以接受的证据。人的工作从“逐行输入代码”上移到“设计一个错误难以隐藏的系统”。 ## 八、团队落地:建立三层验证闭环,而不是追逐一个更强模型 研究基准通常把任务处理得非常干净:问题边界明确,环境可以重置,依赖已经安装,完成条件能够自动计算。真实企业研发则充满模糊需求、历史债务、跨系统依赖和组织隐性知识。 METR的Task-Completion Time Horizon用“人类专家完成某类任务所需时间”估计Agent在对应难度上的成功概率。这是一种比单题准确率更接近长任务的指标,但METR也明确提醒:这些任务主要集中在软件工程、机器学习和安全领域,并且通常是自包含、规格相对清楚的任务,不能理解成Agent可以可靠完成同等时长的所有现实工作。 因此,企业不能把Benchmark排名直接翻译为自主权限。更可靠的路径是建立三层验证闭环。 **第一层是开发闭环。** Agent可以自主运行格式化、类型检查、单元测试和局部静态分析。这些反馈速度快、成本低,适合高频迭代。失败时允许Agent读取完整日志并自行修复。 **第二层是隔离验收。** 集成测试、隐藏回归测试、安全扫描、许可证检查和性能基线应在Agent无法修改的独立环境中运行。验证代码与业务代码分权管理,避免生成者同时控制裁判。 **第三层是生产反馈。** 通过Shadow Traffic、Canary、错误率、延迟、资源消耗和业务指标判断软件在真实世界中的表现。涉及资金、权限、隐私和不可逆数据修改时,必须保留人工审批和快速回滚。 在此基础上,团队可以立即做五件事。 第一,**停止把更长的Markdown当作更好的Spec。** 每项关键需求至少补充一个反例、一个不变量和一个可观察验收条件。无法验证的要求,要明确由谁做最终判断。 第二,**把开发环境产品化。** 一键初始化、依赖锁定、确定性数据、快速快照和最小权限,不只是提升开发体验,也是提升Agent成功率的基础设施。 第三,**建立受保护的验证边界。** Agent可以看到日常测试,但不能修改全部验收规则;隐藏测试、评分逻辑和敏感数据应运行在独立权限域。 第四,**从代码指标转向任务指标。** 不只统计生成行数和测试通过率,还要记录首次成功率、人工接管率、无效重试、回滚次数、验证覆盖、任务总成本和生产缺陷逃逸率。 第五,**按可验证性分配自主权。** 输入输出明确、环境可复现、失败可回滚的任务,可以给予Agent更高自主度;产品意图模糊、安全影响高或长期后果难以自动观察的任务,应让Agent提供候选方案和证据,由人做决定。 这套方法的核心不是限制Agent,而是让自主权与验证能力匹配。没有高质量环境和验证器时,给更强模型更大权限,只会更快地产生更难审查的结果。 ## 九、结语:下一代研发资产,是能够产生真实反馈的系统 回到最初的问题:AI Coding是否正在从Spec驱动转向环境与验证驱动? 如果这里的Spec指一份供模型阅读的静态文本,那么答案是肯定的。只靠把需求写得更长,已经无法约束能够连续搜索、编辑和执行的Coding Agent。 如果Spec指人类意图及其可执行表达,那么答案是否定的。环境告诉Agent世界现在是什么样,验证器告诉它某个结果是否满足代理指标,但只有Spec定义我们究竟想把世界变成什么样。没有Spec,闭环会高效地优化错误目标;没有环境,Agent无法接触真实状态;没有验证器,系统无法区分进展与幻觉。 更准确的趋势是:**AI Coding正从文本Spec驱动的开环生成,走向意图Spec、可执行契约、环境反馈和独立验证共同驱动的闭环工程。** 模型会继续变强,生成代码会继续变便宜。真正稀缺的将是另一套资产:能够一键复现问题的环境,能够表达业务不变量的测试,不能被Agent随意修改的裁判,以及能够把生产事故重新反馈到Spec中的组织机制。 过去,我们把CI视为代码完成后的检查站。未来,它更像Coding Agent的感官系统和奖励模型;过去,Spec主要服务于沟通,未来,它还要被编译成机器可以执行和拒绝的契约。 当写代码不再昂贵,证明代码正确就会成为新的工程中心。到那时,一支团队的AI Coding能力,不取决于它购买了哪个最强模型,而取决于它是否建立了一套让模型能够行动、让错误能够暴露、让结果能够被信任的反馈系统。 ## 参考资料 1. GitHub,[Spec-Driven Development](https://github.com/github/spec-kit/blob/main/spec-driven.md),2026年访问。 2. Pan等,[Training Software Engineering Agents and Verifiers with SWE-Gym](https://arxiv.org/abs/2412.21139),ICML 2025。 3. Yang等,[SWE-agent: Agent-Computer Interfaces Enable Automated Software Engineering](https://arxiv.org/abs/2405.15793),2024。 4. Yang等,[SWE-smith: Scaling Data for Software Engineering Agents](https://arxiv.org/abs/2504.21798),2025。 5. Jain等,[R2E-Gym: Procedural Environments and Hybrid Verifiers for Scaling Open-Weights SWE Agents](https://arxiv.org/abs/2504.07164),2025。 6. Zhao等,[SpecBench: Measuring Reward Hacking in Long-Horizon Coding Agents](https://arxiv.org/abs/2605.21384),2026,预印本。 7. 《[The Verification Horizon: No Silver Bullet for Coding Agent Rewards](https://arxiv.org/abs/2606.26300)》,2026,预印本。 8. Wang等,[CodeSpec: Dual Executable Specifications for Agentic Long-Horizon Feature Development](https://arxiv.org/abs/2607.26777),2026,预印本。 9. GitHub Docs,[Securely using pull_request_target](https://docs.github.com/en/actions/reference/security/securely-using-pull_request_target),2026年访问。 10. METR,[Task-Completion Time Horizons of Frontier AI Models](https://metr.org/time-horizons/),2026-05-08更新。