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

9.5 KiB
Raw Blame History

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

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。