## Why 阶段 6A 已完成内部 Chat Application Use Case,但公开入口仍由 `ChatController` 直接持有旧 `ChatService`、模型、工具、Redis 历史和无界线程池。当前 `/api/chat` 是同步 JSON,`/api/chat_stream` 则在完整答案生成后切片,既绕过新 Harness 释放边界,也让前端维持两套不一致消费者。 ## What Changes - 将唯一 `POST /api/chat` 原子切换为 `text/event-stream`,只调用阶段 6A `ChatApplicationUseCase`。 - 删除同步 Chat 响应路径和 `/api/chat_stream`,Controller 不再获取 ChatModel、ToolCallbackProvider、旧 Session 历史或 ChatService。 - 固定五类 SSE 事件与顺序:`metadata -> status* -> content|failure -> done`;业务 event name 与 payload schema 均稳定。 - `content` 最多一次且只承载阶段 6A typed safe content,不做 Token/字符切片;技术失败使用一次 `failure`。 - 客户端断开、SSE timeout 或发送失败取消同一个 `ChatRunControl`,内部 Run 记录 CANCELLED,断开后不再发送终态。 - 使用 Spring 管理的有界 Chat worker 和 Harness model executor;Controller 不创建线程池。 - 新增完整 Harness 生产 Bean 装配,使 Router、三类 executor、Diagnosis Agent、Guards、canonical Tool boundary 和 JPA store 使用同一 Core/ChatModel/ObjectMapper。 - 前端删除快速/流式双模式,统一以 fetch streaming 消费 `/api/chat` 的 named SSE events,并保存 metadata 中的 session/run ID。 ## Capabilities ### New Capabilities - `single-react-chat-sse-cutover`: 定义唯一 Chat SSE 入口、五事件状态机、连接取消、生产 Harness 装配和前端消费者迁移。 ### Modified Capabilities - None. 阶段 6A application use case 和 `/api/ai_ops` 对外行为保持不变。 ## Scope - `ChatController` Chat 入口、SSE DTO/adapter、连接生命周期和 focused MVC tests。 - Harness 生产配置、集中 limits、受控 executors 和装配启动测试。 - `app.js`/`index.html` Chat consumer 和模式控件清理。 - SSE schema/order/mutual exclusion/cancel/failure tests,以及阶段 2-6A regression。 ## Non-goals - 不修改 `/api/ai_ops` 协议或迁移其旧多 Agent 实现。 - 不删除旧 ChatService、Planner/Executor/Verifier/Composer、Hook 或 ThreadLocal;阶段 7 物理清理。 - 不实现 Token streaming、断线续传、事件重放、轮询或 WebSocket。 - 不运行真实模型/Redis/MySQL live E2E;阶段 7 统一完成。 ## Context Constraints - `Diagnosis Agent` 是唯一拥有 Tool loop 的业务 Agent;Controller 和 SSE adapter 不得拥有模型或工具。 - SemanticGuard 完成前不得发送 `content`;Fallback 使用 `content + done(FALLBACK)`,技术失败使用 `failure + done(FAILED)`。 - metadata 固定第一且一次,done 固定最后且一次;content/failure 互斥。 - 这是 L4 破坏性公开协议变更,不保留旧 endpoint 或同步兼容分支。 ## Risks - 阶段 6A 组件尚未生产装配,单改 Controller 会导致 Spring 启动失败。 - SseEmitter completion/error/timeout 与 worker 完成存在竞态,必须 first-terminal-wins 且断开后禁止继续发送。 - 前端解析器当前按单行 data 和旧 `type` 字段兼容,迁移不完整会丢失 metadata、终态或错误。 - 有界 executor 饱和时必须 fail closed,不能退化为 Controller 线程执行或无界排队。