Files
zclaw_openfang/docs/features/DEEP_AUDIT_REPORT.md
iven 80d98b35a5
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
fix(audit): v5 审计修复 8 项 — 条件编译、安全加固、冗余清理
- N1: Whiteboard Export 动作标注 demo=true
- N2/N3: Director + A2A 通过 #[cfg(feature)] 条件编译隔离
- N4: viking_adapter 文本匹配降级为 LOW(生产路径走 SqliteStorage)
- N5: 移除冗余 compactor_compact_llm Tauri 命令注册
- M3: hand_approve/hand_cancel 添加 hand_id 验证防跨 Hand 审批
- N7: scheduled_task 文档注释标注 PLANNNED
- 新增 COMPREHENSIVE_AUDIT_V5.md 独立审计报告
- 更新 DEEP_AUDIT_REPORT.md 追加修复记录(累计 32 项)
2026-03-27 12:33:44 +08:00

597 lines
37 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# ZCLAW 功能完成度深度审计报告
> **审计日期**: 2026-03-27
> **修复轮次**: 2026-03-27P0/P1 第一轮修复完成)
> **审计方法**: 五步审计法(文档对齐 → 数据流追踪 → dead_code 识别 → trait 实现 → 端到端验证)
> **审计范围**: 全部 10 个 Rust crate + Tauri 后端 + React 前端 + docs/features 文档
> **独立性声明**: 本报告独立于此前三份审计报告VERIFICATION_REPORT、FRONTEND_INTEGRATION_AUDIT、FEATURE_AUDIT_REPORT所有结论均基于代码实际状态得出。
---
## 一、基础数据纠正
### 1.1 现有审计报告的不准确性
| 现有报告 | 声称 | 实际 | 偏差原因 |
|----------|------|------|----------|
| VERIFICATION_REPORT.md | 98.5% (133/135) | ~75% | 包含已删除功能Team/Swarm模拟实现标记为可用 |
| FRONTEND_INTEGRATION_AUDIT.md | "无僵尸组件" | 基本准确 | 但遗漏了 kernel-client.ts 中的幽灵调用 |
| FEATURE_AUDIT_REPORT.md | 85% (22/26) | ~60% | SpeechHand/TwitterHand 误判为"可用",存储双路径未深入验证 |
### 1.2 基础数据事实
| 指标 | 文档声称 | 实际验证 | 差异 |
|------|----------|----------|------|
| Rust crate 数量 | 9 | 10含 zclaw-pipeline、zclaw-growth | +2 |
| Zustand Store 数量 | 18+ | 14gatewayStore 已废弃) | -4 |
| SKILL.md 文件数量 | 78+ | 69 | -9 |
| HAND.toml 文件数量 | 11 | 9predictor/lead 已删除) | -2 |
| Tauri 命令注册数 | 未明确 | 100+ | — |
| 前端 invoke 调用数 | 未明确 | ~50 独立命令名 | — |
---
## 二、功能完成度矩阵
### 2.1 架构层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|------|----------|-----------|----------|--------|
| **通信层** | L4 (85%) | **L4 (85%)** | 无重大差距 | — |
| **状态管理** | L4 (85%) | **L4 (80%)** | gatewayStore 废弃但未清理 | LOW |
| **安全认证** | L4 (80%) | **L4 (80%)** | 无重大差距 | — |
### 2.2 核心功能层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|------|----------|-----------|----------|--------|
| **聊天界面** | L4 (85%) | **L4 (85%)** | 流式响应链路完整 | — |
| **Agent 分身** | L4 (90%) | **L4 (85%)** | ~~Tauri 模式下 CRUD 静默失败~~ ✅ 已修复 (H7) | ~~HIGH~~ FIXED |
| **Hands 系统** | L4 (70%) | **L3 (60%)** | ~~审批流程被绕过~~ ✅ 已修复 (H8)~~幽灵命令~~ ✅ 已修复 (M1)SpeechHand/TwitterHand 已标记 demo | ~~HIGH~~ PARTIAL |
### 2.3 智能层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|------|----------|-----------|----------|--------|
| **Agent 记忆** | L4 (90%) | **L4 (85%)** | ~~双存储路径使用不同数据库~~ ✅ 已修复 (H3) — 统一到 VikingStorage | ~~HIGH~~ FIXED |
| **身份演化** | L2 (70%) | **L2 (70%)** | ~~前端回滚 UI 缺失~~ ✅ 已实现 (IdentityChangeProposal.tsx HistoryItem + restoreSnapshot) | ~~MEDIUM~~ FIXED |
| **反思引擎** | L2 (65%) | **L2 (65%)** | ~~传入空记忆数组~~ ✅ 已修复 (C2)~~结果未持久化~~ ✅ 已修复 (M4)~~历史只存单条~~ ✅ 已修复 (M4-补 累积存储)LLM 分析待接入 | ~~MEDIUM~~ MOSTLY FIXED |
| **心跳引擎** | L2 (70%) | **L2 (60%)** | ~~无持久化~~ ✅ 已修复 (H4)~~历史重启丢失~~ ✅ 已修复 (心跳历史持久化);默认禁用(enabled=false),需前端主动启动 | ~~HIGH~~ MOSTLY FIXED |
| **自主授权** | L2 (75%) | **L2 (70%)** | ~~后端无守卫~~ ✅ 已修复 (M5-补 hand_execute/skill_execute 后端守卫) | ~~MEDIUM~~ FIXED |
| **上下文压缩** | L2 (75%) | **L2 (70%)** | 规则压缩已集成LLM 压缩存在但默认关闭 | LOW |
### 2.4 扩展层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|------|----------|-----------|----------|--------|
| **技能系统** | L3 (80%) | **L3 (75%)** | ~~PromptOnly 不调用 LLM~~ ✅ 已修复 (C1);现在通过 LlmCompleter 桥接调用 LLM | ~~HIGH~~ FIXED |
| **智能路由** | L1 (15%) | **L1 (10%)** | 语义匹配是桩代码(返回 None从未实例化 | MEDIUM |
| **Pipeline DSL** | L2 (75%) | **L2 (70%)** | ~~Presentation 层部分缺失~~ ✅ 已修复 (H6);并行执行实际串行,进度报告粗粒度 | ~~MEDIUM~~ FIXED |
| **OpenViking** | L3 (70%) | **L3 (65%)** | 本地服务器启动慢 | LOW |
| **Browser 自动化** | L3 (80%) | **L3 (80%)** | Fantoccini 集成完整 | — |
| **Channels** | — | **L0 (10%)** | 仅有 ConsoleChannel 测试适配器 | LOW |
### 2.5 总体完成度
| 维度 | 文档声称 | 审计结果 | 修复后 |
|------|----------|----------|--------|
| **整体** | 68% | **~50%** | **~72%** |
| **核心可用** | 85% | **75%** | **~92%** |
| **真实可用** | 100% | **~55%**(排除模拟实现和 PromptOnly 技能后) | **~80%** |
---
## 三、差距清单(按严重度排序)
### 3.1 CRITICAL 严重度2 项)
#### C1: 技能系统 PromptOnly 模式不调用 LLM69/69 技能仅返回 prompt 模板 ✅ **已修复**
- **文件**: `crates/zclaw-skills/src/runner.rs:41-44`
- **修复方案**: 定义 `LlmCompleter` trait`zclaw-skills`),创建 `LlmDriverAdapter` 桥接(`zclaw-kernel`),在 `SkillContext` 中注入 `llm` 字段。`PromptOnlySkill.execute()` 优先调用 LLM 生成结果,无 LLM 时回退到原始 prompt 文本。
- **修复文件**: `skill.rs`, `runner.rs`, `kernel.rs`
- **影响**: 整个技能系统本质上是**prompt 模板库**,不是执行引擎。`skill_execute` 返回的是格式化后的 prompt 文本,不是 AI 生成的内容。技能在 kernel 的 `build_skill_aware_system_prompt()` 中作为系统提示注入 LLM 上下文(这部分是有效的),但直接执行技能本身不产生 AI 输出。
- **差距模式**: 写了没接 — 执行框架完整但核心处理逻辑缺失
- **根因**: PromptOnly 模式设计为"注入 prompt 后由 Agent Loop 的 LLM 调用处理",而非独立执行。但 `execute_skill` Tauri 命令直接返回 prompt 文本给前端,前端将其作为"执行结果"展示,造成功能完整的假象。
- **解决方案**:
- 短期: 在 PromptOnlySkill 中集成 LLM 调用,将 prompt 发送给 LLM 后返回生成结果
- 或: 在 kernel_commands.rs 的 skill_execute 中,获取 prompt 后通过 kernel 的 LLM driver 生成结果
- 或: 在前端展示时明确标注这是"prompt 模板"而非"执行结果"
#### C2: 反思引擎传入空记忆数组,整个子系统是空操作 ✅ **已修复**
- **文件**: `desktop/src-tauri/src/intelligence_hooks.rs:65`
- **修复方案**: 新增 `query_memories_for_reflection()` 函数,在 `reflect()` 调用前从 VikingStorage 查询最多 50 条 agent 记忆,转换为 `MemoryEntryForAnalysis` 后传入。同时为 `post_conversation_hook` 添加 `user_message` 参数。
- **修复文件**: `intelligence_hooks.rs`, `kernel_commands.rs`
- **影响**: `analyze_patterns()` 对空数组进行阈值检测task ≥ 5、preference ≥ 5 等),**永远无法触发任何模式检测**。反思引擎的 patterns、improvements、identity_proposals **永远是空的**。整个反思子系统(~500 行代码 + 文档 + UI 组件)实际上**从未产生过任何有意义的输出**。
- **差距模式**: 接了没传 — 反思逻辑完整但调用时传入了空数据
- **根因**: `post_conversation_hook` 应该先从 VikingStorage 获取记忆数据再传给 `reflect()`
- **解决方案**:
- 修复: 在 `reflect()` 调用前查询 VikingStorage 获取当前 agent 的记忆列表
- 示例: `let memories = fetch_agent_memories(agent_id).await; engine.reflect(agent_id, &memories);`
### 3.2 HIGH 严重度8 项)
#### H1: SpeechHand 完全模拟 ✅ **已标记 demo**
- **文件**: `crates/zclaw-hands/src/hands/speech.rs:236`
- **证据**: `"In real implementation, would call TTS API"` — 返回 `duration_ms: text.len() * 80` 的伪数据
- **差距模式**: 写了没接 — 代码结构完整但无真实 API 调用
- **影响**: 用户触发 SpeechHand 期望得到语音输出,实际只返回 JSON 状态
- **解决方案**:
- 短期: UI 标记为"演示模式"
- 中期: 集成浏览器 Web Speech API通过 Tauri webview.eval
- 长期: 实现 Azure/OpenAI/ElevenLabs TTS API
#### H2: TwitterHand 完全模拟 ✅ **已标记 demo**
- **文件**: `crates/zclaw-hands/src/hands/twitter.rs:297-509`
- **证据**: 所有 10+ 个操作返回 `"(simulated)"` JSON搜索返回空数组
- **差距模式**: 写了没接 — 类型定义完整但无 HTTP 请求
- **影响**: 即使配置了 API Key 也不会生效,返回假数据
- **解决方案**:
- 短期: UI 明确标注"模拟模式",禁用写操作
- 中期: 实现 Twitter API v2 或改为 Mastodon API
#### H3: 记忆系统双存储路径不同步 ✅ **已修复**
- **修复方案**: 完全重写 `memory_commands.rs`,所有操作统一委派到 VikingStorage (SqliteStorage)。移除了 PersistentMemoryStore 的双写逻辑。保留 PersistentMemory 类型作为前端 API 兼容层,内部通过 `to_persistent()` 转换。
- **修复文件**: `memory_commands.rs`, `viking_commands.rs`, `memory/mod.rs`
- **路径A**: `memory_commands.rs``PersistentMemoryStore``{app_data_dir}/memory/memories.db`UI 面板使用)
- **路径B**: `intelligence_hooks.rs``VikingStorage``{data_dir}/zclaw/memories/memories.db`(聊天流程使用)
- **证据**: 两个路径使用**不同的数据库文件**。`memory_store()` 第88-94行虽有双写逻辑`memory_search()` 优先用 VikingStorage`intelligence_hooks` 也只用 VikingStorage。`memory_db_path()` 返回的是 PersistentMemoryStore 的路径。
- **差距模式**: 双系统不同步
- **影响**: UI 面板存储的记忆可能无法在聊天时被检索到
- **解决方案**: 统一到 `zclaw-growth` 的 SqliteStorage已有 FTS5 + TF-IDF + 可选 embedding
#### H4: 心跳引擎无持久化(已在启动时运行) ✅ **已修复**
- **修复方案**: `record_interaction()` 现在通过 `tokio::spawn` 将交互时间戳持久化到 VikingStorage metadatakey: `heartbeat:last_interaction:{agent_id}`)。`heartbeat_init()` 在初始化时调用 `restore_last_interaction()` 从 VikingStorage 恢复上次交互时间,确保 `idle-greeting` 检查在应用重启后仍能正确工作。
- **修复文件**: `heartbeat.rs`
- **文件**: `desktop/src-tauri/src/intelligence/heartbeat.rs`
- **证据**:
- `HeartbeatConfig::default()``enabled: false`第103行`App.tsx:181` 主动调用 `heartbeat.start()`
- `start()` **确实启动了后台 tokio 任务**,每 30 分钟执行一次 tick第138-180行
- `record_interaction()` 只写入全局静态 HashMap第378-382行不持久化到磁盘
- `history` 存储在内存 `Arc<Mutex<Vec<HeartbeatResult>>>`,重启丢失
- `MEMORY_STATS_CACHE` 需要前端调用 `heartbeat_update_memory_stats` 才能填充,否则 `check_pending_tasks``check_memory_health` 发出"记忆统计未同步"警告
- **差距模式**: 传了没存
- **影响**: 心跳引擎已运行但所有状态重启后丢失;记忆统计检查需要前端主动同步
- **解决方案**:
- 使用 SQLite 持久化交互记录和心跳历史
- 自动同步记忆统计,不依赖前端手动调用
#### H5: VERIFICATION_REPORT 包含已删除功能 ✅ **已归档**
- **文件**: `docs/features/VERIFICATION_REPORT.md`
- **证据**: 报告验证了 "Multi-Agent Collaboration" 和 "Team/Swarm" 功能,但 commit `c399657` 已删除这些功能
- **差距模式**: 存了没用 — 过时文档误导开发者
- **影响**: 审计结论不可信98.5% 通过率严重虚高
- **解决方案**: 立即更新或归档此报告,以本审计报告替代
#### H6: Presentation 层部分渲染器缺失 ✅ **已修复**
- **修复方案**:
- Chart: 新增 `ChartRenderer.tsx`,使用 recharts 实现 line/bar/pie/scatter/area 五种图表
- Document: 替换手写 markdown 解析器为 react-markdown + remark-gfm支持 tables、links、images、inline code
- Slideshow: 实现完整 slide type 渲染title/content/image/code/twoColumn集成 react-markdown
- Whiteboard: 保留占位但添加 "即将推出" 标签
- **修复文件**: `ChartRenderer.tsx`(新)、`DocumentRenderer.tsx``SlideshowRenderer.tsx``PresentationContainer.tsx`
- **文件**: `desktop/src/components/presentation/`
- **证据**:
- Chart 渲染器**完全缺失** — PresentationAnalyzer 可检测 Chart 类型,但无对应 UI 渲染器,选择 "chart" 会显示默认占位
- Whiteboard 渲染器是**占位文本** — `PresentationContainer.tsx:113-116` 显示 "白板渲染器开发中..."
- Slideshow 渲染器**导航可用但内容渲染是 stub** — 复杂内容显示 "Complex content rendering" 占位,无实际 markdown/代码/图片渲染
- Document 渲染器**手写 markdown 解析器** — 不支持 inline code、links、images、tables、nested lists
- **差距模式**: 写了没接 — 分析器能识别类型但渲染器未实现
- **解决方案**:
- 短期: Chart 用 recharts 库实现Whiteboard 保持占位但移除 "可用" 标签
- 中期: Slideshow 集成 markdown 渲染库react-markdownDocument 替换手写解析器
#### H7: Agent Store 接口不匹配 — Tauri 模式下 Agent CRUD 静默失败 ✅ **已修复**
- **修复方案**: 在 `KernelClient` 上添加 `listClones/createClone/deleteClone/updateClone` 适配方法,内部映射到 `listAgents/createAgent/deleteAgent`
- **修复文件**: `kernel-client.ts`
- **文件**: `desktop/src/store/agentStore.ts:137-204``desktop/src/lib/kernel-client.ts`
- **证据**: `agentStore.ts` 调用 `client.listClones()``client.createClone()``client.deleteClone()` — 这些方法定义在 `GatewayClient` 接口上,但 `KernelClient` **没有这些方法**。KernelClient 只有 `listAgents()``createAgent()``deleteAgent()`(使用 `agent_list`/`agent_create`/`agent_delete` 命令)。在 Tauri 内核模式下Agent 管理操作会静默失败。
- **差距模式**: 接了没传 — 前端调用的方法在当前客户端上不存在
- **影响**: Tauri 模式下用户无法创建、列出、删除 Agent
- **解决方案**: agentStore 适配 KernelClient 接口(调用 `listAgents`/`createAgent`/`deleteAgent`
#### H8: Hand 审批流程被绕过 — needs_approval 从未检查 ✅ **已修复**
- **修复方案**: `hand_execute` 在执行前查询 `list_hands()` 检查 `needs_approval`,如需审批则创建 pending approval 并返回 `pending_approval` 状态。
- **修复文件**: `kernel_commands.rs`
- **文件**: `desktop/src-tauri/src/kernel_commands.rs:805-820`
- **证据**: `hand_execute()` 直接调用 `kernel.execute_hand(&id, input)`**完全不检查** `needs_approval` 配置。审批系统(`approval_list``approval_respond``hand_approve``hand_cancel`)的 Tauri 命令都存在,但执行 Hand 时从未触发审批流程。
- **差距模式**: 写了没接 — 审批基础设施完整但执行路径不检查
- **影响**: 标记为 `needs_approval: true` 的 Hand如 browser.HAND.toml可以直接执行审批流是死代码
- **解决方案**: 在 `hand_execute` 中检查 `needs_approval`,如需审批则创建审批请求并返回 pending 状态
### 3.2 MEDIUM 严重度7 项)
#### M1: 3 个幽灵 Tauri 命令调用 ✅ **已修复**
- **修复方案**: 在 `kernel_commands.rs` 注册 `hand_get`(查询 hand 详情)、`hand_run_status`(返回 not_found`hand_run_list`(返回空列表)三个桩命令,并在 `lib.rs``generate_handler!` 中注册。
- **修复文件**: `kernel_commands.rs`, `lib.rs`
- **前端调用** (kernel-client.ts):
- `invoke('hand_get')` — 第618行try/catch 返回 `{}`
- `invoke('hand_run_status')` — 第641行try/catch 返回 `{ status: 'unknown' }`
- `invoke('hand_run_list')` — 第680行try/catch 返回 `{ runs: [] }`
- **后端注册**: 仅有 `hand_list`, `hand_execute`, `hand_approve`, `hand_cancel`
- **差距模式**: 接了没传 — 静默失败
- **解决方案**: 注册显式命令或移除前端调用
#### M2: plugin:tinker|ping 调用不存在的插件
- **文件**: `desktop/src/lib/kernel-client.ts:164`
- **证据**: `await invoke('plugin:tinker|ping')` — 项目中无 tinker 插件
- **差距模式**: 接了没传
- **解决方案**: 移除此调用或实现实际的健康检查
#### M3: hand_approve 忽略 hand_name 参数
- **文件**: `desktop/src-tauri/src/kernel_commands.rs:1109`
- **证据**: `fn hand_approve(_hand_name: String, run_id: String, ...)`
- **差距模式**: 接了没传 — 参数传递但被忽略
- **影响**: 无法按 hand 类型筛选审批
- **解决方案**: 实现按 hand_name + run_id 联合查找
#### M4: 反思引擎结果未反馈到行为 ✅ **已修复(持久化部分)**
- **修复方案**: `reflect()` 完成后通过 `tokio::spawn` 将 ReflectionState 和 ReflectionResult 持久化到 VikingStorage metadata。新增 `restore_state()` 方法在初始化时从 VikingStorage 恢复状态,确保 `conversations_since_reflection` 计数器在重启后保持。`intelligence_hooks` 在首次 `post_conversation_hook` 时通过 `pop_restored_state/result` 消费恢复数据。
- **修复文件**: `reflection.rs`, `intelligence_hooks.rs`
- **文件**: `desktop/src-tauri/src/intelligence/reflection.rs:190-233`
- **证据**: `reflect()` 基于规则检测模式task ≥ 5、preference ≥ 5、lesson ≥ 5生成改进建议但结果仅存入内存 `history: Vec<ReflectionResult>`(最多保留 20 条),不持久化且不用于修改后续行为。**更严重的是,由于 C1 bug这些结果永远是空的。**
- **差距模式**: 传了没存 + 存了没用
- **影响**: 反思产出patterns、improvements、identity_proposals仅记录在日志中用户看不到Agent 也不会据此调整行为
- **解决方案**: 先修复 C1传入真实记忆再将结果持久化到 SQLite在 RightPanel 中展示,用于身份演化触发
#### M4b: LLM 压缩器孤立kernel 只用规则压缩 ✅ **已修复**
- **修复方案**: 在 `zclaw-runtime::compaction` 中新增 `CompactionConfig``CompactionOutcome` 和异步 `maybe_compact_with_config()` 函数。AgentLoop 根据 config 中的 `use_llm` 标志选择 LLM 摘要或规则摘要路径。LLM 失败时自动回退到规则摘要。
- **修复文件**: `compaction.rs``loop_runner.rs``lib.rs`
- **文件**: `desktop/src-tauri/src/intelligence/compactor.rs` vs `crates/zclaw-runtime/src/compaction.rs`
- **证据**: Kernel AgentLoop 使用 `zclaw-runtime::compaction`纯规则CJK token 估算Tauri 的 `compactor_compact_llm`(支持 LLM 摘要)虽然注册为命令但**从未被 kernel 调用**。`use_llm` 配置只影响 Tauri 命令,不影响 kernel 循环。
- **差距模式**: 写了没接
- **影响**: 即使配置 `use_llm: true`,聊天压缩也不会使用 LLM 生成摘要
- **解决方案**: 在 kernel 的 AgentLoop 中集成 LLM 压缩路径
#### M4c: 压缩时记忆刷出是空操作 ✅ **已修复**
- **修复方案**:
- Runtime 层: `maybe_compact_with_config()` 在压缩前调用 `GrowthIntegration.process_conversation()` 提取记忆
- Tauri 层: `compactor_compact``compactor_compact_llm` 命令在压缩前调用 `flush_old_messages_to_memory()` 将用户消息和助手回复刷出到 VikingStorage
- **修复文件**: `compaction.rs`runtime`compactor.rs`tauri
- **文件**: `crates/zclaw-runtime/src/compaction.rs`, `desktop/src-tauri/src/intelligence/compactor.rs`
- **证据**: 两个压缩器都设置 `flushed_memories: 0``memory_flush_enabled` 配置存在但**无实现**
- **差距模式**: 写了没接
- **影响**: 长对话压缩时不会自动提取和保存关键记忆
- **解决方案**: 实现压缩时的记忆提取逻辑
#### M5: 自主授权未集成到执行链路
- **文件**: `desktop/src/lib/autonomy-manager.ts`, `desktop/src/components/AutonomyConfig.tsx`
- **证据**: 组件存在且渲染在 RightPanel`canAutoExecute()` 未在 `kernel_commands.rs` 的 hand_execute 或 skill_execute 中被调用
- **差距模式**: 写了没接
- **影响**: 用户配置的自主级别不影响实际执行
- **解决方案**: 在 Tauri 命令层集成自主授权检查
#### M6: Pipeline 语义路由是桩代码
- **文件**: `crates/zclaw-pipeline/src/intent.rs:454-457`
- **证据**: 构建了 LLM prompt 但 `let _ = prompt; // Suppress unused warning` 然后 `return None`
- **差距模式**: 写了没接
- **影响**: Pipeline 只能用关键词匹配触发
- **解决方案**: 接入 LLM driver 实现真正的语义匹配
#### M7: Pipeline 无 YAML 模板文件
- **证据**: `find config/ skills/ hands/` 未找到任何 `.yaml`/`.yml` 文件
- **差距模式**: 存了没用 — 文档声称 5 个模板但文件不存在
- **影响**: 用户无法使用预设的 Pipeline 模板
- **解决方案**: 创建实际可用的 YAML 模板文件
### 3.3 LOW 严重度6 项)
#### L1: Pipeline 并行执行实际串行
- **文件**: `crates/zclaw-pipeline/src/engine/stage.rs:321-322`
- **证据**: `execute_parallel` 使用 for 循环,注释 "True parallel execution would require Send-safe drivers"
- **差距模式**: 写了没接
#### L2: gatewayStore.ts 废弃但仍被引用
- **文件**: `desktop/src/store/gatewayStore.ts`@deprecated`HandApprovalModal.tsx:25` 仍导入
- **差距模式**: 写了没接
#### L3: Wasm/Native 技能模式未实现
- **文件**: `crates/zclaw-skills/src/skill.rs`
- **证据**: SkillMode::Wasm 和 SkillMode::Native 注释为 "not yet implemented, falls back to PromptOnly"
- **差距模式**: 写了没接
#### L4: 28 个 `#[allow(dead_code)]` 标注
- **分布**:
- LLM driver 反序列化字段anthropic.rs、openai.rs、local.rs、gemini.rs— 合理
- intelligence 模块预留方法identity export/import、heartbeat is_running/subscribe、compactor get_config/update_config、reflection get_last_result— 预留
- export 预留html template、markdown without_front_matter— 预留
- `lib.rs` build_staged_runtime_legacy、HealthStatus — 遗留代码
- `intent.rs` DefaultLlmIntentDriver — 桩代码
- `persistent.rs` tags 字段 — 预留
- `browser/session.rs` session_count — 预留
- **建议**: 遗留代码lib.rs legacy可删除其余保留
#### L5: 5 个 TODO 注释
- `registry.rs:56` — message_count tracking
- `orchestration.rs:41` — graph storage
- `pipeline_commands.rs:442` — use actual time
- `pipeline_commands.rs:781` — pattern support
- `html.rs:17` — template-based export
- **建议**: 均为功能增强,非阻塞
#### L6: zclaw-channels 仅有测试适配器
- **文件**: `crates/zclaw-channels/src/adapters/console.rs`
- **证据**: 仅有 ConsoleChannel无 Discord/Slack/飞书等真实适配器
- **影响**: 低 — 桌面端不依赖外部通道
- **建议**: 维持现状或移除 crate
---
## 四、调用链验证报告
### 4.1 聊天消息流 ✅ 已验证
```
ChatArea.tsx → chatStore.sendStreamMessage()
→ kernel-client.ts sendStreamMessage() → invoke('agent_chat_stream')
→ kernel_commands.rs agent_chat_stream()
→ intelligence_hooks.rs pre_conversation_hook()
→ build_memory_context() → VikingStorage.find() ✅
→ build_identity_prompt() → IdentityManager.build_system_prompt() ✅
→ kernel.agent_chat_stream()
→ loop_runner.rs AgentLoopcompaction threshold 15k
→ LLM driver4个实现Anthropic/OpenAI/Gemini/Local
→ intelligence_hooks.rs post_conversation_hook()
→ heartbeat.record_interaction() ✅(仅内存)
→ reflection.record_conversation() + should_reflect() ✅ 已修复 (C2: 传入真实记忆)
→ Tauri events 发射 ✅
→ kernel-client.ts 事件监听 ✅
→ ChatArea.tsx 渲染 ✅
```
### 4.2 Hand 执行流 ⚠️ 部分验证
```
HandList.tsx → handStore.triggerHand()
→ kernel-client.ts triggerHand() → invoke('hand_execute')
→ kernel_commands.rs hand_execute() → kernel.hand_execute()
→ HandRegistry.get() → Hand.execute()
→ [真实] QuizHand: LLM 生成题目 ✅
→ [真实] ResearcherHand: DuckDuckGo 搜索 ✅
→ [真实] CollectorHand: HTML 抓取 ✅
→ [真实] ClipHand: FFmpeg 调用 ✅
→ [真实] SlideshowHand: 状态管理 ✅
→ [真实] WhiteboardHand: 状态管理 ✅
→ [模拟] SpeechHand: 返回伪 JSON ❌
→ [模拟] TwitterHand: 返回 "(simulated)" ❌
→ [委托] BrowserHand: 委托给 Tauri browser commands ✅
→ 审批检查(如 needs_approval✅ 已修复 (H8)
→ 结果返回
→ handStore 处理结果
→ UI 显示结果
```
### 4.3 记忆存储流 ⚠️ 双路径
```
路径A (UI面板):
MemoryPanel.tsx → intelligence-backend.ts memory_store()
→ invoke('memory_store') → memory_commands.rs
→ PersistentMemoryStore.store() → {app_data}/memory/memories.db
→ VikingStorage.add() → {data_dir}/zclaw/memories/memories.db (双写)
路径B (聊天流程):
intelligence_hooks.rs build_memory_context()
→ VikingStorage.find() → {data_dir}/zclaw/memories/memories.db
```
### 4.4 技能执行流 ⚠️ PromptOnly 不产生 AI 输出
```
SkillMarket.tsx → kernel-client.ts executeSkill()
→ invoke('skill_execute') → kernel_commands.rs skill_execute()
→ kernel.execute_skill() → SkillRegistry → SkillExecutor
→ PromptOnlySkill: 通过 LlmCompleter 调用 LLM 生成内容 ✅ 已修复 (C1)
→ PythonSkill: subprocess 执行 ✅(但无技能使用此模式)
→ ShellSkill: subprocess 执行 ✅(仅 shell-command 使用此模式)
→ WasmSkill → 回退到 PromptOnly ❌
→ NativeSkill → 回退到 PromptOnly ❌
注意: 技能在 kernel 的 build_skill_aware_system_prompt() 中作为上下文注入是有效的,
但通过 skill_execute 命令直接执行时PromptOnly 不产生 AI 生成内容。
```
### 4.5 Pipeline 执行流 ⚠️ 部分验证
```
PipelinesPanel.tsx → workflowStore.runPipeline()
→ invoke('pipeline_run') → pipeline_commands.rs pipeline_run()
→ StageEngine.execute()
→ Llm stage: 调用 LLM ✅
→ Parallel stage: 实际串行 ❌
→ Sequential stage: 顺序链 ✅
→ Conditional stage: 条件评估 ✅
→ Skill stage: 调用技能系统 ✅
→ Hand stage: 调用 Hand 系统 ✅
→ Http stage: HTTP 请求 ✅
→ SetVar stage: 设置变量 ✅
→ Compose stage: 模板组合 ✅
→ Progress 事件
```
---
## 五、Dead Code 分类清单
### 5.1 真正的死代码(建议删除)
| 位置 | 类型 | 建议 |
|------|------|------|
| `lib.rs` build_staged_runtime_legacy | 遗留函数 | 删除 |
| `lib.rs` HealthStatus enum | 预留枚举 | 删除或实现 |
### 5.2 预留功能(暂时保留)
| 位置 | 类型 | 建议 |
|------|------|------|
| `identity.rs` export_all/import/get_all_proposals | 预留方法 | 保留,添加 Tauri 命令 |
| `heartbeat.rs` is_running/subscribe | 预留方法 | 保留 |
| `compactor.rs` get_config/update_config | 预留方法 | 保留 |
| `reflection.rs` get_last_result | 预留方法 | 保留 |
| `persistent.rs` tags 字段 | 预留字段 | 保留 |
| `browser/session.rs` session_count | 预留方法 | 保留 |
| `html.rs` template/with_template | 预留功能 | 保留 |
| `markdown.rs` without_front_matter | 预留功能 | 保留 |
| `stage.rs` clone_with_drivers | 预留功能 | 保留 |
| `a2a.rs` new() | 预留构造器 | 保留 |
| `sqlite.rs` path 字段 | 预留字段 | 保留 |
| `cache.rs` CacheKey struct | 预留类型 | 保留 |
### 5.3 桩代码(需要实现或明确标注)
| 位置 | 类型 | 建议 |
|------|------|------|
| `intent.rs` DefaultLlmIntentDriver.semantic_match | 桩代码 | 接入 LLM driver |
| `speech.rs` execute_action (Speak) | 模拟实现 | 集成真实 TTS |
| `twitter.rs` 所有 execute_* 方法 | 模拟实现 | 集成真实 API 或标记为演示 |
---
## 六、跨部门专家头脑风暴
### 议题 1: SpeechHand/TwitterHand 是否应该保留在发布版中?
**产品视角**:
- 用户看到"可用"标签会期望真实功能,模拟实现会损害信任
- 建议: 短期在 UI 中标记为"演示/Preview"状态,长期要么实现要么移除
**工程视角**:
- 模拟实现有其价值:验证了类型系统、配置传递、审批流程的正确性
- 可以作为真实实现的骨架,替换核心逻辑即可
- 建议: 保留代码但移除"可用"标签
**安全视角**:
- TwitterHand 的模拟实现不会造成安全问题(无网络请求)
- 但 UI 不应让用户误以为操作已生效
- 建议: 写操作的 UI 按钮必须添加明确提示
**结论**: 保留代码UI 标记为"演示模式",写操作添加确认提示
### 议题 2: 双存储路径如何统一?
**架构视角**:
- PersistentMemoryStoresqlx 直连)和 VikingStorage/zclaw-growthtrait 抽象)本质上是同一个功能的两套实现
- zclaw-growth 的 SqliteStorage 有 FTS5 + TF-IDF + embedding 支持,能力更强
- 统一到 zclaw-growth 是正确的方向
**数据迁移视角**:
- 需要将 PersistentMemoryStore 中已有的数据迁移到 VikingStorage
- `memory_store()` 已有双写逻辑,只需确保搜索也统一使用 VikingStorage
**结论**: 统一到 VikingStorage删除 PersistentMemoryStore确保所有搜索路径走同一数据库
### 议题 3: 反思引擎的产出是否有价值?
**AI 研究视角**:
- 当前的 `analyze_patterns()` 基于简单阈值task ≥ 5检测粒度粗
- 没有使用 LLM 进行深度分析,无法发现复杂的行为模式
- 但作为 L0 级别的规则检测,它提供了基础的价值
**产品视角**:
- 反思结果目前只存在内存中,用户看不到
- 如果不展示给用户、不影响 Agent 行为,等于不存在
- 建议: 至少在 RightPanel 中展示反思日志
**结论**: 保留规则检测作为基础,将结果持久化并在 UI 中展示,中期升级为 LLM 驱动
### 议题 4: 心跳引擎是否值得维护?
**运维视角**:
- 默认禁用意味着这个功能从未被用户使用过
- 如果没有用户需求,维护它只是增加代码复杂度
- 但作为 Agent 主动性的基础,长期有战略价值
**工程视角**:
- `record_interaction()` 仅写入内存 HashMap重启丢失
- `tick()` 没有定时器自动执行,需要手动触发
- 建议: 要么完整实现(持久化 + 定时器 + 通知),要么降级为按需触发
**结论**: 将 enabled 默认改为 true实现 SQLite 持久化,保留定时器但简化检查项
---
## 七、修复优先级矩阵
| 优先级 | ID | 问题 | 工作量 | 建议时间线 | 状态 |
|--------|-----|------|--------|-----------|------|
| **P0** | C1 | PromptOnly 技能不调用 LLM — 集成 LLM driver | 1-2d | **立即** | ✅ 已修复 |
| **P0** | C2 | 反思引擎传入空记忆 — 修复 reflect() 调用 | 1h | **立即** | ✅ 已修复 |
| **P0** | H5 | 更新/归档过时的 VERIFICATION_REPORT | 1h | **立即** | ✅ 已归档 |
| **P1** | H7 | Agent Store 适配 KernelClient 接口 | 1d | 本周 | ✅ 已修复 |
| **P1** | H8 | Hand 执行前检查 needs_approval | 4h | 本周 | ✅ 已修复 |
| **P1** | M1 | 注册 3 个幽灵命令或移除调用 | 2h | 本周 | ✅ 已修复 |
| **P1** | H1 | SpeechHand 标记为演示模式 | 2h | 本周 | ✅ 已标记 |
| **P1** | H2 | TwitterHand 标记为演示模式 | 2h | 本周 | ✅ 已标记 |
| **P1** | H3 | 统一记忆双存储路径 | 2-3d | 本周 | ✅ 已修复 |
| **P1** | H4 | 心跳引擎持久化 + 自动同步记忆统计 | 1-2d | 本周 | ✅ 已修复 |
| **P1** | P7 | Presentation 层缺失 Chart/Whiteboard 渲染器 | 2-3d | 本周 | ✅ 已修复 |
| **P2** | M4b | LLM 压缩器集成到 kernel AgentLoop | 1-2d | 下周 | ✅ 已修复 |
| **P2** | M4c | 实现压缩时的记忆刷出 | 1d | 下周 | ✅ 已修复 |
| **P2** | M4 | 反思结果持久化 + UI 展示 | 2d | 下周 | ✅ 已修复 |
| **P2** | M5 | 自主授权集成到执行链路 | 1-2d | 下周 | ✅ 已修复 |
| **P2** | M3 | hand_approve 使用 hand_name 参数 | 1h | 下周 | ✅ 已修复 |
| **P2** | L2 | 清理 gatewayStore 废弃引用 | 1h | 下周 | ✅ 已确认(仅注释) |
| **P2** | S9 | 消息搜索仅当前会话 — 新增 Global 模式 | 1d | 下周 | ✅ 已修复 |
| **P3** | M6 | 实现语义路由 | 2-3d | 下个迭代 |
| **P3** | L1 | Pipeline 并行执行 | 2d | 下个迭代 |
| **P3** | L3 | Wasm/Native 技能模式 | 3-5d | 长期 |
| **P3** | L4 | 清理死代码标注 | 4h | 长期 |
| **P3** | L5 | 处理 TODO 注释 | 1d | 长期 |
| **P3** | L6 | zclaw-channels 决策 | 评估后决定 | 长期 |
---
## 八、审计命令速查(已验证)
```bash
# Dead code 扫描(已验证 28 处)
rg '#\[allow\(dead_code\)\]' crates/ desktop/src-tauri/ -B 1 -A 3 --type rust
# TODO 扫描(已验证 5 处)
rg 'TODO|FIXME' crates/ desktop/src-tauri/ --type rust -n
# 模拟代码扫描(已确认 speech.rs + twitter.rs
rg 'simulated|In real implementation' crates/ desktop/src-tauri/ --type rust -n -i
# Tauri 命令交叉验证(已确认 3 个幽灵调用)
rg 'kernel_commands::|pipeline_commands::|viking_commands::|memory_commands::|intelligence::|browser::commands::|secure_storage::|memory::|llm::' desktop/src-tauri/src/lib.rs -o | sort -u
rg "invoke\(['\"]" desktop/src/ --type ts -o | sort -u
```
---
## 九、结论
ZCLAW 的核心架构通信、状态管理、安全认证、聊天、Agent 管理)是**坚实可靠的**。Rust 核心代码质量高,测试覆盖好,无 `todo!()``unimplemented!()` 宏。
主要问题集中在:
1. ~~**技能系统 PromptOnly 不调用 LLM**~~ ✅ 已修复 — 通过 LlmCompleter 桥接调用 LLM
2. ~~**反思引擎是空操作**~~ ✅ 已修复 — 传入真实记忆,结果持久化到 VikingStorage
3. ~~**Agent Store 接口不匹配**~~ ✅ 已修复 — KernelClient 添加适配方法
4. ~~**Hand 审批流程被绕过**~~ ✅ 已修复 — 执行前检查 needs_approval
5. ~~**2 个 Hand 是模拟实现**~~ ✅ 已标记 demo 标签
6. ~~**记忆系统双存储路径**~~ ✅ 已统一 — VikingStorage 元数据持久化
7. ~~**心跳引擎**无持久化~~ ✅ 已修复 — 交互时间戳 + 历史数组持久化
8. ~~**LLM 压缩器孤立**~~ ✅ 已修复 — runtime compaction 支持 LLM 摘要 + 记忆刷出
9. ~~**Presentation 层**渲染器缺失~~ ✅ 已修复 — Chart(recharts)、Document(react-markdown)、Slideshow 完整渲染
10. ~~**3 份审计报告**过时~~ ✅ 已归档
11. ~~**自主授权后端无守卫**~~ ✅ 已修复 — hand_execute/skill_execute 接收 autonomy_level 参数
12. ~~**hand_approve 忽略参数**~~ ✅ 已修复 — 使用 hand_name 审计日志
13. ~~**反思历史只存单条**~~ ✅ 已修复 — 累积存储到 reflection:history 数组
14. ~~**身份回滚 UI 缺失**~~ ✅ 已实现 — IdentityChangeProposal.tsx HistoryItem
15. **28 处 dead_code 标注**中大部分是合理的预留功能,少数是遗留代码
16. ~~**剩余 P2/P3 项**: 反思 LLM 分析、语义路由、Pipeline 并行等~~ ✅ 已修复 — 见下方 18-20
17. ~~**消息搜索仅当前会话**~~ ✅ 已修复 — MessageSearch 新增 Global 模式,调用 VikingStorage memory_search 跨会话搜索记忆
18. ~~**反思引擎规则升级为 LLM**~~ ✅ 已修复 — `analyze_patterns_with_llm()` 调用 LLM 做深度行为分析,失败回退规则
19. ~~**语义路由是桩代码**~~ ✅ 已修复 — `RuntimeLlmIntentDriver` 包装 LlmDriver 实现真实语义匹配
20. ~~**Pipeline 并行执行实际串行**~~ ✅ 已修复 — `execute_parallel()` 改用 `buffer_unordered(max_workers)` 真正并行
**累计修复 27 项** (P0×3 + P1×8 + P2×7 + P3×4 + 误判×2 + 审计×3),系统真实可用率从 ~50% 提升到 ~85%。
---
## 九、v5 审计追加修复2026-03-27
v5 审计独立验证了上述 27 项修复,确认 25 项完全到位、2 项部分到位,并新发现 8 项问题。以下为追加修复:
| # | 问题 | 修复方案 | 状态 |
|---|------|---------|------|
| 28 | WhiteboardHand Export 返回伪造 data_url | HAND.toml 添加 `demo = true` + 描述标注 | ✅ 已修复 |
| 29 | Director(907行) + A2A(690行) 孤立 | `#[cfg(feature = "multi-agent")]` 条件编译 + Cargo.toml feature 定义 | ✅ 已修复 |
| 30 | compactor_compact_llm 冗余 Tauri 命令 | 从 `generate_handler!` 移除注册 | ✅ 已修复 |
| 31 | hand_approve hand_name 仅用于日志 | 添加 hand_id 匹配验证 + hand_cancel 同步修复 | ✅ 已修复 |
| 32 | scheduled_task 调度循环未实现 | 更新文档注释标注 PLANNNED | ✅ 已修复 |
**v5 审计后累计修复 32 项**,系统真实可用率 ~85%。孤立代码通过条件编译控制,不影响默认编译。