Files
SuperBizAgent-java/devflow/projects/2026-07-26-diagnosis-information-gain-stop-contract/decisions.md
T

158 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Diagnosis 信息增益停止契约 Decisions
## Discover Status
- Checkpoint:Discover。
- Capability source:`sm-flow` 内置 Discover 协议;grill 使用 `grill-with-docs`,代码可证问题通过源码、测试和引用搜索处理。
- Scale:`complex`。变更跨越 Agent、Tool 协议、Run 生命周期、Release、Guard、配置、Trace 和 E2E。
- 接口影响:L3。模型可见 Tool Schema 发生有意协议变更,公开 HTTP/SSE 和业务 Tool backend 协议不变。
- 工具降级:当前没有 `codebase-retrieval` 和 LSP 工具;以 `rg`、源码和测试引用核查替代。用户已明确“可以忽略gitnexus”。
## Question Pool
| # | 维度 | 问题 | 模式 | 状态 |
|---|---|---|---|---|
| Q1 | 术语 | Tool 客观状态、信息增益、收集状态、停止原因和最终发布状态是否应合并为一个枚举? | user-interview | 已解决 |
| Q2 | 语义 | Tool 返回价值由谁判断,是否需要多级质量分数? | user-interview | 已解决 |
| Q3 | 协议 | 模型继续调用 Tool 时如何回传上一轮信息增益,是否需要 `next_action`? | user-interview | 已解决 |
| Q4 | 边界 | Tool Schema 应来自 Prompt 还是服务端原生 Tool Calling 注册? | user-interview | 已解决 |
| Q5 | 边界 | Harness 能确定性判定哪些 `NO_GAIN`,RAG `REFERENCE` 由谁判定? | user-interview | 已解决 |
| Q6 | 范围 | 首版是否需要 `new_count` 或自然语言语义去重? | user-interview | 已解决 |
| Q7 | 配置 | 连续无增益阈值是否可配置,默认值与生效时机是什么? | user-interview | 已解决 |
| Q8 | 发布 | 信息饱和、预算终止和 `conclusion=null` 由谁转换为用户可见结果? | user-interview | 已解决 |
| Q9 | 验收 | 如何证明未知问题不再以通用内部错误结束,同时不放过无证据结论? | evidence-driven | 已解决 |
| Q10 | 技术 | 当前 Tool schema 是否能直接容纳 `previous_observation`? | evidence-driven | 已解决 |
| Q11 | 技术 | 进展控制状态应扩展 Redis Store 还是放入 RunContext handle? | evidence-driven | 已解决 |
| Q12 | 技术 | RAG `relevance_level` 在哪一层丢失,前端是否已有过程展示能力? | evidence-driven | 已解决 |
## Evidence-driven
| 结论 | 证据来源 | 是否已汇报用户 |
|---|---|---|
| 当前三个 Agent-facing Tool 直接使用 `RagToolRequest`、`QueryLogsRequest`、`MysqlToolRequest` 生成 Schema;要增加 `previous_observation + input` 必须显式演进 Tool Schema,不能只改 interceptor。 | `HarnessEvidenceTools`、三个 request records、`DiagnosisAgentFactory` | 已汇报 |
| `HarnessToolInterceptor` 当前把完整 `agentResult` 放入 `ToolCallResponse.content`,控制视图与模型观察尚未分离。 | `HarnessToolInterceptor` | 已汇报 |
| `RunContext` 已采用结构不可变、可变状态存在线程安全 handle 的模式;进展 tracker 放入 RunContext 比扩展 Redis 按 Run 枚举更符合现有所有权。 | `RunContext`、`DiagnosisHarnessCore.startRun` | 已汇报 |
| `CanonicalInvocationStore` 只有 begin/find/markReady/markError,扩展按 Run 枚举会影响 Redis 实现和多组 fake store;首版可由 tracker 保存完成调用 key,在结束时按 key 读取 canonical 记录。 | `CanonicalInvocationStore` 及其引用测试 | 已汇报 |
| `RagResultProjector` 只按 evidence 是否为空生成 `EVIDENCE_FOUND / NO_EVIDENCE`,没有读取上游 `relevanceLevel / relevance_level`。 | `RagResultProjector`、`LookupResult`、`KnowledgeEvidencePostProcessor` | 已汇报 |
| `DiagnosisReleaseUseCase.execute` 当前强制 draft 非空并对所有 Draft 运行 EvidenceGuard;`EvidenceGuard` 又把空 analysis 判为 `ANALYSIS_MISSING`,与合法无结论结果冲突。 | `DiagnosisReleaseUseCase`、`EvidenceGuard` | 已汇报 |
| `ChatApplicationUseCase.recoverBudgetExhaustion` 已有未提交预算 Fallback,但它绕过 Diagnosis Release,需迁移而不是丢弃用户价值。 | `ChatApplicationUseCase`、`SafeFallbackFactory`、现有测试 diff | 已汇报 |
| 前端已渲染 `observed_facts / verified_sources / limitations / next_steps`,不需要新增公开展示协议。 | `src/main/resources/static/app.js` | 已汇报 |
| 验收必须同时覆盖主动无结论、Harness 饱和、预算终止、无证据结论被 Guard 拦截,以及原始未知 Query 的 live SSE、日志和 exact run 数据。 | 当前事故现象、ISS-016 验收项、现有 E2E 工具 | 已汇报 |
## User-interview
| 问题原文 | 用户原话 | 确认状态 | OpenSpec 回写 |
|---|---|---|---|
| 是否精简状态而不建立第二套生命周期? | “这里我觉得设计得太混乱了,怎么简化”以及对最终简化架构“我觉得可以” | 已确认 | 已回写 |
| 是否只保留 `GAINED / NO_GAIN`? | “质量状态只要 information_gain = GAINED \| NO_GAIN 就够了?”后确认“我觉得可以” | 已确认 | 已回写 |
| 是否需要 `new_count`? | “好那就去掉new_count” | 已确认 | 已回写 |
| 是否需要 `next_action`? | “那就去掉next_action,我觉得由llm自己去判断就好了,不用显示的指定” | 已确认 | 已回写 |
| Tool 如何注入? | “首先 tool注入,由服务端注入,而不是写死在提示词中” | 已确认 | 已回写 |
| Prompt 是否强调合法放弃和正确但无用的内容? | “需要说明 模型不必须要给出一个答案”以及“如果你发现工具返回的是正确但对推导无用的废话,请停止调用” | 已确认 | 已回写 |
| 阈值是否可配置? | “我觉得这个可以暴露出一个配置来控制” | 已确认 | 已回写 |
| 首版重复检测做到什么程度? | “也就是说这一版只是做参数的去重校验”后确认“可以” | 已确认 | 已回写 |
| 是否按当前简化方案进入实施? | “可以用更简单的方式”“可以。修正一下文档”“用sm-flow开始实施把” | 已确认 | 已回写,并授权完成 Commit 后进入 Apply |
## 关键取舍
- 决策:停止权归 Harness,语义价值判断由模型与确定性规则共同产生。
- 原因:Tool 只能知道客观返回,模型才能判断内容是否推进当前假设;但空结果和完全重复 scope 可由代码零 Token 判定。
- 影响:Harness 只消费二值信息增益,不引入独立 Judge 或质量分数。
- 决策:使用下一次 Tool Call Envelope 回传上一轮模型评价。
- 原因:模型只有看到 Tool Observation 后才能评价,下一次真实行为正好提供受 Schema 约束的回传边界。
- 影响:这是 L3 Agent-facing Tool Schema 变更,业务 request 在 interceptor 内解包后保持不变。
- 决策:进展 tracker 是 RunContext handle,Canonical Store 保持 Tool 真相源。
- 原因:停止决策需要低延迟 Run 内状态,完整证据仍应由 canonical 记录提供;两者职责不同。
- 影响:tracker 保存计数、scope、待评价调用和 canonical keys,不复制 raw payload。
- 决策:不创建 ADR。
- 原因:这些是 ISS-016 范围内可通过 OpenSpec 回滚的内部协议演进,已有架构文档详细记录取舍,尚不满足独立 ADR 的必要性。
## OpenSpec 回写
- 必须进入 proposal/design/spec/tasks:Tool Envelope、L3 影响、Run tracker、确定性 `NO_GAIN`、RAG `relevance_level`、双视图、STOP_REQUIRED、ProgressSnapshot、统一 Release、Prompt、配置和 E2E。
- 必须保留非目标:无 `new_count`、无 `next_action`、无 Judge、无语义去重、无第二套诊断生命周期、无公开 SSE 协议新增。
- 当前没有未确认的 user-interview 问题,也没有 devflow/OpenSpec 冲突。
## Cross-Artifact 对齐检查
| 上游 → 下游 | 检查内容 | 状态 |
|---|---|---|
| ISS-016/架构文档 → proposal | 未知问题、合法放弃、信息增益、饱和停止、双视图、统一 Release、非目标和 E2E | 已对齐 |
| proposal → design | L3 Envelope、Run tracker、scope、STOP_REQUIRED、ProgressSnapshot、预算终态、Prompt 和迁移方案 | 已对齐 |
| design → specs/tasks | 状态机、Tool 门禁、RAG relevance、无结论 Guard、Release 所有权、Trace 和兼容边界 | 已对齐 |
| specs → tasks | 每个可观察行为均有 contract/state/loop/release/config/E2E 可执行切片 | 已对齐 |
### Gap 详情
- 无。
## Architecture Audit
- Capability source:`zoom-out`。按 glossary 的 Diagnosis Agent、Diagnosis Harness、RunContext、Evidence Status、Invocation Status、Release Outcome 术语审计。
- 顶层链路:`ChatApplicationUseCase -> DiagnosisChatExecutor -> DiagnosisAgentUseCase -> ReactAgent/interceptors -> ToolBoundary/canonical store -> ProgressSnapshot -> DiagnosisReleaseUseCase -> SSE/persistence`。
- 所有权:Agent 负责诊断语义;Tool/Projector 负责客观结果;Run tracker 负责停止控制;Canonical Store 负责 Tool 真相;Guard 负责引用与结论安全;Release 负责用户可见 SUCCESS/FALLBACK;Application 只负责编排和持久化。
- `RunContext` 的生产代码构造点只有 `DiagnosisHarnessCore.startRun`,大量测试通过该工厂获取;新增 tracker 不需要扩散手工构造。
- `DiagnosisAgentUseCase`、`HarnessToolInterceptor`、`HarnessEvidenceTools` 和 `DiagnosisReleaseUseCase` 的直接消费者均已由配置类和 focused tests 覆盖,任务清单包含所有构造调用更新。
- `FallbackType` 新语义只通过通用 SafeFallback JSON/前端渲染消费,没有前端枚举 switch;公开协议不新增字段。
- 最大框架风险是 Tool Envelope Schema 和 STOP_REQUIRED 后异常传播;design 要求三个具体 record、真实 callback schema 测试和 scripted framework-loop 测试在 Release 迁移前锁定行为。
- 最大生命周期风险是预算已把 RunLifecycle 置为 `BUDGET_EXHAUSTED` 后 Application 再次 `checkActive`;design 将其限制为“Diagnosis Release 已处理的预算 Fallback”窄分支,并禁止 Application 重建业务内容。
- 审计结论:模块职责没有形成新的循环依赖或第二真相源;L3 风险已进入 specs 和 tasks,可进入 commit gate。
## Commit Gate Preflight
- `proposal.md`、`design.md`、六份 capability delta specs 和 `tasks.md` 均存在。
- `openspec status --change diagnosis-information-gain-stop-contract --json` 返回 `isComplete=true`。
- `openspec validate diagnosis-information-gain-stop-contract --strict` 通过。
- question pool 全部已解决;evidence-driven 结论已汇报;user-interview 决策均有用户原话和确认状态。
- 接口影响已判为 L3,并有独立 Interface Impact、兼容、迁移、回滚和验收说明。
- Cross-artifact 检查无 gap;架构风险均已进入 design/tasks。
- 用户已通过“用sm-flow开始实施把”明确授权 Commit 后进入 Apply。
## Pre-apply Research
### 参考实现
- `HarnessEvidenceTools`:现有三类 `FunctionToolCallback` 注册点和 adapter bridge,继续作为 Agent-facing Schema 唯一入口。
- `HarnessToolInterceptor`:可获得 exact framework Tool Call ID,适合消费 Envelope 和执行 progress gate。
- `ToolBoundary`:Tool 预算、Run 校验、canonical 写入和安全错误的单点,不在 interceptor 重复 reserve。
- `RunContext` / `DiagnosisHarnessCore.startRun`:结构不可变 + 可变 handle 模式和唯一生产构造点。
- `RagResultProjector` / `QueryLogsResultProjector` / `MysqlResultProjector`:bounded canonical agent result 的现有标准化模式。
- `EvidenceGuard` / `DiagnosisReleaseUseCase`:当前结论验证链和无结论冲突位置。
- `ChatApplicationUseCase.recoverBudgetExhaustion`:保留用户价值、需要迁移所有权的临时预算 Fallback。
- `DiagnosisAgentUseCaseTest.ScriptedChatModel`:真实框架 model -> Tool -> model loop 回归模式。
### 技术栈清单
- Tool Schema:三个具体 record 交给 Spring AI `FunctionToolCallback.inputType`,共享 `PreviousObservation`,不使用泛型擦除或 JsonNode Schema。
- JSON:继续使用项目 `ObjectMapper` 严格解析/序列化;控制字段在 interceptor 消费后只传业务 input。
- Run 状态:新增线程安全 tracker handle,由 `DiagnosisHarnessCore.startRun` 创建,不使用 ThreadLocal。
- Canonical 真相:继续使用 `ToolCallKeyFactory + CanonicalInvocationStore.find`;tracker 只记录 identity。
- 视图:从 bounded canonical `agent_result` 白名单投影 Model Observation,不读取 raw response。
- 异常:受控停止使用专用异常和 cause-chain 分类;未知异常保持 fail closed。
- 测试:JUnit 5、scripted ChatModel、现有 fake store/adapter fixture;不增加 Maven 依赖。
### 新建基础设施
- `harness.progress`:信息增益、收集状态、停止原因、tracker、scope、snapshot/projector。
- `harness.agent`:三个 Agent-facing Envelope、白名单 observation projector、受控停止异常和执行结果。
- 不新增数据库表、Redis 数据结构、HTTP DTO、SSE event 或外部依赖。
## Apply 期间设计补充:Draft 合同失败
- 真实 E2E `runId=4e667111-524e-4407-87ab-b4b262952017` 已完成一次 READY RAG 调用,第二轮模型返回文本后在 Draft/Release 边界失败;后续三次同 Query 均走零 Tool 的 `MISSING_REQUIRED_CONTEXT`,证明模型输出存在随机分支。
- 用户确认采用窄化降级:非法 Draft 自身不被接受;已有当前 Run 的安全 ProgressSnapshot 时发布 `INSUFFICIENT_EVIDENCE`,没有安全过程时继续 `FAILED`。
- 这是有意行为变更:从“所有非法 Draft 都发布技术失败”调整为“非法 Draft + 已验真过程可发布过程型 Fallback”;公开 SSE 字段、Tool 协议和最终生命周期枚举不变。
- 不新增 stop reason,不把 Draft 解析失败伪装成 `INFORMATION_SATURATED` 或 `BUDGET_LIMIT_REACHED`;使用 Agent 输出异常携带有界 snapshot,并以脱敏 Trace 区分输出合同失败。
## Apply Verification
- Focused tests:`DiagnosisAgentUseCaseTest`、`DiagnosisReleaseUseCaseTest`、`DiagnosisChatExecutorTest`、`HarnessChatConfigurationTest` 通过。
- 完整回归:`mvn -q -Dtest='!MilvusConnectionTest' test` 退出码为 `0`;本轮 Surefire 报告汇总 `Tests=292, Failures=0, Errors=0, Skipped=3`。
- 外部凭据边界:未排除时唯一失败为 `MilvusConnectionTest.connect`,原因是当前测试进程未设置 `MILVUS_TOKEN`;这不是本变更回归。
- OpenSpec:`openspec.cmd validate diagnosis-information-gain-stop-contract --strict` 通过。
- 格式与清理:`git diff --check` 通过;未发现临时 E2E JSON、DEBUG 或 tmp 文件。
- named SSE E2E:Query `诊断切换企业失败的问题`,`sessionId=iss016-final-20260726-a`,`runId=3ab22ed7-d0ed-45d8-b928-dce5790c0542`;SSE 返回 `SAFE_FALLBACK`、`type=MISSING_REQUIRED_CONTEXT`、`done.outcome=FALLBACK`。
- 数据库核对:`status=SUCCESS`、`intent=DIAGNOSIS`、`release_outcome=FALLBACK`、`tool_call_count=0`、`total_token_count=2890`、answer 非空。
- Trace 核对:`RUN_STARTED -> ROUTING_ATTEMPT -> ROUTING_DECISION -> AGENT_MODEL_STEP -> EVIDENCE_GUARD_INITIAL -> RELEASE_DECISION/FALLBACK -> RUN_FINISHED/FALLBACK`。
- 兼容性:公开 HTTP/SSE 字段、前端 SafeFallback 消费结构、数据库表和业务 Tool request 均未新增字段;模型侧 Tool Envelope 是本变更已确认的 L3 协议变更。