官方长时任务与迭代修复案例:Review–Repair–Validate 闭环
把官方 repair loop 与 long-horizon 文章转译为有状态、有预算、有停止条件的修复系统。
先知道终点
- 做完你会得到
- 完成一个最多三轮、每轮都有新证据的自动修复实验
- 开始前只需要
- 有确定性测试或检查器;能把实现、review 与验证分开;实验不接触生产数据和不可逆动作
- 最后留下这些证据
- 每轮输入状态、finding、修改与验证;重试预算和重复失败停止记录;最终通过或诚实阻塞交接
内容校准于 2026-07-31 · 第 18 / 38 节已发布课程
跟着材料做,不只阅读
本节练习资料
修到第七轮,问题反而越来越多
第一轮 review 找到真实缺陷。修完以后,第二轮出现新回归。到了第七轮,列表里只剩风格建议,任务却仍然因为「还有发现」拒绝结束。
循环不会天然收敛。每次修复都会创造一个新候选状态。
Review–Repair–Validate 应该是一台有预算、有状态、有出口的机器。 这节课把官方长时案例拆成一张循环账本,重点看什么时候继续,什么时候回退,什么时候接受残余风险。
循环不是“继续,直到成功”
OpenAI Cookbook 的 iterative repair loop 可抽象为 Review、Repair、Validate:
- Review 读取当前状态并找具体问题;
- Repair 只修确认的问题;
- Validate 用独立检查器产生新证据;
- 根据证据决定完成、继续或停止。
长时任务文章进一步强调计划、执行、验证、修复和项目记忆。关键不是循环次数,而是每一轮必须缩小已知差距。没有新证据的重复不是进展。
一个闭环需要哪些状态
run-id:
iteration:
输入版本 / commit:
当前失败:
本轮 finding:
允许修改范围:
实际修改:
验证命令与结果:
与上轮差异:
剩余失败:
下一决策:
若缺少输入版本,下一轮可能基于已变化的状态却仍使用旧诊断。若缺少“与上轮差异”,循环可能重复同一修复。
Review:发现必须具体
Review 输出应该能触发:
- 精确到文件和最小范围;
- 说明输入条件;
- 解释错误行为;
- 指定可证伪的验证。
“代码可能有性能问题”不能直接进入 Repair。先建立可测量场景。Review 阶段默认不改代码,以免 finding 与工作树同时变化。
Repair:一次只修一个确认问题
Repair prompt:
只修复 finding F-02。
允许修改 [文件范围]。
保留 [公共行为与约束]。
不要顺便重构,不更新依赖,不处理其他 findings。
完成后展示最小 diff,并说明每处修改如何对应触发条件。
聚焦修改让下一步验证具有因果意义。如果一轮改十个无关问题,即使测试变绿也不知道真正原因。
Validate:独立于 agent 自述
验证器可以是测试、类型检查、schema、视觉比较、lint、数据对账或真实浏览器脚本。它应:
- 可重复;
- 对通过和失败有明确退出或结构化结果;
- 尽量不依赖本轮 Repair 的自然语言总结;
- 覆盖原触发条件与相邻回归;
- 记录环境和输入版本。
“Codex 重新看了一遍,认为已经解决”不算 Validate。
停止条件与预算
在循环开始前定义:
- 最多轮数或时间预算;
- 同一失败重复几次后停止;
- 失败集合不再缩小时停止;
- 需要新权限、外部服务或产品决定时停止;
- 变化超出允许文件或破坏基线时回退;
- 所有目标验证通过且 review 无高优先级 finding 时完成。
示例:
最多三轮。
同一测试连续两轮以相同堆栈失败,停止并交接。
新增依赖、修改公开 schema 或联网均需人工批准。
每轮结束保存 diff、测试 JSON 和状态表。
Harness engineering 给出的环境启示
官方 Harness engineering 文章讨论了为 agent 设计工作环境:仓库要可读、worktree 可启动、验证可执行、浏览器可观察、重复流程可沉淀。修复循环的上限往往不只由模型决定,还由“能否快速启动、能否得到确定反馈、失败是否可恢复”决定。
改善 harness 的例子:
- 提供一条可靠启动命令;
- 让测试输出结构化;
- 用 fixture 固定输入;
- 为页面变化保存双视口截图;
- 把项目规则写入 AGENTS.md;
- 把稳定循环沉淀为 Skill;
- 把 secrets、网络和生产动作隔离。
三轮实验
选择一个刻意带两个小错误的练习项目。运行最多三轮:
- 保存初始失败;
- Review 生成 findings;
- 人工确认一个 finding;
- Repair 最小范围;
- Validate;
- 更新状态并决定下一轮。
至少模拟一次停止:例如让一个检查器持续以相同错误失败,按规则交接而不是无限修。
失败交接格式
最后安全状态:
已通过验证:
仍失败验证:
重复模式:
已经排除:
需要的新信息或授权:
恢复命令:
未执行动作:
诚实阻塞是闭环的一种正确结果。伪造完成或无限重试才是失败。
完整案例:修复 47 个静态检查发现
一次 review 返回 47 条发现,其中有重复、误报、风格建议和真实缺陷。直接要求“全部修复”会让 repair 阶段扩大 diff,并可能为了消除告警改变行为。
第一轮先分类,不修改
| 类别 | 处理 |
|---|---|
| 可复现缺陷 | 建最小失败测试,进入修复 |
| 同根因重复项 | 合并为一个修复单元 |
| 缺少上下文 | 补调用链和运行证据 |
| 误报 | 记录反证,不修改 |
| 风格或偏好 | 与项目规则核对后再决定 |
Review 的输出是候选问题,不是自动授权的修改清单。
给每个修复窗口一个预算
本轮目标:修复 session 过期后仍返回缓存用户
允许文件:session-cache.ts、对应测试
基线:新增失败测试能稳定复现
停止条件:修复后原测试通过,相关缓存测试不回归
预算:不重构缓存接口,不处理其他 review 项
一次窗口只解决一个根因。这样 validate 失败时能知道是哪项变化造成。
Validate 不只是重跑同一检查器
三层验证:
- 原始反例:发现描述的行为不再出现;
- 相邻反例:有效 session、并发刷新和缓存失败仍正确;
- 独立检查:测试、类型、review 或真实运行从另一角度确认。
若只让同一个检查器从红变绿,可能只是迎合规则而没有修复用户问题。
识别修复振荡
典型振荡:
- A 修复让 B 检查失败;
- B 修复又恢复 A 的问题;
- diff 越来越大,证据没有增加。
此时停止自动循环,比较两条规则的真实目的、优先级和共同约束。可能需要架构决定或人工裁决,而不是更多 repair。
长循环的状态记录
每轮保存:
发现 ID 与原始证据:
分类与优先级:
本轮假设:
修改范围:
验证结果:
新增风险:
剩余发现:
是否继续及理由:
这样任务被中断后可以从证据恢复,而不是重新扫描、重复修复。
什么时候交给人判断
以下情况不适合继续自动 repair:两条规则目标冲突、修复会改变公共契约、没有稳定复现、需要业务决定,或验证环境本身不可信。人工接管不意味着 agent 失败;它是循环设计中的明确出口。交接应包含最小复现、已排除假设、两种选项和各自风险,让人只判断真正不可自动决定的部分。
人工决定后要把结论写回状态记录,并明确哪些旧发现因此关闭、哪些修复窗口需要重新运行。否则下一轮仍会从过期假设开始。
故障诊所
| 现象 | 原因 | 恢复 |
|---|---|---|
| 发现数下降但 diff 暴涨 | 追指标而非根因 | 回退本轮,按根因重组 |
| 同一项反复出现 | 修复未覆盖真实执行路径 | 重建最小复现并追调用链 |
| 误报也被强行改代码 | 缺少接受/拒绝标准 | 保存反证并关闭该项 |
| 循环永不结束 | 没有预算和停止条件 | 设置轮次、范围与人工接管点 |
知识检查
Review 剩下两条低优先级风格建议时,Goal 是否必须继续到零发现?不一定。若它们不在验收范围、与项目规则无关或修改风险更高,应记录未处理原因并停止。
先写出口,再启动循环
为你的修复任务写下最大轮次、时间预算、必须清零的风险和允许保留的问题。每轮只对一个明确候选做 review、repair 和 validate。
没有出口的循环不是负责,它只是把停止决策推迟。能解释为什么结束,才算真正控制了长期任务。
完成检查
- Review、Repair、Validate 三阶段分离
- 每轮绑定输入版本和新证据
- Repair 只处理确认 finding
- 验证器独立、可重复、覆盖触发条件
- 重试预算和停止条件在开始前定义
- 最终通过或阻塞都留下可恢复状态
参考与校准来源
本文是官方资料的中文转译与教学重组,不是逐字翻译;产品能力、命令、默认值与安全边界以下列官方原文为准。