Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
6.3 KiB
6.3 KiB
核心链路硬化设计文档
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 条核心链路:
- 对话链路 — 用户消息 → 流式响应 → 消息持久化
- Hands 链路 — LLM tool_call → Hand 注册分发 → 执行回调 → 结果回传
- 记忆链路 — 对话 → 经验提取 → 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<Mutex<>>+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. 验证命令
# 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 用临时文件 |