Harness Engineering实战:防止 Agent 过早宣告完成(Why Agents Declare Victory Too Early)

Harness Engineering实战:防止 Agent 过早宣告完成(Why Agents Declare Victory Too Early)

课程原文:https://walkinglabs.github.io/learn-harness-engineering/zh/lectures/lecture-09-why-agents-declare-victory-too-early/

0. 一句话核心

Agent 系统性过早宣称任务完成 ,因为它依据"代码层面的局部信心"判断;而系统级正确性需要全局验证。

Harness 必须用基于执行的外部验证替代 Agent 的"感觉"------把"完成判定"从主观变客观。

1. 为什么 Agent 会"提前交卷"

  • 过度自信(校准偏差):Guo et al. 2017(ICML)证明现代神经网络置信度系统性高于准确率;AI 编码 Agent 同样"觉得"做完了,实际差得远。
  • 滑坡效应(Slippery Slope):代码看着还行、静态检查无误,但 harness 未强制全面执行验证 → Agent 跳过实际运行/部分测试 → 每次跳过加剧信息不对称(任务规范→代码实现→运行时行为持续丢失)。
  • 同一模型既生成又评估会系统性过度正面评价(Anthropic 2026):即使人类认为不达标,Agent 也会给自己打高分。

2. 本课关键概念 → 代码映射

概念(原文) 落地的类 / 文件 作用
终止标准(Termination Criteria) model/TerminationCriterion.java + state/TERMINATION.md 把"什么叫做完"固化为外部化、机器可读的 required 标准
三层终止校验 harness/gates/TerminationGate.java STATIC→RUNTIME→SYSTEM 层层门控,低层不过不许进高层
过早完成声明(Premature Victory) TerminationGate.evaluate 返回 PREMATURE_VICTORY Agent 声称完成但标准未全过即判过早
验证-确认双闸门(V&V Dual Gate) harness/gates/VerificationValidationGate.java Verification(代码实现行为)+ Validation(系统端到端)两层都过才算完成
完成优先级约束(Completion Priority) harness/state/CompletionPriorityGuard.java 核心未验证前禁止重构/性能/风格("顺便重构"是毒药)
生成与评估分离 harness/skills/EvaluatorSkill.java 独立、刻意挑剔的评估者,可否决生成者过度自信声明
运行时反馈信号 harness/state/RuntimeSignalCollector.java 应用启动/健康检查/关键路径/副作用/临时资源清理
可操作错误反馈 harness/skills/ActionableFeedbackGenerator.java 把 "Test failed" 转成含修复步骤的反馈
置信度校准偏差 model/ConfidenceCalibration.java 量化自报信心 vs 实际质量的系统性偏差

3. 三条你必须记住的 Harness 纪律

  1. 完成判定外部化 :Agent 不许自己宣布"做完了"。是否完成由 TerminationGate 依据运行时信号独立判定。
  2. 三层缺一不可:语法、行为、系统,层层递进。单元测试通过只是 RUNTIME 的极小一部分,不构成停止信号。
  3. 核心验证前不许重构:核心功能没验证通过就开始重构/优化,会把隐式正确的路径改坏。

注:

博客:

https://blog.csdn.net/badao_liumang_qizhi

4. 项目结构与运行

复制代码
spring-ai-alibaba-bailian-harness-victory/
├── pom.xml
├── src/main/java/com/badao/ai/
│   ├── SpringAiDemoApplication.java
│   ├── model/        TerminationCriterion / VictoryClaim / ConfidenceCalibration
│   ├── harness/
│   │   ├── gates/    TerminationGate / VerificationValidationGate   (三层门控 + V&V 双闸门)
│   │   ├── skills/   EvaluatorSkill / ActionableFeedbackGenerator    (评估分离 + 可操作反馈)
│   │   └── state/    CompletionPriorityGuard / RuntimeSignalCollector(优先级 + 运行时信号)
│   ├── service/      VictoryService             (编排演示链路)
│   ├── controller/   VictoryController          (/api/victory/demo, /report)
│   ├── runner/       VictoryDemoRunner          (启动即演示)
│   └── config/       VictoryConfig              (模块化指令)
├── src/main/resources/instructions/
│   ├── AGENTS.md
│   ├── docs/         termination-criteria.md / actionable-feedback.md / anti-pattern.md
│   └── legacy/       SELF_APPROVAL.md           (反面教材:让 Agent 自己审批自己)
├── src/test/java/com/badao/ai/   7 个测试(见下)
└── state/            TERMINATION.md / DECISIONS.md / HANDOFF.md  (跨会话单一来源)

运行:

bash 复制代码
mvn test                                  # 验证三层门控 / 校准 / 多层防御 / 双闸门 / 反馈 / 评估分离
mvn spring-boot:run
curl -X POST "http://localhost:888/api/victory/demo"    # 看"提前交卷→被捕获→强制端到端→确认胜利"
curl "http://localhost:888/api/victory/report"          # 查看外部化终止标准

5. 课后练习的落地(Project 05:让 Agent 自己检查自己做的对不对)

练习 测试文件 验证点
1. 终止校验函数设计 TerminationGateTest 三层门控(低层不过禁止进高层)+ 过早完成检测 + 缺失标准定位
2. 校准偏差测量 ConfidenceCalibrationTest 复杂任务正偏差、简单任务低偏差、越界拒绝
3. 多层防御实验 MultiLayerDefenseTest (a)仅静态/(b)+单测/©完整三层:过早完成比例 5→5→1,捕获 4 个缺陷
完成优先级 CompletionPriorityTest 核心未验证拒绝重构,验证后允许
V&V 双闸门 VerificationValidationTest 两层都过才算完成;单测过≠完成
可操作反馈 ActionableFeedbackTest 反馈含修复步骤、比原始错误更长
生成/评估分离 EvaluatorSeparationTest 评估者否决过度自信声明,结论不随自报信心变化

6. 一个完整例子(密码重置功能)

  • 提前交卷路径:改 schema、写 API、加邮件模板、单元测试通过、声明完成。
  • 实际遗漏:(1) 端到端流程未测;(2) DB 迁移部分失败致 schema 不一致;(3) 邮件服务配置缺失。
  • Harness 介入TerminationGate 强制三层校验 → 仅在 C1/C2 过时判 PREMATURE_VICTORY,列出缺失 C3/C4/C5;
    EvaluatorSkill 因缺少客观端到端证据否决生成者(confidence=0.95);缺陷在会话内发现,节省 5-10 倍后续修复成本。

关键代码:

VictoryConfig:

复制代码
package com.badao.ai.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;

import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * 终止校验相关的指令配置(模块化指令风格)。
 * 入口概览常驻,专题文档按需加载,避免巨型任务说明(见 legacy/SELF_APPROVAL.md)。
 */
@Configuration
public class VictoryConfig {

    /** 入口指令:概览 + 硬约束(完成判定外部化等) + 文档索引 */
    @Bean
    public String entryInstructions() throws IOException {
        return load("instructions/AGENTS.md");
    }

    /** 终止标准:定义三层校验、门控关系、校准偏差时加载 */
    @Bean
    public String terminationCriteria() throws IOException {
        return load("instructions/docs/termination-criteria.md");
    }

    /** 可操作反馈:设计/对比"无效 vs 可操作"错误反馈时加载 */
    @Bean
    public String actionableFeedback() throws IOException {
        return load("instructions/docs/actionable-feedback.md");
    }

    /** 反面教材:让 Agent 自己审批自己 */
    @Bean
    public String selfApproval() throws IOException {
        return load("instructions/legacy/SELF_APPROVAL.md");
    }

    /**
     * 按场景组装提示词:规划阶段给"终止标准",实现阶段给"可操作反馈"。
     */
    public String buildPromptForPhase(String phase) throws IOException {
        StringBuilder sb = new StringBuilder();
        sb.append(entryInstructions()).append("\n\n");
        if ("plan".equals(phase)) {
            sb.append("【当前阶段:定义外部化终止标准】先把'什么叫做完'拆成三层 required 标准。\n");
            sb.append(terminationCriteria());
        } else {
            sb.append("【当前阶段:实现+验证】单元测试通过 ≠ 完成;错误必须转成可操作反馈。\n");
            sb.append(actionableFeedback());
        }
        return sb.toString();
    }

    private String load(String path) throws IOException {
        ClassPathResource r = new ClassPathResource(path);
        return new String(r.getInputStream().readAllBytes(), StandardCharsets.UTF_8);
    }
}

TerminationGate:

复制代码
package com.badao.ai.harness.gates;

import com.badao.ai.model.TerminationCriterion;
import com.badao.ai.model.VictoryClaim;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 终止闸门(Termination Gate)------第九讲的核心 Harness 原语:<b>三层终止校验</b>。
 *
 * <p>它把"完成判定"从 Agent 主观感觉外部化到 Harness,输入是运行时信号而非置信度。
 * 三层递进、层层门控:
 * <ol>
 *   <li>STATIC(语法/静态):最低成本,必须通过</li>
 *   <li>RUNTIME(运行时行为):核心证据</li>
 *   <li>SYSTEM(系统级端到端):最后防线</li>
 * </ol>
 * 低层未全通过,禁止进入高层;三层全部 required 标准通过,才允许声明胜利。
 * 若 Agent 提前声称完成而标准未全过,判为 {@link Verdict#PREMATURE_VICTORY}(过早完成)。
 */
@Component
public class TerminationGate {

    private static final Logger log = LoggerFactory.getLogger(TerminationGate.class);

    public enum Verdict {
        /** 三层全部 required 标准通过 → 可确认胜利 */
        VICTORY_CONFIRMED,
        /** Agent 声称完成,但 required 标准未全过 → 过早完成声明 */
        PREMATURE_VICTORY,
        /** 未声明完成、且尚未全部通过 */
        INCOMPLETE
    }

    /**
     * 层门控:判断能否进入目标层。
     * STATIC 永远可进入;RUNTIME 需 STATIC 全过;SYSTEM 需 STATIC+RUNTIME 全过。
     */
    public boolean canEnterLayer(TerminationCriterion.Layer target, List<TerminationCriterion> criteria) {
        if (target == TerminationCriterion.Layer.STATIC) return true;
        if (target == TerminationCriterion.Layer.RUNTIME) return allPassed(criteria, TerminationCriterion.Layer.STATIC);
        if (target == TerminationCriterion.Layer.SYSTEM) {
            return allPassed(criteria, TerminationCriterion.Layer.STATIC)
                    && allPassed(criteria, TerminationCriterion.Layer.RUNTIME);
        }
        return false;
    }

    private boolean allPassed(List<TerminationCriterion> criteria, TerminationCriterion.Layer layer) {
        return criteria.stream()
                .filter(c -> c.getLayer() == layer && c.isRequired())
                .allMatch(TerminationCriterion::isPassed);
    }

    /**
     * 终止判定(外部化,不信任 Agent 感觉):
     * 只有三层全部 required 标准通过,才允许声明胜利;
     * Agent 若提前声称完成,则判为 {@link Verdict#PREMATURE_VICTORY}。
     */
    public TerminationReport evaluate(VictoryClaim claim, List<TerminationCriterion> criteria) {
        boolean staticOk = allPassed(criteria, TerminationCriterion.Layer.STATIC);
        boolean runtimeOk = allPassed(criteria, TerminationCriterion.Layer.RUNTIME);
        boolean systemOk = allPassed(criteria, TerminationCriterion.Layer.SYSTEM);
        boolean allOk = staticOk && runtimeOk && systemOk;

        if (claim.isDeclaredDone() && !allOk) {
            log.warn("【终止判定】检测到过早完成声明:agent 声称完成(confidence={}),但 静态={} 运行时={} 系统={}",
                    claim.getSelfConfidence(), staticOk, runtimeOk, systemOk);
            return new TerminationReport(Verdict.PREMATURE_VICTORY, staticOk, runtimeOk, systemOk, missingCriteria(criteria));
        }
        if (allOk) {
            log.info("【终止判定】三层全部通过,确认胜利");
            return new TerminationReport(Verdict.VICTORY_CONFIRMED, true, true, true, List.of());
        }
        return new TerminationReport(Verdict.INCOMPLETE, staticOk, runtimeOk, systemOk, missingCriteria(criteria));
    }

    private List<String> missingCriteria(List<TerminationCriterion> criteria) {
        return criteria.stream()
                .filter(c -> c.isRequired() && !c.isPassed())
                .map(TerminationCriterion::getId)
                .toList();
    }

    /** 终止判定报告 */
    public record TerminationReport(Verdict verdict, boolean staticOk, boolean runtimeOk,
                                    boolean systemOk, List<String> missing) {
        /** 是否过早完成声明 */
        public boolean premature() {
            return verdict == Verdict.PREMATURE_VICTORY;
        }

        /** 是否确认胜利 */
        public boolean confirmed() {
            return verdict == Verdict.VICTORY_CONFIRMED;
        }
    }
}

VerificationValidationGate:

复制代码
package com.badao.ai.harness.gates;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 验证-确认双闸门(Verification-Validation Dual Gate)------第九讲"V&V 双闸门"。
 *
 * <ul>
 *   <li><b>Verification(第一层验证)</b>:代码是否正确实现了"指定行为"(对应 RUNTIME 层)。
 *       单元测试通过只覆盖这一层的极小一部分,无法暴露接口不匹配 / 状态传播错误 / 环境依赖。</li>
 *   <li><b>Validation(第二层确认)</b>:系统级行为是否满足"端到端需求"(对应 SYSTEM 层)。</li>
 * </ul>
 * 两层都过才算完成;任一不过即视为未完成。
 */
@Component
public class VerificationValidationGate {

    private static final Logger log = LoggerFactory.getLogger(VerificationValidationGate.class);

    /**
     * 执行 V&V 双闸门检查。
     *
     * @param codeImplementsBehavior 代码是否实现了指定行为(Verification)
     * @param endToEndSatisfied       系统级端到端需求是否满足(Validation)
     */
    public VVReport check(boolean codeImplementsBehavior, boolean endToEndSatisfied) {
        boolean v = codeImplementsBehavior;
        boolean val = endToEndSatisfied;
        if (!v) {
            log.warn("【Verification 失败】代码未正确实现指定行为(接口不匹配 / 状态传播错误 / 环境依赖)");
        } else if (!val) {
            log.warn("【Validation 失败】系统级端到端需求未满足(单元测试通过 ≠ 任务完成)");
        } else {
            log.info("【V&V 双闸门】验证 + 确认均通过");
        }
        return new VVReport(v, val, v && val ? "OK" : "FAIL");
    }

    /** V&V 报告 */
    public record VVReport(boolean verificationPassed, boolean validationPassed, String detail) {
        /** 两层都过才算完成 */
        public boolean bothPassed() {
            return verificationPassed && validationPassed;
        }
    }
}

ActionableFeedbackGenerator:

复制代码
package com.badao.ai.harness.skills;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 可操作反馈生成器(Actionable Feedback Generator)------第九讲"可操作错误反馈"。
 *
 * <p>把"无效反馈"(如 {@code "Test failed"})转成<b>含具体修复步骤</b>的反馈:
 * 明确错在哪、怎么改。仅说"错了"不够,Agent 会在同一处反复失败。
 */
@Component
public class ActionableFeedbackGenerator {

    private static final Logger log = LoggerFactory.getLogger(ActionableFeedbackGenerator.class);

    /**
     * 把原始错误转成可操作反馈。
     *
     * @param rawError 原始错误现象(如 "Test failed" / "POST /api/reset-password returned 500")
     * @param fixHint  具体修复步骤(定位线索 + 可执行动作)
     * @return 形如 "错误: <rawError> | 修复步骤: <fixHint>" 的可操作反馈
     */
    public String makeActionable(String rawError, String fixHint) {
        String actionable = String.format("错误: %s | 修复步骤: %s", rawError, fixHint);
        log.info("【可操作反馈】{}", actionable);
        return actionable;
    }
}

EvaluatorSkill:

复制代码
package com.badao.ai.harness.skills;

import com.badao.ai.model.VictoryClaim;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 评估者技能(Evaluator Skill)------第九讲"生成与评估分离"的落地。
 *
 * <p>基于 Anthropic 2026 研究:同一模型既生成又评估会系统性过度正面评价。
 * 因此本组件刻意扮演一个<b>独立、挑剔</b>的评估角色("检查的人"),
 * 不信任生成者("干活的人")的自评,而是基于独立收集的运行时客观证据重新判定。
 *
 * <p>当生成者自信地声称完成、但独立证据未满足端到端需求时,评估者<b>否决</b>该声明,
 * 把"过早完成"挡在门外。
 */
@Component
public class EvaluatorSkill {

    private static final Logger log = LoggerFactory.getLogger(EvaluatorSkill.class);

    /**
     * 独立评估生成者的胜利声明。
     *
     * @param generatorClaim    生成者(干活的人)的自评与胜利声明
     * @param objectiveEvidence 独立收集的运行时客观证据是否满足端到端需求
     * @return 评估结论:是否真的可以宣告胜利
     */
    public EvaluationReport evaluate(VictoryClaim generatorClaim, boolean objectiveEvidence) {
        if (generatorClaim.isDeclaredDone() && objectiveEvidence) {
            log.info("【评估者】生成者声称完成且独立证据支持,确认胜利");
            return new EvaluationReport(true, true, "生成者自评与独立证据一致");
        }
        if (generatorClaim.isDeclaredDone() && !objectiveEvidence) {
            log.warn("【评估者否决】生成者过度自信(confidence={}),但独立证据未满足端到端,判定为过早完成",
                    generatorClaim.getSelfConfidence());
            return new EvaluationReport(false, false, "评估者否决生成者自评:缺少客观端到端证据");
        }
        return new EvaluationReport(false, false, "尚未声明完成");
    }

    /** 评估结论 */
    public record EvaluationReport(boolean objectiveMet, boolean victoryAllowed, String detail) {
        /** 评估者是否允许宣告胜利 */
        public boolean overridesGenerator() {
            return !victoryAllowed;
        }
    }
}

CompletionPriorityGuard:

复制代码
package com.badao.ai.harness.state;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

/**
 * 完成优先级守门(Completion Priority Guard)------第九讲"完成优先级约束"。
 *
 * <p>先验证功能正确性,再处理性能,最后管风格。
 * <b>核心功能验证通过前,禁止重构 / 优化 / 风格调整</b>------
 * "顺便重构"是完成判定的毒药:它会改变"已验证 / 未验证"边界,
 * 可能破坏之前隐式正确的路径(Knuth:过早优化是万恶之源的新含义)。
 */
@Component
public class CompletionPriorityGuard {

    private static final Logger log = LoggerFactory.getLogger(CompletionPriorityGuard.class);

    private boolean coreFunctionalVerified = false;

    /** 标记核心功能已验证通过,进入性能 / 风格阶段 */
    public void markCoreFunctionalVerified() {
        this.coreFunctionalVerified = true;
        log.info("【完成优先级】核心功能已验证通过,可进入性能 / 风格阶段");
    }

    public boolean isCoreFunctionalVerified() {
        return coreFunctionalVerified;
    }

    /**
     * 请求重构 / 优化 / 风格调整。核心未验证则拒绝(防止过早优化破坏正确路径)。
     *
     * @param reason 重构理由
     */
    public RefactorDecision requestRefactor(String reason) {
        if (coreFunctionalVerified) {
            log.info("【重构】允许:{}", reason);
            return new RefactorDecision(true, "核心已验证,允许重构");
        }
        log.warn("【重构被拒】核心功能尚未验证通过,禁止重构(过早优化的毒药)。理由={}", reason);
        return new RefactorDecision(false, "核心功能未验证,禁止重构");
    }

    /** 重构决策 */
    public record RefactorDecision(boolean allowed, String detail) {
    }
}

RuntimeSignalCollector:

复制代码
package com.badao.ai.harness.state;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.EnumMap;
import java.util.Map;

/**
 * 运行时信号采集器(Runtime Signal Collector)------第九讲"运行时反馈信号是客观基础"。
 *
 * <p>完成质量不以 Agent 感觉为准,而以程序执行的客观信号为准:
 * 应用是否成功启动就绪、健康检查是否通过、关键功能路径运行时是否成功、
 * 副作用(DB 写入 / 文件操作)是否正确、临时资源是否清理。
 */
@Component
public class RuntimeSignalCollector {

    private static final Logger log = LoggerFactory.getLogger(RuntimeSignalCollector.class);

    /** 五类运行时反馈信号 */
    public enum Signal {
        /** 应用是否成功启动就绪 */
        APP_STARTED,
        /** 健康检查通过 */
        HEALTH_CHECK,
        /** 关键功能路径运行时成功 */
        CRITICAL_PATH_OK,
        /** 副作用(DB 写入 / 文件操作)是否正确 */
        SIDE_EFFECTS_CORRECT,
        /** 临时资源已清理 */
        TEMP_RESOURCES_CLEANED
    }

    private final Map<Signal, Boolean> signals = new EnumMap<>(Signal.class);
    private final Map<Signal, String> evidence = new EnumMap<>(Signal.class);

    /** 记录一条运行时信号及其证据 */
    public void record(Signal signal, boolean ok, String evidenceMsg) {
        signals.put(signal, ok);
        evidence.put(signal, evidenceMsg == null ? "" : evidenceMsg);
        log.info("【运行时信号】{} = {} ({})", signal, ok, evidenceMsg);
    }

    /** 全部信号是否全绿(且五类均已采集) */
    public boolean allGreen() {
        if (signals.size() != Signal.values().length) return false;
        return signals.values().stream().allMatch(Boolean::booleanValue);
    }

    /** 当前信号快照(不可变) */
    public Map<Signal, Boolean> snapshot() {
        return Map.copyOf(signals);
    }
}

VictoryService:

复制代码
package com.badao.ai.service;

import com.badao.ai.harness.gates.TerminationGate;
import com.badao.ai.harness.gates.VerificationValidationGate;
import com.badao.ai.harness.skills.ActionableFeedbackGenerator;
import com.badao.ai.harness.skills.EvaluatorSkill;
import com.badao.ai.harness.state.CompletionPriorityGuard;
import com.badao.ai.harness.state.RuntimeSignalCollector;
import com.badao.ai.model.TerminationCriterion;
import com.badao.ai.model.VictoryClaim;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

/**
 * 终止校验服务(Victory Service)------把第九讲各 Harness 组件编排成"防过早完成"流程。
 *
 * <p>演示链路:构建外部化终止标准 → Agent 在"单元测试通过"后提前宣称完成
 * → 三层终止校验捕获过早完成 → 强制端到端验证 → 最终确认胜利;
 * 并演示完成优先级约束、生成/评估分离、可操作反馈、V&V 双闸门。
 */
@Service
public class VictoryService {

    private static final Logger log = LoggerFactory.getLogger(VictoryService.class);

    private final TerminationGate terminationGate;
    private final VerificationValidationGate vvGate;
    private final EvaluatorSkill evaluator;
    private final CompletionPriorityGuard priorityGuard;
    private final RuntimeSignalCollector signalCollector;
    private final ActionableFeedbackGenerator feedbackGen;

    public VictoryService(TerminationGate terminationGate, VerificationValidationGate vvGate,
                          EvaluatorSkill evaluator, CompletionPriorityGuard priorityGuard,
                          RuntimeSignalCollector signalCollector, ActionableFeedbackGenerator feedbackGen) {
        this.terminationGate = terminationGate;
        this.vvGate = vvGate;
        this.evaluator = evaluator;
        this.priorityGuard = priorityGuard;
        this.signalCollector = signalCollector;
        this.feedbackGen = feedbackGen;
    }

    /**
     * 完整演示:Agent 在"单元测试通过"后提前宣告完成 → 三层终止校验捕获过早完成 →
     * 强制端到端验证 → 最终确认胜利;并演示完成优先级约束与可操作反馈。
     */
    public String runDemo() {
        StringBuilder sb = new StringBuilder();
        sb.append("=== 第九讲演示:防止 Agent 过早宣告完成 ===\n\n");

        // 1. 构建外部化终止标准(单一来源)
        List<TerminationCriterion> criteria = buildCriteria();
        sb.append("1) 终止标准已外部化(").append(criteria.size()).append(" 条,分三层)\n");

        // 2. Agent 在"单元测试通过"后提前宣告完成(STATIC 全过、RUNTIME 仅单测过、SYSTEM 未验)
        criteria.get(0).markPassed("BUILD SUCCESS");          // C1 STATIC
        criteria.get(1).markPassed("unit tests green");       // C2 RUNTIME: 单元测试
        // C3 RUNTIME: 端到端未验;C4/C5 SYSTEM: 未验
        VictoryClaim premature = new VictoryClaim(0.95, true, "单元测试都过了,功能肯定没问题");
        TerminationGate.TerminationReport r1 = terminationGate.evaluate(premature, criteria);
        sb.append("2) Agent 提前宣称完成(confidence=0.95) → 判定=").append(r1.verdict())
                .append(",缺失标准=").append(r1.missing()).append("\n");

        // 3. 层门控:未过全部 RUNTIME 时不得进入 SYSTEM
        boolean canSystem = terminationGate.canEnterLayer(TerminationCriterion.Layer.SYSTEM, criteria);
        sb.append("3) 门控:未过全部 RUNTIME 时能否进入 SYSTEM=").append(canSystem).append("\n");

        // 4. 强制补完所有层(端到端 + 系统级),再次判定
        criteria.get(2).markPassed("E2E reset-password 流程跑通");  // C3
        criteria.get(3).markPassed("DB 迁移一致性校验通过");          // C4
        criteria.get(4).markPassed("邮件服务配置与模板存在");         // C5
        TerminationGate.TerminationReport r2 = terminationGate.evaluate(premature, criteria);
        sb.append("4) 补完三层后再次判定=").append(r2.verdict()).append("\n");

        // 5. 独立评估者否决过度自信(生成与评估分离):生成者声称完成,但客观证据未满足
        signalCollector.record(RuntimeSignalCollector.Signal.APP_STARTED, true, "app up on :8080");
        EvaluatorSkill.EvaluationReport ev = evaluator.evaluate(previousPremature(), false);
        sb.append("5) 独立评估者:victoryAllowed=").append(ev.victoryAllowed())
                .append("(").append(ev.detail()).append(")\n");

        // 6. 完成优先级约束:核心验证前禁止重构
        CompletionPriorityGuard.RefactorDecision ref = priorityGuard.requestRefactor("重命名变量提升可读性");
        sb.append("6a) 核心未验证时请求重构 → allowed=").append(ref.allowed()).append("\n");
        priorityGuard.markCoreFunctionalVerified();
        ref = priorityGuard.requestRefactor("重命名变量提升可读性");
        sb.append("6b) 核心验证后请求重构 → allowed=").append(ref.allowed()).append("\n");

        // 7. 可操作反馈
        String fb = feedbackGen.makeActionable("Test failed",
                "POST /api/reset-password 返回 500;检查邮件服务配置是否存在于环境变量,模板应在 templates/reset-email.html");
        sb.append("7) 可操作反馈:").append(fb).append("\n");

        // 8. V&V 双闸门
        VerificationValidationGate.VVReport vv = vvGate.check(true, false);
        sb.append("8) V&V 双闸门: verification=").append(vv.verificationPassed())
                .append(" validation=").append(vv.validationPassed())
                .append(" both=").append(vv.bothPassed()).append("\n");

        return sb.toString();
    }

    /** 构造一个"过度自信的提前胜利声明"(用于演示生成/评估分离) */
    private VictoryClaim previousPremature() {
        return new VictoryClaim(0.95, true, "单元测试都过了");
    }

    /** 生成外部化终止标准的机器可读报告(单一权威来源) */
    public String criteriaReport() {
        List<TerminationCriterion> criteria = buildCriteria();
        StringBuilder sb = new StringBuilder();
        sb.append("# 终止标准(Termination Criteria · 单一权威来源)\n\n");
        sb.append("完成判定外部化到 Harness;三层全部 required 通过才允许胜利。\n\n");
        sb.append("| id | 描述 | 层 | 运行时信号 | required |\n");
        sb.append("|:---|:---|:---|:---|:---|\n");
        for (TerminationCriterion c : criteria) {
            sb.append(String.format("| %s | %s | %s | %s | %s |\n",
                    c.getId(), c.getDescription(), c.getLayer(), c.getRuntimeSignal(), c.isRequired()));
        }
        return sb.toString();
    }

    /** 构建默认终止标准(密码重置功能示例,对应第九讲案例) */
    private List<TerminationCriterion> buildCriteria() {
        List<TerminationCriterion> list = new ArrayList<>();
        list.add(new TerminationCriterion("C1", "编译与静态分析无错", TerminationCriterion.Layer.STATIC, "BUILD SUCCESS"));
        list.add(new TerminationCriterion("C2", "单元测试通过(隔离单元、模拟依赖)", TerminationCriterion.Layer.RUNTIME, "unit tests green"));
        list.add(new TerminationCriterion("C3", "端到端关键路径(重置密码)运行时通过", TerminationCriterion.Layer.RUNTIME, "E2E_OK"));
        list.add(new TerminationCriterion("C4", "DB 迁移一致性校验通过(无 schema 不一致)", TerminationCriterion.Layer.SYSTEM, "db migration consistent"));
        list.add(new TerminationCriterion("C5", "邮件服务配置与模板存在", TerminationCriterion.Layer.SYSTEM, "email config present"));
        return list;
    }
}
相关推荐
霸道流氓气质5 小时前
Harness Engineering实战:用功能清单约束 Agent 该做什么示例
harness
带刺的坐椅2 天前
多 Agent 协作实战:任务编排与子代理系统
java·ai·llm·agent·solon·harness
予枫的编程笔记3 天前
Agent 到底是什么?从架构演进看 AI Agent 的工程定义
人工智能·agent·harness·agent的演进
小当家.1053 天前
Harness 工程:给 AI Coding 套上缰绳的第一次实践
人工智能·ai编程·harness·约束工程
想ai抽3 天前
Hermes Agent vs Loop Agent 技术调研
agent·loop·harness
带刺的坐椅3 天前
代码审查 Agent Harness 实战:AI 自动 Code Review
java·ai·llm·agent·solon·soloncode·harness
霸道流氓气质4 天前
Harness Engineering 从理论到实战:基于 Spring AI Alibaba 的完整实现指南
数据库·人工智能·spring·harness
无心水6 天前
【全域智能营销实战】2、Spring AI 模块化架构深度解读:从 1.0 到 2.0 的演进与最佳实践
人工智能·spring·架构·harness·顶尖架构师·全域智能营销·harmess
aovenus6 天前
Harness 介绍及使用场景
harness