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
H3: 重写 memory_commands.rs 统一到 VikingStorage 单一存储,移除双写 H4: 心跳引擎 record_interaction() 持久化到 VikingStorage,启动时恢复 M4: 反思结果/状态持久化到 VikingStorage metadata,重启后自动恢复 - HandApprovalModal import 修正 (handStore 替代 gatewayStore) - kernel-client.ts 幽灵调用替换为 kernel_status - PersistentMemoryStore dead_code warnings 清理 - 审计报告和 README 更新至 v0.6.3,完成度 58%→62%
33 KiB
33 KiB
ZCLAW 功能完成度深度审计报告
审计日期: 2026-03-27 修复轮次: 2026-03-27(P0/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+ | 14(gatewayStore 已废弃) | -4 |
| SKILL.md 文件数量 | 78+ | 69 | -9 |
| HAND.toml 文件数量 | 11 | 9(predictor/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%) | ||
| Hands 系统 | L4 (70%) | L3 (60%) |
2.3 智能层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|---|---|---|---|---|
| Agent 记忆 | L4 (90%) | L4 (85%) | ||
| 身份演化 | L2 (70%) | L2 (65%) | SOUL.md 注入已验证,但前端回滚 UI 缺失 | MEDIUM |
| 反思引擎 | L2 (65%) | L2 (60%) | ||
| 心跳引擎 | L2 (70%) | L1 (40%) | ||
| 自主授权 | L2 (75%) | L2 (60%) | 前端组件存在但未在执行链路中调用 canAutoExecute | MEDIUM |
| 上下文压缩 | L2 (75%) | L2 (70%) | 规则压缩已集成,LLM 压缩存在但默认关闭 | LOW |
2.4 扩展层
| 功能 | 文档声称 | 真实完成度 | 差距模式 | 严重度 |
|---|---|---|---|---|
| 技能系统 | L3 (80%) | L3 (75%) | ||
| 智能路由 | L1 (15%) | L1 (10%) | 语义匹配是桩代码(返回 None),从未实例化 | MEDIUM |
| Pipeline DSL | L2 (75%) | L2 (60%) | 并行执行实际串行,进度报告粗粒度,Presentation 层部分缺失 | MEDIUM |
| OpenViking | L3 (70%) | L3 (65%) | 本地服务器启动慢 | LOW |
| Browser 自动化 | L3 (80%) | L3 (80%) | Fantoccini 集成完整 | — |
| Channels | — | L0 (10%) | 仅有 ConsoleChannel 测试适配器 | LOW |
2.5 总体完成度
| 维度 | 文档声称 | 审计结果 | 修复后 |
|---|---|---|---|
| 整体 | 68% | ~50% | ~62% |
| 核心可用 | 85% | 75% | ~85% |
| 真实可用 | 100% | ~55%(排除模拟实现和 PromptOnly 技能后) | ~72% |
三、差距清单(按严重度排序)
3.1 CRITICAL 严重度(2 项)
C1: 技能系统 PromptOnly 模式不调用 LLM,69/69 技能仅返回 prompt 模板 ✅ 已修复
- 文件:
crates/zclaw-skills/src/runner.rs:41-44 - 修复方案: 定义
LlmCompletertrait(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_skillTauri 命令直接返回 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 metadata(key: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 层部分渲染器缺失
- 文件:
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-markdown),Document 替换手写解析器
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 只用规则压缩
- 文件:
desktop/src-tauri/src/intelligence/compactor.rsvscrates/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: 压缩时记忆刷出是空操作
- 文件:
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.rsbuild_staged_runtime_legacy、HealthStatus — 遗留代码intent.rsDefaultLlmIntentDriver — 桩代码persistent.rstags 字段 — 预留browser/session.rssession_count — 预留
- 建议: 遗留代码(lib.rs legacy)可删除,其余保留
L5: 5 个 TODO 注释
registry.rs:56— message_count trackingorchestration.rs:41— graph storagepipeline_commands.rs:442— use actual timepipeline_commands.rs:781— pattern supporthtml.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 AgentLoop(compaction threshold 15k)✅
→ LLM driver(4个实现: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: 双存储路径如何统一?
架构视角:
- PersistentMemoryStore(sqlx 直连)和 VikingStorage/zclaw-growth(trait 抽象)本质上是同一个功能的两套实现
- 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 | 下周 | |
| 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 决策 | 评估后决定 | 长期 |
八、审计命令速查(已验证)
# 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!() 宏。
主要问题集中在:
- 技能系统 PromptOnly 不调用 LLM — 69/69 技能仅返回 prompt 模板文本,不产生 AI 生成内容(P0)
- 反思引擎是空操作 —
reflect(agent_id, &[])传入空数组,~500 行代码从未产生有意义输出(P0) - Agent Store 接口不匹配 — Tauri 模式下
listClones()/createClone()不存在,Agent CRUD 静默失败(P1) - Hand 审批流程被绕过 —
needs_approval从未检查,整个审批流是死代码(P1) - 2 个 Hand 是模拟实现(Speech、Twitter),但被标记为可用
- 记忆系统双存储路径使用不同数据库文件,可能导致数据不一致
- 心跳引擎已运行但无持久化,所有状态重启后丢失
- LLM 压缩器孤立 — kernel 只用规则压缩,LLM 压缩能力从未被调用
- Presentation 层 — Chart 渲染器缺失、Whiteboard 是占位、Slideshow 内容渲染不完整
- 3 份审计报告存在严重不准确,需要替换
- 28 处 dead_code 标注中大部分是合理的预留功能,少数是遗留代码
建议: 优先处理 3 个 P0 项(技能 LLM 集成 1-2d、反思引擎空数组 1h、归档报告 1h),然后处理 7 个 P1 项(约 2 周工作量),可以将系统真实可用率从 ~50% 提升到 ~80%。