5.7 KiB
5.7 KiB
ISS-009 negative_observation 精确引用 no-evidence 结果
严重程度:中 状态:已修复 发现时间:2026-07-08 关联:
ISS-007-verifier-evidence-summary-fidelityISS-008-executor-narrow-scope-overreachexecutor-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 只表示:
该工具对当前查询返回无匹配证据。
它不表示:
- 问题绝对不存在。
- 根因被排除。
- 系统已经健康。
- 没有必要继续排查。
实施范围
已修改
ToolInvocationRecorderquery_logsno-hit 时生成evidence_refs[0].raw_path="$.no_evidence"。query_metricsno-hit 时生成evidence_refs[0].raw_path="$.no_evidence"。lookup_knowledgeno-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 编排。
验收标准
query_logs返回logs=[] / total=0 / evidence_status=no_evidence时,tool_invocation.retrieval_details.evidence_refs包含:
{
"raw_path": "$.no_evidence"
}
-
Executor 输出
negative_observation并引用$.no_evidence时,Gatekeeper 可以校验通过。 -
Executor 如果用
$.no_evidence搭配正向证据文本,例如HikariCP active=50/50,Gatekeeper 必须拒绝。 -
$.no_evidence不得被解释为“问题绝对不存在”,只能表达“当前查询未检索到匹配证据”。 -
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_logsno-hit 生成$.no_evidence。query_metricsno-hit 生成$.no_evidence。lookup_knowledgeno-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_evidencebinding。 - 如果
source_invocation_id缺失,Gatekeeper 会按tool_name + raw_path + evidence_excerpt唯一匹配真实 invocation 并写入 warning。 - 最终答案不使用“排除”“确认没有”“不存在该问题”等过度表达。