Files
SuperBizAgent-java/mvp/issues/ISS-007-verifier-evidence-summary-fidelity.md
T

52 KiB
Raw Blame History

ISS-007 Verifier 证据摘要保真与工具命中质量问题

状态:设计已收口,待实施 严重程度:高 发现时间:2026-07-08 来源:Executor V2 / Gatekeeper / Verifier / Composer 端到端验证 关联:

  • executor-structured-output-v2
  • executor-evidence-attribution-hallucination
  • ISS-005-evidence-trace-hardening
  • ISS-006-diagnosis-eval-harness

背景

当前复杂诊断链路已经形成:

chat_planner
  -> chat_executor
  -> VerifierInputHook 内 Gatekeeper
  -> chat_verifier
  -> chat_composer
  -> final answer

最近端到端验证中,部分窄范围问题本应具备足够证据,但最终仍被 Verifier 判为 LOW_CONFID。进一步查看审计数据后发现,这几类失败并不完全是 Executor 幻觉,也不完全是 Verifier 代码 bug,而是暴露出一组更经典的工程问题:

  1. 工具原始返回和 Executor evidence_excerpt 中存在证据,但 tool_trace_summary.output_summary 压缩后丢失关键证据。
  2. Verifier 当前更依赖工具摘要,而不是直接消费 Executor 绑定的原文片段。
  3. mock 工具命中规则存在质量问题,某些查询返回了 generic-service 占位日志,导致负向结论虽然被正确识别,但无法验证正向路径。
  4. Executor 对窄范围问题仍可能输出过多扩展 claim,增加 Verifier 判定压力。

这个 issue 的目标不是立即确定实现方案,而是把这些问题归档为一组可讨论、可优化、可验收的工程问题。


复现样例

1. HighCPUUsage:正向 PASS

Session:e2e-pass-highcpu-raw-20260708-1106

问题范围:只确认 payment-service 当前是否存在 CPU 使用率过高告警。

结果:

  • verdict=PASS
  • groundedness_score=1.0
  • gatekeeper_result.status=pass
  • composer_output.status=valid

结论:

  • 工具 mock、日志、知识库 runbook 三者可以匹配。
  • 这是当前链路能够通过的健康样例,可作为后续回归基线。

2. HighMemoryUsage:证据存在但 LOW_CONFID

Session:e2e-pass-memory-20260708-1117-a1

结果:

  • verdict=LOW_CONFID
  • groundedness_score=0.2
  • gatekeeper_result.status=pass

审计发现:

  • Executor 的 evidence_excerpt 中包含完整证据:
    • HighMemoryUsage firing
    • 当前内存使用率 91%
    • JVM 堆内存 3.8GB/4GB
    • 持续 15m
    • 多个采样点:86.2 -> 87.4 -> 88.6 -> 89.8 -> 91.0
    • Full GC 15 次,平均 850ms
  • 但 tool_trace_summary.output_summary 只保留了一条内存日志:
    • [11:17][WARN][order-service] 内存使用率过高: 91.0%, JVM堆内存: 3.8GB/4GB, GC次数: 128

初步归类:

  • 主要问题:ToolTraceSummaryService 摘要压缩丢失趋势和 GC 证据。
  • 次要问题:Verifier 未直接使用 Executor 的 evidence_excerpt 做可推导性判断。
  • 不是主要幻觉问题:Executor 引用的片段里确实包含关键事实。

3. SlowResponse:证据存在但 LOW_CONFID

Session:e2e-pass-slowresponse-20260708-1117-a1

结果:

  • verdict=LOW_CONFID
  • groundedness_score=0.2
  • gatekeeper_result.status=pass

审计发现:

  • Executor 的 evidence_excerpt 中包含:
    • SlowResponse alert:user-service P99=4.2s,firing,持续 10m
    • 慢请求日志:
      • /api/v1/users/profile: 3600 / 3900 / 4200ms
      • /api/v1/users/orders: 3750 / 4050ms
  • 但 tool_trace_summary.output_summary 只保留了一条 /api/v1/users/profile 4200ms。
  • query_metrics summary 没有完整展示 SlowResponse firing alert。

初步归类:

  • 主要问题:工具摘要没有保留足够多的关键事件和指标。
  • 次要问题:Verifier 过度依赖 summary,导致它看不到 Executor 已经绑定的证据。
  • 不是主要幻觉问题:证据片段本身存在。

4. HikariCP:负向 PASS,但正向路径缺失

Session:e2e-pass-hikari-20260708-1117-a1

结果:

  • verdict=PASS
  • groundedness_score=1.0
  • gatekeeper_result.status=pass

实际结论:

application-logs 中未检索到 order-service 的真实 HikariCP 连接池耗尽日志

审计发现:

  • mock 工具返回的是 generic-service 占位日志。
  • evidence_level=none
  • no_hit_invocation_count=6
  • Verifier 正确识别“没查到真实 HikariCP 日志”。

初步归类:

  • Verifier 的负向 PASS 是合理的。
  • 真正问题在 mock 工具命中质量:HikariCP、active=50/50、order-service 等查询没有命中正向 mock 分支。

问题归类

问题 类型 严重程度 当前判断
tool_trace_summary.output_summary 只保留少量日志,丢失趋势、采样点、关键 alert 工具摘要质量 高 需要优化
Verifier 主要依赖 summary,未充分利用 Executor evidence_bindings[].evidence_excerpt 架构 / 输入设计 高 需要讨论
query_metrics summary 没有完整展示所有 firing alert 工具摘要质量 高 需要优化
Executor 对窄范围问题输出多条扩展 claim Agent 约束 中 需要讨论
mock 日志返回 generic-service 占位日志 工具 / mock 质量 中 需要优化
Gatekeeper pass 但 Verifier LOW_CONFID 分层行为 低 不是问题,属于正常分工

当前结论

Memory / SlowResponse

主要不是 LLM 编造事实,也不是 Gatekeeper 漏拦,而是证据在链路中被摘要层压缩丢失。

当前证据链路存在一个断点:

tool raw output / executor evidence_excerpt 有证据
  -> tool_trace_summary.output_summary 丢失部分证据
  -> verifier 看不到足够材料
  -> LOW_CONFID

HikariCP

当前负向 PASS 是合理的,因为系统确实没有检索到真实 order-service HikariCP 连接池耗尽证据。

真正需要优化的是工具 mock 的命中规则和 fixture 数据质量,否则后续很难验证 HikariCP 的正向路径。


已确认设计方向:Executor 引用证据,Gatekeeper 核对引用

针对“摘要失真”问题,优先采用以下主线,而不是继续让 Executor 或 ToolTraceSummaryService 承担更重的自然语言压缩职责:

tool raw output
  -> Executor 产出 claim + 引用证据片段
  -> Gatekeeper 用代码核对引用是否真实
  -> Verifier 判断 claim 是否能由已核对证据推出
  -> Composer 只表达 Verifier 允许输出的内容

分工边界

Executor:证据引用器,而不是可信摘要器

Executor 不再把工具结果压缩成一段“可信诊断摘要”后交给 Verifier 判断,而是负责:

  • 产出结构化 claim。
  • 为每个 claim / recommended action 绑定证据引用。
  • 引用真实 source_invocation_id + raw_path。
  • 给出与 claim 直接相关的 evidence_excerpt。
  • 不编造 invocation id。
  • 不把 runbook 通用经验升级成当前已确认事实。

目标是让 Executor “少总结,多引用”。

Gatekeeper:引用真实性校验

Gatekeeper 负责用代码检查 Executor 的引用是否真实,先拦截物理级幻觉:

  • source_invocation_id 是否真实存在于本轮 session 的 tool invocation 历史中。
  • source_invocation_id 是否属于允许被引用的 evidence tool。
  • evidence_excerpt 是否能在对应 tool invocation 的原始输出中找到,或达到可接受的相似度。
  • 是否存在“真实 invocation id + 编造 excerpt”的张冠李戴问题。
  • 是否存在空证据、伪造证据、引用无关工具输出等问题。

Gatekeeper 只判断“引用是否真实”,不判断“claim 是否成立”。

Verifier:判断可推导性

Verifier 在 Gatekeeper 通过后,再判断:

  • 这些已核对的证据是否足以支持 claim。
  • claim 是否存在过度推断。
  • claim 是否只是合理怀疑,而不是已确认事实。
  • recommended action 是否能由当前证据和缺口合理推出。

Verifier 不再把主要精力放在逐字核对引用真伪上,而是做“证据能否推出结论”的判断。

ToolTraceSummary:全局导航摘要,不再作为唯一证据源

tool_trace_summary.output_summary 仍然保留,但定位调整为:

  • 帮助 Verifier / 审计理解本轮工具调用全貌。
  • 提供全局 evidence overview。
  • 作为辅助证据视图,而不是唯一判定依据。

也就是说,summary 可以继续优化,但不应该再承担“唯一证据源”的职责。

这个方向解决的问题

该设计直接针对当前 Memory / SlowResponse 的失败模式:

工具原始返回和 Executor evidence_excerpt 有证据
  -> summary 压缩时丢失关键证据
  -> Verifier 看不到足够材料
  -> LOW_CONFID

调整后变为:

工具原始返回有证据
  -> Executor 引用关键片段
  -> Gatekeeper 校验片段来自真实工具输出
  -> Verifier 基于已核对片段判断 claim 是否可推出

这样即使 output_summary 较短,Verifier 仍能看到 claim-local evidence。

设计约束

  • Verifier 不能无条件相信 Executor 的 evidence_excerpt。
  • Gatekeeper 的 excerpt 原文回溯是 Verifier 消费 excerpt 的前置安全条件。
  • Gatekeeper 校验通过不代表 claim 通过,只代表“引用是真的”。
  • Verifier 判为 PASS 必须基于“真实引用 + 可推导结论”两个条件同时成立。
  • 不能通过简单放宽 Verifier 阈值来掩盖证据传递问题。

Verifier 输入数据结构定义(当前设计)

本节定义“Executor 引用证据,Gatekeeper 核对引用”方案下,进入 Verifier 的数据结构。核心原则:

证据定位:source_invocation_id + raw_path
证据文本:evidence_excerpt
证据真实性:由 Gatekeeper 在 Verifier 前校验
Verifier 职责:只判断 claim_text 是否能由已核验 evidence_excerpt 推出

1. 工具调用侧最小证据引用

当前工具尚未统一返回 evidence_items。第一版不引入复杂 metadata,也不要求新增数据库表,建议在 tool_invocation.retrieval_details 中补充最小 evidence_refs:

{
  "evidence_status": "supported",
  "evidence_refs": [
    {
      "raw_path": "$.alerts[1]",
      "text": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m; JVM heap usage 3.8GB/4GB"
    }
  ]
}

字段定义:

字段 类型 必填 说明
raw_path string 是 证据在该工具返回中的稳定定位符。第一版只支持 $.alerts[i]、$.logs[i]、$.evidence_blocks[i]。
text string 是 系统从该位置提取出的最小证据文本。Gatekeeper 用它比对 Executor 的 evidence_excerpt,Verifier 用 evidence_excerpt 做推导判断。

设计约束:

  • 第一版不需要 metadata。
  • 第一版不需要 evidence_id。
  • raw_path 只在单次 tool_invocation 内有意义,必须和 source_invocation_id 搭配使用。
  • 如果工具返回会被 output_preview 截断,evidence_refs[].text 必须保存在 retrieval_details 中,不能只依赖 output_preview。

2. Executor 结构化输出

Executor 输出不再把证据压缩成可信摘要,而是输出 claim 与证据引用:

{
  "claims": [
    {
      "claim_id": "claim-1",
      "claim_type": "observation",
      "claim_text": "order-service 当前存在 HighMemoryUsage 告警,内存使用率达到 91%。",
      "evidence_bindings": [
        {
          "tool_name": "query_metrics",
          "source_invocation_id": 12345,
          "raw_path": "$.alerts[1]",
          "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
        }
      ]
    }
  ],
  "hypotheses": [
    {
      "hypothesis_id": "hyp-1",
      "hypothesis_text": "order-service 可能存在内存泄漏风险。",
      "basis_claim_ids": ["claim-1"],
      "missing_info": "缺少堆 dump、对象分配统计或更长时间窗口的内存曲线,不能确认内存泄漏。"
    }
  ],
  "missing_info": [
    {
      "info_id": "missing-1",
      "description": "缺少堆 dump 或对象分配统计,无法确认内存泄漏根因。"
    }
  ],
  "recommended_actions": [
    {
      "action_id": "action-1",
      "action_text": "继续查看 order-service 的 GC 日志、堆 dump 或对象分配统计。",
      "reason": "当前证据可以确认内存使用率过高,但不足以确认是否存在内存泄漏。",
      "evidence_bindings": [
        {
          "tool_name": "query_metrics",
          "source_invocation_id": 12345,
          "raw_path": "$.alerts[1]",
          "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
        }
      ]
    }
  ]
}

字段定义:

字段 类型 必填 说明
claims array 是 Executor 提出的待验证事实断言。
claims[].claim_id string 是 claim 唯一标识,供 Verifier / Composer 引用。
claims[].claim_type string 是 claim 类型,例如 observation、root_cause、risk、negative_observation。
claims[].claim_text string 是 Executor 提出的事实断言,不是证据本体,也不是已验证结论。
claims[].evidence_bindings array 是 支撑该 claim 的证据引用列表。
evidence_bindings[].tool_name string 是 证据来源工具,例如 query_metrics、query_logs、lookup_knowledge。
evidence_bindings[].source_invocation_id number 是 单次真实工具调用 ID。第一版使用单数;如果一个 claim 需要多个工具调用,拆成多条 binding。
evidence_bindings[].raw_path string 是 该证据在工具返回中的路径,和 source_invocation_id 共同定位唯一证据位置。
evidence_bindings[].evidence_excerpt string 是 Executor 引用出来给 Verifier 阅读的证据片段。Gatekeeper 必须先核对其真实性。
hypotheses array 否 假设,不是 confirmed fact。不能因为写在这里就进入最终确认结论。
missing_info array 否 证据缺口。
recommended_actions array 否 建议动作。本期只允许证据收集动作,不允许修复动作;动作可以绑定证据,但不能把缺证据假设写成已确认事实。

3. Gatekeeper 输出

Gatekeeper 在 Verifier 前校验所有 evidence_bindings:

{
  "status": "pass",
  "severity": "none",
  "checked_bindings": [
    {
      "claim_id": "claim-1",
      "tool_name": "query_metrics",
      "source_invocation_id": 12345,
      "raw_path": "$.alerts[1]",
      "status": "pass",
      "matched_text": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
    }
  ],
  "failed_rules": [],
  "warnings": [],
  "errors": []
}

字段定义:

字段 类型 必填 说明
status string 是 pass 或 fail。失败时 Verifier 不得输出 PASS。
severity string 是 none、low_confid 或 reject。status=pass 时必须为 none。
checked_bindings array 是 已校验的证据绑定明细。
checked_bindings[].claim_id string 否 对应 claim。recommended action 的 binding 可使用 action_id。
checked_bindings[].tool_name string 是 Executor 声称的工具名,必须和真实 invocation 对齐。
checked_bindings[].source_invocation_id number 是 被核验的真实工具调用 ID。
checked_bindings[].raw_path string 是 被核验的工具返回路径。
checked_bindings[].status string 是 单条 binding 的校验结果:pass 或 fail。
checked_bindings[].matched_text string 否 Gatekeeper 从 retrieval_details.evidence_refs 或工具返回中找到的系统侧证据文本。
failed_rules array 是 失败规则列表,例如 evidence.invocation_ref、evidence.raw_path、evidence.excerpt_mismatch。
warnings array 是 非阻断风险。
errors array 是 阻断错误。

Gatekeeper 校验规则:

  1. source_invocation_id 必须存在于当前 session。
  2. tool_name 必须与该 invocation 的真实工具名一致。
  3. raw_path 必须能定位到该 invocation 的真实证据引用。
  4. evidence_excerpt 必须与系统侧 text 一致或高度相似。
  5. Gatekeeper 只判断“引用是否真实”,不判断 claim 是否成立。

4. Verifier 输入完整结构

Verifier 最终接收的输入结构如下:

{
  "original_query": "请排查 order-service 当前是否存在 HighMemoryUsage 告警,只确认内存使用率过高这一件事。",
  "executor_structured_output": {
    "claims": [
      {
        "claim_id": "claim-1",
        "claim_type": "observation",
        "claim_text": "order-service 当前存在 HighMemoryUsage 告警,内存使用率达到 91%。",
        "evidence_bindings": [
          {
            "tool_name": "query_metrics",
            "source_invocation_id": 12345,
            "raw_path": "$.alerts[1]",
            "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
          }
        ]
      },
      {
        "claim_id": "claim-2",
        "claim_type": "observation",
        "claim_text": "order-service JVM 堆内存使用接近上限,当前为 3.8GB/4GB。",
        "evidence_bindings": [
          {
            "tool_name": "query_metrics",
            "source_invocation_id": 12345,
            "raw_path": "$.alerts[1]",
            "evidence_excerpt": "JVM heap usage 3.8GB/4GB"
          }
        ]
      },
      {
        "claim_id": "claim-3",
        "claim_type": "observation",
        "claim_text": "order-service 日志中也出现了内存使用率过高记录。",
        "evidence_bindings": [
          {
            "tool_name": "query_logs",
            "source_invocation_id": 12346,
            "raw_path": "$.logs[0]",
            "evidence_excerpt": "[11:17][WARN][order-service] 内存使用率过高: 91.0%, JVM堆内存: 3.8GB/4GB, GC次数: 128"
          }
        ]
      }
    ],
    "hypotheses": [
      {
        "hypothesis_id": "hyp-1",
        "hypothesis_text": "order-service 可能存在内存泄漏风险。",
        "basis_claim_ids": ["claim-1", "claim-2"],
        "missing_info": "缺少堆 dump、对象分配统计或更长时间窗口的内存曲线,不能确认内存泄漏。"
      }
    ],
    "missing_info": [
      {
        "info_id": "missing-1",
        "description": "缺少堆 dump 或对象分配统计,无法确认内存泄漏根因。"
      }
    ],
    "recommended_actions": [
      {
        "action_id": "action-1",
        "action_text": "继续查看 order-service 的 GC 日志、堆 dump 或对象分配统计。",
        "reason": "当前证据可以确认内存使用率过高,但不足以确认是否存在内存泄漏。",
        "evidence_bindings": [
          {
            "tool_name": "query_metrics",
            "source_invocation_id": 12345,
            "raw_path": "$.alerts[1]",
            "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
          }
        ]
      }
    ]
  },
  "gatekeeper_result": {
    "status": "pass",
    "severity": "none",
    "checked_bindings": [
      {
        "claim_id": "claim-1",
        "tool_name": "query_metrics",
        "source_invocation_id": 12345,
        "raw_path": "$.alerts[1]",
        "status": "pass",
        "matched_text": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
      },
      {
        "claim_id": "claim-2",
        "tool_name": "query_metrics",
        "source_invocation_id": 12345,
        "raw_path": "$.alerts[1]",
        "status": "pass",
        "matched_text": "JVM heap usage 3.8GB/4GB"
      },
      {
        "claim_id": "claim-3",
        "tool_name": "query_logs",
        "source_invocation_id": 12346,
        "raw_path": "$.logs[0]",
        "status": "pass",
        "matched_text": "[11:17][WARN][order-service] 内存使用率过高: 91.0%, JVM堆内存: 3.8GB/4GB, GC次数: 128"
      }
    ],
    "failed_rules": [],
    "warnings": [],
    "errors": []
  },
  "tool_trace_summary": [
    {
      "trace_ref": "trace-1",
      "tool_name": "query_metrics",
      "source_invocation_ids": [12345],
      "evidence_level": "direct",
      "output_summary": "metric_evidence: HighMemoryUsage service=order-service current=91% duration=15m",
      "invocation_count": 1,
      "no_hit_invocation_count": 0
    },
    {
      "trace_ref": "trace-2",
      "tool_name": "query_logs",
      "source_invocation_ids": [12346],
      "evidence_level": "direct",
      "output_summary": "log_evidence: [11:17][WARN][order-service] 内存使用率过高: 91.0%",
      "invocation_count": 1,
      "no_hit_invocation_count": 0
    }
  ],
  "executor_output_parse_status": {
    "status": "valid",
    "detail": "parsed executor evidence contract"
  },
  "retry_context": null
}

Verifier 处理规则:

  • 先看 gatekeeper_result.status。如果为 fail,不得输出 PASS。
  • 正常校验时,只基于已通过 Gatekeeper 的 evidence_bindings[].evidence_excerpt 判断 claim_text 是否可推导。
  • tool_trace_summary.output_summary 只作为全局导航摘要,不作为主证据源。
  • raw_path 是 Gatekeeper 回查字段,不是 Verifier 推理字段。
  • Verifier 不读取 raw tool output,不重新检索,不替 Executor 补证据。

5. tool_trace_summary 精简字段

在该设计下,tool_trace_summary 只保留全局导航和审计索引能力。建议进入 Verifier 的最小字段为:

{
  "trace_ref": "trace-1",
  "tool_name": "query_logs",
  "source_invocation_ids": [12346],
  "evidence_level": "direct",
  "output_summary": "log_evidence: ...",
  "invocation_count": 1,
  "no_hit_invocation_count": 0
}

字段定义:

字段 类型 必填 说明
trace_ref string 是 Verifier / 审计引用证据组的编号。
tool_name string 是 证据组对应工具名。
source_invocation_ids array 是 该证据组聚合的真实工具调用 ID。
evidence_level string 是 direct、indirect 或 none。只代表证据组强度,不代表 claim 通过。
output_summary string 是 全局导航摘要。不得作为 Verifier 唯一证据源。
invocation_count number 是 该证据组聚合的调用次数。
no_hit_invocation_count number 是 无有效证据调用次数,用于负向场景和审计。

以下字段不建议进入 Verifier 输入,只保留在审计或 trace UI:

  • input_summary
  • failed_invocation_count
  • query_samples
  • retrieval_layers
  • relevance_levels
  • source_documents

已确认优化方向:mock 工具命中质量先做小阶段

HikariCP 类问题归属工具 / mock 命中质量,不归属 Verifier。当前负向 PASS 是合理的,因为系统没有检索到真实 order-service HikariCP 连接池耗尽证据;不能通过放宽 Verifier 或让 runbook 代替事实证据来解决。

该问题可以作为独立小阶段优先落地,风险低、见效快。

阶段目标

让 HikariCP 相关问题能够稳定区分:

有真实 mock 日志
  -> Executor 可以引用真实 evidence
  -> Gatekeeper / Verifier 可以验证
  -> 正向场景允许 PASS

没有真实 mock 日志
  -> 明确 logs=[]
  -> evidence_status=no_evidence
  -> 不被 generic-service 占位日志污染

改造点

  1. query_logs no-hit 时不得 fallback 到 generic-service 占位日志。
  2. query_logs 应补齐 HikariCP / connection pool / active=50/50 / order-service 的正向 mock 日志。
  3. HikariCP 相关查询应支持同义表达命中:
    • HikariCP
    • HikariPool
    • connection pool
    • 数据库连接池
    • 连接池耗尽
    • active=50/50
    • waiting
    • request timed out after 30000ms
    • order-service
  4. no-hit 应表达为“工具调用成功但没有证据”,而不是工具失败:
{
  "success": true,
  "logs": [],
  "total": 0,
  "message": "未找到匹配的日志"
}

并在 tool_invocation.retrieval_details.evidence_status 中记录:

{
  "evidence_status": "no_evidence"
}

HikariCP 正向 mock 日志示例

[ERROR][order-service] HikariPool-1 - Connection is not available, request timed out after 30000ms
[WARN][order-service] HikariCP pool stats: active=50/50, idle=0, waiting=32

验收标准

  1. 查询 HikariCP / connection pool / active=50/50 / order-service 能命中真实 order-service 连接池日志。
  2. 查询不存在的服务或不相关关键词时,返回 logs=[],并记录 evidence_status=no_evidence。
  3. 不再返回 generic-service 占位日志作为假证据。
  4. HikariCP positive case 能稳定走到 PASS。
  5. HikariCP negative case 仍然表达“未检索到真实证据”,不能误判 PASS。

边界

  • 不通过 Verifier 放宽解决工具未命中问题。
  • 不允许 runbook 通用排查建议升级成“当前已经发生 HikariCP 连接池耗尽”的事实结论。
  • mock 数据应尽量和 knowledge_base 中的连接池排查 runbook 对齐,便于 eval 和 demo 形成闭环。

已确认优化方向:本期先用 Executor Prompt 控制过度展开

Planner 当前不会产出 scope_contract。本期先不改 Planner 输出契约,也不新增 scope contract 解析逻辑;先通过 Executor prompt 控制窄范围问题的过度展开。

本期边界

不改 Planner
不新增 scope_contract
不新增 Controller
不做复杂 scope Gatekeeper
只调整 Executor Prompt 的单一职责和输出边界

Executor 单一职责

Executor 在本期应被约束为:

证据收集 + 微观事实提炼

也就是:

  • 调用工具收集当前任务范围内的证据。
  • 输出工具证据直接支持的 observation / negative_observation claim。
  • 为 claim 绑定证据引用。
  • 输出 missing_info 表达证据缺口。

Executor 不应负责:

  • 生成最终用户答案。
  • 输出修复方案。
  • 扩展到用户未要求的服务、订单、告警、数据库、连接池或下游依赖。
  • 将 Runbook、Skill 或知识库中的通用经验写成当前环境已发生的事实。
  • 在证据不足时用“可能是、一般来说、根据经验”等话术补 claim。

窄范围问题识别

如果用户问题包含以下表达,Executor 应视为窄范围确认任务:

  • 只确认
  • 只排查
  • 只看
  • 不要分析
  • 不要扩展
  • 只回答
  • 是否真实存在
  • 是否存在某告警 / 某日志 / 某错误

窄范围确认任务下,Executor 必须遵守:

  1. 只输出 observation / negative_observation 类型 claim。
  2. claim 数量应为最少必要数量,通常 1 条,最多 2 条。
  3. 只能围绕用户明确要求的目标对象和主题输出 claim。
  4. 用户明确排除的对象、告警、服务、订单、数据库、连接池等,禁止出现在 claim 中。
  5. Runbook / Skill / 知识库只能用于指导要查什么,不能作为当前事实 claim。
  6. 如果证据不足,只输出 missing_info,不要补充合理化解释。
  7. recommended_actions 如果保留,只能是继续收集证据的动作,不允许是修复动作。

限制 claim 数量不是限制证据数量

这里限制的是:

claim 数量

不是限制:

工具调用数量
证据数量
evidence_bindings 数量
missing_info 数量

窄范围任务的理想输出是:

1 条核心 claim
多条直接相关 evidence_bindings
必要的 missing_info

示例:

{
  "claim_id": "claim-1",
  "claim_type": "observation",
  "claim_text": "order-service 当前存在 HighMemoryUsage 告警,内存使用率达到 91%。",
  "evidence_bindings": [
    {
      "tool_name": "query_metrics",
      "source_invocation_id": 12345,
      "raw_path": "$.alerts[1]",
      "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
    },
    {
      "tool_name": "query_metrics",
      "source_invocation_id": 12345,
      "raw_path": "$.alerts[1]",
      "evidence_excerpt": "JVM heap usage 3.8GB/4GB"
    },
    {
      "tool_name": "query_logs",
      "source_invocation_id": 12346,
      "raw_path": "$.logs[0]",
      "evidence_excerpt": "[11:17][WARN][order-service] 内存使用率过高: 91.0%, JVM堆内存: 3.8GB/4GB, GC次数: 128"
    }
  ]
}

不建议拆成:

claim-1: 存在 HighMemoryUsage
claim-2: 当前 91%
claim-3: JVM 3.8GB/4GB
claim-4: Full GC 增多
claim-5: 可能内存泄漏

原因是这些大多属于同一观察事实或证据细节,应合并到一条 claim 的 evidence_bindings 中。证据不足时应进入 missing_info,而不是生成更多弱 claim。

Prompt 草案

可加入 chat-executor-prompt.md 的约束草案:

## 单一职责与输出边界

你是证据收集与微观事实提炼专家。
你只负责调用工具收集证据,并输出工具证据直接支持的微观事实断言。

你不得输出最终用户答案。
你不得生成修复方案。
你不得扩展到用户未要求的服务、订单、告警、数据库、连接池或下游依赖。
你不得将 Runbook、Skill 或知识库中的通用经验写成当前环境已发生的事实。

## 窄范围问题 HARD-GATE

如果用户问题包含“只确认、只排查、只看、不要分析、不要扩展、只回答、是否真实存在、是否存在某告警/日志/错误”等表达,视为窄范围确认任务。

窄范围确认任务必须遵守:
1. 只输出 observation / negative_observation 类型 claim。
2. claim 数量使用最少必要数量,通常 1 条,最多 2 条。
3. 限制 claim 数量不限制 evidence_bindings 数量;每条 claim 应绑定所有直接相关证据。
4. 不得把同一观察事实拆成多条 claim。
5. 只能围绕用户明确要求的目标对象和主题输出 claim。
6. 用户明确排除的对象、告警、服务、订单、数据库、连接池等,禁止出现在 claim 中。
7. Runbook / Skill / 知识库只能用于指导要查什么,不能作为当前事实 claim。
8. 如果证据不足,只输出 missing_info,不要补充合理化解释。
9. recommended_actions 只能是继续收集证据的动作,不能是修复动作。

验收标准

  1. 用户说“只确认 HighCPUUsage”时,Executor 不输出订单、OOM、DB、HikariCP。
  2. 用户说“只确认 HighMemoryUsage”时,Executor 不输出“内存泄漏已确认”。
  3. 用户说“不要分析连接池”时,claim 中不出现 HikariCP / connection pool。
  4. runbook 内容只能进入 missing_info 或证据收集动作,不能变成 confirmed claim。
  5. 窄范围正向场景仍能绑定多条证据,不因 claim 数量限制导致证据不足。

后续可选增强

如果仅靠 Executor prompt 不稳定,再考虑后续引入:

  • Planner scope_contract
  • Gatekeeper scope 校验
  • eval fixture 中的 forbidden claim 断言

当前剩余实施问题

当前真正剩余的设计问题主要是实施细节,而不是方向选择:

  1. 已决:evidence_refs 第一版由 ToolInvocationRecorder 根据工具返回统一抽取生成。
  2. 已决:raw_path 第一版只支持 $.alerts[i] / $.logs[i] / $.evidence_blocks[i] 三类稳定定位符。
  3. 已决:Gatekeeper 校验失败分级处理;伪造 / 张冠李戴类 REJECT,证据缺失 / 过渡期兼容类 LOW_CONFID。
  4. 已决:VerifierInputHook 自动回填必须收紧;本期只作兼容,不作为 PASS 依据,后续废弃。
  5. 已决:本期采用 Prompt-first 策略,只实现 Executor Prompt 约束;scope_contract 作为后续增强。
  6. 已决:补最小 eval / E2E 覆盖矩阵,覆盖 Memory、SlowResponse、HikariCP positive、HikariCP negative、Gatekeeper reject、窄范围 forbidden claim。

已确认实施决策:evidence_refs 第一版由 Recorder 统一抽取

第一版 evidence_refs 由 ToolInvocationRecorder 在工具调用入库时,根据 toolName 和工具返回 JSON 统一抽取生成,并写入 tool_invocation.retrieval_details.evidence_refs。

采用该方案的原因:

  • 当前 query_logs / query_metrics 返回已经是结构化 JSON。
  • 第一版只需要 raw_path + text,不需要复杂 metadata。
  • 抽取逻辑集中在 recorder 附近,更容易保证 evidence_refs 格式一致。
  • 不需要一次性改造所有工具返回协议。

第一版抽取规则:

query_metrics:
  $.alerts[i] -> text = alert_name + state + description/duration

query_logs:
  $.logs[i] -> text = timestamp + level + service + message

lookup_knowledge:
  retrieval_details.evidence_blocks[i] -> text = content/title/source

实现边界:

  • Recorder 只做结构化抽取,不做诊断推理。
  • Recorder 不得把 HighMemoryUsage、JVM 3.8GB/4GB 等证据推理成“内存泄漏已确认”。
  • 如果 output JSON 解析失败或工具无可抽取结构,evidence_refs 可以为空,但必须保留原有 evidence_status。
  • 后续如果某个工具返回特别复杂,可以允许工具显式传入 evidence_refs 覆盖默认抽取,但第一版不做。

已确认实施决策:raw_path 第一版使用稳定定位符

第一版 raw_path 不实现完整 JSONPath,也不支持任意深层字段路径。它只是 retrieval_details.evidence_refs 内的稳定定位符,用来和 source_invocation_id 共同定位一条证据。

支持的路径格式仅包括:

$.alerts[i]
$.logs[i]
$.evidence_blocks[i]

对应工具:

工具 raw_path 格式 说明
query_metrics $.alerts[i] 第 i 条告警证据
query_logs $.logs[i] 第 i 条日志证据
lookup_knowledge $.evidence_blocks[i] 第 i 个知识库证据块

第一版不支持:

$.alerts[1].description
$.logs[0].message
$.data.alerts[0]
$.retrieval_details.evidence_blocks[0]
过滤表达式或复杂 JSONPath

原因:

  • Gatekeeper 不需要实现通用 JSONPath 引擎。
  • Executor 不需要理解工具返回内部字段细节。
  • evidence_refs[].text 已经保存该 raw path 对应的最小证据文本。
  • Gatekeeper 只需要在 retrieval_details.evidence_refs 中按 raw_path 精确匹配,然后比对 evidence_excerpt 与系统侧 text。

示例:

{
  "evidence_refs": [
    {
      "raw_path": "$.alerts[1]",
      "text": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m; JVM heap usage 3.8GB/4GB"
    }
  ]
}

Executor 引用:

{
  "tool_name": "query_metrics",
  "source_invocation_id": 12345,
  "raw_path": "$.alerts[1]",
  "evidence_excerpt": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m"
}

Gatekeeper 校验:

  1. 查 source_invocation_id=12345 是否属于当前 session。
  2. 查该 invocation 的 retrieval_details.evidence_refs 是否存在 raw_path="$.alerts[1]"。
  3. 比对 evidence_excerpt 是否被该 text 支撑。

已确认实施决策:Gatekeeper 失败分级并入库审计

Gatekeeper 校验失败不一律 REJECT。第一版按失败性质分级:

物理级幻觉 / 证据污染 -> REJECT
证据缺失 / 格式不完整 / 过渡期兼容问题 -> LOW_CONFID

Gatekeeper 输出结构

建议 Gatekeeper 输出增加 severity 字段:

{
  "status": "fail",
  "severity": "reject",
  "checked_bindings": [
    {
      "claim_id": "claim-1",
      "tool_name": "query_metrics",
      "source_invocation_id": 12345,
      "raw_path": "$.alerts[9]",
      "status": "fail",
      "rule": "evidence.raw_path",
      "message": "raw_path not found in retrieval_details.evidence_refs"
    }
  ],
  "failed_rules": ["evidence.raw_path"],
  "warnings": [],
  "errors": [
    {
      "rule": "evidence.raw_path",
      "message": "raw_path not found in retrieval_details.evidence_refs"
    }
  ]
}

字段定义:

字段 类型 必填 说明
status string 是 pass 或 fail。
severity string 是 none、low_confid、reject。status=pass 时为 none。
checked_bindings array 是 每条 evidence binding 的校验结果。
failed_rules array 是 命中的失败规则名。
warnings array 是 非阻断风险。
errors array 是 阻断错误,必须可审计。

REJECT 级失败

以下属于物理级幻觉或证据污染,应标记:

{
  "status": "fail",
  "severity": "reject"
}

规则:

  1. source_invocation_id 不存在。
  2. source_invocation_id 不属于当前 session。
  3. source_invocation_id 存在,但 tool_name 与真实 invocation 不一致。
  4. raw_path 不存在于该 invocation 的 retrieval_details.evidence_refs。
  5. evidence_excerpt 与 evidence_refs[].text 明显不匹配。

这些情况表示 Executor 声称引用了某条证据,但系统无法核实,或核实结果与声称内容冲突。该类结果不得进入正常 Verifier 推导链路。

LOW_CONFID 级失败

以下属于证据不足、格式不完整或过渡期兼容问题,应标记:

{
  "status": "fail",
  "severity": "low_confid"
}

规则:

  1. evidence_bindings 为空。
  2. raw_path 缺失,但 source_invocation_id 存在。
  3. 旧工具调用未生成 retrieval_details.evidence_refs。
  4. evidence_excerpt 太短或太泛,无法稳定比对。
  5. Executor 输出格式不完整,但没有伪造具体 invocation / raw_path / excerpt。

这些情况不得 PASS,但不一定构成模型造假。

下游处理

  • severity=reject:Verifier 不得输出 PASS,最终倾向 REJECT。
  • severity=low_confid:Verifier 不得输出 PASS,最终输出 LOW_CONFID。
  • severity=none:Verifier 正常判断 claim 是否可由已核验证据推出。

Gatekeeper 不直接生成最终用户答案,也不替代 Verifier。它只输出确定性校验结果和处理严重程度。

审计入库

Gatekeeper 的完整结果必须记录到数据库审计数据中。第一版不新增复杂表,复用当前 DiagnosisSession.selfEvaluation 中的 verifier_evaluation.gatekeeper_result。

需要入库的最小字段:

{
  "gatekeeper_result": {
    "status": "fail",
    "severity": "reject",
    "checked_bindings": [],
    "failed_rules": [],
    "warnings": [],
    "errors": []
  }
}

入库要求:

  • 每次 Verifier 前置 Gatekeeper 执行结果都必须保存。
  • checked_bindings 至少记录失败 binding;通过 binding 可按体积控制保留摘要。
  • failed_rules / errors 必须保留,便于离线定位是伪造 ID、raw_path 不存在,还是 excerpt 不匹配。
  • 审计数据必须能回答:Executor 引用了什么、Gatekeeper 查到了什么、为什么拦截或降级。

已确认实施决策:收紧 VerifierInputHook 自动回填

当前 VerifierInputHook 会在 Executor 未填写 source_invocation_id 时,根据 tool_name 从 tool_trace_summary 自动回填 invocation id。旧版实现里该字段可能表现为 source_invocation_ids。该逻辑是旧链路中的兼容补救,但与新设计的“精确证据引用”存在冲突。

新设计下,证据引用必须由:

source_invocation_id + raw_path + evidence_excerpt

共同构成。只按 tool_name 自动回填 invocation id,会把宽泛工具调用误包装成精确证据引用。

本期策略:兼容但收紧

本期暂不完全删除自动回填,但必须收紧:

  1. 不再根据 tool_name 批量回填多个 invocation id。
  2. 只有同一 tool_name 下存在唯一候选 invocation 时,才允许回填 source_invocation_id。
  3. 不允许自动回填 raw_path。
  4. 自动回填必须写入 gatekeeper_result.warnings。
  5. 自动回填后的 binding 如果缺少 raw_path,Gatekeeper 必须标记为 severity=low_confid,不得作为 PASS 依据。
  6. 伪造 source_invocation_id、raw_path 或 evidence_excerpt 仍然是 severity=reject。

warning 示例:

{
  "rule": "evidence.invocation_auto_backfill",
  "message": "source_invocation_id was auto-filled from the unique tool invocation candidate; raw_path remains missing"
}

后续策略:废弃自动回填

等 Executor prompt 和输出结构稳定后,废弃自动回填:

Executor 必须自己输出 source_invocation_id + raw_path + evidence_excerpt。
缺少精确引用时,不能 PASS。

最终规则:

缺失引用 -> LOW_CONFID
伪造引用 -> REJECT
真实引用 + 可推导 claim -> PASS 候选

已确认实施决策:Prompt-first,Contract-later

本期不实现 Planner scope_contract,只通过 Executor Prompt 控制窄范围问题的过度展开。

原因:

scope_contract 不只是加一个字段。
它会牵动 Planner 输出契约、PlannerSkillMetadataHook、Executor 对 planner_plan 的解析、可能的 Gatekeeper scope 校验和 eval fixture。

本期真正要先验证的是:

Executor 是否能在 prompt 约束下减少无关 claim、根因推断和修复建议。

本期做

  1. 调整 chat-executor-prompt.md。
  2. 强化 Executor 单一职责:证据收集 + 微观事实提炼。
  3. 窄范围问题只输出 observation / negative_observation。
  4. 输出最少必要 claim,通常 1 条,最多 2 条。
  5. 不限制 evidence_bindings 数量。
  6. Runbook / Skill / 知识库不能作为当前事实。
  7. recommended_actions 如果保留,只能是证据收集动作,不能是修复动作。
  8. 增加 eval / E2E 验证 forbidden claim。

本期不做

  1. 不改 Planner。
  2. 不新增 scope_contract。
  3. 不解析 planner_plan.scope_contract。
  4. 不做 Gatekeeper scope 校验。
  5. 不改多 Agent 编排。

何时再引入 scope_contract

如果出现以下情况,再进入下一阶段:

  1. Prompt 调整后,Executor 仍频繁输出用户明确排除的服务或主题。
  2. 窄范围问题仍然生成 root_cause / risk / 修复建议。
  3. eval 中 forbidden claim 仍不稳定。
  4. Planner 已经能稳定识别用户 scope,但 Executor 不遵守。

本期验收

  1. HighCPUUsage 窄范围 case:不出现 HighMemoryUsage、SlowResponse、order-123、HikariCP、DB。
  2. HighMemoryUsage 窄范围 case:不出现“内存泄漏已确认”。
  3. SlowResponse 窄范围 case:不出现数据库连接池耗尽根因。
  4. 用户明确排除 HikariCP 时,claim_text 和最终答案不出现 HikariCP 确认结论。

已确认实施决策:最小 eval / E2E 覆盖矩阵

本期 eval / E2E 不铺太大,围绕已确认的改造点做最小闭环:

evidence_refs 抽取
raw_path / excerpt Gatekeeper 校验
Verifier 基于已核验 evidence_excerpt 推导
mock 工具命中质量
Executor 窄范围 prompt 约束

1. HighMemoryUsage positive

目标:验证 evidence_refs -> Executor evidence_binding -> Gatekeeper -> Verifier 能让 HighMemoryUsage 从证据存在但 LOW_CONFID 变成可通过。

场景:

只确认 order-service 是否存在 HighMemoryUsage 告警。

期望:

  • Gatekeeper pass。
  • Verifier PASS。
  • claim 只包含 HighMemoryUsage 观察事实。
  • 不确认内存泄漏。

覆盖点:

  • query_metrics 生成 evidence_refs。
  • raw_path=$.alerts[i]。
  • evidence_excerpt 可核验。
  • Verifier 基于已核验 excerpt 做推导。

2. SlowResponse positive

目标:验证一个 claim 可以绑定多条证据,不靠拆出多条 claim 凑信息。

场景:

只确认 user-service 是否存在 SlowResponse 告警和慢请求日志。

期望:

  • Verifier PASS。
  • claim 数量 1-2 条。
  • evidence_bindings 同时包含 alert 和 logs。
  • 不推断数据库连接池耗尽。

覆盖点:

  • query_metrics + query_logs。
  • raw_path=$.alerts[i]。
  • raw_path=$.logs[i]。
  • 多 evidence_bindings。
  • 窄范围不扩展根因。

3. HikariCP positive

目标:验证 HikariCP 相关查询能命中真实 mock 日志。

场景:

确认 order-service 是否存在 HikariCP 连接池耗尽。

期望:

  • query_logs 命中 order-service HikariCP 日志。
  • 不返回 generic-service。
  • Gatekeeper pass。
  • Verifier PASS。
  • 最终答案可以确认连接池耗尽日志存在。

覆盖点:

  • HikariCP / HikariPool / connection pool / active=50/50 同义匹配。
  • raw_path=$.logs[i]。
  • HikariCP 正向 mock 数据。

4. HikariCP negative

目标:验证 no-hit 不污染证据链。

场景:

确认 inventory-service 是否存在 HikariCP 连接池耗尽。

期望:

  • logs=[]。
  • evidence_status=no_evidence。
  • 不返回 generic-service。
  • Verifier 不输出正向 PASS 结论。
  • 最终表达“未检索到真实证据”。

覆盖点:

  • no-hit 语义。
  • negative_observation。
  • generic-service 占位日志清理。

5. Gatekeeper reject

目标:验证伪造 raw_path 或 “真实 invocation + 编造 excerpt” 会被拦截。

该场景优先做单元测试,不一定需要 E2E。

输入示例:

{
  "source_invocation_id": 12345,
  "raw_path": "$.alerts[99]",
  "evidence_excerpt": "HikariCP active=50/50"
}

期望:

  • gatekeeper_result.status=fail。
  • gatekeeper_result.severity=reject。
  • failed_rules 包含 evidence.raw_path 或 evidence.excerpt_mismatch。
  • 结果不得 PASS。
  • gatekeeper_result 入库审计。

覆盖点:

  • raw_path 不存在。
  • excerpt 不匹配。
  • REJECT 分级。
  • 审计入库。

6. Executor narrow forbidden claim

目标:验证 Executor Prompt 对窄范围问题的约束有效。

场景:

只确认 HighCPUUsage,不要分析订单123、OOM、数据库慢查询、连接池或 user-service。

期望:

  • claims 只围绕 HighCPUUsage / payment-service。
  • 不出现 order-123。
  • 不出现 OOM。
  • 不出现 DB / database。
  • 不出现 HikariCP / connection pool。
  • 不出现 user-service。

覆盖点:

  • Executor Prompt。
  • forbidden claim keywords。
  • Composer 不泄漏 blocked 内容。

推荐测试层级

单元测试:

  • evidence_refs 抽取。
  • raw_path 校验。
  • Gatekeeper severity 分级。
  • VerifierInputHook 自动回填收紧。

离线 eval fixture:

  • Gatekeeper reject。
  • unsupported / forbidden claim。
  • Memory / SlowResponse 的结构化输入。

E2E:

  • HighMemoryUsage positive。
  • SlowResponse positive。
  • HikariCP positive。
  • HikariCP negative。
  • HighCPUUsage narrow forbidden。

本期最小可验收

如果时间紧,至少完成:

  1. Gatekeeper raw_path reject 单测。
  2. evidence_refs 抽取单测。
  3. HikariCP positive E2E。
  4. HikariCP negative E2E。
  5. HighMemoryUsage positive E2E。
  6. narrow forbidden E2E。

历史候选优化方向

说明:本节保留早期候选方向,便于理解设计演进。当前已确认的决策以上文“已确认设计方向 / 已确认优化方向”为准:

  • Verifier 主证据源改为 Gatekeeper 已核验的 evidence_excerpt。
  • Gatekeeper 需要核对 source_invocation_id + raw_path + evidence_excerpt。
  • tool_trace_summary 降级为全局导航摘要,不再作为唯一证据源。
  • HikariCP / generic-service 问题先作为 mock 工具命中质量小阶段处理。
  • 本期暂不做 Planner scope_contract,先通过 Executor Prompt 控制窄范围过度展开。

方向 A:增强 ToolTraceSummaryService 的证据摘要保真度

让 summary 不再只是人类可读摘要,而是保留 Verifier 可用的最小机器证据。

候选策略:

  • 每个 tool invocation 至少保留 top 3-5 条关键 evidence excerpt。
  • 每个 firing alert 保留结构化摘要:告警名、服务、状态、当前值、阈值、持续时间。
  • 日志类工具按错误码、服务名、时间、endpoint、耗时等字段保留关键片段。
  • 对趋势型证据保留首尾值和采样数量。

需要讨论:

  • output_summary 继续做人类摘要,还是升级为机器证据索引?
  • 是否需要新增字段,而不是继续塞进 output_summary?

方向 B:Verifier 直接消费 Executor 的 evidence_excerpt

Verifier 判断 claim 是否可推导时,不只看 tool_trace_summary.output_summary,也看 Executor 已经绑定到 claim / action 的证据片段。

优点:

  • 证据离 claim 更近。
  • 对 Memory / SlowResponse 这类 case 更容易 PASS。
  • 不要求 summary 承担全部证据承载职责。

风险:

  • 如果 Executor 编造 excerpt,Verifier 会被污染。
  • 需要 Gatekeeper 先保证 excerpt 能回溯到真实 tool output。

需要讨论:

  • Verifier 消费 excerpt 前,Gatekeeper 是否必须加入原文回溯 / 相似度校验?
  • Verifier 应该把 excerpt 当作主证据,还是辅助证据?

方向 C:Gatekeeper 增加 excerpt 原文回溯校验

在 Verifier 前,用代码验证 Executor 声称的 evidence_excerpt 是否能在对应 tool invocation 的原始输出中找到或高度相似。

候选规则:

  • 证据引用必须能回溯到真实 tool invocation。
  • evidence_excerpt 与系统侧证据文本明显不匹配时拒绝。
  • 找不到引用片段时,不进入 Verifier,避免张冠李戴。

优点:

  • 为 Verifier 直接消费 excerpt 建立前置安全条件。
  • 能拦住“真实 ID + 编造文本”的物理级幻觉。

风险:

  • 原始输出和 excerpt 经过格式化后可能不完全一致,需要容忍截断、空白、标点差异。
  • 相似度阈值需要通过 fixture 校准。

方向 D:窄范围问题限制 Executor claim 数量

对于用户明确要求“只确认某一件事”的问题,Executor 输出应更克制。

候选策略:

  • Planner 或 Executor prompt 生成 scope contract。
  • Executor 对窄范围问题最多输出 1-2 个核心 claim。
  • 与用户明确排除的服务、告警、错误类型无关的 claim 不输出。

需要讨论:

  • 这个约束放在 Planner,还是 Executor 自己根据用户问题判断?
  • 是否需要 Gatekeeper 增加 scope 校验?

方向 E:修复 mock 工具命中质量

针对 HikariCP 这类 case,补齐正向 mock 分支或改进查询匹配。

候选策略:

  • query_logs 支持 HikariCP、connection pool、active=50/50、order-service 等同义匹配。
  • 避免正向场景返回 generic-service 占位日志。
  • no-hit 时明确标记为无证据,减少污染。

需要讨论:

  • mock 工具是只服务 eval,还是也作为 demo 数据源长期维护?
  • mock 数据是否应该和 knowledge_base fixture 建立对应关系?

初步验收标准

优化后至少需要覆盖以下回归:

  1. HighCPUUsage 正向场景稳定 PASS。
  2. HighMemoryUsage 在证据存在时不再因为 summary 丢证据而 LOW_CONFID。
  3. SlowResponse 在 alert 与慢请求日志都存在时不再因为 summary 丢证据而 LOW_CONFID。
  4. HikariCP 负向场景仍能正确表达“未检索到真实证据”。
  5. HikariCP 正向场景能够命中真实 mock 数据并被 Verifier 正确识别。
  6. Gatekeeper 审计字段完整记录校验结果。
  7. 最终 user_facing_answer 不泄漏 raw JSON、tool raw output 或 Executor 未通过 Verifier 的 claim。

历史问题记录

以下问题是早期讨论时提出的候选方向,当前均已被上文“已确认设计方向 / 已确认实施决策”覆盖:

历史问题 当前决策
Verifier 后续应该以 tool_trace_summary 为唯一证据源,还是同时消费 Executor evidence_excerpt? Verifier 主证据源改为 Gatekeeper 已核验的 evidence_excerpt,tool_trace_summary 降级为全局导航摘要。
如果 Verifier 消费 evidence_excerpt,Gatekeeper 是否必须先做 excerpt 原文回溯? 必须。Gatekeeper 校验 source_invocation_id + raw_path + evidence_excerpt 后,Verifier 才能使用 excerpt。
ToolTraceSummaryService 应该增强现有 output_summary,还是新增更结构化的 evidence excerpt 字段? 本期不把 output_summary 作为主证据源;结构化证据引用进入 tool_invocation.retrieval_details.evidence_refs。
summary 保留多少条 excerpt 才够,不会重新变成超长上下文? 不靠 summary 承载主证据;claim-local evidence 由 Executor 引用并经 Gatekeeper 校验。
generic-service 占位日志是否应该彻底视为 success=false 或 evidence_level=none? no-hit 应返回 logs=[] 且 evidence_status=no_evidence,不再返回 generic-service 占位日志作为证据。
窄范围问题是否需要显式 scope contract,避免 Executor 过度展开? 本期采用 Prompt-first,只调 Executor Prompt;scope_contract 作为后续增强。