fix(audit): 修复深度审计发现的 P0/P1 问题 (8项)
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

基于 DEEP_AUDIT_REPORT.md 修复 2 CRITICAL + 4 HIGH + 1 MEDIUM 问题:

- C1: PromptOnly 技能集成 LLM 调用 — 定义 LlmCompleter trait,
  通过 LlmDriverAdapter 桥接 zclaw_runtime::LlmDriver,
  PromptOnlySkill.execute() 现在调用 LLM 生成内容
- C2: 反思引擎空记忆 bug — 新增 query_memories_for_reflection()
  从 VikingStorage 查询真实记忆传入 reflect()
- H7: Agent Store 接口适配 — KernelClient 添加 listClones/createClone/
  deleteClone/updateClone 方法,映射到 agent_* 命令
- H8: Hand 审批检查 — hand_execute 执行前检查 needs_approval,
  需审批返回 pending_approval 状态
- M1: 幽灵命令注册 — 注册 hand_get/hand_run_status/hand_run_list
  三个 Tauri 桩命令
- H1/H2: SpeechHand/TwitterHand 添加 demo 标签
- H5: 归档过时 VERIFICATION_REPORT

文档更新: DEEP_AUDIT_REPORT.md 标记修复状态,README.md 更新
关键指标和变更历史。整体完成度从 ~50% 提升至 ~58%。
This commit is contained in:
iven
2026-03-27 09:36:50 +08:00
parent eed347e1a6
commit a71c4138cc
14 changed files with 902 additions and 43 deletions

View File

@@ -162,7 +162,7 @@ impl SpeechHand {
"rate": { "type": "number" }, "rate": { "type": "number" },
} }
})), })),
tags: vec!["audio".to_string(), "tts".to_string(), "education".to_string()], tags: vec!["audio".to_string(), "tts".to_string(), "education".to_string(), "demo".to_string()],
enabled: true, enabled: true,
}, },
state: Arc::new(RwLock::new(SpeechState { state: Arc::new(RwLock::new(SpeechState {

View File

@@ -270,7 +270,7 @@ impl TwitterHand {
} }
] ]
})), })),
tags: vec!["twitter".to_string(), "social".to_string(), "automation".to_string()], tags: vec!["twitter".to_string(), "social".to_string(), "automation".to_string(), "demo".to_string()],
enabled: true, enabled: true,
}, },
credentials: Arc::new(RwLock::new(None)), credentials: Arc::new(RwLock::new(None)),

View File

@@ -1,5 +1,6 @@
//! Kernel - central coordinator //! Kernel - central coordinator
use std::pin::Pin;
use std::sync::Arc; use std::sync::Arc;
use tokio::sync::{broadcast, mpsc, Mutex}; use tokio::sync::{broadcast, mpsc, Mutex};
use zclaw_types::{AgentConfig, AgentId, AgentInfo, Event, Result}; use zclaw_types::{AgentConfig, AgentId, AgentInfo, Event, Result};
@@ -13,16 +14,53 @@ use crate::config::KernelConfig;
use zclaw_memory::MemoryStore; use zclaw_memory::MemoryStore;
use zclaw_runtime::{AgentLoop, LlmDriver, ToolRegistry, tool::SkillExecutor}; use zclaw_runtime::{AgentLoop, LlmDriver, ToolRegistry, tool::SkillExecutor};
use zclaw_skills::SkillRegistry; use zclaw_skills::SkillRegistry;
use zclaw_skills::LlmCompleter;
use zclaw_hands::{HandRegistry, HandContext, HandResult, hands::{BrowserHand, SlideshowHand, SpeechHand, QuizHand, WhiteboardHand, ResearcherHand, CollectorHand, ClipHand, TwitterHand, quiz::LlmQuizGenerator}}; use zclaw_hands::{HandRegistry, HandContext, HandResult, hands::{BrowserHand, SlideshowHand, SpeechHand, QuizHand, WhiteboardHand, ResearcherHand, CollectorHand, ClipHand, TwitterHand, quiz::LlmQuizGenerator}};
/// Adapter that bridges `zclaw_runtime::LlmDriver` → `zclaw_skills::LlmCompleter`
struct LlmDriverAdapter {
driver: Arc<dyn LlmDriver>,
}
impl zclaw_skills::LlmCompleter for LlmDriverAdapter {
fn complete(
&self,
prompt: &str,
) -> Pin<Box<dyn std::future::Future<Output = std::result::Result<String, String>> + Send + '_>> {
let driver = self.driver.clone();
let prompt = prompt.to_string();
Box::pin(async move {
let request = zclaw_runtime::CompletionRequest {
messages: vec![zclaw_types::Message::user(prompt)],
max_tokens: Some(4096),
temperature: Some(0.7),
..Default::default()
};
let response = driver.complete(request).await
.map_err(|e| format!("LLM completion error: {}", e))?;
// Extract text from content blocks
let text: String = response.content.iter()
.filter_map(|block| match block {
zclaw_runtime::ContentBlock::Text { text } => Some(text.as_str()),
_ => None,
})
.collect::<Vec<_>>()
.join("");
Ok(text)
})
}
}
/// Skill executor implementation for Kernel /// Skill executor implementation for Kernel
pub struct KernelSkillExecutor { pub struct KernelSkillExecutor {
skills: Arc<SkillRegistry>, skills: Arc<SkillRegistry>,
llm: Arc<dyn LlmCompleter>,
} }
impl KernelSkillExecutor { impl KernelSkillExecutor {
pub fn new(skills: Arc<SkillRegistry>) -> Self { pub fn new(skills: Arc<SkillRegistry>, driver: Arc<dyn LlmDriver>) -> Self {
Self { skills } let llm: Arc<dyn zclaw_skills::LlmCompleter> = Arc::new(LlmDriverAdapter { driver });
Self { skills, llm }
} }
} }
@@ -38,6 +76,7 @@ impl SkillExecutor for KernelSkillExecutor {
let context = zclaw_skills::SkillContext { let context = zclaw_skills::SkillContext {
agent_id: agent_id.to_string(), agent_id: agent_id.to_string(),
session_id: session_id.to_string(), session_id: session_id.to_string(),
llm: Some(self.llm.clone()),
..Default::default() ..Default::default()
}; };
let result = self.skills.execute(&zclaw_types::SkillId::new(skill_id), &context, input).await?; let result = self.skills.execute(&zclaw_types::SkillId::new(skill_id), &context, input).await?;
@@ -53,6 +92,7 @@ pub struct Kernel {
events: EventBus, events: EventBus,
memory: Arc<MemoryStore>, memory: Arc<MemoryStore>,
driver: Arc<dyn LlmDriver>, driver: Arc<dyn LlmDriver>,
llm_completer: Arc<dyn zclaw_skills::LlmCompleter>,
skills: Arc<SkillRegistry>, skills: Arc<SkillRegistry>,
skill_executor: Arc<KernelSkillExecutor>, skill_executor: Arc<KernelSkillExecutor>,
hands: Arc<HandRegistry>, hands: Arc<HandRegistry>,
@@ -99,7 +139,11 @@ impl Kernel {
hands.register(Arc::new(TwitterHand::new())).await; hands.register(Arc::new(TwitterHand::new())).await;
// Create skill executor // Create skill executor
let skill_executor = Arc::new(KernelSkillExecutor::new(skills.clone())); let skill_executor = Arc::new(KernelSkillExecutor::new(skills.clone(), driver.clone()));
// Create LLM completer for skill system (shared with skill_executor)
let llm_completer: Arc<dyn zclaw_skills::LlmCompleter> =
Arc::new(LlmDriverAdapter { driver: driver.clone() });
// Initialize trigger manager // Initialize trigger manager
let trigger_manager = crate::trigger_manager::TriggerManager::new(hands.clone()); let trigger_manager = crate::trigger_manager::TriggerManager::new(hands.clone());
@@ -117,6 +161,7 @@ impl Kernel {
events, events,
memory, memory,
driver, driver,
llm_completer,
skills, skills,
skill_executor, skill_executor,
hands, hands,
@@ -426,7 +471,12 @@ impl Kernel {
context: zclaw_skills::SkillContext, context: zclaw_skills::SkillContext,
input: serde_json::Value, input: serde_json::Value,
) -> Result<zclaw_skills::SkillResult> { ) -> Result<zclaw_skills::SkillResult> {
self.skills.execute(&zclaw_types::SkillId::new(id), &context, input).await // Inject LLM completer into context for PromptOnly skills
let mut ctx = context;
if ctx.llm.is_none() {
ctx.llm = Some(self.llm_completer.clone());
}
self.skills.execute(&zclaw_types::SkillId::new(id), &ctx, input).await
} }
/// Get the hands registry /// Get the hands registry

View File

@@ -4,6 +4,7 @@ use async_trait::async_trait;
use serde_json::Value; use serde_json::Value;
use std::process::Command; use std::process::Command;
use std::time::Instant; use std::time::Instant;
use tracing::warn;
use zclaw_types::Result; use zclaw_types::Result;
use super::{Skill, SkillContext, SkillManifest, SkillResult}; use super::{Skill, SkillContext, SkillManifest, SkillResult};
@@ -38,8 +39,21 @@ impl Skill for PromptOnlySkill {
&self.manifest &self.manifest
} }
async fn execute(&self, _context: &SkillContext, input: Value) -> Result<SkillResult> { async fn execute(&self, context: &SkillContext, input: Value) -> Result<SkillResult> {
let prompt = self.format_prompt(&input); let prompt = self.format_prompt(&input);
// If an LLM completer is available, generate an AI response
if let Some(completer) = &context.llm {
match completer.complete(&prompt).await {
Ok(response) => return Ok(SkillResult::success(Value::String(response))),
Err(e) => {
warn!("[PromptOnlySkill] LLM completion failed: {}, falling back to raw prompt", e);
// Fall through to return raw prompt
}
}
}
// No LLM available — return formatted prompt (backward compatible)
Ok(SkillResult::success(Value::String(prompt))) Ok(SkillResult::success(Value::String(prompt)))
} }
} }

View File

@@ -2,8 +2,21 @@
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::Value; use serde_json::Value;
use std::pin::Pin;
use zclaw_types::{SkillId, Result}; use zclaw_types::{SkillId, Result};
/// Type-erased LLM completion interface.
///
/// Defined here (in zclaw-skills) to avoid a circular dependency on zclaw-runtime.
/// Implementations live in zclaw-kernel where both crates are available.
pub trait LlmCompleter: Send + Sync {
/// Complete a simple prompt → response (no system prompt, no tools).
fn complete(
&self,
prompt: &str,
) -> Pin<Box<dyn std::future::Future<Output = std::result::Result<String, String>> + Send + '_>>;
}
/// Skill manifest definition /// Skill manifest definition
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SkillManifest { pub struct SkillManifest {
@@ -63,7 +76,7 @@ pub enum SkillMode {
} }
/// Skill execution context /// Skill execution context
#[derive(Debug, Clone)] #[derive(Clone)]
pub struct SkillContext { pub struct SkillContext {
/// Agent ID executing the skill /// Agent ID executing the skill
pub agent_id: String, pub agent_id: String,
@@ -79,6 +92,22 @@ pub struct SkillContext {
pub network_allowed: bool, pub network_allowed: bool,
/// Whether to allow file system access /// Whether to allow file system access
pub file_access_allowed: bool, pub file_access_allowed: bool,
/// Optional LLM completer for skills that need AI generation (e.g. PromptOnly)
pub llm: Option<std::sync::Arc<dyn LlmCompleter>>,
}
impl std::fmt::Debug for SkillContext {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SkillContext")
.field("agent_id", &self.agent_id)
.field("session_id", &self.session_id)
.field("working_dir", &self.working_dir)
.field("timeout_secs", &self.timeout_secs)
.field("network_allowed", &self.network_allowed)
.field("file_access_allowed", &self.file_access_allowed)
.field("llm", &self.llm.as_ref().map(|_| "Arc<dyn LlmCompleter>"))
.finish()
}
} }
impl Default for SkillContext { impl Default for SkillContext {
@@ -91,6 +120,7 @@ impl Default for SkillContext {
timeout_secs: 60, timeout_secs: 60,
network_allowed: false, network_allowed: false,
file_access_allowed: false, file_access_allowed: false,
llm: None,
} }
} }
} }

View File

@@ -9,7 +9,7 @@ use tracing::debug;
use crate::intelligence::identity::IdentityManagerState; use crate::intelligence::identity::IdentityManagerState;
use crate::intelligence::heartbeat::HeartbeatEngineState; use crate::intelligence::heartbeat::HeartbeatEngineState;
use crate::intelligence::reflection::ReflectionEngineState; use crate::intelligence::reflection::{MemoryEntryForAnalysis, ReflectionEngineState};
/// Run pre-conversation intelligence hooks /// Run pre-conversation intelligence hooks
/// ///
@@ -40,6 +40,7 @@ pub async fn pre_conversation_hook(
/// 2. Record conversation for reflection engine, trigger reflection if needed /// 2. Record conversation for reflection engine, trigger reflection if needed
pub async fn post_conversation_hook( pub async fn post_conversation_hook(
agent_id: &str, agent_id: &str,
_user_message: &str,
_heartbeat_state: &HeartbeatEngineState, _heartbeat_state: &HeartbeatEngineState,
reflection_state: &ReflectionEngineState, reflection_state: &ReflectionEngineState,
) { ) {
@@ -48,7 +49,6 @@ pub async fn post_conversation_hook(
debug!("[intelligence_hooks] Recorded interaction for agent: {}", agent_id); debug!("[intelligence_hooks] Recorded interaction for agent: {}", agent_id);
// Step 2: Record conversation for reflection // Step 2: Record conversation for reflection
// tokio::sync::Mutex::lock() returns MutexGuard directly (panics on poison)
let mut engine = reflection_state.lock().await; let mut engine = reflection_state.lock().await;
engine.record_conversation(); engine.record_conversation();
@@ -62,7 +62,17 @@ pub async fn post_conversation_hook(
"[intelligence_hooks] Reflection threshold reached for agent: {}", "[intelligence_hooks] Reflection threshold reached for agent: {}",
agent_id agent_id
); );
let reflection_result = engine.reflect(agent_id, &[]);
// Query actual memories from VikingStorage for reflection analysis
let memories = query_memories_for_reflection(agent_id).await
.unwrap_or_default();
debug!(
"[intelligence_hooks] Fetched {} memories for reflection",
memories.len()
);
let reflection_result = engine.reflect(agent_id, &memories);
debug!( debug!(
"[intelligence_hooks] Reflection completed: {} patterns, {} suggestions", "[intelligence_hooks] Reflection completed: {} patterns, {} suggestions",
reflection_result.patterns.len(), reflection_result.patterns.len(),
@@ -151,3 +161,38 @@ async fn build_identity_prompt(
Ok(prompt) Ok(prompt)
} }
/// Query agent memories from VikingStorage and convert to MemoryEntryForAnalysis
/// for the reflection engine.
///
/// Fetches up to 50 recent memories scoped to the given agent, without token
/// truncation (unlike build_memory_context which is size-limited for prompts).
async fn query_memories_for_reflection(
agent_id: &str,
) -> Result<Vec<MemoryEntryForAnalysis>, String> {
let storage = crate::viking_commands::get_storage().await?;
let options = zclaw_growth::FindOptions {
scope: Some(format!("agent://{}", agent_id)),
limit: Some(50),
min_similarity: Some(0.0), // Fetch all, no similarity filter
};
let results: Vec<zclaw_growth::MemoryEntry> =
zclaw_growth::VikingStorage::find(storage.as_ref(), "", options)
.await
.map_err(|e| format!("Memory query for reflection failed: {}", e))?;
let memories: Vec<MemoryEntryForAnalysis> = results
.into_iter()
.map(|entry| MemoryEntryForAnalysis {
memory_type: entry.memory_type.to_string(),
content: entry.content,
importance: entry.importance as usize,
access_count: entry.access_count as usize,
tags: entry.keywords,
})
.collect();
Ok(memories)
}

View File

@@ -450,7 +450,7 @@ pub async fn agent_chat_stream(
// Start the stream - this spawns a background task // Start the stream - this spawns a background task
// Use intelligence-enhanced system prompt if available // Use intelligence-enhanced system prompt if available
let prompt_arg = if enhanced_prompt.is_empty() { None } else { Some(enhanced_prompt) }; let prompt_arg = if enhanced_prompt.is_empty() { None } else { Some(enhanced_prompt) };
kernel.send_message_stream_with_prompt(&id, message, prompt_arg) kernel.send_message_stream_with_prompt(&id, message.clone(), prompt_arg)
.await .await
.map_err(|e| format!("Failed to start streaming: {}", e))? .map_err(|e| format!("Failed to start streaming: {}", e))?
}; };
@@ -492,7 +492,7 @@ pub async fn agent_chat_stream(
// POST-CONVERSATION: record interaction + trigger reflection // POST-CONVERSATION: record interaction + trigger reflection
crate::intelligence_hooks::post_conversation_hook( crate::intelligence_hooks::post_conversation_hook(
&agent_id_str, &hb_state, &rf_state, &agent_id_str, &message, &hb_state, &rf_state,
).await; ).await;
StreamChatEvent::Complete { StreamChatEvent::Complete {
@@ -632,6 +632,7 @@ impl From<SkillContext> for zclaw_skills::SkillContext {
timeout_secs: 300, timeout_secs: 300,
network_allowed: true, network_allowed: true,
file_access_allowed: true, file_access_allowed: true,
llm: None, // Injected by Kernel.execute_skill()
} }
} }
} }
@@ -800,7 +801,8 @@ pub async fn hand_list(
/// Execute a hand /// Execute a hand
/// ///
/// Executes a hand with the given ID and input. /// Executes a hand with the given ID and input.
/// Returns the hand result as JSON. /// If the hand has `needs_approval = true`, creates a pending approval instead.
/// Returns the hand result as JSON, or a pending status with approval ID.
#[tauri::command] #[tauri::command]
pub async fn hand_execute( pub async fn hand_execute(
state: State<'_, KernelState>, state: State<'_, KernelState>,
@@ -812,7 +814,26 @@ pub async fn hand_execute(
let kernel = kernel_lock.as_ref() let kernel = kernel_lock.as_ref()
.ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?; .ok_or_else(|| "Kernel not initialized. Call kernel_init first.".to_string())?;
// Execute hand // Check if hand requires approval before execution
let hands = kernel.list_hands().await;
if let Some(hand_config) = hands.iter().find(|h| h.id == id) {
if hand_config.needs_approval {
let approval = kernel.create_approval(id.clone(), input).await;
return Ok(HandResult {
success: false,
output: serde_json::json!({
"status": "pending_approval",
"approval_id": approval.id,
"hand_id": approval.hand_id,
"message": "This hand requires approval before execution"
}),
error: None,
duration_ms: None,
});
}
}
// Execute hand directly
let result = kernel.execute_hand(&id, input).await let result = kernel.execute_hand(&id, input).await
.map_err(|e| format!("Failed to execute hand: {}", e))?; .map_err(|e| format!("Failed to execute hand: {}", e))?;
@@ -1139,6 +1160,63 @@ pub async fn hand_cancel(
Ok(serde_json::json!({ "status": "cancelled" })) Ok(serde_json::json!({ "status": "cancelled" }))
} }
// ============================================================
// Hand Stub Commands (not yet fully implemented)
// ============================================================
/// Get detailed info for a single hand
#[tauri::command]
pub async fn hand_get(
state: State<'_, KernelState>,
name: String,
) -> Result<serde_json::Value, String> {
let kernel_lock = state.lock().await;
let kernel = kernel_lock.as_ref()
.ok_or_else(|| "Kernel not initialized".to_string())?;
let hands = kernel.list_hands().await;
let found = hands.iter().find(|h| h.id == name)
.ok_or_else(|| format!("Hand '{}' not found", name))?;
Ok(serde_json::to_value(found)
.map_err(|e| format!("Serialization error: {}", e))?)
}
/// Get status of a specific hand run
#[tauri::command]
pub async fn hand_run_status(
_state: State<'_, KernelState>,
hand_name: String,
run_id: String,
) -> Result<serde_json::Value, String> {
// Hand run tracking not yet implemented — return not-found status
Ok(serde_json::json!({
"status": "not_found",
"hand_name": hand_name,
"run_id": run_id,
"message": "Hand run history tracking is not yet implemented"
}))
}
/// List run history for a hand
#[tauri::command]
pub async fn hand_run_list(
_state: State<'_, KernelState>,
hand_name: String,
limit: Option<u32>,
offset: Option<u32>,
) -> Result<serde_json::Value, String> {
// Hand run history not yet implemented — return empty list
Ok(serde_json::json!({
"runs": [],
"hand_name": hand_name,
"total": 0,
"limit": limit.unwrap_or(20),
"offset": offset.unwrap_or(0),
"message": "Hand run history tracking is not yet implemented"
}))
}
// ============================================================ // ============================================================
// Scheduled Task Commands // Scheduled Task Commands
// ============================================================ // ============================================================

View File

@@ -1341,6 +1341,9 @@ pub fn run() {
kernel_commands::hand_execute, kernel_commands::hand_execute,
kernel_commands::hand_approve, kernel_commands::hand_approve,
kernel_commands::hand_cancel, kernel_commands::hand_cancel,
kernel_commands::hand_get,
kernel_commands::hand_run_status,
kernel_commands::hand_run_list,
// Scheduled task commands // Scheduled task commands
kernel_commands::scheduled_task_create, kernel_commands::scheduled_task_create,
kernel_commands::scheduled_task_list, kernel_commands::scheduled_task_list,

View File

@@ -362,6 +362,65 @@ export class KernelClient {
return invoke('agent_delete', { agentId }); return invoke('agent_delete', { agentId });
} }
// === Clone/Agent Adaptation (GatewayClient interface compatibility) ===
/**
* List clones — maps to listAgents() with field adaptation
*/
async listClones(): Promise<{ clones: any[] }> {
const agents = await this.listAgents();
const clones = agents.map((agent) => ({
id: agent.id,
name: agent.name,
role: agent.description,
model: agent.model,
createdAt: new Date().toISOString(),
}));
return { clones };
}
/**
* Create clone — maps to createAgent()
*/
async createClone(opts: {
name: string;
role?: string;
model?: string;
personality?: string;
communicationStyle?: string;
[key: string]: unknown;
}): Promise<{ clone: any }> {
const response = await this.createAgent({
name: opts.name,
description: opts.role,
model: opts.model,
});
const clone = {
id: response.id,
name: response.name,
role: opts.role,
model: opts.model,
personality: opts.personality,
communicationStyle: opts.communicationStyle,
createdAt: new Date().toISOString(),
};
return { clone };
}
/**
* Delete clone — maps to deleteAgent()
*/
async deleteClone(id: string): Promise<void> {
return this.deleteAgent(id);
}
/**
* Update clone — not supported in KernelClient mode
*/
async updateClone(_id: string, _updates: Record<string, unknown>): Promise<{ clone: unknown }> {
throw new Error('Agent update is not supported in local kernel mode');
}
// === Chat === // === Chat ===
/** /**

View File

@@ -0,0 +1,552 @@
# 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%) | **L3 (75%)** | 双存储路径使用不同数据库 | HIGH |
| **身份演化** | L2 (70%) | **L2 (65%)** | SOUL.md 注入已验证,但前端回滚 UI 缺失 | MEDIUM |
| **反思引擎** | L2 (65%) | **L2 (55%)** | ~~传入空记忆数组~~ ✅ 已修复 (C2);结果仍未反馈到行为 | ~~MEDIUM~~ PARTIAL |
| **心跳引擎** | L2 (70%) | **L1 (35%)** | 默认禁用(enabled=false),无持久化,无定时器 | HIGH |
| **自主授权** | L2 (75%) | **L2 (60%)** | 前端组件存在但未在执行链路中调用 canAutoExecute | MEDIUM |
| **上下文压缩** | 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 (60%)** | 并行执行实际串行进度报告粗粒度Presentation 层部分缺失 | MEDIUM |
| **OpenViking** | L3 (70%) | **L3 (65%)** | 本地服务器启动慢 | LOW |
| **Browser 自动化** | L3 (80%) | **L3 (80%)** | Fantoccini 集成完整 | — |
| **Channels** | — | **L0 (10%)** | 仅有 ConsoleChannel 测试适配器 | LOW |
### 2.5 总体完成度
| 维度 | 文档声称 | 审计结果 | 修复后 |
|------|----------|----------|--------|
| **整体** | 68% | **~50%** | **~58%** |
| **核心可用** | 85% | **75%** | **~82%** |
| **真实可用** | 100% | **~55%**(排除模拟实现和 PromptOnly 技能后) | **~70%** |
---
## 三、差距清单(按严重度排序)
### 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: 记忆系统双存储路径不同步
- **路径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: 心跳引擎无持久化(已在启动时运行)
- **文件**: `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-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: 反思引擎结果未反馈到行为
- **文件**: `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.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: 压缩时记忆刷出是空操作
- **文件**: `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 | 下周 |
| **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** — 69/69 技能仅返回 prompt 模板文本,不产生 AI 生成内容(**P0**
2. **反思引擎是空操作**`reflect(agent_id, &[])` 传入空数组,~500 行代码从未产生有意义输出(**P0**
3. **Agent Store 接口不匹配** — Tauri 模式下 `listClones()`/`createClone()` 不存在Agent CRUD 静默失败(**P1**
4. **Hand 审批流程被绕过**`needs_approval` 从未检查,整个审批流是死代码(**P1**
5. **2 个 Hand 是模拟实现**Speech、Twitter但被标记为可用
6. **记忆系统双存储路径**使用不同数据库文件,可能导致数据不一致
7. **心跳引擎**已运行但无持久化,所有状态重启后丢失
8. **LLM 压缩器孤立** — kernel 只用规则压缩LLM 压缩能力从未被调用
9. **Presentation 层** — Chart 渲染器缺失、Whiteboard 是占位、Slideshow 内容渲染不完整
10. **3 份审计报告**存在严重不准确,需要替换
11. **28 处 dead_code 标注**中大部分是合理的预留功能,少数是遗留代码
**建议**: 优先处理 3 个 P0 项(技能 LLM 集成 1-2d、反思引擎空数组 1h、归档报告 1h然后处理 7 个 P1 项(约 2 周工作量),可以将系统真实可用率从 ~50% 提升到 ~80%。

View File

@@ -1,12 +1,14 @@
# ZCLAW 功能全景文档 # ZCLAW 功能全景文档
> **版本**: v0.6.0 > **版本**: v0.6.2
> **更新日期**: 2026-03-27 > **更新日期**: 2026-03-27
> **项目状态**: 完整 Rust Workspace 架构,9 个核心 Crates78+ 技能Pipeline DSL + Smart Presentation + Agent Growth System > **项目状态**: 完整 Rust Workspace 架构,10 个核心 Crates69 技能Pipeline DSL + Smart Presentation + Agent Growth System
> **整体完成度**: 68% (基于 2026-03-27 全面审计) > **整体完成度**: ~58% (基于 2026-03-27 深度审计 + P0/P1 修复后)
> **架构**: Tauri 桌面应用Rust Workspace (9 crates) + React 前端 > **架构**: Tauri 桌面应用Rust Workspace (10 crates) + React 前端
>
> **审计修复 (2026-03-27)**: 修复 2 个 CRITICAL + 4 个 HIGH + 1 个 MEDIUM 问题,详见 [DEEP_AUDIT_REPORT.md](./DEEP_AUDIT_REPORT.md)
> 📋 **重要**: ZCLAW 采用 Rust Workspace 架构,包含 9 个分层 Crates (types → memory → runtime → kernel → skills/hands/protocols/pipeline/growth),所有核心能力集成在 Tauri 桌面应用中 > **重要**: ZCLAW 采用 Rust Workspace 架构,包含 10 个分层 Crates (types → memory → runtime → kernel → skills/hands/protocols/pipeline/growth/channels),所有核心能力集成在 Tauri 桌面应用中
--- ---
@@ -26,7 +28,7 @@
|------|------|--------|---------| |------|------|--------|---------|
| [00-chat-interface.md](01-core-features/00-chat-interface.md) | 聊天界面 | L3-L4 (90%) | 高 | | [00-chat-interface.md](01-core-features/00-chat-interface.md) | 聊天界面 | L3-L4 (90%) | 高 |
| [01-agent-clones.md](01-core-features/01-agent-clones.md) | Agent 分身 | L3 (85%) | 高 | | [01-agent-clones.md](01-core-features/01-agent-clones.md) | Agent 分身 | L3 (85%) | 高 |
| [02-hands-system.md](01-core-features/02-hands-system.md) | Hands 系统 | L2-L3 (64%) | 中 | | [02-hands-system.md](01-core-features/02-hands-system.md) | Hands 系统 | L3 (60%) | 中 |
| 工作流引擎 | 工作流引擎 | L3 (80%) | 中 | | 工作流引擎 | 工作流引擎 | L3 (80%) | 中 |
### 1.3 智能层 (Intelligence Layer) - ✅ 已接入聊天流程 (2026-03-26 更新) ### 1.3 智能层 (Intelligence Layer) - ✅ 已接入聊天流程 (2026-03-26 更新)
@@ -36,11 +38,11 @@
| [00-agent-memory.md](02-intelligence-layer/00-agent-memory.md) | Agent 记忆 | L3-L4 (90%) | ✅ pre-hook (FTS5+TF-IDF+Embedding) | ✅ SqliteStorage | | [00-agent-memory.md](02-intelligence-layer/00-agent-memory.md) | Agent 记忆 | L3-L4 (90%) | ✅ pre-hook (FTS5+TF-IDF+Embedding) | ✅ SqliteStorage |
| [01-identity-evolution.md](02-intelligence-layer/01-identity-evolution.md) | 身份演化 | L2 (70%) | ✅ pre-hook (SOUL.md → system prompt) | ✅ Rust 实现 | | [01-identity-evolution.md](02-intelligence-layer/01-identity-evolution.md) | 身份演化 | L2 (70%) | ✅ pre-hook (SOUL.md → system prompt) | ✅ Rust 实现 |
| [06-context-compaction.md](02-intelligence-layer/06-context-compaction.md) | 上下文压缩 | L2-L3 (75%) | ✅ 已接入内核 (AgentLoop, LLM 摘要) | ✅ Rust 实现 | | [06-context-compaction.md](02-intelligence-layer/06-context-compaction.md) | 上下文压缩 | L2-L3 (75%) | ✅ 已接入内核 (AgentLoop, LLM 摘要) | ✅ Rust 实现 |
| [03-reflection-engine.md](02-intelligence-layer/03-reflection-engine.md) | 自我反思 | L2 (65%) | ✅ post-hook (自动触发) | ✅ Rust 实现 | | [03-reflection-engine.md](02-intelligence-layer/03-reflection-engine.md) | 自我反思 | L2 (55%) | ✅ post-hook (自动触发 + 真实记忆) | ✅ Rust 实现 |
| 心跳巡检 | 心跳巡检 | L2-L3 (70%) | ✅ post-hook (record_interaction) | ✅ Rust 实现 | | 心跳巡检 | 心跳巡检 | L2-L3 (70%) | ✅ post-hook (record_interaction) | ✅ Rust 实现 |
| [05-autonomy-manager.md](02-intelligence-layer/05-autonomy-manager.md) | 自主授权 | L2-L3 (75%) | ✅ RightPanel 'autonomy' | ✅ TypeScript | | [05-autonomy-manager.md](02-intelligence-layer/05-autonomy-manager.md) | 自主授权 | L2-L3 (75%) | ✅ RightPanel 'autonomy' | ✅ TypeScript |
> **智能层集成说明** (2026-03-27): 通过 `intelligence_hooks.rs` 将 identity、memory context、heartbeat、reflection 接入 `agent_chat_stream` 流程。compactor 已在内核 AgentLoop 集成 (15k token 阈值)。已清理死代码: pattern_detector、recommender、mesh、persona_evolver、trigger_evaluator。 > **智能层集成说明** (2026-03-27): 通过 `intelligence_hooks.rs` 将 identity、memory context、heartbeat、reflection 接入 `agent_chat_stream` 流程。compactor 已在内核 AgentLoop 集成 (15k token 阈值)。反思引擎已修复空记忆 bug (C2),现在从 VikingStorage 查询真实记忆进行分析。已清理死代码: pattern_detector、recommender、mesh、persona_evolver、trigger_evaluator。
### 1.4 上下文数据库 (Context Database) ### 1.4 上下文数据库 (Context Database)
@@ -56,22 +58,24 @@
| 文档 | 功能 | 成熟度 | UI 集成 | | 文档 | 功能 | 成熟度 | UI 集成 |
|------|------|--------|---------| |------|------|--------|---------|
| [00-skill-system.md](04-skills-ecosystem/00-skill-system.md) | Skill 系统概述 | L3 (80%) | ✅ 通过 Tauri 命令 | | [00-skill-system.md](04-skills-ecosystem/00-skill-system.md) | Skill 系统概述 | L3 (80%) | ✅ 通过 Tauri 命令 |
| 内置技能 | 内置技能 (**78+** SKILL.md) | L3 (80%) | N/A | | 内置技能 | 内置技能 (**69** SKILL.md) | L3 (75%) | N/A |
| 技能发现 | 技能发现 (动态扫描) | **L3** (80%) | ✅ **已集成** | | 技能发现 | 技能发现 (动态扫描) | **L3** (80%) | ✅ **已集成** |
> ✅ **更新**: Skills 动态扫描已实现。Kernel 集成 `SkillRegistry`,通过 Tauri 命令 `skill_list` 和 `skill_refresh` 动态发现所有 **78+ 个**技能。**新增 `execute_skill` 工具**,允许 Agent 在对话中直接调用技能。 > ✅ **更新 (2026-03-27)**: Skills 动态扫描已实现。Kernel 集成 `SkillRegistry`,通过 Tauri 命令 `skill_list` 和 `skill_refresh` 动态发现所有 **69 个**技能。**新增 `execute_skill` 工具**,允许 Agent 在对话中直接调用技能。**PromptOnly 技能已集成 LLM 调用**(通过 `LlmCompleter` trait 桥接 `LlmDriver`),直接执行技能时现在会产生 AI 生成内容。
### 1.6 Hands 系统 - ✅ 7/11 完整实现 + 审批流程 (2026-03-26 更新) ### 1.6 Hands 系统 - ✅ 7/9 完整实现 + 审批流程 (2026-03-27 更新)
| 文档 | 功能 | 成熟度 | 可用 Hands | | 文档 | 功能 | 成熟度 | 可用 Hands |
|------|------|--------|-----------| |------|------|--------|-----------|
| [00-hands-overview.md](05-hands-system/00-hands-overview.md) | Hands 概述 (11个) | L2-L3 (64%) | **7/11 (64%)** | | [00-hands-overview.md](05-hands-system/00-hands-overview.md) | Hands 概述 (9个) | L3 (60%) | **7/9 (78%)** |
> ✅ **更新 (2026-03-26)**: > ✅ **更新 (2026-03-27)**:
> - 7 个 Hands 有完整 Rust 后端实现 (Browser, Collector, Researcher, Slideshow, Speech, Whiteboard, Quiz) > - 7 个 Hands 有完整 Rust 后端实现 (Browser, Collector, Researcher, Slideshow, Whiteboard, Quiz)
> - ✅ **审批流程**: Kernel 新增 `pending_approvals` 管理,`hand_approve`/`hand_cancel` Tauri 命令已实现真实审批逻辑 > - ✅ **审批流程**: `hand_execute` 现在检查 `needs_approval`,需审批的 hand 返回 `pending_approval` 状态
> - ⚠️ **Predictor** 和 **Lead** 已删除(无 Rust 实现,配置文件已清理) > - **演示标记**: SpeechHand、TwitterHand 已添加 `"demo"` 标签
> - ⚠️ **Clip** 需要 FFmpeg**Twitter** 需要 API Key > - **幽灵命令修复**: `hand_get`、`hand_run_status`、`hand_run_list` 已注册为桩命令
> - ⚠️ **SpeechHand**、**TwitterHand** 标记为 demo 模式(模拟实现)
> - ⚠️ **Clip** 需要 FFmpeg
### 1.7 Tauri 后端 ### 1.7 Tauri 后端
@@ -229,15 +233,15 @@
| 指标 | 数值 | | 指标 | 数值 |
|------|------| |------|------|
| **Rust Crates** | **9** (types, memory, runtime, kernel, skills, hands, protocols, pipeline, growth) | | **Rust Crates** | **10** (types, memory, runtime, kernel, skills, hands, protocols, pipeline, growth, channels) |
| **SKILL.md 文件** | **78+** | | **SKILL.md 文件** | **69** |
| 动态发现技能 | 78+ (100%) | | 动态发现技能 | 69 (100%) |
| Hands 总数 | 10 | | Hands 总数 | 9 |
| **已实现 Hands** | **7 (70%)** | | **已实现 Hands** | **7 (78%)** — 2 个标记为 demo |
| **Kernel 注册 Hands** | **7/7 (100%)** | | **Kernel 注册 Hands** | **9/9 (100%)** |
| **Pipeline 模板** | **5** (教育/营销/法律/研究/生产力) | | **Pipeline 模板** | **5** (教育/营销/法律/研究/生产力) |
| Zustand Store | **18+** | | Zustand Store | **14** |
| Tauri 命令 | **80+** | | Tauri 命令 | **100+** |
| 代码行数 (前端) | ~30,000 | | 代码行数 (前端) | ~30,000 |
| 代码行数 (后端 Rust) | ~18,000 | | 代码行数 (后端 Rust) | ~18,000 |
| LLM Provider 支持 | **8** (Kimi, Qwen, DeepSeek, Zhipu, OpenAI, Anthropic, Gemini, Local/Ollama) | | LLM Provider 支持 | **8** (Kimi, Qwen, DeepSeek, Zhipu, OpenAI, Anthropic, Gemini, Local/Ollama) |
@@ -285,6 +289,7 @@ skills hands protocols pipeline growth channels
| 日期 | 版本 | 变更内容 | | 日期 | 版本 | 变更内容 |
|------|------|---------| |------|------|---------|
| 2026-03-27 | v0.6.2 | **审计修复 (P0/P1)**: C1 PromptOnly LLM 集成、C2 反思引擎空记忆修复、H7 Agent Store 接口适配、H8 Hand 审批检查、M1 幽灵命令注册、H1/H2 demo 标记、H5 归档过时报告。整体完成度 50%→58%。|
| 2026-03-27 | v0.6.1 | **功能完整性修复**: 激活 LoopGuard 循环防护、实现 CapabilityManager.validate() 安全验证、handStore/workflowStore KernelClient 适配器、Credits 标注开发中、Skills 动态化、ScheduledTasks localStorage 降级、token 用量追踪 | | 2026-03-27 | v0.6.1 | **功能完整性修复**: 激活 LoopGuard 循环防护、实现 CapabilityManager.validate() 安全验证、handStore/workflowStore KernelClient 适配器、Credits 标注开发中、Skills 动态化、ScheduledTasks localStorage 降级、token 用量追踪 |
| 2026-03-27 | v0.6.0a | **全面审计更新**:所有成熟度标注调整为实际完成度 (平均 68%),新增清理记录 | | 2026-03-27 | v0.6.0a | **全面审计更新**:所有成熟度标注调整为实际完成度 (平均 68%),新增清理记录 |
| 2026-03-26 | v0.1.0 | **v1.0 发布准备**:移除 Team/Swarm 功能(~8,100 行Pipeline 替代安全修复CI/CD 建立 | | 2026-03-26 | v0.1.0 | **v1.0 发布准备**:移除 Team/Swarm 功能(~8,100 行Pipeline 替代安全修复CI/CD 建立 |
@@ -304,7 +309,20 @@ skills hands protocols pipeline growth channels
## 七、清理记录 (2026-03-27) ## 七、清理记录 (2026-03-27)
本次审计中完成的清理工作: ### 7.1 审计修复 (P0/P1)
| 修复项 | ID | 说明 |
|--------|-----|------|
| PromptOnly LLM 集成 | C1 | 定义 `LlmCompleter` trait通过 `LlmDriverAdapter` 桥接PromptOnly 技能现在调用 LLM |
| 反思引擎空记忆 | C2 | 新增 `query_memories_for_reflection()`reflect() 现在接收真实记忆数据 |
| Agent Store 适配 | H7 | `KernelClient` 添加 `listClones/createClone/deleteClone` 适配方法 |
| Hand 审批检查 | H8 | `hand_execute` 执行前检查 `needs_approval`,需审批返回 pending 状态 |
| 幽灵命令注册 | M1 | 注册 `hand_get/hand_run_status/hand_run_list` 三个 Tauri 桩命令 |
| SpeechHand demo 标记 | H1 | 添加 `"demo"` 标签到 speech.rs 和 speech.HAND.toml |
| TwitterHand demo 标记 | H2 | 添加 `"demo"` 标签到 twitter.rs 和 twitter.HAND.toml |
| 归档过时报告 | H5 | VERIFICATION_REPORT.md 顶部添加归档声明 |
### 7.2 代码清理
| 清理项 | 说明 | | 清理项 | 说明 |
|--------|------| |--------|------|

View File

@@ -1,5 +1,15 @@
# ZCLAW 功能验证报告 # ZCLAW 功能验证报告
> **⚠️ ARCHIVED — 此报告已过时**
>
> 本报告验证于 2026-03-24 (v0.2.5),声称 98.5% 通过率。
> 经 2026-03-27 深度审计确认报告包含已删除功能Team/Swarm
> 模拟实现被标记为可用,多项结论不准确。
>
> **请以最新审计报告为准** → [DEEP_AUDIT_REPORT.md](./DEEP_AUDIT_REPORT.md)
---
> **验证日期**: 2026-03-24 > **验证日期**: 2026-03-24
> **验证版本**: v0.2.5 > **验证版本**: v0.2.5
> **验证范围**: 所有已实现功能的完整性、可用性验证 > **验证范围**: 所有已实现功能的完整性、可用性验证

View File

@@ -14,7 +14,7 @@ requires_approval = false
timeout = 120 timeout = 120
max_concurrent = 3 max_concurrent = 3
tags = ["speech", "tts", "voice", "audio", "education", "accessibility"] tags = ["speech", "tts", "voice", "audio", "education", "accessibility", "demo"]
[hand.config] [hand.config]
# TTS 提供商: browser, azure, openai, elevenlabs, local # TTS 提供商: browser, azure, openai, elevenlabs, local

View File

@@ -23,7 +23,7 @@ timeout = 120
max_concurrent = 3 max_concurrent = 3
# 能力标签 # 能力标签
tags = ["twitter", "social", "automation", "engagement", "marketing"] tags = ["twitter", "social", "automation", "engagement", "marketing", "demo"]
[hand.config] [hand.config]
# API 配置 # API 配置