Skip to content

[Harness Epic] 不再相信 Agent 自称完成:用真实检查决定任务是否成功 #94

Open

Description

@rojim666

这条 Issue 要解决什么

现在,只要模型结束回答,Agent Loop 就可能把任务标记为成功;达到步数上限时,模型输出 [COMPLETE] 也能得到成功状态。

这只能证明“模型不准备继续了”,不能证明:

  • 代码真的修好了;
  • 测试真的通过了;
  • 用户要求全部满足;
  • 没有改坏其他功能;
  • 测试通过后代码没有再次变化。

本 Issue 要让 Harness 成为裁判:模型可以说“我完成了”,但最终是否成功必须由与用户要求对应的真实检查决定。

用一个实际场景说明

用户要求:“修复删除按钮误删数据的问题,并补测试。”

Agent 修改了代码,随后说“已经完成并通过测试”,但实际情况可能是:

  • 根本没有运行测试;
  • 只运行了一个无关测试;
  • 测试命令返回成功,但没有覆盖误删场景;
  • 测试通过后,Agent 又改了代码;
  • 仓库本来就有失败,Agent 没说明哪些是旧问题;
  • 子 Agent 在 JSON 里写了 test_summary: passed,Harness 就把它当成证据。

成熟 Harness 应能区分这些情况,而不是都显示“完成”。

当前实现的具体限制

  • AgentLoop 在模型返回 end_turn 时直接 mark_success();
  • _conclude() 通过模型输出的 [COMPLETE] 判断是否完成;
  • system prompt 只是在文字上提醒模型测试,不是强制规则;
  • TestResultEvent 主要通过 Bash 命令里是否出现 pytest、vitest 等关键词识别测试;
  • Workflow 检查 Tester/Reviewer 返回的命令、输出和总结是否非空,但这些内容仍可能只是 Agent 自己填写;
  • sztu-eval 已经具备“Agent 运行结束后独立执行验证”的能力,但这套判断没有用于普通任务;
  • 当前 CI 验证项目代码本身,却没有系统测试“模型谎称完成、证据过期、修复反复失败”等 Harness 行为。

主要入口:

  • src/sztu_code/core/loop.py
  • src/sztu_code/core/context.py
  • src/sztu_code/core/tools/invocation.py
  • src/sztu_code/core/workflow/orchestrator.py
  • src/sztu_code/core/workflow/evaluation.py
  • src/sztu_code/evaluation/

修改后应该是什么样

1. 把“程序停了”和“任务成功了”分开

至少分别记录:

  • 执行状态:正在运行、等待、已经停止;
  • 修改状态:没有修改、待审核、有冲突、已接受、已撤销、存在未知副作用;
  • 验证结果:已证明成功、只验证了一部分、未验证、验证失败、环境阻塞、无法判断。

例如,模型正常结束但没跑测试,应显示“执行结束,修改待审核,尚未验证”,而不是“成功”。

2. 开始任务时明确“怎样才算完成”

把用户要求转换成一份完成条件,例如:

  • 删除操作必须有二次确认;
  • 取消确认后数据不能变化;
  • 删除失败时界面显示错误;
  • 相关测试通过;
  • 不得修改数据库迁移文件。

完成条件来源可以包括用户要求、项目配置、CI、仓库开发说明和 Agent 建议,但必须标明来源。用户明确提出的条件,Agent 不能在执行过程中自行删除或降低。

3. 每条完成条件都要有真实证据

证据不能只是一句“测试通过”,至少要记录:

  • 验证了哪条要求;
  • 针对哪个代码版本;
  • 实际执行的命令或检查;
  • 工作目录和关键环境;
  • 退出码、测试数量和失败项;
  • 原始输出保存位置;
  • 检查结果是否仍然有效。

如果测试通过后代码又发生变化,原测试自动变成“已过期”,不能继续用来证明新代码正确。

4. 验证由 Harness 独立运行

Agent 可以建议验证命令,但真正用于判定成功的检查由 Harness 自己执行和记录。

Harness 应从以下位置发现项目验证方式:

  • pyproject.toml、package scripts、Cargo/Go 配置;
  • CI workflow;
  • 测试目录和项目开发文档;
  • 已有的 lint、typecheck、build 和生成文件检查。

它不需要每次运行全部测试,而是先根据改动范围选择相关、成本合适的检查;高风险改动再扩大验证范围。

5. 验证失败后自动进入修复闭环

失败后不要只把几千行日志重新丢给模型。Harness 应:

  1. 判断是代码问题、旧失败、测试环境问题、权限问题、超时还是偶发失败;
  2. 提取最相关的报错、修改内容和失败测试;
  3. 让 Agent 进行下一次修复;
  4. 先重跑失败检查,再运行可能受影响的回归检查;
  5. 保存每轮“为什么修改、改了什么、结果如何”。

如果相同错误反复出现,或者代码在 A/B 两种改法之间来回切换,应停止并明确报告,不无限消耗模型调用。

6. 验证结果控制接受和暂存

对于要求验证的任务:

  • 验证失败时不能显示成功;
  • 测试证据已经过期时不能直接接受;
  • 工作区存在冲突或未知副作用时,即使测试通过也不能自动标记为完全成功;
  • 用户可以明确选择跳过某项检查,但要记录是谁、为什么、跳过了什么。

必须保证的规则

  • 模型的话是“声明”,不是“证据”。
  • [COMPLETE] 和 end_turn 不能直接产生“已验证成功”。
  • 每个成功结论都能追溯到用户要求、代码版本和真实检查结果。
  • 代码变化后,旧验证结果自动失效。
  • 验证失败不能被最后一段成功总结覆盖。
  • 仓库已有失败、Agent 新增失败、环境故障和偶发失败必须分开报告。
  • Reviewer 的 LGTM 不能替代测试或实际检查。
  • 无法验证时诚实显示“未验证”或“环境阻塞”,不能伪装成成功。

建议分阶段实现

第一阶段:完成条件和真实证据

  • 定义 CompletionContract、Evidence 和 VerificationResult;
  • 普通 Agent 结束后不再默认已验证;
  • 支持用户显式验证要求和项目固定检查;
  • 把验证结果绑定到工作区版本。

第二阶段:自动选择检查并修复

第三阶段:持续评测 Harness 自己

  • 把真实失败整理为脱敏、版本化的回归任务;
  • CI 运行不需要真实模型的 Harness 行为测试;
  • 定期运行真实模型和 SWE-bench;
  • 报告已验证成功率、误报成功率、未验证比例、成本和耗时。

验收标准

  • 模型直接说“完成”但没有运行检查时,结果只能是“未验证”。
  • 模型伪造“测试通过”,但 Harness 独立运行失败时,最终结果必须失败。
  • 测试通过后再修改任意相关代码,旧证据立即过期,不能用于接受或暂存。
  • 每个“已验证成功”都能查到对应完成条件、代码版本、验证命令、退出码和原始输出。
  • 人为注入一次测试失败后,系统能完成“发现失败—修复—重新验证”的完整过程并保留两轮记录。
  • 仓库旧失败、Agent 引入的新失败、环境缺失和偶发失败得到不同结果分类。
  • 同一错误连续出现或修改来回震荡达到阈值后,系统停止自动修复并说明原因。
  • CI 包含以下固定场景:模型谎称完成、无关测试通过、证据过期、环境阻塞、偶发失败、工作区冲突和未知副作用。

和现有 Issue 的关系

本 Epic 负责把这些能力接入每天真实运行的“是否完成”判断,而不是只做离线评分。

维护者备注

底层可以使用“完成条件—证据—结论”的关联图,但用户和普通贡献者不需要理解图结构。对外最重要的是:每条要求是否满足、证据是什么、针对哪个代码版本、为什么最终得到成功或失败。

Activity

  1. added
    area/testing自动化测试与回归保障
    area/harness编码 Agent 的任务生命周期、工作区事务、验证反馈与评测闭环
    on Aug 13, 2026
  2. changed the title [-][Harness Epic] 建立证据驱动的完成门禁与自动修复闭环[/-] [+][Harness Epic] 建立 Outcome Kernel:用版本化证据图判定完成并驱动修复[/+] on Aug 13, 2026
  3. changed the title [-][Harness Epic] 建立 Outcome Kernel:用版本化证据图判定完成并驱动修复[/-] [+][Harness Epic] 不再相信 Agent 自称完成:用真实检查决定任务是否成功[/+] on Aug 13, 2026
  4. LambertClark commented on Aug 20, 2026

    @LambertClark
    Collaborator

    我想认领这个 issue。按 CONTRIBUTING 的要求先说明方案和计划:
    方案:拆成 4 个可独立 Review 的堆叠 PR,自底向上实现验证门禁

    1. 验证数据模型与协议事件:新增 CompletionContract / CompletionCheck 数据模型,以及 VerificationStartedEvent /VerificationFinishedEvent 事件类型,并扩展 RunFinishedEvent 携带验证结果字段。纯增量,不改变现有行为。
    2. 验证执行与门禁:新增 check executor,在任务收尾时真实执行契约中声明的检查(命令退出码等),用检查结果而非 Agent 自述决定 run 的成功状态。
    3. 契约自动发现:从项目配置/约定位置自动发现可用检查(如 lint、test 命令),无契约时保持现状(不破坏现有用户)。
    4. 修复闭环:检查失败时把失败证据回喂给 Agent 进行有限次修复重试,带三重熔断(最大轮次/无进展/超时)防止死循环。

    验证方式:每层配套单元测试(合计 36 个),全量测试套件与 main 基线对比零新增失败,mypy/ruff 通过。
    兼容性:默认无契约时行为完全不变;RunFinishedEvent 新字段为可选字段,TS protocol 包的同步计划在后续跟进(会在 PR 中注明)。
    预计时间:方案已在本地 fork 完成开发和验证,确认认领后提交第一个 PR,后续 PR 随前置合入依次提交。

  5. LambertClark commented on Aug 20, 2026

    @LambertClark
    Collaborator

    第一个 PR 已提交:#112(第 1 层,验证数据模型层)。后续三层(verification-gating → check-discovery → repair-loop)将随前置 PR 合入依次提交。

  6. LambertClark commented on Aug 25, 2026

    @LambertClark
    Collaborator

    实施进度(Python 四层已全部合入,进入 TS runtime parity 阶段)

    Python 侧(src/sztu_code)— 已完成 ✅

    Python 运行时现在已具备完整的验证门禁能力:任务完成不再依赖模型自称,而是由真实检查裁决;发现不到检查时结果只能是 unverified。

    TypeScript 侧(产品主线 parity)— 进行中

    接下来把同样的验证门禁带到 TS runtime(当前 run-manager 在 loop 结束后直接标记 success,agent-loop 的 conclude 仍依赖 [COMPLETE] 文本标记,与本 issue 要消除的模式一致):

    • Layer 5 — protocol 扩展:packages/protocol 新增 VerificationOutcome 等类型,RunFinishedEvent 增加可选验证结果字段(向后兼容)
    • Layer 6 — TS runtime 验证门禁:packages/runtime-ts/src/verification/(models / executor / discovery / repair),接入 run-manager 成功路径与 settings 配置
    • (可选)桌面端时间线展示验证状态

    最后一个 PR 将以 Closes #94 收尾。如对 TS 侧拆分粒度有不同意见欢迎指出。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area/evaluation评测模块area/harness编码 Agent 的任务生命周期、工作区事务、验证反馈与评测闭环area/testing自动化测试与回归保障challenge/C4-collaboration人机及多智能体协作priority/P0必须优先解决type/epic大型课题

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions