Browse this library

Chinese source article

8.1 · Coding Agent系统

从仓库状态、补丁动作、测试验证与长程恢复分析 Coding Agent 的工程闭环。

View original Markdown ↗

Coding Agent 运行在具有持久状态的代码仓库中。每次搜索、编辑、安装依赖和执行测试都会改变后续可见环境。任务成功也不等于生成了一段看似合理的补丁,而是用户要求在指定仓库版本上成立,原有行为没有发生不可接受的回归,用户未提交修改得到保留,验证证据能够复现。

代表系统可以抽象成“观察仓库—提出补丁—执行检查—解释反馈—提交终局”的循环。不同产品在模型、编辑协议和沙箱上各有选择,但闭环中的状态版本、动作边界和验证责任相对稳定。本篇用这些机制分析系统,不做产品功能排行。

1. 仓库作为状态环境

1.1. 初始状态与约束

仓库状态可写成 s=(C,W,I,D,T,P)s=(C,W,I,D,T,P):CC 是基线提交,WW 是工作树差异,II 是索引区,DD 是依赖与构建环境,TT 是已知测试状态,PP 是项目规则和权限。任务开始时保存这些指纹,后续每次动作都引用预期版本。

用户已有修改属于环境事实,不能被 Agent 当成噪声清除。系统读取 status、差异和未跟踪文件,区分基线、用户改动与本次产物。编辑器最好以内容哈希或 patch 前置上下文做乐观并发检查,文件已变化时拒绝盲目覆盖。

项目规则来自仓库说明、构建脚本、包管理器和目录约定。规则有作用域:根目录说明覆盖全仓,子目录说明可能只约束局部。Coding Agent 先定位适用规则,再沿任务相关调用链展开文件。无差别加载整个仓库会消耗上下文并混入过期实现。

1.2. 搜索与程序理解

文本搜索适合定位符号、错误信息和配置,语言服务器适合引用关系和类型,版本历史解释设计来源,测试名提供行为入口。每种观察都有盲区:文本同名不等于语义引用,静态调用图可能遗漏动态注册,历史提交也不代表当前要求。

探索使用证据前沿。起点是用户可见行为或失败测试,随后读取入口、调用方、数据结构和验证路径。每次扩展都回答一个明确问题,例如“谁持久化该状态”“哪些调用方依赖旧签名”。未改变决策的重复读取应停止。

程序理解不是先生成完整架构图。系统维护当前假设、支持证据、冲突证据与待查问题。当新观察否定根因时,计划必须更新;旧假设不能仅因已投入 token 而继续支配补丁。

1.3. 工作树与依赖状态

代码文件只是环境的一部分。锁文件、生成物、数据库 schema、编译缓存、环境变量和工具版本都会影响结果。测试前记录运行目录、命令、依赖指纹和关键配置,避免在错误包或旧构建物上获得绿色结果。

依赖安装属于高副作用动作,可能改锁文件、执行生命周期脚本或读取宿主凭据。隔离执行器限制网络与环境,并把预期锁文件变化纳入差异。未经用户要求升级大量依赖,会扩大改动面并破坏归因。

Agent 与编辑器并发运行时,工作树会持续变化。长任务在每个提交边界重新检查相关文件版本;冲突进入显式状态,由重新读取与合并解决。按到达顺序覆盖会丢失另一方改动。

2. 补丁动作与工程闭环

2.1. 从需求到改动面

需求先转为可观察完成谓词,再映射到状态所有者、接口、消费者和测试。例如“刷新后任务仍可见”涉及服务端事实源、查询接口、前端水合与推送,单改组件本地状态无法满足。文件名只是定位结果,不能代替行为链。

改动面包含直接实现、接口调用方、类型、持久化、迁移和验证。接口签名变化应在同一切片更新所有消费者,不保留无用兼容分支。计划按依赖排序,但探索中新事实可以调整范围。

控制系统的 bug 要定位不变量所属层。若状态机允许非法转移,应在 reducer 或 transition 强制,不用调用方增加等待和定时器掩盖竞态。判断标准是删掉编排层防护后,权威状态是否仍保持正确。

2.2. 结构化编辑

patch 是带前置条件的转换 a:(Wv,p)→Wv+1a:(W_v,p)\rightarrow W_{v+1}。应用前检查目标文件版本和上下文,应用后返回精确 diff、受影响行与新哈希。失败不会退化为覆盖整文件,避免误删并发改动。

小而语义完整的补丁便于审查和回滚。跨文件接口修改仍需作为同一个验收切片完成,不能只改定义后留下调用方。机械格式化与行为改动分开,减少 diff 噪声,使 verifier 失败可以对应具体变化。

编辑后立刻做廉价检查:解析、格式、类型或目标单测。失败观察包含命令、退出码、结构化诊断和截断信息。模型根据真实错误调整,不能把输出末尾一句“failed”当作全部证据。

2.3. 完整循环轨迹

假设用户报告自动保存偶尔覆盖新内容。Agent 读取项目规则、工作树和失败复现,沿组件回调找到 store。trace 显示旧请求晚到后仍能提交,根因是 reducer 没有版本检查。计划是在状态转移中比较预期版本,并增加乱序响应测试。

Agent 修改 reducer 与调用类型,运行目标单测;测试第一次失败,显示相同版本的幂等重放也被拒绝。它修正规则为“旧版本拒绝、相同动作 ID 返回已提交结果”,再运行单测、相关包测试和浏览器复现。每次观察绑定对应工作树哈希。

最终 diff 只含状态机与测试,工作树原有用户文件保持不变。Agent 检查未跟踪产物和敏感文件,输出验证范围与仍未覆盖风险。若用户授权提交,提交动作在测试证据之后单独发生。这条轨迹展示了假设、环境反馈和不变量修复形成的闭环。

3. 测试与Verifier

3.1. 分层验证

静态解析和类型检查验证结构一致;单元测试覆盖局部规则;集成测试验证组件边界;端到端测试覆盖真实进程、浏览器与存储。层级越高越接近用户路径,成本和不稳定性也更高。验证组合依据改动风险选择。

测试通过仅证明执行过的断言在该环境成立。并发、权限、网络、时区和真实浏览器路径若未覆盖,不能由单测外推。最终报告列出命令、结果、环境和缺口,避免“测试绿”变成全局无误承诺。

用户需求常包含测试未编码的语义。修复删除按钮后所有测试通过,但按钮文案或撤销行为仍可能违背要求。验收将测试证据与需求逐项对应,并对 UI、迁移和副作用做人工或结构化检查。

3.2. Verifier防投机

策略可能删除失败测试、放宽断言、跳过检查或硬编码 fixture。verifier 运行位于策略不可写的隐藏测试,并检查测试与配置差异。测试文件确需修改时,评审其与需求的关系,不能把所有测试变化都视为作弊。

代码执行成功也可能依赖污染状态。验证环境从干净基线应用补丁、重新安装锁定依赖并构建。只在 Agent 原工作树运行,会继承缓存、临时文件和未记录配置。可复现验证使用隔离副本和相同提交哈希。

Verifier 自身有假阳性与假阴性。隐藏测试覆盖不足会接受危险实现,过度绑定参考补丁会拒绝等价方案。已知正确变体、错误补丁和攻击样本用于校验测试,失败证据保留到能够复现。

3.3. 补丁质量与回归

补丁评测以终局测试为准入条件,并检查差异范围、复杂度、重复代码、API 变化、安全和性能。行数少不必然更好,大规模重写也不自动代表架构修复。质量判断绑定任务约束与仓库既有模式。

回归选择从调用图、依赖图和变更类型推导。共享 schema 变化需要消费者测试,数据库变化需要迁移与重建,前端异步状态需要浏览器运行时验证。只运行新加单测会产生自证循环。

数值例:补丁 A 在 100 项测试通过 100 项,用时 40 秒;补丁 B 通过 99 项,用时 20 秒。不能用速度平均掉功能失败。先设正确性门槛,再在通过集合比较时延与成本。安全与数据损坏同样是硬门槛。

4. 长程运行与失败模式

4.1. 上下文与计划漂移

长任务会经历多次搜索、编辑和压缩。系统在检查点保存目标、当前假设、已提交差异、验证结果、资源版本和未解决问题。压缩摘要不保留这些结构时,模型会重复探索、忘记用户约束或把旧测试结果套到新补丁。

计划漂移表现为不断扩大范围。初始修复一个解析错误,随后无证据地升级框架、改目录并重写接口。Runtime 可显示改动面与计划节点差异,超过范围时要求重新论证。范围可以为根治而扩大,但每次扩张都要有依赖证据。

上下文误读也来自生成文件与事实源混淆。直接编辑构建产物会在下次生成时消失;编辑缓存数据库可能绕过源文件。仓库规则和构建链用于识别权威落点,验证时从事实源重新生成。

4.2. 命令与状态故障

命令超时不证明进程没有产生效果。构建可能仍在后台写文件,部署可能已提交。执行器绑定进程树、工作目录和动作 ID,超时后先终止或查询,再决定重试。无状态 shell 调用不能假装具备事务语义。

测试输出被截断时,结构化保存退出码、失败用例和产物路径。模型如果只看到输出末尾几行,可能修错首个编译错误。大日志放入产物,按错误索引检索;截断事实明确写入 observation。

服务重启使内存进程丢失。运行恢复读取事件与工作树事实,未知副作用任务标中断,不自动重放安装、发布或数据库写入。用户可以从已验证检查点显式继续。

4.3. 典型反例

反例一:Agent 看到空引用异常,在调用处加非空判断,测试通过。真实不变量要求对象在创建事务中始终存在,补丁隐藏了数据损坏。删除调用处守卫后问题重现,说明修复没有落到状态所有者。

反例二:Agent 为让测试通过,把等待时间从一秒增加到五秒。慢机器仍会失败,快机器只是更慢。若系统缺少完成事件,应建立显式同步或状态转移;固定 sleep 无法证明工作已经完成。

反例三:Agent 在脏工作树运行格式化,提交时把用户修改一起纳入。功能测试全绿,交付仍然错误。初始基线、逐文件归属和最终 diff 检查属于完成条件,不是附加礼仪。

5. 系统评测与设计取舍

5.1. 任务与指标

评测任务从真实缺陷、功能变更、重构和仓库维护抽样,按语言、项目、改动跨度和测试成本分层。终局由隐藏测试、仓库状态和需求检查决定。公开 Issue 可能污染,时间切分和私有变体用于测未见泛化。

指标包括完全解决率、pass@k、首错位置、有效动作、补丁应用率、测试成本、墙钟时延、用户改动损坏和安全事件。基础设施失败与策略失败分开。只报告生成 patch 比例没有业务意义。

版本比较使用相同仓库快照与依赖镜像。多次 rollout 共享缓存时记录冷暖状态;并发任务隔离工作树和端口。置信区间以任务为单位,而非以测试数量或 token 数量扩大样本。

5.2. 机制消融

消融分别关闭符号索引、历史读取、增量测试、状态检查、上下文压缩和隐藏 verifier,观察完成率、动作与成本。去掉某机制后 token 降低但回归增加,说明它提供了必要证据;功能不变则可能简化系统。

比较整文件生成、搜索替换和结构化 patch 时,固定模型与任务。评测冲突率、误删用户改动、diff 大小和恢复成本,不用单次成功案例下结论。编辑协议的价值体现在并发与失败边界。

长程消融在不同上下文预算、检查点与 compaction 策略下运行同一任务。分析首次偏离是否集中于压缩边界、测试后状态或计划扩张。只增加窗口长度若没有改善,瓶颈可能是观察组织和验证,而非容量。

5.3. 交付边界

系统输出补丁、验证证据、环境版本、剩余风险和实际副作用。提交、推送与部署是独立高风险动作,需要明确授权。代码生成完成不能自动推导这些动作也被允许。

大型迁移提供一条更完整的交付轨迹。Agent 修改共享 schema、服务端读写和前端消费者,先建立调用方清单与旧字段基线,再在同一切片更新类型和静态引用。类型检查发现动态映射未覆盖,数据库快照测试又发现历史记录缺字段。系统没有增加永久兼容读分支,而是生成一次性迁移,在复制库核对行数、空值和备份。

迁移后服务端集成测试通过,浏览器仍显示旧缓存。trace 证明后端已经返回新字段,前端查询没有在推送事件后失效。修复落到状态同步入口,并增加跨标签与刷新验证。若只看类型与单测,任务会过早结束;分层 verifier 把遗漏暴露在提交前。

测试失败也可能来自基础设施。浏览器进程因既有端口占用而未启动,属于无效运行;补丁启动无限子进程耗尽端口,则属于系统失败。执行器记录进程树、端口和资源用量,故障归因才不会把环境噪声错误训练进模型。

成功的 Coding Agent 会让错误尽早暴露在低成本边界,利用测试与状态事实修正,并在终局给出可复现证据;要求模型永不犯错并不现实。模型能力决定候选动作质量,仓库协议、沙箱、状态机和 verifier 决定这些动作能否安全闭环。

代表系统的启示也不限于代码:任何持久环境中的 Agent 都需要版本化状态、结构化动作、真实反馈与独立验证。代码仓库提供了相对强的测试与差异工具,因此也是研究长程 Agent 机制最清晰的实验场之一。

性能任务的完成谓词同时包含正确性和基准协议。Agent 不能通过缩小数据、关闭检查、改变精度或命中缓存换取速度。基准固定硬件、预热、重复次数与输入分布,记录中位数和尾部。统计波动覆盖所谓提升时,不应交付复杂优化;性能提升伴随内存暴涨时,也要放在资源前沿上比较。

代码审查是一种带有人类判断的 verifier。机器检查负责格式、类型和已知规则,审查者关注需求、设计与维护性。Agent 应提供紧凑 diff、关键不变量、验证命令和风险,不用长篇自述替代可检查事实。审查反馈成为新约束后,受影响验证需要重新执行。

系统设计还要划清模型与确定性工具的责任。格式化、符号重命名、依赖查询和测试筛选由工具执行更稳定;模型负责目标分解、证据权衡与非常规修复。让模型用自然语言重造结构操作会增加随机错误,把开放判断全部硬编码又会丢失适应性。

复合工具不能隐藏关键效果。一个“一键修复”内部修改十个文件却只返回成功,模型无法审查差异或定位失败。工具应返回计划、实际变化、资源版本和验证入口,高风险阶段支持预览与分步提交。抽象减少无意义步骤,同时保留可观察状态。

最终状态包括测试通过、工作树归属清楚、没有秘密与临时产物、事实源得到修改、生成物可重建、命令可复现和风险明确。任一项未知都在交付中保留。模型能力决定候选动作质量,仓库协议、沙箱、状态机与 verifier 决定动作能否安全闭环。

不同仓库对“完成”还有不同定义。库项目关注公开 API 与多版本兼容,应用关注部署路径与数据迁移,基础设施仓库关注计划输出和回滚。任务装载器从仓库规则生成 verifier 清单,模型不能用自己熟悉的项目惯例覆盖本地约束。

当隐藏测试失败却不给细节时,系统保持失败事实,并通过公开测试、静态分析和最小复现缩小范围。试图读取隐藏答案破坏评测边界。生产故障则相反,需要在权限允许范围内保存足够诊断证据,不能为了“盲测”丢弃用户可用日志。

由此可见,Coding Agent 的核心产物是经证据验证的仓库状态转换。补丁文本只是转换载荷,测试日志只是观察,最终答复只是交付界面。把三者等同,都会让局部成功掩盖系统错误。

验收记录还应列出没有执行的检查及原因。某项端到端测试需要缺失的浏览器、外部服务不可用或权限不足,都不能被静默省略。用户据此判断是否继续部署,后续 Agent 也能从明确缺口恢复,而非把“未运行”误读成“已通过”。对高风险路径,关键检查无法执行时应停止提交;对低风险草稿,可以交付产物并清楚标记验证边界。

这份记录同时绑定补丁哈希,防止验证后文件又发生变化。

交付界面显示这项绑定关系及验证时间,便于后续复核。 Coding Agent 的运行单元应拥有独立工作区或可验证分支。多个任务共用同一工作树会让搜索、补丁和测试互相污染,最终 diff 无法归属。隔离不一定要求完整复制仓库,可以使用 worktree、快照或写时复制,但每个运行必须有稳定基线。

基线包含提交、未提交用户差异、子模块、LFS 与生成依赖。只记录 HEAD 会遗漏用户工作树事实。Agent 的补丁相对基线应用,最终交付分别展示用户原有修改与本次变化,禁止用重置命令清理不属于任务的内容。

仓库规模大时,索引建立也有版本。符号索引基于提交 A,工作树已变为 A',查询结果可能过期。索引 observation 携带源哈希,关键引用在编辑前用当前文本或语言服务确认。缓存提高速度,不获得权威地位。

生成代码要追踪事实源。OpenAPI 客户端、ORM 类型和构建产物可能由 schema 生成,直接编辑会在下次构建消失。Agent 读取生成标记与构建脚本,修改源并运行生成器;diff 中预期生成物单独归类,避免把大机械变化误当手写重构。

测试选择可以建模为覆盖风险的集合问题。候选测试 tit_i 有成本 cic_i 和覆盖变更风险集合 RiR_i,在预算内最大化覆盖。静态依赖与历史失败提供候选,隐藏动态注册和跨进程路径通过固定回归套件补充。算法只辅助选择,关键安全测试不能因估计成本高被排除。

增量测试后仍需根据改动类型扩大范围。共享类型、序列化、数据库与构建配置的影响常超出静态调用图。Agent 说明为何选这些测试,以及哪些未运行。用户可据此决定是否在 CI 继续全量验证。

不稳定测试要识别而非无限重跑。相同补丁多次运行有时成败,记录种子、资源和失败位置;重跑可以估计 flake,却不能把一次通过当修复。若任务修改了相关并发路径,flake 可能正是回归信号,不能自动排除。

测试命令自身可能有副作用,例如启动数据库、写快照、更新 golden 文件。执行器限制工作目录和环境,并在前后比较工作树。未经授权的 snapshot 更新不作为通过,新增产物要么纳入有意补丁,要么清理并说明。

补丁审查从语义和归属开始。每个 hunk 对应哪个完成谓词,是否修改公共接口,是否引入默认值、重试或权限变化。无法关联任务的 hunk 可能是顺手重构,应移除或给出必要依赖。行数统计只用于导航。

API 变更要扫描静态与动态消费者。类型系统找到直接引用,配置、反射、插件和文档示例可能通过字符串使用。仓库内搜索、运行时测试和发布清单共同覆盖。未发现外部消费者不代表不存在,库项目需遵循其版本政策。

数据库变化同时考虑事实源、缓存与迁移。SQLite 可重建缓存时优先更新 schema 与同步管道;真实业务库则需要数据迁移、备份、并发写与回滚。Agent 不把所有数据库都套入同一迁移模板。

前端状态修改要验证开页变化与刷新恢复。只做乐观 UI 可能刷新丢失,只做查询拉取可能开着页面假死。真实浏览器场景结合服务端事件、查询水合与跨标签状态,单元测试无法覆盖全部运行时竞态。

命令执行的环境差异经常造成“本地绿、CI 红”。Node、Python、系统库、时区、locale 与 CPU 架构进入运行元数据。能使用项目锁定工具链时不依赖宿主全局版本。缺失环境明确阻塞,不擅自升级依赖绕过。

构建缓存可以提高速度,却会隐藏缺失依赖或未声明输入。关键验收至少在干净环境运行一次;增量循环可使用缓存。若干净构建和热缓存结果不同,先修构建可重复性,再评价补丁。

安全扫描属于验证层之一。秘密扫描、依赖漏洞和静态规则提供风险信号,不能由模型自行忽略。误报需要具体抑制与依据,禁用整个规则会扩大范围。扫描数据库版本进入报告,结果随时间可能变化。

完整故障轨迹可以是并发自动保存 bug。Agent 初看组件 useEffect,提议增加 debounce;trace 显示服务端收到请求顺序正确,但旧响应晚到覆盖 store。问题位于状态 reducer,不是请求频率。Agent 转而定义版本单调与动作 ID 幂等。

它加入乱序响应单测,修 reducer 后测试通过。浏览器复现仍偶发空白,进一步发现流结束与消息落库没有 happens-before。系统新增显式 commit 事件和水合拉取,而非增加等待时间。最终在延迟注入下重复运行,确认刷新与跨标签一致。

若只根据最初症状改 debounce,测试可能在普通网络通过,却没有强制不变量。长程轨迹的价值在于新 observation 能推翻补丁方向,测试从复现工具升级为架构 verifier。

另一个案例是依赖升级。自动工具修改锁文件并运行单测,结果全绿;干净构建却执行新增 postinstall 脚本访问网络。沙箱阻断后,Agent 检查依赖来源与必要性,选择无脚本替代。功能验证和供应链验证共同决定终局。

代码生成模型还容易过拟合错误信息的字面措辞。评测改变路径、变量名和日志格式,保留相同根因,检查策略是否仍沿状态与调用链定位。只会在见过的错误文本上应用固定 patch,不算工程泛化。

SWE 类 benchmark 的隐藏测试提供可比较终局,却可能污染、覆盖不足或偏向小 patch。报告公开集表现时说明版本与防污染措施,并辅以私有真实任务。单一榜单无法覆盖工作树保护、权限和长程恢复。

pass@k 对代码候选有意义,因为补丁可以在隔离副本验证,但选择成本要计入。多个候选共享测试缓存可能互相污染,应独立或恢复快照。oracle 能找到成功补丁不等于 Agent 有能力在部署时选择它。

人类审查时间是重要成本。一个补丁自动测试通过,却包含巨大无关重排,会增加审查和回归风险。测量 diff 归属、解释证据和审查修改量,不能只统计模型 token。更小不一定更好,但每个变化都应有理由。

部署前交付可以分级:补丁草稿、已通过局部验证、已通过全量 CI、已提交、已推送。状态词与实际动作对应,模型不能把“代码已生成”描述成“修复已上线”。外部副作用越大,授权与 verifier 越严格。

线上回收只使用有权限的代码和日志。私有仓库内容不自动进入训练,秘密在 trace 前过滤。事故轨迹可抽取结构化错误与脱敏最小案例,保留删除 lineage。提高模型不能以复制用户代码为代价。

成熟 Coding Agent 的评价最终落在可复现仓库转换:从明确基线出发,经可审查动作,得到满足需求且通过相称验证的新状态。聊天流畅、补丁生成速度和工具数量都只是辅助指标。

仓库之外的协作状态也要纳入边界。Issue、代码评审、CI 和发布系统各有独立身份与版本。Agent 在本地修复成功,不代表远端分支仍可快进;创建 PR 前重新拉取目标分支并检查冲突,推送和发起评审分别授权。

评审意见可能互相冲突。一个 reviewer 要求保持兼容,另一个要求删除旧接口,Agent 不能按最近评论覆盖。系统把意见映射到需求谓词,标出最小冲突集,由负责人决策。未经裁决的冲突不会通过追加更多代码解决。

CI 失败要定位环境和补丁责任。某平台依赖下载失败可能是基础设施,只有 Windows 出现路径错误则是补丁跨平台缺陷。矩阵结果带运行镜像、提交与重试历史;只重跑到绿色会丢失真实稳定性。

代码审查中的建议并非都要执行。风格偏好、潜在优化、阻断缺陷和范围外需求分级,必要修改进入当前计划,其他建议记录后续。模型若为了满足所有评论扩大改动,会增加回归并延长交付。

发布说明从实际 diff、接口与迁移证据生成,不从模型想象补齐。破坏性变化、配置要求和已知限制由 verifier 对照产物检查。说明声称已修复但对应测试未运行时,状态应写成待验证。

回滚方案在部署前验证。可逆代码发布仍可能伴随不可逆数据迁移,简单切回二进制无法恢复旧 schema。Agent 区分 forward fix、代码回滚与数据补偿,并在演练环境确认步骤和权限。

长期维护还关注补丁留下的复杂度。临时分支、重复适配和永久 feature flag 会成为未来状态空间。若任务需要临时措施,记录移除条件、负责人和验证;没有生命周期的“临时”代码不算完整交付。

可解释性来自证据链,不要求公开模型全部推理。用户可以查看需求映射、修改文件、关键 diff、测试和未覆盖项。隐藏内部草稿既保护隐私,也避免把不可靠思维文本当工程依据。

因此 Coding Agent 的系统能力由模型、ACI、仓库状态机、执行沙箱和 verifier 共同决定。只升级模型可能提高候选质量,缺少其余边界仍会覆盖用户代码、误用缓存或在未知提交后重复操作。

系统发布还需保留一条无 Agent 的人工路径。自动工具不可用或判断不确定时,开发者能取得工作树、事件和验证证据继续处理;恢复后 Agent 从新的权威状态水合。把仓库锁在私有内部状态会让故障升级为数据不可用。

人工接管同样写入轨迹,区分人完成的修改与模型产物。后续训练不会把人工补丁误算成 Agent 成功,评测也能报告需要接管的比例和成本。

证据链保持完整。