# 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` --- ## 背景 当前复杂诊断链路已经形成: ```text 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` **实际结论**: ```text 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 漏拦,而是证据在链路中被摘要层压缩丢失。 当前证据链路存在一个断点: ```text 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` 承担更重的自然语言压缩职责: ```text 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 的失败模式: ```text 工具原始返回和 Executor evidence_excerpt 有证据 -> summary 压缩时丢失关键证据 -> Verifier 看不到足够材料 -> LOW_CONFID ``` 调整后变为: ```text 工具原始返回有证据 -> 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 的数据结构。核心原则: ```text 证据定位:source_invocation_id + raw_path 证据文本:evidence_excerpt 证据真实性:由 Gatekeeper 在 Verifier 前校验 Verifier 职责:只判断 claim_text 是否能由已核验 evidence_excerpt 推出 ``` ### 1. 工具调用侧最小证据引用 当前工具尚未统一返回 `evidence_items`。第一版不引入复杂 metadata,也不要求新增数据库表,建议在 `tool_invocation.retrieval_details` 中补充最小 `evidence_refs`: ```json { "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 与证据引用: ```json { "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`: ```json { "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 最终接收的输入结构如下: ```json { "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 的最小字段为: ```json { "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 相关问题能够稳定区分: ```text 有真实 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 应表达为“工具调用成功但没有证据”,而不是工具失败: ```json { "success": true, "logs": [], "total": 0, "message": "未找到匹配的日志" } ``` 并在 `tool_invocation.retrieval_details.evidence_status` 中记录: ```json { "evidence_status": "no_evidence" } ``` ### HikariCP 正向 mock 日志示例 ```text [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 控制窄范围问题的过度展开。 ### 本期边界 ```text 不改 Planner 不新增 scope_contract 不新增 Controller 不做复杂 scope Gatekeeper 只调整 Executor Prompt 的单一职责和输出边界 ``` ### Executor 单一职责 Executor 在本期应被约束为: ```text 证据收集 + 微观事实提炼 ``` 也就是: - 调用工具收集当前任务范围内的证据。 - 输出工具证据直接支持的 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 数量不是限制证据数量 这里限制的是: ```text claim 数量 ``` 不是限制: ```text 工具调用数量 证据数量 evidence_bindings 数量 missing_info 数量 ``` 窄范围任务的理想输出是: ```text 1 条核心 claim 多条直接相关 evidence_bindings 必要的 missing_info ``` 示例: ```json { "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" } ] } ``` 不建议拆成: ```text 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` 的约束草案: ```text ## 单一职责与输出边界 你是证据收集与微观事实提炼专家。 你只负责调用工具收集证据,并输出工具证据直接支持的微观事实断言。 你不得输出最终用户答案。 你不得生成修复方案。 你不得扩展到用户未要求的服务、订单、告警、数据库、连接池或下游依赖。 你不得将 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` 格式一致。 - 不需要一次性改造所有工具返回协议。 第一版抽取规则: ```text 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` 共同定位一条证据。 支持的路径格式仅包括: ```text $.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 个知识库证据块 | 第一版不支持: ```text $.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`。 示例: ```json { "evidence_refs": [ { "raw_path": "$.alerts[1]", "text": "HighMemoryUsage firing, service=order-service, current=91%, duration=15m; JVM heap usage 3.8GB/4GB" } ] } ``` Executor 引用: ```json { "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`。第一版按失败性质分级: ```text 物理级幻觉 / 证据污染 -> REJECT 证据缺失 / 格式不完整 / 过渡期兼容问题 -> LOW_CONFID ``` ### Gatekeeper 输出结构 建议 Gatekeeper 输出增加 `severity` 字段: ```json { "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` 级失败 以下属于物理级幻觉或证据污染,应标记: ```json { "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` 级失败 以下属于证据不足、格式不完整或过渡期兼容问题,应标记: ```json { "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`。 需要入库的最小字段: ```json { "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`。该逻辑是旧链路中的兼容补救,但与新设计的“精确证据引用”存在冲突。 新设计下,证据引用必须由: ```text 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 示例: ```json { "rule": "evidence.invocation_auto_backfill", "message": "source_invocation_id was auto-filled from the unique tool invocation candidate; raw_path remains missing" } ``` ### 后续策略:废弃自动回填 等 Executor prompt 和输出结构稳定后,废弃自动回填: ```text Executor 必须自己输出 source_invocation_id + raw_path + evidence_excerpt。 缺少精确引用时,不能 PASS。 ``` 最终规则: ```text 缺失引用 -> LOW_CONFID 伪造引用 -> REJECT 真实引用 + 可推导 claim -> PASS 候选 ``` --- ## 已确认实施决策:Prompt-first,Contract-later 本期不实现 Planner `scope_contract`,只通过 Executor Prompt 控制窄范围问题的过度展开。 原因: ```text scope_contract 不只是加一个字段。 它会牵动 Planner 输出契约、PlannerSkillMetadataHook、Executor 对 planner_plan 的解析、可能的 Gatekeeper scope 校验和 eval fixture。 ``` 本期真正要先验证的是: ```text 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 不铺太大,围绕已确认的改造点做最小闭环: ```text 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` 变成可通过。 场景: ```text 只确认 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 凑信息。 场景: ```text 只确认 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 日志。 场景: ```text 确认 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 不污染证据链。 场景: ```text 确认 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。 输入示例: ```json { "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 对窄范围问题的约束有效。 场景: ```text 只确认 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` 作为后续增强。 |