Files
SuperBizAgent-java/mvp/engineering/harness/Harness证据安全链-从引用真实到结论可发布.md

13 KiB
Raw Permalink Blame History

Harness 证据安全链:从引用真实到结论可发布

更新日期:2026-07-29 主题:EvidenceGuard、EvidenceRepair、SemanticGuard 与 Diagnosis Release 术语与状态:CONTEXT.md · Harness生命周期与状态.md 前置阅读:Harness-Tool双视图-从原始结果到可验证证据.md

1. 证据存在,不代表结论成立

诊断报告至少可能出现三类不同错误:

  1. 伪造引用:Draft 引用了不存在、失败或属于其他 Run 的 Tool Call。
  2. 引用断裂:analysis 有证据,但 conclusion、action plan 或 recommendation 没有绑定对应 analysis。
  3. 牵强推论:引用和结构都真实,但证据并不足以支持所写根因。

例如,系统确实查到了一条支付超时日志,但报告把根因写成“数据库连接池耗尽”。此时 Tool Call 真实、日志真实、引用格式也正确,结论仍然不成立。

因此“报告是否安全”不能由一个笼统的 Verifier 回答。它至少包含两个不同命题:

P1:引用的证据是否真实、属于当前 Run,并形成结构闭包?
P2:这些真实证据是否足以支持报告中的结论?

P1 可以由代码确定性证明;P2 是语义判断。把两者都交给模型,会让本可机械验证的身份和状态也变成概率结果;全部交给规则,则规则代码会逐渐变成另一套业务诊断引擎。

2. 设计目标:验证链不能产生新事实

证据安全链遵守四个约束:

  • Diagnosis Agent 是唯一报告作者;
  • EvidenceGuard 只做确定性验真;
  • SemanticGuard 只做受限语义审查;
  • Release 是唯一公开决策点。

任何 Guard 都不能调用业务 Tool、探索新证据或重写最终报告。否则验证链会变成第二条隐式 Agent 链,重新引入多 Agent 架构的问题。

flowchart LR
    D["DiagnosisDraft<br/>唯一业务 Draft"] --> R["DiagnosisReleaseUseCase<br/>发布编排所有者"]
    R --> E["EvidenceGuard<br/>确定性引用验真"]
    E -->|"invalid"| X["EvidenceRepair<br/>只修结构/引用"]
    X --> E2["EvidenceGuard Recheck"]
    E -->|"valid"| V["VerifiedEvidenceSnapshot"]
    E2 -->|"valid"| V
    V --> S["SemanticGuard<br/>SUPPORTED / UNSUPPORTED"]
    S -->|"SUPPORTED"| OK["发布原始或等义修复 Draft"]
    E -->|"repair 失败"| F["SafeFallback"]
    E2 -->|"invalid"| F
    S -->|"UNSUPPORTED / unavailable"| F

3. 第一层:EvidenceGuard 证明引用真实性

EvidenceGuard 不调用模型。它从当前 RunContext 出发,对 Draft 进行两阶段检查。

3.1 Draft 结构与引用闭包

首先检查报告自身结构:

  • Draft、analysis、analysis ID、kind 和正文是否存在;
  • analysis ID 是否重复;
  • 每条有结论分析是否绑定 Tool Call;
  • conclusion、action plan 和 recommendation 是否绑定已存在的 analysis ID;
  • limitations 是否存在并声明报告范围。

引用链的目标不是让 JSON 看起来完整,而是形成下面的闭包:

Conclusion / Action / Recommendation
              |
              v
         Analysis Item
              |
              v
       framework tool_call_id
              |
              v
    Canonical READY Invocation

只要其中一跳缺失,公开报告就不能证明其来源。

3.2 Canonical Invocation 验真

对每个 tool_call_id,Guard 使用当前 runId 重新生成 canonical key,然后检查:

  1. ID 格式是否合法;
  2. canonical record 是否存在;
  3. record 内 ID 是否与引用一致;
  4. record 是否属于当前 Run;
  5. invocation 是否 READY;
  6. analysis kind 是否接受该 evidence status;
  7. Tool 类型是否受支持;
  8. agent_result 是否能严格解析为对应 typed result;
  9. typed result 中的 ID、状态、count 和集合是否自洽。

因此,即使模型猜中了另一个 Run 的 Tool Call ID,也无法通过当前 Run key 和 ownership 检查。

3.3 正向证据和负向观察不能混用

AnalysisKind 与 EvidenceStatus 的匹配是关键约束。

一条 READY + NO_EVIDENCE 日志结果,只能支持如下陈述:

在企业 A、时间窗 T、服务 S、查询条件 Q 下没有匹配事件。

它不能支持:

系统没有发生故障。

EvidenceGuard 会把空结果投影为带 source 和 scope 的负向观察,而不是把它提升为支持任意根因的正向证据。

4. VerifiedEvidenceSnapshot 为什么是必要中间产物

EvidenceGuard 验证通过后不会把 canonical raw 直接交给 SemanticGuard,而是生成 VerifiedEvidenceSnapshot。它保存:

  • analysis ID、正文和 kind;
  • 已验证证据的 source type、source、scope、timestamp、excerpt;
  • Tool-specific 的有限结构化 values;
  • 去重后的 verified sources。

Snapshot 的作用是形成一条新的最小信任边界:SemanticGuard 不需要访问 Redis,也不能看到 request、raw response 或内部错误。它只判断“这组已经验真的事实是否支持 Draft”。

这也避免了语义审查阶段重新解释 backend 私有格式。

5. 第二层:EvidenceRepair 只允许修引用

5.1 为什么需要 Repair

模型可能生成业务语义正确、但引用结构存在局部问题的 Draft,例如:

  • conclusion 漏写 based_on_analysis_ids;
  • analysis 引用了错误的 Tool Call ID;
  • 输出字段结构不符合严格 Schema。

如果所有结构错误都直接 Fallback,会丢掉部分可修复结果。但让 Repair 自由重写又会产生更严重的问题:最终结论不再来自 Diagnosis Agent,Repair 事实上成为第二个报告作者。

5.2 Repair 的不变量

EvidenceRepair 只获得:

  • 原始 query;
  • 原始 Draft;
  • EvidenceGuard 给出的 violations。

它没有 Tool,也不能获取新证据。修复输出必须再次严格解析,并满足:

SemanticDraftView(original)
        ==
SemanticDraftView(repaired)

即用户可见的 analysis、conclusion、action plan、recommendations 和 limitations 语义不变,只允许修复引用和结构。之后必须重新执行 EvidenceGuard,不能因为“已经 Repair”就跳过验真。

当前策略只给 EvidenceRepair 一次 attempt。Repair 失败、改变语义或复检仍不通过,直接进入 EVIDENCE_VALIDATION_FAILED Fallback。

6. 第三层:SemanticGuard 判断结论支持度

EvidenceGuard 证明的是“证据是真的”,SemanticGuard 判断的是“推论是否成立”。为了不让它变成第二个 Agent,系统主动削减了它的能力:

约束 目的
无 Tool 不能自行寻找新事实
无会话记忆 不能引入当前输入之外的信息
单轮调用 不形成新的 ReAct loop
输入固定 只接收 query、Draft 和 VerifiedEvidenceSnapshot
输出严格 只能返回 verdict + reason
二值 verdict 只允许 SUPPORTED / UNSUPPORTED
无发布权限 不能改写或直接返回用户报告

技术超时、传输失败、解析失败和 Schema 非法可以按完全相同输入进行一次显式重试。仍失败时不假设“可能支持”,而是 fail closed,发布 SEMANTIC_UNAVAILABLE Fallback。

这里需要准确描述“确定性边界”:SemanticGuard 的语义判断仍然是概率性的;确定的是它的权限、输入、输出、成本、重试次数和失败后的发布行为。

7. Release 为什么必须是唯一发布入口

如果 Application、EvidenceGuard 和 SemanticGuard 都能构造公开结果,同一种失败会出现多个含义,甚至可能绕过前置校验。DiagnosisReleaseUseCase 集中处理以下分支:

输入情况 验证路径 发布结果
Draft 有 conclusion EvidenceGuard -> 可选 Repair/Recheck -> SemanticGuard 原 Draft/等义修复 Draft,或安全 Fallback
Draft 无 conclusion,有已验真进展 只验证其中已有 Tool 引用 INSUFFICIENT_EVIDENCE
Draft 无 conclusion,无进展但声明缺失信息 检查引用边界 MISSING_REQUIRED_CONTEXT
Harness 受控停止,有已验真进展 ProgressSnapshot INSUFFICIENT_EVIDENCE
Draft 非法,但有已验真进展 丢弃非法 Draft,使用 ProgressSnapshot INSUFFICIENT_EVIDENCE
Draft 非法且没有安全进展 无可发布事实 FAILED,保持 fail closed

有结论时,只有 SUPPORTED 可以发布 Draft。发布的是 Diagnosis Agent 原始 Draft,或者经证明用户可见语义相同的 Repair Draft,不让 SemanticGuard生成“更好的答案”。

8. conclusion=null 为什么不进入完整语义审查

当模型明确表示无法确认根因时,不存在需要验证的根因结论。继续调用 EvidenceRepair 或 SemanticGuard,不仅浪费 Token,还可能让验证模型反向补出一个原本不存在的结论。

因此无结论路径只做必要的引用真实性检查,然后根据安全进展决定:

有 verified progress
  -> INSUFFICIENT_EVIDENCE

没有 progress,但有 limitations.missing_info
  -> MISSING_REQUIRED_CONTEXT

两者都没有
  -> 不是合法业务结果,fail closed

这项设计把“没有找到根因”从模型失败中分离出来,但没有降低证据要求。

9. SafeFallback 不是通用错误文案

SafeFallback 是结构化、确定性的发布结果。它可以包含:

  • verified_sources:通过当前 Run 验真的来源;
  • observed_facts:有界、去重后的事实或负向观察;
  • limitations:为什么不能确认根因;
  • next_steps:下一步需要补充的信息或检查;
  • validation_issues:稳定违规码和目标字段;
  • failure_stage:失败发生在收集、证据还是语义阶段。

它不能包含 Prompt、原始 Draft、raw Tool payload、内部异常或模型 reasoning。Fallback 不是“把错误吞掉”,而是只发布系统已经能够证明的部分。

10. 为什么不采用其他方案

10.1 单个 Verifier Agent

优点是实现表面简单,缺点是把 ID、Run ownership、Schema 和业务支持度混在同一次模型判断中。本来可以 100% 用代码拒绝的跨 Run 引用,也会变成概率审查。

10.2 Guard 自动改写报告

可以提高表面成功率,但破坏唯一作者原则。Guard 为了“修好”结论,往往会引入新解释;此时必须重新验证新内容,最终形成循环。

10.3 只做引用存在检查

能阻止伪造 ID,却无法阻止“真实证据 + 错误根因”。这正是 SemanticGuard 存在的原因。

10.4 语义失败直接技术报错

丢失了已经验真的事实,也把“结论不受支持”错误表达为基础设施故障。SafeFallback 可以保留过程价值,同时拒绝发布根因。

11. 真实问题如何改变设计

问题 暴露的设计缺陷 修正
旧 Verifier 同时验引用、判断语义和改写答案 验证职责没有边界 EvidenceGuard、SemanticGuard、Release 三段拆分
Tool 结果面向开发者,含 raw 和重复正文 Guard 与 Agent 没有独立事实面 先建立 canonical truth 和 verified snapshot
NO_EVIDENCE 被当成一般失败或正向证据 负向观察没有范围约束 AnalysisKind 与 EvidenceStatus 匹配校验
Repair 可能改变结论 修复者变成新的报告作者 SemanticDraftView 前后等义检查
非法 Draft 使已完成 Tool 检查全部丢失 Draft 是唯一可发布价值来源 只在 ProgressSnapshot 已验真时允许过程型 Fallback
SemanticGuard 技术失败时行为不一致 各层自行决定降级 Release 统一生成 SEMANTIC_UNAVAILABLE

12. 代价与剩余风险

  1. SemanticGuard 增加一次模型调用和延迟;这是语义安全与成本之间的明确取舍。
  2. Semantic verdict 不是形式化证明,仍可能误判;当前设计限制的是权限和失败影响,而不是宣称模型绝对正确。
  3. EvidenceGuard 需要理解每种 Tool 的 typed result;新增 Tool 必须同步增加验证规则。
  4. Repair 的语义等价由结构化视图定义,无法证明两个自然语言文本在所有解释下完全等价,因此 Repair 能力被刻意限制。
  5. Canonical record TTL 到期后无法重新完成完整验真,所以公开决策必须在当前 Run 内完成。

13. 如何验证

需要证明 代表性验证
缺失、重复、未知 analysis 引用被拒绝 EvidenceGuardTest
cross-run、非 READY、ID/status 不一致被拒绝 EvidenceGuardTest + canonical fixtures
NO_EVIDENCE 只能形成限定负向观察 Evidence kind focused cases
Repair 不得改变用户可见语义 DiagnosisReleaseUseCaseTest、Repair tests
Semantic 非法输出只有限重试并安全降级 SemanticGuardTest
Guard 不改写报告,Release 只发布原 Draft 或 Fallback DiagnosisReleaseUseCaseTest
无结论、非法 Draft、受控停止正确映射 DiagnosisChatExecutorTest、Release focused cases
exact-run Trace 能解释每一道门禁 live E2E Timeline

14. 与前后链路的关系

证据安全链依赖 Tool 双视图提供独立 canonical truth;它解决的是“哪些内容能够发布”,不负责判断 Agent 是否还应该继续取证。正常收敛由Harness信息增益停止-让无证据诊断正常收敛.md负责。