diff --git a/docs/superpowers/specs/2026-04-21-core-chain-hardening-design.md b/docs/superpowers/specs/2026-04-21-core-chain-hardening-design.md new file mode 100644 index 0000000..09aea94 --- /dev/null +++ b/docs/superpowers/specs/2026-04-21-core-chain-hardening-design.md @@ -0,0 +1,179 @@ +# 核心链路硬化设计文档 + +> 2026-04-21 | 状态: 实施中 | 计划文件: `plans/skill-mellow-valiant.md` + +## 1. 问题定义 + +ZCLAW 经过 20+ 轮审计修复,仍频繁发现功能链路断链。根因不是"Bug 修不完",而是 **系统复杂度超出了可验证范围**: + +- 190 个 Tauri 命令 × 137 个 API 端点 × 15 层中间件 = 数千个集成点 +- 手动审计永远无法覆盖全部集成点 + +### 1.1 胶水层诊断 + +架构骨架健康(crate 分层无环、中间件设计优雅),但 3 个"胶水点"是断链重灾区: + +| 胶水点 | 文件 | 行数 | 问题 | +|--------|------|------|------| +| Tauri 命令层 | `desktop/src-tauri/src/kernel_commands/chat.rs` | 548 | 业务逻辑未下沉,`agent_chat_stream` ~390行 | +| 流式状态管理 | `desktop/src/store/chat/streamStore.ts` | 886 | `sendMessage` ~397行,嵌套回调,依赖 5 个 Store | +| 连接管理 | `desktop/src/store/connectionStore.ts` | 891 | 连接 + 模型配置 + 网关生命周期混杂 | + +### 1.2 影响范围 + +断链集中在 3 条核心链路: + +1. **对话链路** — 用户消息 → 流式响应 → 消息持久化 +2. **Hands 链路** — LLM tool_call → Hand 注册分发 → 执行回调 → 结果回传 +3. **记忆链路** — 对话 → 经验提取 → FTS5 存储 → 检索 → system prompt 注入 + +--- + +## 2. 方案设计 + +### 2.1 策略:先建安全网再瘦身 + +混合路径,避免"边修边破": + +``` +Phase 1 (Week 1): 缝测试安全网 — 自动检测断链 +Phase 2 (Week 2): 瘦身 chat.rs — 消除 Rust 侧 Bug 温床 +Phase 3 (Week 3): 瘦身 Store 层 — 消除前端侧 Bug 温床 +Phase 4 (Week 4): 全量冒烟验证 — 建立发布前信心基线 +``` + +### 2.2 缝测试策略 + +"缝测试"(seam test) 验证的是**集成点之间的契约**,不是单元行为: + +``` +[Store] --缝1--> [Tauri invoke] --缝2--> [Kernel] --缝3--> [LLM Driver] --缝4--> [UI Event] +``` + +每个缝测试只验证一个集成点的输入/输出格式是否正确。 + +#### MockLlmDriver(已有) + +`crates/zclaw-runtime/src/test_util.rs` 已包含完整的 `MockLlmDriver`: + +- Builder 风格响应队列:`with_text_response()`, `with_tool_call()`, `with_error()` +- 调用检查:`call_count()`, `last_request()` +- 流式模拟:默认发射 `TextDelta("mock stream")` + `Complete` +- 线程安全:`Arc>` + `AtomicUsize` + +**无需新建**,只需在集成测试中引用。 + +### 2.3 缝测试清单 + +#### 对话链路(4 缝) + +| 缝 | 位置 | 验证内容 | +|----|------|---------| +| Store→Tauri | Vitest (mock invoke) | `sendMessage()` 调用参数格式正确 | +| Tauri→Kernel | Rust 集成测试 | `chat_command` 正确转发给 kernel | +| Kernel→LLM | Rust 集成测试 | 中间件处理后 prompt 正确传递给 MockLlmDriver | +| LLM→UI | Rust + Vitest | 事件顺序: delta → delta → complete | + +#### Hands 链路(3 缝) + +| 缝 | 位置 | 验证内容 | +|----|------|---------| +| 工具路由 | Rust 集成测试 | LLM tool_call → HandRegistry 正确分发 | +| 执行回调 | Rust + Vitest | Hand 完成 → Tauri event → Store 收到结果 | +| Approval | Rust 集成测试 | needs_approval=true → 确认后继续 | + +#### 记忆链路(3 缝) + +| 缝 | 位置 | 验证内容 | +|----|------|---------| +| 提取存储 | Rust 集成测试 | 对话 → 经验提取 → FTS5 写入 | +| 检索注入 | Rust 集成测试 | 新对话 → FTS5 检索 → system prompt 包含记忆 | +| 去重 | Rust 集成测试 | 同一经验不重复存储 | + +### 2.4 chat.rs 瘦身方案 + +将 `agent_chat_stream`(~390行)从 Tauri 命令层下沉到 kernel/runtime: + +| 下沉项 | 当前位置 | 目标位置 | +|--------|---------|---------| +| 调度拦截 | `chat_command` 内联 | kernel `chat_stream()` | +| 会话守卫 | `chat_command` 内联 | kernel `SessionGuard` | +| 事件翻译 | `LoopEvent→StreamChatEvent` 内联 | runtime `StreamEventTranslator` | +| Intelligence Hooks | `chat_command` 内联 | kernel `chat_stream()` | + +预期效果:`chat.rs` 548→~200行,Tauri 命令层只做参数验证和调用转发。 + +### 2.5 Store 层瘦身方案 + +#### streamStore.sendMessage 拆分(~397行 → 5 个函数) + +``` +sendMessage() → startStream() + bufferDeltas() + handleToolCalls() + handleHandEvents() + completeStream() +``` + +#### connectionStore 拆分(891行 → 3 个 Store) + +| 新 Store | 职责 | 预计行数 | +|----------|------|---------| +| `connectionStore` | 只管连接状态 | ~300 | +| `modelConfigStore` | 模型列表 + 当前模型 + API Key | ~300 | +| `gatewayStore` | 外部网关 start/stop/restart | ~300 | + +--- + +## 3. 执行时间线 + +| 周 | Phase | 交付物 | 验证标准 | +|----|-------|--------|---------| +| W1 | 缝测试 | 13 缝测试 + 3 冒烟测试 | 能自动检测 3 条核心链路断链 | +| W2 | chat.rs 瘦身 | chat.rs 548→~200行 | 所有缝测试 + 987 Rust 测试通过 | +| W3 | Store 瘦身 | streamStore 886→~300行, connectionStore 拆分 3×~300行 | 所有缝测试 + 前端测试通过 | +| W4 | 全量验证 | 发布前信心基线 | 全量测试 + 生产构建 + 手动验证 | + +--- + +## 4. 约束 + +- **不新增功能** — 只做内部重组和测试覆盖 +- **不新增 API 端点** — 稳定化约束 +- **不新增 Tauri 命令** — 只瘦身已有命令 +- **每步验证** — 重构前先有缝测试,重构后验证通过 +- **立即提交** — 每完成一个独立工作单元立即 commit + push + +--- + +## 5. 验证命令 + +```bash +# Rust 全量 +cargo test --workspace --exclude zclaw-saas + +# 缝测试(新增) +cargo test -p zclaw-kernel --test chat_chain --test smoke_chat --test smoke_hands +cargo test -p zclaw-growth --test memory_chain --test smoke_memory +cargo test -p zclaw-runtime --test hand_chain + +# 前端全量 +cd desktop && pnpm vitest run + +# 前端缝测试(新增) +cd desktop && pnpm vitest run chat-seam hand-seam + +# 类型检查 +pnpm tsc --noEmit +cargo check --workspace --exclude zclaw-saas + +# 生产构建 +pnpm build +``` + +--- + +## 6. 风险与缓解 + +| 风险 | 概率 | 缓解 | +|------|------|------| +| 缝测试发现新断链 | 高 | Phase 1 的目的就是发现断链,发现后立即修复 | +| chat.rs 下沉破坏现有功能 | 中 | 缝测试作为安全网,每步验证 | +| Store 拆分导致 import 风暴 | 中 | 逐步迁移,保留旧 Store re-export | +| 测试环境搭建复杂 | 低 | MockLlmDriver 已就绪,FTS5 用临时文件 |