Files
SuperBizAgent-java/openspec/changes/archive/2026-07-22-single-react-cleanup-e2e/design.md
T

125 lines
9.5 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.
## Context
阶段 6B 后,`POST /api/chat` 已经只调用新 `ChatApplicationUseCase`,但仓库仍有四类遗留:一是 bundled frontend 可达的 `/api/ai_ops` Supervisor/Planner/Executor 链;二是只有测试引用的 `ChatService`、Redis Session API、Verifier/Gatekeeper/ThreadLocal;三是被新 Harness adapter 复用但仍带旧 `@Tool` 和 DB recorder 副作用的 RAG/log backend;四是仍描述旧架构的文档和 demo。
新 Harness 已以 Redis canonical invocation 保存当前 Run 完整 Tool 调用并用 EvidenceGuard 验真,但 `ToolBoundary` 没有写长期 `tool_invocation` audit。当前 `AgentLoggingHook` 又会持久化/日志输出模型正文、Tool arguments 和 `thought`,且回退到 Session ThreadLocal。阶段 7 必须同时删除旧链和收紧审计,否则代码结构与最终 E2E 都不能满足 ISS-014。
这是 L4 协议/前端删除和跨模块物理重构。历史数据库表与历史数据保持不变;现有 `chat_session` JPA 元数据仍由 `JpaChatRunStore` 使用,不属于 Redis conversation Session 遗留。
## Goals / Non-Goals
**Goals:**
- 业务代码只剩一个拥有 Tool loop 的 Diagnosis ReAct Agent,公开诊断只剩 `/api/chat`。
- 删除旧 Chat/AiOps/Session 编排、Hook、ThreadLocal、prompts、Tool compatibility annotations 和过时测试。
- RAG/log backend 只通过 Harness adapters 调用,不自行写旧 ToolInvocation。
- AgentStep 与 ToolInvocation durable audit 按 exact Run 持久化有界脱敏 metadata。
- 文档、issues、OpenSpec strict 状态与最终代码一致。
- 真实启动应用并完成 SSE、日志、MySQL exact-run E2E。
**Non-Goals:**
- 不改变 Intent Router、Diagnosis Draft、EvidenceGuard、SemanticGuard、Fallback 或 SSE 五事件语义。
- 不删除历史表/数据,不做 schema destructive migration。
- 不实现真实 CLS 或生产业务 MySQL datasource live 连接。
- 不改 RAG 算法、Trace API response schema 或 UI 视觉设计。
## Decisions
### 1. 删除 legacy AiOps 和 Redis Session surface,不迁移第二条诊断链
删除 `AiOpsController`、`AiOpsService`、AIOps DTO/config/rule evaluation、三个 prompts、前端按钮/consumer 和相应 tests。删除 `ChatSessionController`、Redis `SessionManager`/`SessionContext` 和 tests。告警诊断通过 `/api/chat` 提交自然语言或结构化文本,由同一个 Intent Router 进入 Diagnosis。
替代方案是把 `/api/ai_ops` 适配到新 use case;拒绝,因为它保留第二个公开诊断协议和前端双轨,违反 ISS-014 唯一入口与无兼容分支目标。`chat_session` entity/repository 不删除,因为它是当前 Run 目录与 PreviousTurn 生命周期的一部分。
### 2. 旧 Chat orchestration 按闭包删除
删除 `ChatService` 及其 Sequential Planner/Executor/Verifier/Composer tests、旧 prompts、Verifier/Gatekeeper helpers、Skill metadata hook、Token ThreadLocal wrapper、旧 Tool trace summary/recorder。删除顺序为公开 caller -> service/orchestration -> helper/hook/context -> resources/tests,并在每层后编译/引用扫描。
`SelfEvaluationMergeService`、`DiagnosisTraceService`、repositories 和 eval 基础设施若仍有非旧链调用则保留。替代仅取消 Spring annotation 而保留死类;拒绝,因为阶段 7 明确要求物理清理。
### 3. RAG/log 是 backend,不是 Agent-facing Tool
保留 `LookupKnowledgeTool.lookupKnowledge` 的检索管线和 `QueryLogsTools.queryLogs` 的 Mock/边界实现,供 `RagToolAdapter`/`QueryLogsToolAdapter` 调用;移除所有 `@Tool/@ToolParam`、旧 topic discovery contract、Session ThreadLocal、session dedup 和 `ToolInvocationRecorder`。Agent-facing schema/description 只来自 `HarnessEvidenceTools` 与 `AgentToolContracts`。
替代完全重写 RAG/log;拒绝,因为阶段 3B 已验证 adapter/projector contract,阶段 7 只需清除双 contract 与副作用。
### 4. Agent audit 使用 Harness-native metadata-only Hook
新增 Harness audit hook,强制从 `RunnableConfig` 读取 exact sessionId/runId。before-model 只保存 message count/roles;after-model 只保存是否有文本、是否有 Tool call、Tool names 和 duration,不保存 message content、model output text、Tool arguments、Prompt 或 Thought。缺少 metadata 时跳过持久化并记录安全 warning,不回退 ThreadLocal。
替代继续修补 `AgentLoggingHook`;拒绝,因为旧类包含 verifier 特例、Token ThreadLocal、正文日志和 thought persistence,保留会让旧边界继续存在。
### 5. ToolBoundary 通过安全 port 写 durable audit
新增 `ToolInvocationAuditSink` 和不可变 audit event。`ToolBoundary.execute` 在 canonical 结果确定后调用 sink;event 只包含 sessionId、runId、toolCallId、toolName、InvocationStatus、EvidenceStatus、stable error code、duration、request/agent-result byte count。audit 调用 fail-open:JPA 审计失败写 warning,但不改变已经确定的 Tool observation;canonical Redis store 仍按原设计 fail-closed。
JPA adapter 复用现有 `tool_invocation` 表:`input_params` 只保存 tool_call_id/request_bytes,`output_preview` 只保存 status/evidence_status,`output_length` 保存 agent result bytes,`error_message` 只保存 stable error code。禁止 raw response、完整 request、SQL、日志正文和模型内容。
替代让旧 backend recorder 继续双写;拒绝,因为它依赖 ThreadLocal、不同 Tool 各自实现且可能保存大 payload。替代审计失败阻断业务;拒绝,因为 durable audit 不是 canonical evidence truth source。
### 6. 文档与 issue 以当前单链架构为准
重写当前 MVP、Agent、Harness、Trace/Demo 文档中的旧双入口与多 Agent 描述;ISS-012/ISS-013 标记由 ISS-014 吸收并归档。历史架构文档保留在 archive,不篡改历史。
### 7. 最终 E2E 使用 exact metadata identity
启动 Spring Boot 后向 `/api/chat` 发送固定 payment-timeout 诊断,严格解析 named SSE,取得 metadata sessionId/runId 并要求 `content|failure -> done`。检查 `logs/` 不含 Prompt/Thought/raw Tool payload/stack leakage;使用 `scripts/query_mysql.py` 按 exact runId 查询 `diagnosis_run`、`agent_step`、`tool_invocation`,核对 intent/outcome/status、唯一 Diagnosis Agent、Tool 名称/次数、同一 identity 和最终 safe content。
query_logs 使用 Mock,query_mysql 使用配置的隔离 datasource contract;不声称真实 CLS/生产业务库 live。若真实模型选择非 Diagnosis intent,则使用明确诊断 query 重试一次,不伪造数据库结果。
## Module and Ownership Audit
```text
Browser POST /api/chat
-> ChatController / ChatSseSession
-> ChatApplicationUseCase
-> Intent Router
-> System / Knowledge / Diagnosis executor
-> Diagnosis Harness
-> Diagnosis Agent (only Tool loop)
-> HarnessEvidenceTools
-> ToolBoundary
-> Redis canonical invocation (full, TTL)
-> Durable audit sink (bounded metadata)
-> EvidenceGuard / SemanticGuard / Release
-> named SSE safe content
-> diagnosis_run + agent_step + tool_invocation exact-run Trace
```
- Application owns Session/Run/PreviousTurn;Controller 不拥有业务状态。
- Core owns budget/cancel/lifecycle;Diagnosis Agent owns diagnosis authorship;Guards own verification/release。
- Redis canonical invocation owns short-lived complete Tool truth;MySQL ToolInvocation owns long-lived metadata audit。
- `chat_session` is current JPA run directory;Redis SessionContext is legacy conversation memory and is removed。
- 最大耦合风险是复用 backend 时旧 annotations/recorder 被 Spring 自动发现;static scan + context startup 覆盖。
## Interface Impact
- Level: L4 breaking HTTP/frontend contract。
- Removed: `POST /api/ai_ops`、`POST /api/chat/clear`、`GET /api/chat/session/{sessionId}`、`GET /api/chat/session/{sessionId}/runs`、legacy AiOps message-wrapper SSE。
- Retained: `POST /api/chat` named SSE、Trace/feedback/document/search APIs。
- Consumer migration: bundled frontend 同 commit 删除 AiOps 按钮和 consumer;外部调用方迁移到 `/api/chat`。
- Rollback: 整体回滚阶段 7 commit;不单独恢复旧 endpoint 或 old Tool discovery。
## Risks / Trade-offs
- [外部 AiOps caller 失败] -> L4 文档明确迁移到 `/api/chat`,不提供双轨。
- [删除 bean 导致 context 启动失败] -> compile、focused context test、全量 tests、真实 Spring startup 分层验证。
- [backend 仍被 ToolCallbackProvider 发现] -> 删除 annotations/imports 并静态扫描旧 Tool 名/description。
- [audit 泄漏敏感内容] -> typed metadata-only event + serialization tests + DB query preview inspection。
- [audit 写失败丢 Trace 明细] -> warning + Run 主记录仍完成;验收环境要求 audit row 存在,生产运行可观测 failure。
- [live 环境依赖不可用] -> 先检查服务与启动日志,分类环境/实现失败;不降低为假 E2E。
## Migration Plan
1. 删除 frontend/Controller/Service 可达旧入口和旧 orchestration 闭包。
2. 解耦 RAG/log backend,替换 Agent/Tool durable audit。
3. 删除剩余 dead resources/tests/config,跑 compile/focused/full regression 和 static scans。
4. 更新 docs/issues/OpenSpec,并修复已知 strict validation。
5. 启动应用,执行 final SSE/log/DB E2E,记录 exact identity evidence。
6. 同一 commit 部署所有删除与文档;回滚整体回滚该 commit。
## Open Questions
- None。live 默认值是否需要校准由 E2E 数据决定,但不会改变 architecture direction。