9.4 KiB
9.4 KiB
Decisions: single-react-chat-sse-cutover
Discover Status
- Checkpoint: Discover
- Capability source:
sm-flow+grill-with-docs;codebase-retrieval、LSP 和 GitNexus MCP 当前不可用,使用rg引用核对、源码阅读和 focused tests 降级。 - Scale: complex。涉及 L4 HTTP/SSE 协议、前端消费者、异步连接生命周期、生产 Bean 装配和阶段 7 删除边界。
devflow/index.md命中阶段 0-6A、ISS-013 和 session-run-trace-isolation;ISS-014 是更新且已冻结的最终协议源。
Question Pool
| # | 维度 | 问题 | 模式 | 状态 |
|---|---|---|---|---|
| Q1 | 术语 | “真正 SSE”是 Token streaming,还是过程事件实时 + 最终内容一次释放? | evidence-driven | 已解决 |
| Q2 | 协议 | 唯一 endpoint、事件名称、payload、顺序、互斥和终态是什么? | evidence-driven | 已解决 |
| Q3 | 边界 | Controller、Application Use Case、Harness 和 SSE adapter 各自拥有何种职责? | evidence-driven | 已解决 |
| Q4 | 生命周期 | disconnect/timeout/send failure 如何取消同一个 Run,正常 complete 如何避免误取消? | evidence-driven | 已解决 |
| Q5 | 执行器 | 如何消除 Controller 自建无界线程池并处理饱和? | evidence-driven | 已解决 |
| Q6 | 装配 | 阶段 2-6A plain Java components 如何形成可启动的生产 Bean graph? | evidence-driven | 已解决 |
| Q7 | 前端 | 快速/流式双模式如何迁移到唯一 SSE consumer? | evidence-driven | 已解决 |
| Q8 | 安全 | 哪些内部状态/内容禁止进入 SSE? | evidence-driven | 已解决 |
| Q9 | 兼容 | 是否保留同步 /api/chat 或 /api/chat_stream 兼容? |
evidence-driven | 已解决 |
| Q10 | 范围 | /api/ai_ops 和旧多 Agent 何时处理? |
evidence-driven | 已解决 |
| Q11 | 验收 | 如何证明 event order、single terminal、same IDs、cancel 和 production wiring? | evidence-driven | 已解决 |
Evidence-driven
| 结论 | 证据来源 | 是否已汇报用户 |
|---|---|---|
| 真正 SSE 固定为状态实时发送、最终 typed content 一次释放,不做 Token/字符切片。 | ISS-014 4.7 | 已汇报 |
唯一入口是 POST /api/chat;顺序为 `metadata -> status* -> content |
failure -> done`。 | ISS-014 4.7、阶段 6B |
metadata/status/content/failure/done 使用 named SSE event;payload 不再包含旧 type/data 包装。 |
ISS-014 最小事件结构 | 已汇报 |
| 当前 Controller 同时拥有旧 ChatService、模型、Tools、SessionManager、同步/伪流式流程和 cached thread pool。 | ChatController.java |
已汇报 |
当前前端 quick 调 /chat JSON,stream 调 /chat_stream 并保留大量旧格式 fallback。 |
static/app.js |
已汇报 |
ChatApplicationUseCase 已提供 observer、同一 run control、typed content 和 stable failure code,但组件尚无完整生产 Bean graph。 |
阶段 6A code + Spring annotation scan | 已汇报 |
客户端断开必须通过 observer 得到的 ChatRunControl 取消,同一引用需覆盖断开早于 onStarted 的竞态。 |
阶段 6A design + SseEmitter lifecycle |
已汇报 |
/api/ai_ops 是独立公开入口,不属于阶段 6B Chat 原子切换;旧实现阶段 7 清理/处置。 |
ISS-014 阶段 6B/7 | 已汇报 |
User-interview
- 无新增 user-interview。唯一 endpoint、破坏性迁移、事件 schema、非 Token 流、自动 Apply/Archive/commit 均由 ISS-014 与用户持续授权冻结。
Key Decisions
- Controller 使用构造注入的
ChatApplicationUseCase与受控TaskExecutor;不注入 ChatModel、Tools、ChatService 或 SessionManager 来处理 Chat。 - SSE adapter 为每个请求维护单一 state machine 和
AtomicReference<ChatRunControl>;disconnect 标记先于 onStarted 时,onStarted 立即取消。 - 正常 result 只产生一次 typed content 和 done;异常只产生 failure 和 done;IOException/timeout/disconnect 只取消,不尝试补发终态。
- executor rejection 在没有 Run 时发送稳定 failure/done;worker 启动后所有 failure code 来自
ChatApplicationException,不暴露 cause。 - 生产装配使用集中
harness.chatproperties 和 Spring-managed bounded executors;所有模型调用复用同一ChatModel和GuardModelCall。 - 前端移除 mode selector 和 quick path,只保留一个严格 named-event parser;unknown event/schema fail closed。
- 不创建 ADR:L4 方案已经在 ISS-014 设计冻结,本 change 负责原子落地和迁移说明。
OpenSpec Backfill
- 需进入 proposal/design/spec/tasks:唯一 SSE、五事件 state machine、typed payload、安全 failure、same IDs、disconnect cancellation、bounded executors、production assembly、frontend migration、L4 rollback。
- 非目标:AiOps 协议、旧类物理删除、live E2E。
Cross-artifact Alignment
| 上游 -> 下游 | 检查内容 | 状态 |
|---|---|---|
| ISS-014/brief -> proposal | 唯一 SSE、五事件、断开取消、前端迁移、生产装配、阶段 7 边界 | 已对齐 |
| proposal -> design | named events、state machine、bounded executors、Bean graph、AiOps 隔离、L4 rollback | 已对齐 |
| design -> specs/tasks | 每项 ownership/lifecycle/safety/migration 均有可观察 requirement 和纵向切片 | 已对齐 |
| specs -> tasks | 10 组 requirements 覆盖 wiring、SSE、cancel、frontend、AiOps regression 和 verification | 已对齐 |
Architecture Audit
- Capability source:
zoom-out,使用 Chat Application Use Case、RunContext、Run Lifecycle、Diagnosis Harness 和 Chat SSE Contract 术语。 - 链路为
browser -> Controller -> SSE session -> bounded worker -> Application Use Case -> Harness -> typed release -> SSE session;业务真理源不进入 Controller。 - SSE session 独占协议状态,Application 独占 Run/dispatch/persistence,Core 独占 cancel/budget,configuration 独占 infrastructure graph。
- 最大风险是 disconnect/onStarted 与 terminal callback 竞态,design/tasks 已固定 pending-disconnect、atomic terminal 和 no-send-after-close tests。
- L4 部署必须 Controller/frontend 同版本;回滚成对返回阶段 6A commit,V012 可保留。
Interface Impact
- Level: L4 breaking HTTP/frontend contract。
- 删除同步 JSON
POST /api/chat、POST /api/chat_stream和旧 Chat SSE wrapper;新增 named-event SSEPOST /api/chat。 - 消费者:bundled
static/app.js、外部 Chat callers、Controller/MockMvc tests;Trace/feedback 继续使用 metadata IDs。 - 迁移/回滚:前后端同 commit 原子部署/回滚;不提供兼容开关、双 endpoint 或旧 parser。
Commit Gate Preflight
- proposal、design、specs、tasks 完整,change strict validation 通过。
- Question pool 全部 evidence-driven 解决并已汇报,无 user-interview、未判级接口或未接受架构风险。
- Cross-artifact 四段对齐无 gap;L4 migration/rollback、production wiring、disconnect race 和阶段 7 边界均进入 design/spec/tasks。
openspec-propose补全产物,zoom-out完成架构审计;可提交为 Committed OpenSpec。
Apply Progress
- 1.1-1.4 完成:新增
ChatHarnessProperties、bounded worker/model executors 和显式HarnessChatConfigurationgraph;空 MySQL datasource 只允许 fail-closed unknown logical ID。 - 2.1-2.4 完成:新增 named-event
ChatSseEvent/ChatSseSession,Chat 唯一 SSE Controller,移除/chat_stream和同步 Chat;AiOps 模型/Tool 依赖下沉到 service。 - 3.1-3.3 完成:前端移除 quick/stream 双轨,统一 named-event parser、typed renderer 和静态 contract test。
JpaChatRunStore生产构造器改为注入集中PublishedResultPolicy,避免读写边界漂移;这是实现偏差修复,无需改需求方向。
Apply Review
- Review 发现
ChatController虽然 Chat path 已经只调用应用用例,但类本身仍承载 AiOps 和 Session 管理依赖,不完全满足“Chat Controller 只负责 Chat 协议”的 ownership 要求。 - 用户确认将职责拆分为
ChatController(仅/api/chat)、AiOpsController(保持/api/ai_ops)和ChatSessionController(保持 clear/session/runs URL)。 - 该修正保持所有公开 URL、AiOps message-wrapper payload 和 Session observable behavior,不修改 Committed OpenSpec 的范围或方向。
styles.css中 mode selector/dropdown 死样式随前端双轨删除一并移除。- AGENTS.md 指定的
codebase-retrieval和 LSP 工具在当前环境不可用;使用 OpenSpec 全量上下文、rg引用检查、Java 编译、结构测试和综合回归完成等价影响面确认。
Verification and Migration
- Stage 2-6B + AiOps regression:24 suites / 101 tests,0 failure/error/skipped;包含
HarnessChatConfigurationTestSpring wiring。 mvn -q -DskipTests compile、openspec validate single-react-chat-sse-cutover --strict、node --check src/main/resources/static/app.js均通过。- 生产 Controller/前端遗留 token 静态扫描为 0;
ChatController中模型、Tool、ChatService、AiOps、Session 和 Trace service 禁止依赖扫描为 0。 - L4 部署必须将后端
/api/chatSSE 与 bundled frontend consumer 同版本原子部署;回滚必须成对回滚到阶段 6A commit,不提供兼容 endpoint、旧 parser 或双轨开关。 - live 模型、Redis、日志和 MySQL E2E 按 ISS-014 门禁明确延后到阶段 7,本阶段没有把 focused/Mock 验证表述为 live 验收。