Files
SuperBizAgent-java/interview/topic-evidence-attribution-and-gates.md
T
zhuyongxin de5a5b09d9 docs(interview): refresh materials for single-agent harness narrative
Archive pre-refactor interview notes and add current deep-dives on
architecture evolution, issue-derived stories, and evidence gates.
2026-07-24 18:14:49 +08:00

30 KiB
Raw Blame History

主题深读:证据归因幻觉 + 现行质量门禁

用途:巩固知识 + 面试准备 + 举一反三
不是:逐字讲稿、旧 Issue 复述、过时五段流水线说明书
材料日期:2026-07-24
叙事原则:以现行设计为主讲;早期 Issue 只说明「问题从哪来」
主题定位:质量辨识度主故事——「工具调了,结论为何仍不能直接给用户」

现行依据(面试默认口径)

层级 路径
架构 mvp/architecture/current-mvp-architecture.md
编排 mvp/architecture/agent-orchestration.md
门禁 mvp/architecture/harness-quality-gates.md
Draft 契约 .../harness/contract/DiagnosisDraft.java、AnalysisKind.java
物理验真 .../harness/guard/evidence/EvidenceGuard.java
语义审查 .../harness/guard/semantic/SemanticGuard.java、semantic-guard-prompt.md
发布 .../harness/release/DiagnosisReleaseUseCase.java、SafeFallbackFactory.java
Agent 规则 src/main/resources/prompts/diagnosis-agent-prompt.md

历史依据(只作起源,不代表 runtime)

  • mvp/issues/archived/executor-evidence-attribution-hallucination.md(2026-07-07,旧 Executor 链路)
  • Phase2 Gatekeeper / executor_evidence_v2 归档文档

配套


0. 怎么用 / 怎么讲

目标 用法
巩固 先背现行三道门与 DiagnosisDraft 引用闭包,再看历史问题为何逼出这套设计
面试 先讲现在怎么拦,再补一句早期怎么发现;禁止把主链路讲成 Planner→Executor→Verifier
举一反三 用现行组件名迁移到客服/代码/合规场景

开场主线(先背这句,现行口径)

当前系统里,Diagnosis Agent 是唯一报告作者,它在 ReAct 里查只读工具并写出结构化 DiagnosisDraft。
但 Draft 默认不能出门:必须先过 EvidenceGuard(0 LLM,验 tool_call 归属与投影),再过 SemanticGuard(隔离单轮,判是否越证),最后由 Release Policy 决定公开报告还是 SAFE_FALLBACK。
这套门禁要防的核心失败,是早期线上已经见过的 证据归因幻觉:有工具调用,却把 runbook/常识写成「本 Run 已证实事实」。

禁止的过时口径

不要说 要说
我们主链路是 Planner→Executor→Gatekeeper→Verifier→Composer 单 Diagnosis Agent + Harness 门禁
Gatekeeper 验 source_invocation_id + raw_path + excerpt EvidenceGuard 验 tool_call_id + 当前 Run canonical/projection
Verifier 输出 LOW_CONFID/PASS SemanticGuard 输出 SUPPORTED / UNSUPPORTED
工具有 metrics/Prometheus 现行诊断 Tool:lookup_knowledge / query_logs / query_mysql
引用主键是 DB tool_invocation.id 框架 tool_call_id;完整调用在 Redis canonical

四轴(现行)

  1. 谁写报告:仅 Diagnosis Agent
  2. 谁保证引用真:EvidenceGuard + Redis canonical(Harness only)
  3. 谁保证语义不越界:SemanticGuard(无 Tool、无记忆)
  4. 谁决定用户看见什么:Release Policy(Draft ≠ 公开 SSE)

图目录

图 位置 白板优先级
现行主链(质量视角) §1 ★★★
DiagnosisDraft 引用闭包 §2 ★★★
EvidenceGuard 校验步骤 §3 ★★★
AnalysisKind × EvidenceStatus §3.3 ★★
SemanticGuard 输入冻结 §4 ★★★
Release / Repair / Fallback §5 ★★★
数据三层如何服务验真 §6 ★★
历史问题 → 现行映射(30 秒) §8 ★★
白板速画 §13 ★★★

1. 现行设计:质量门禁长什么样

1.1 在系统中的位置

POST /api/chat (SSE)
  → ChatApplicationUseCase
  → Intent Router → DIAGNOSIS
  → Diagnosis ReAct Agent
        只读 Tool × 3,观察的是 projection
        产出 DiagnosisDraft
  → DiagnosisReleaseUseCase
        EvidenceGuard →(可选 EvidenceRepair 一次)→ SemanticGuard → Release
  → 公开 content | SAFE_FALLBACK | failure
flowchart TB
    Q["query + safe previous_turn"] --> A["Diagnosis Agent<br/>唯一报告作者 · ReAct"]
    A <--> TB["ToolBoundary"]
    TB --> Redis["Redis canonical<br/>Harness only"]
    TB --> Proj["bounded agent_result"]
    Proj --> A
    A --> Draft["DiagnosisDraft<br/>内部制品"]
    Draft --> RU["DiagnosisReleaseUseCase"]
    RU --> EG["EvidenceGuard · 0 LLM"]
    EG -->|invalid| RP["EvidenceRepair 最多一次"]
    RP --> EG
    EG -->|valid snapshot| SG["SemanticGuard · 隔离单轮"]
    SG -->|SUPPORTED| Out["Release SUCCESS<br/>公开 typed report"]
    SG -->|UNSUPPORTED / 不可用| FB["SAFE_FALLBACK"]
    EG -->|仍 invalid| FB

面试一句话

Agent 负责「尽量基于证据写对」;Harness 负责「写错了也不能当成功答案发出去」。

1.2 职责切分(现行,必背)

组件 做 不做
Diagnosis Agent 规划、调 Tool、写完整 Draft、证据不足时写 limitations HTTP/SSE、预算、物理验真、语义终审、发布
ToolBoundary schema/只读/预算、写 canonical、projector、只回有界观察 业务推理
EvidenceGuard Draft 结构、analysis 闭包、tool_call_id 属本 Run、READY/可引用、kind↔status、投影可解析 调模型、改报告语义
EvidenceRepair 在证据失败时尝试一次结构化修复 无限重试、绕过验真
SemanticGuard 在 verified snapshot 上判断整份报告是否被支持 Tool、记忆、Redis、改写报告、部分放行
Release SUPPORTED 才公开 Draft;否则固定 fallback/failure 把未验证 Draft 流式出去

对应代码入口:DiagnosisReleaseUseCase.execute(run, query, draft)。

1.3 和「纯 ReAct Demo」的差(质量视角)

纯 ReAct:  Model ↔ Tools → 文本直接给用户

现行:      Model ↔ ToolBoundary/projection → DiagnosisDraft
              → EvidenceGuard → SemanticGuard → Release → SSE
           + run 预算/取消 + Timeline(EVIDENCE/SEMANTIC/RELEASE 事件)

2. 现行契约:DiagnosisDraft 如何逼归因诚实

2.1 结构(代码事实)

DiagnosisDraft
  conclusion?
    text
    based_on_analysis_ids[]          ← 必须指向本 Draft 内 analysis_id
  analysis[]
    analysis_id                      ← 唯一
    kind: NORMAL | NEGATIVE_OBSERVATION
    text
    tool_call_ids[]                  ← 至少一个;必须是本 Run 真实 id
  action_plan[]
    action
    based_on_analysis_ids[]
    requires_human_confirmation
  recommendations[]
    text
    based_on_analysis_ids[]
  limitations                        ← 必填 scope(EvidenceGuard 校验)
    scope
    missing_info[]
flowchart TB
    C["conclusion / actions / recommendations"] -->|"based_on_analysis_ids"| A["analysis_id"]
    A -->|"tool_call_ids"| T["本 Run tool_call_id"]
    T --> Canon["Redis canonical<br/>runId + toolCallId"]
    Canon --> Status["evidence_status<br/>FOUND / NO_EVIDENCE"]
    A --> Kind["kind NORMAL / NEGATIVE"]
    Kind -.->|"must match"| Status

设计意图(对着归因幻觉)

约束 防什么
每条 analysis 必须带 tool_call_ids 「凭空结论」「常识当观测」
conclusion 不直接绑 tool,只绑 analysis 结论必须落在已声明的分析链上,形成闭包
limitations 强制存在 证据不足时不能装成完整结案
kind 二分 负向观察与正向命中不能混用同一类证据状态

2.2 Agent Prompt 里的硬规则(现行)

diagnosis-agent-prompt.md 关键口径(面试可直接引用思想,不必背原文):

  1. 唯一报告作者;内部规划,不对外输出 CoT。
  2. PreviousTurn 不是本 Run 证据,不能引用其 tool_call_id。
  3. 只有 evidence_status=EVIDENCE_FOUND|NO_EVIDENCE 且带真实 tool_call_id 的观察才能当证据。
  4. NORMAL 只能引 FOUND;NEGATIVE_OBSERVATION 只能引 NO_EVIDENCE。
  5. NO_EVIDENCE ≠ 系统健康 / 已排除根因。
  6. Tool ERROR 不是证据,禁止引用。
  7. 证据不足:conclusion=null,写 scope/missing_info,禁止编根因。
  8. 不暴露 raw、凭据、内部错误、hidden reasoning。

金句

Prompt 负责教 Agent「怎么写才诚实」;EvidenceGuard 负责「写得不诚实就过不了」。两者缺一不可,但安全边界在代码。

2.3 和早期「分区文案」的关系(30 秒)

早期 Issue 要求 Executor 输出「已证实 / 推测 / 缺口 / 动作」分区。
现行不是同一套 JSON 字段名,但语义被结构吸收了:

早期分区意图 现行落点
已证实事实 analysis(NORMAL + FOUND)
负向观察 analysis(NEGATIVE_OBSERVATION + NO_EVIDENCE)
证据缺口 limitations.missing_info + 可空 conclusion
建议动作 action_plan / recommendations(必须 based_on analysis)
禁止常识当事实 Guard 不认无 tool_call 的 analysis;Semantic 审越证

3. EvidenceGuard:现行物理验真(0 LLM)

3.1 它在防什么

不是「这句话好不好听」,而是:

报告里声明依赖的每一个 tool_call,是否真的在本 Run 发生过、状态是否可引用、投影是否自洽、analysis kind 是否与 evidence_status 匹配,以及 conclusion/action 是否只引用存在的 analysis。

3.2 校验流水(按代码路径讲)

EvidenceGuard.validate(RunContext, DiagnosisDraft) 大致两段:

A. Draft 结构与报告闭包

  • draft / analysis 非空
  • analysis_id 存在且唯一
  • kind、text 必填
  • 每条 analysis 的 tool_call_ids 非空
  • conclusion / action_plan / recommendations:text 非空,且 based_on_analysis_ids 非空、id 都认识
  • limitations.scope 必填

B. 逐 tool_call 验真

对每个 tool_call_id:

  1. 用 runId + toolCallId 生成 key,查 Redis canonical
  2. 找不到 → INVOCATION_MISSING(典型:编造 id)
  3. id 不一致 → INVOCATION_ID_MISMATCH
  4. !isReferencableBy(runId) 或 agent_result 空 → INVOCATION_NOT_REFERENCABLE
    (跨 Run、未 READY、不可引用状态)
  5. analysis.kind.accepts(invocation.evidenceStatus)
    • NORMAL ↔ EVIDENCE_FOUND
    • NEGATIVE_OBSERVATION ↔ NO_EVIDENCE
      否则 EVIDENCE_KIND_MISMATCH
  6. 按 tool 反序列化 agent_result 投影(不是让模型再读 raw 讲故事):
    • lookup_knowledge / query_logs / query_mysql
  7. 投影内 tool_call_id、evidence_status 与 canonical 一致
  8. FOUND 必须有可展示证据条目;NO_EVIDENCE 必须空列表且 count=0
  9. 通过则写入 VerifiedEvidence,汇总为 VerifiedEvidenceSnapshot
flowchart TB
    Draft["DiagnosisDraft"] --> S["结构 + analysis 闭包"]
    S --> Loop["foreach tool_call_id"]
    Loop --> Key["key = runId + toolCallId"]
    Key --> Redis["Canonical store"]
    Redis -->|missing| V1["INVOCATION_MISSING"]
    Redis -->|not referencable| V2["NOT_REFERENCABLE"]
    Redis -->|ok| K["kind vs evidence_status"]
    K -->|mismatch| V3["KIND_MISMATCH"]
    K --> P["Parse projection"]
    P -->|invalid| V4["PROJECTION_*"]
    P --> Snap["VerifiedEvidenceSnapshot"]

3.3 AnalysisKind × EvidenceStatus(高频考点)

NORMAL                 → 只能绑 EVIDENCE_FOUND
NEGATIVE_OBSERVATION   → 只能绑 NO_EVIDENCE
ERROR                  → 根本不是证据(Agent Prompt + 边界)

面试例子

Agent 想说 错误绑法 Guard
「CPU 告警 92%」 编造 tool_call_id MISSING
「未查到池耗尽日志」 kind=NORMAL 却绑 NO_EVIDENCE KIND_MISMATCH
「已排除内存泄漏」 仅 NO_EVIDENCE 却写排除结论 物理可能过,Semantic 应 UNSUPPORTED
引用上一轮 previous_turn 的 id 非本 Run canonical MISSING / NOT_REFERENCABLE

3.4 为什么验的是 projection 且 canonical 在 Redis

设计 原因
Agent 只见 projection 有界 ACI;降低上下文里的 debug 噪声与胡拼素材
Guard 读 canonical 元数据 + 校验投影 确认「Agent 引用的 id」对应真实调用,且投影自洽
Agent 不能访问 Redis 防止自己翻 raw 再编第二套故事
MySQL tool_invocation 只 metadata 长期审计 ≠ 验真主存;完整 raw 短 TTL

与早期 Gatekeeper 的差异(讲清楚就加分)

早期 Gatekeeper 现行 EvidenceGuard
多角色流水线中的一环 Harness Release 路径上的确定性步骤
source_invocation_id + raw_path + excerpt 字符串闭合 tool_call_id + Run ownership + 投影结构/状态闭合
面向 executor_evidence_v2 claims 面向 DiagnosisDraft analysis 闭包
工具集合含 metrics 等 现行三 Tool;投影类型 Rag/Logs/Mysql

语义继承:都是 0 LLM 的物理/契约验真;协议与装载层已现代化。

3.5 失败码怎么用于口述

挑几个最能讲故事的 EvidenceViolationCode:

Code 一句话
TOOL_REFERENCE_MISSING analysis 根本没绑工具
INVOCATION_MISSING 引用了不存在的 tool_call(归因造假)
INVOCATION_NOT_REFERENCABLE 调用存在但不可作为证据(错 Run/未就绪/空结果)
EVIDENCE_KIND_MISMATCH 负向/正向证据用错 kind
ANALYSIS_REFERENCE_UNKNOWN 结论引用了不存在的 analysis_id
PROJECTION_INVALID 投影与契约不一致,不能当干净证据

4. SemanticGuard:现行语义保险丝

4.1 输入被故意冻死

SemanticGuardInput.from(query, draft, verifiedSnapshot):

只给:
  原始 query
  + 完整 Draft 视图
  + EvidenceGuard 产出的 verified snapshot

明确没有:
  Tool / 记忆 / Redis / 主 Agent 回调 / 诊断历史

Prompt(semantic-guard-prompt.md)要求:

  • 查:evidence 是否支持各 analysis;analysis 是否支持 conclusion;action/recommendation 是否越界;limitations 是否如实
  • 禁止改写、纠正、摘要扩展、部分批准
  • 只返回 {"verdict":"SUPPORTED|UNSUPPORTED","reason":"..."}

4.2 它专门接住 EvidenceGuard 接不住的归因幻觉

EvidenceGuard 通过只说明:

「你引用的调用是真的,投影也合法。」

仍可能:

漏洞 例子 谁拦
真日志推不出该根因 只有超时日志 → 写「确定是死锁」 SemanticGuard
负向观察说成排除 NO_EVIDENCE → 「不可能是池耗尽」 SemanticGuard + Agent 规则
结论超出 analysis 集合语义 analysis 只谈 A,conclusion 谈 B SemanticGuard
建议动作无分析支撑 乱给变更建议 SemanticGuard + 结构上 based_on
flowchart LR
    EG["EvidenceGuard<br/>物理真"] --> SG["SemanticGuard<br/>语义立"]
    SG -->|SUPPORTED| R["可发布"]
    SG -->|UNSUPPORTED| F["Fallback<br/>保留 observed_facts"]

4.3 为什么必须隔离、且无 Tool

若 SemanticGuard 能再查库 后果
自建第二证据世界 与主 Agent / snapshot 不一致
「审稿时补证」 绕过用户可见的排查过程
又变成带 Tool 的第二 Executor 归因问题换个角色重演

金句

SemanticGuard 是保险丝,不是第二名侦探。

4.4 技术失败策略(现行)

  • 输入/输出字节上限(SemanticGuardLimits)
  • 同输入有限重试;仍失败 → semanticUnavailable fallback(有 snapshot 时仍可带已验证事实)
  • 不把内部异常原文甩给用户

5. Release:Draft 与公开通道切断

5.1 DiagnosisReleaseUseCase 决策序

1) EvidenceGuard.validate
2) 若失败 → EvidenceRepair 一次 → 再 validate
3) 仍失败 → EVIDENCE_VALIDATION_FAILED fallback
4) SemanticGuard.review(query, draft, snapshot)
5) SUPPORTED → SUCCESS(公开 candidate Draft + snapshot 元数据路径)
6) UNSUPPORTED → SEMANTIC_UNSUPPORTED fallback(可带 observed_facts)
7) Semantic 技术不可用 → SEMANTIC_UNAVAILABLE fallback

Timeline 会记:EVIDENCE_GUARD_INITIAL / RECHECK / semantic / release 决策(普通 Trace 可回放阶段,不靠「感觉」)。

5.2 SAFE_FALLBACK 在防什么

不是空白 500,而是可信的不完整:

Fallback 类型 用户侧含义(思想)
证据校验失败 引用/结构没过,不能确认根因;可带 validation 问题方向
语义不支持 已有可验证事实,但撑不起当前根因结论
语义不可用 有事实,但审不过/审不了,暂不发根因

SafeFallbackFactory 会从 snapshot 抽取有界 observed_facts / sources(有上限),并给出 failure_stage、next_steps 等——在不泄 Prompt/raw/内部 Draft 细节的前提下尽量可操作。

金句

我们宁可发布「已经核实到什么、卡在哪」,也不发布「流畅但未过门禁的完整故事」。

5.3 PreviousTurn 与门禁的衔接

  • 仅 同 Session、最近一次 DIAGNOSIS + SUCCESS + published_result 可进下一轮
  • Fallback/失败/raw 不进 PreviousTurn
  • Prompt 明确:previous_turn 不可当本 Run 证据

防止「上一轮没过门禁的句子」在下一轮被当成已证实事实——这是归因幻觉的跨轮版本。


6. Tool 边界:归因幻觉的上游防线

门禁是下游闸门;上游仍要减少「胡拼素材」。

framework tool_call_id
  → exact Run / schema / read-only / budget
  → 执行
  → Redis canonical(request/raw/agent_result/status)
  → projector → bounded agent_result
  → 只把 projection 给 Agent
  → MySQL 仅 metadata audit

现行 Agent 可见 Tool 固定三个:

  • lookup_knowledge
  • query_logs
  • query_mysql

与归因的关系

机制 作用
投影有界 少把 rerank/debug 大字段留给模型拼案情
统一 evidence_status FOUND/NO_EVIDENCE/ERROR 语义稳定,供 kind 匹配
每调必有 tool_call_id Draft 绑定有稳定主键
禁止 Agent 见 Redis 不能「翻完整 raw 再假装引用」

7. Reasoning 明确不是证据(现行安全边界)

架构硬约束:

  • Provider reasoning 若存在,进独立 agent_reasoning_audit
  • 不进普通 SSE、Trace 正文、Evidence Snapshot、业务判断
  • 不能绕过 EvidenceGuard / SemanticGuard
  • 未返回则记 unavailable,禁止伪造

面试若被问「你们保存思考过程吗」:

审计与事实分离。思考不是 tool evidence,更不能当发布依据。


8. 历史问题:只用来回答「为什么要这套现行设计」

8.1 早期现象(30–45 秒够)

2026-07 旧 Chat 链路(Planner/Executor/Verifier…)上:

  • 多次 E2E:lookup_* / logs / metrics 有调用,仍大量 LOW_CONFID
  • 答案出现工具 raw 中不存在的「精确事故事实」(OOM 次数、慢 SQL 秒数等)
  • 根因命名:证据归因幻觉——把 runbook/常识/他服事实写成「本会话已证实」
  • 曾伴随摘要失真、自证闭环(自己总结再自己绑引用)

正确用法

这段证明「只靠模型自觉 + 事后 LLM Verifier」不够,必须把物理引用做成确定性约束,并把发布权从生成模型手里拿走。

错误用法

把整场面试讲成旧五段角色和 executor_evidence_v2 字段细节,却说不清现在的类名与 API。

8.2 语义迁移表(历史 → 现行)

历史概念 现行概念 说明
Executor 综合答案 Diagnosis Agent 写 Draft 仍是模型生成,但是唯一作者
claim + excerpt binding analysis + tool_call_ids 主键协议变更
Gatekeeper EvidenceGuard 仍 0 LLM;装入 Release 用例
Verifier LOW_CONFID SemanticGuard UNSUPPORTED 隔离输入;二元 verdict
Composer 控表达 Draft 结构 + Release/Fallback 表达权在 Agent,发布权在 Harness
调低阈值换 PASS 明确不做 用 fallback 信息量换体验
flowchart LR
    H1["早期:归因幻觉被发现"] --> H2["正确性模型:物理验真+语义审+控表达"]
    H2 --> H3["ISS-014:装载到单 Agent + Harness"]
    H3 --> Now["现行:Draft→EG→SG→Release"]

8.3 一句话定位两阶段

早期 Issue 解决的是 「要什么正确性」;
现行架构解决的是 「正确性如何成为默认运行路径」。


9. 和业界主流的区别(用现行组件说)

常见做法 缺口 本项目现行
纯 ReAct 直接吐最终答案 无发布闸 Draft 默认内部,Release 才公开
答案末尾 sources 角标 角标可假 tool_call_id 必须在本 Run canonical 可解析
单一 LLM-as-Judge 真伪与语义混判、不可复现引用检查 EG 代码 + SG 隔离模型
质检 Agent 再带 Tool 第二证据世界 SG 无 Tool,冻结 snapshot
离线 RAGAS 不挡单次错误出门 在线门禁 + Timeline + eval 夹具
只靠更强模型 无工程边界 与模型代际正交的 Harness

三个不一样(现行表述)

  1. 引用是 Run 级所有权问题,不是文案装饰。
  2. 物理与语义拆分,失败阶段可进 Trace / fallback。
  3. 公开通道与生成通道切断,SUPPORTED 才是成功产品语义。

10. 决策环(填的是现行答案)

# 问题 现行答案
1 威胁? 带 tool 外观的完整假案情进入 SSE
2 谁强制? EG 强制引用;SG 强制语义;Release 强制发布
3 数据面? canonical / projection / metadata audit;reasoning 另表
4 失败用户看到? SAFE_FALLBACK(阶段、有界事实、下一步),非假成功
5 如何证明? 单元/契约测 violation;E2E release_outcome;Timeline 事件
6 演进? 误杀先查投影与 schema/Repair;不给 SG 加 Tool;停止策略见 ISS-015

11. 面试题库(默认用现行答)

11.1 90 秒主叙述(推荐背这个版本)

故障诊断里最危险的不是完全不查工具,而是查了一点真实信号就补成完整事故——我们早期在旧链路上把它定义为证据归因幻觉。
现在的做法是:唯一 Diagnosis Agent 用 ReAct 查三个只读工具,只看投影,输出结构化 DiagnosisDraft;每条分析必须绑定本 Run 的 tool_call_id。
Draft 先过 EvidenceGuard:纯代码检查结构闭包、调用是否存在于当前 Run 的 Redis canonical、证据状态是否与 NORMAL/负向观察匹配、投影是否自洽。
通过后生成 verified snapshot,再交给无工具的 SemanticGuard 做整份语义是否越证的审查。
只有 SUPPORTED 才经 Release 进入 SSE;否则走 SAFE_FALLBACK,宁可告诉用户已核实事实和卡住的阶段,也不发未验证根因。
所以质量辨识度是三句话:可调用 ≠ 可归因;可归因 ≠ 语义成立;语义成立才可发布。

11.2 为什么题

问题 现行得分点
怎么防幻觉? Draft 绑定 tool_call_id → EG → SG → Release
为什么 EG 不用模型? 归属与状态是确定性的;要可回归
为什么还要 SG? 真调用推不出假根因;负向≠排除
为什么 SG 不能有 Tool? 冻结证据集,防第二世界
引用主键为什么是 tool_call_id? 框架协议 id;与当次调用一致;不靠「最新 DB 行」
Agent 能看 raw 吗? 不能;只看 projection;canonical Harness only
证据不足怎么办? conclusion 可空 + limitations;或 fallback;不编根因
和旧 Gatekeeper 啥关系? 语义祖先;现装在 Harness,协议已换

11.3 对抗题

Q:这不就是多 Agent 质检吗?

A:不是。业务侧只有一个带 Tool 的 Diagnosis Agent。SG 是无 Tool 的隔离单轮审查,属于 Harness 控制面,不是协作同事。

Q:你们重构掉多角色后质量是不是弱了?

A:弱的是重复的 LLM 角色编排;强的是默认路径上的确定性 EG + 发布切断。正确性模型保留,装载点从流水线角色变成 Release 用例。

Q:投影校验不看 raw 原文子串,会不会漏?

A:现行 EG 强调 调用所有权 + 状态 + 投影结构自洽 + kind 匹配,再交给 SG 做语义。上游靠 projector 把可引用证据做成稳定结构。若追问 excerpt 级闭合,可承认协议从早期 raw_path/excerpt 演进到投影契约,并强调 不能引用 ERROR/跨 Run/不可引用调用 仍是硬的。

Q:用户体验会不会总是 fallback?

A:体验做在「信息化 fallback + 成功路径的 limitations」,不是放宽 Guard。ISS-015 继续收敛停止策略与 fallback 信息量。

11.4 现场设计题

  1. 给「工单退款 Agent」设计等价于 tool_call_ids + EG 的字段。
  2. 若增加第四个 Tool,EG 要补哪些分支?kind/status 如何扩展?
  3. Knowledge Query 路径(非完整 DIAGNOSIS)如何复用「引用必须真实」而不照搬整份 SemanticGuard?
  4. 如何用 Timeline 事件向面试官演示一次 UNSUPPORTED 的失败阶段?

12. 原则清单(现行)

  1. 唯一报告作者,多个确定性关卡
  2. Draft 是 staging,SSE 是 production
  3. 引用主键 = 本 Run 的 framework tool_call_id
  4. NORMAL / NEGATIVE 与 FOUND / NO_EVIDENCE 强匹配
  5. NO_EVIDENCE 不是健康证明
  6. ERROR 与跨 Run id 绝不能当证据
  7. PreviousTurn 不是证据
  8. SemanticGuard 冻结 snapshot,无 Tool
  9. Reasoning 不是证据
  10. 历史 Issue 论证问题,现行代码定义答案

13. 白板默画(只画现行)

13.1 图 A · 60 秒主链

Diagnosis Agent → DiagnosisDraft
        ↓
EvidenceGuard (0 LLM, tool_call_id)
        ↓ verified snapshot
SemanticGuard (no tools)
        ↓ SUPPORTED?
Release → SSE  or  SAFE_FALLBACK

13.2 图 B · 45 秒闭包

conclusion.based_on → analysis_id → tool_call_ids
                              ↓
                     Redis canonical (this runId)
                              ↓
                     FOUND / NO_EVIDENCE
                              ↓
                     kind must match

13.3 图 C · 30 秒历史锚点(可选)

早期发现:有 tool 仍假案情
    → 要物理验真 + 语义审 + 发布权
    → 现装在 EG / SG / Release

13.4 红线

  • 画出 Planner/Executor/Composer 当主路径
  • 说 Verifier 输出 LOW_CONFID 当现行 API
  • SG 带检索箭头
  • Draft 直连用户
  • 说 metrics Tool 仍是诊断三件套之一(现行是 knowledge/logs/mysql)

14. 复习路径(偏现行)

步骤 动作
1 读 diagnosis-agent-prompt.md + DiagnosisDraft / AnalysisKind
2 通读 EvidenceGuard.validate 与 EvidenceViolationCode
3 读 DiagnosisReleaseUseCase + semantic-guard-prompt.md
4 对照 harness-quality-gates.md 默画 §13 图 A/B
5 用 §11.1 录音;再花 20 秒提早期归因幻觉作动机
6 扫一眼归档 Issue 标题与现象表即可,不背旧字段

15. 源文件索引

现行(主)

内容 路径
架构总览 mvp/architecture/current-mvp-architecture.md
执行序列 mvp/architecture/agent-orchestration.md
门禁 mvp/architecture/harness-quality-gates.md
Draft src/main/java/.../harness/contract/DiagnosisDraft.java
Kind/Status AnalysisKind.java / EvidenceStatus.java
EG .../guard/evidence/EvidenceGuard.java
SG .../guard/semantic/SemanticGuard.java
Release .../release/DiagnosisReleaseUseCase.java
Fallback .../release/SafeFallbackFactory.java
Agent Prompt src/main/resources/prompts/diagnosis-agent-prompt.md
SG Prompt src/main/resources/prompts/semantic-guard-prompt.md

历史(辅)

内容 路径
归因幻觉发现 mvp/issues/archived/executor-evidence-attribution-hallucination.md
自证闭环笔记 mvp/issues/design-notes/executor-self-evidence-loop-design-note.md
旧证据契约 mvp/architecture/archive/2026-07-22-legacy/executor-evidence-pipeline-refactor.md
重构承接 mvp/issues/archived/ISS-014-...
运行质量后续 mvp/issues/active/ISS-015-...

16. 自测(必须能用现行组件名回答)

  1. 画出 Draft 从产生到 SSE 的完整门禁序,并标出哪步 0 LLM。
  2. NORMAL 与 NEGATIVE_OBSERVATION 分别能绑哪种 evidence_status?
  3. EvidenceGuard 如何发现「编造 tool_call_id」?
  4. 为什么 conclusion 要 based_on_analysis_ids 而不是直接绑 tool?
  5. SemanticGuard 的输入有哪三样?为什么不能有 Tool?
  6. Evidence 失败时 Repair 最多几次?仍失败用户看到什么产品语义?
  7. PreviousTurn 为什么不能提供可引用的 tool_call_id?
  8. Reasoning 能否帮助 Draft 过 EG/SG?
  9. 用 20 秒说明早期归因幻觉与现行三道门的关系(动机 vs 实现)。
  10. 举一个「EG 通过但 SG 应 UNSUPPORTED」的例子。

17. 和旧版材料的关系

若你曾按「五段流水线 + excerpt 外键」准备:

  • 保留:归因幻觉定义、物理/语义拆分、发布切断思想
  • 替换:所有主路径类名、Tool 列表、verdict 枚举、引用主键、API
  • 降级:Executor/Gatekeeper/Composer 仅出现在「历史动机」小节

面试默认叠词顺序

1. 现行:Agent → Draft → EG → SG → Release
2. 机制:tool_call_id、kind/status、snapshot、fallback
3. 动机:早期归因幻觉(可选一句)
4. 演进:正确性模型保留,装载进 Harness(若追问重构)