docs(specs): 核心链路硬化设计文档 — 缝测试+胶水层瘦身方案
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>
This commit is contained in:
iven
2026-04-21 21:04:22 +08:00
parent c5f98beb7c
commit 751ec000d5

View File

@@ -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<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. 验证命令
```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 用临时文件 |