Files
SuperBizAgent-java/mvp/issues/ISS-009-negative-observation-no-evidence-reference.md
T

5.7 KiB
Raw Blame History

ISS-009 negative_observation 精确引用 no-evidence 结果

严重程度:中 状态:已修复 发现时间:2026-07-08 关联:

  • ISS-007-verifier-evidence-summary-fidelity
  • ISS-008-executor-narrow-scope-overreach
  • executor-structured-output-v2

背景

ISS-007 已经把正向证据引用收敛为:

source_invocation_id + raw_path + evidence_excerpt

Gatekeeper 通过 tool_invocation.retrieval_details.evidence_refs 校验 Executor 引用是否真实存在。

但负向观察存在一个缺口:当工具明确返回“没查到”时,结果通常是空数组:

{
  "logs": [],
  "total": 0,
  "message": "未找到匹配的日志"
}

这时没有 $.logs[0]、$.alerts[0] 或 $.evidence_blocks[0] 可以引用。Executor 如果输出 negative_observation,Gatekeeper 无法稳定验证它引用的“无证据结果”,容易降级为 LOW_CONFID 或 REJECT。


问题

用户问:

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

工具返回:

{
  "success": false,
  "logs": [],
  "total": 0,
  "message": "未找到匹配的日志"
}

合理 claim 是:

{
  "claim_type": "negative_observation",
  "claim_text": "未检索到 inventory-service 的 HikariCP 连接池耗尽日志。"
}

但旧设计只支持正向数组项:

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

因此负向观察缺少可回溯的精确引用点。


修复决策

给 no-hit / no-evidence 结果增加一等证据引用:

{
  "raw_path": "$.no_evidence",
  "text": "query_logs returned no evidence; evidence_status=no_evidence; query=inventory-service HikariCP; topic=application-logs; total=0; message=未找到匹配的日志"
}

Executor 可以引用:

{
  "tool_name": "query_logs",
  "source_invocation_id": 123,
  "raw_path": "$.no_evidence",
  "evidence_excerpt": "query_logs returned no evidence; query=inventory-service HikariCP; total=0; evidence_status=no_evidence"
}

语义边界

$.no_evidence 只表示:

该工具对当前查询返回无匹配证据。

它不表示:

  • 问题绝对不存在。
  • 根因被排除。
  • 系统已经健康。
  • 没有必要继续排查。

实施范围

已修改

  • ToolInvocationRecorder
    • query_logs no-hit 时生成 evidence_refs[0].raw_path="$.no_evidence"。
    • query_metrics no-hit 时生成 evidence_refs[0].raw_path="$.no_evidence"。
    • lookup_knowledge no-hit 且无 evidence blocks 时生成 evidence_refs[0].raw_path="$.no_evidence"。
  • ExecutorGatekeeperService
    • 复用既有 evidence_refs 校验逻辑,无需新增特殊分支。
    • $.no_evidence 和普通 raw_path 一样必须存在于 retrieval_details.evidence_refs。
  • chat-executor-prompt.md
    • 明确 negative_observation 必须引用 $.no_evidence。
    • 明确没有实际工具调用时禁止使用 $.no_evidence。

未修改

  • 不新增数据库表。
  • 不新增复杂 metadata。
  • 不改变 Planner。
  • 不改变 Agent 编排。

验收标准

  1. query_logs 返回 logs=[] / total=0 / evidence_status=no_evidence 时,tool_invocation.retrieval_details.evidence_refs 包含:
{
  "raw_path": "$.no_evidence"
}
  1. Executor 输出 negative_observation 并引用 $.no_evidence 时,Gatekeeper 可以校验通过。

  2. Executor 如果用 $.no_evidence 搭配正向证据文本,例如 HikariCP active=50/50,Gatekeeper 必须拒绝。

  3. $.no_evidence 不得被解释为“问题绝对不存在”,只能表达“当前查询未检索到匹配证据”。

  4. HikariCP negative E2E:

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

期望:

  • 工具返回 no-hit。
  • 不返回 generic-service。
  • Executor 输出 negative_observation。
  • raw_path="$.no_evidence"。
  • Gatekeeper pass/none。
  • Verifier 不误判为正向 HikariCP 证据。

验证记录

2026-07-08 单元测试

命令:

mvn '-Dtest=ToolInvocationRecorderTest,ExecutorGatekeeperServiceTest,QueryLogsToolsTest' test

结果:

Tests run: 23, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

覆盖点:

  • query_logs no-hit 生成 $.no_evidence。
  • query_metrics no-hit 生成 $.no_evidence。
  • lookup_knowledge no-hit 生成 $.no_evidence。
  • Gatekeeper 可以校验 $.no_evidence。
  • 多个 no-evidence 调用存在时,Gatekeeper 可按 tool_name + raw_path + evidence_excerpt 唯一回填 source_invocation_id。
  • negative_observation 混绑正向 $.logs[i] 会被拒绝。
  • HikariCP negative mock 不返回 generic-service。

2026-07-08 E2E 验证

输入:

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

最终通过 session:

sessionId: iss009-hikari-negative-latest-20260708-232428
verdict: PASS
groundedness_score: 1.0
gatekeeper_result.status: pass
gatekeeper_result.severity: none
claim_count: 1
claim_type: negative_observation
raw_path: $.no_evidence
generic_service_hit: false
overstate_hit: false

Executor claim:

当前查询未检索到 inventory-service 的 HikariCP 连接池耗尽日志。

最终答案:

本次查询在 inventory-service 中未发现 HikariCP 连接池耗尽的日志记录,检索结果未匹配到相关证据。

说明:

  • Executor 仍可能输出多个 $.no_evidence binding。
  • 如果 source_invocation_id 缺失,Gatekeeper 会按 tool_name + raw_path + evidence_excerpt 唯一匹配真实 invocation 并写入 warning。
  • 最终答案不使用“排除”“确认没有”“不存在该问题”等过度表达。