(null);
+
const connected = connectionState === 'connected';
const selectedClone = useMemo(
() => clones.find((clone) => clone.id === currentAgent?.id),
@@ -170,6 +180,46 @@ export function RightPanel() {
}
};
+ const loadSnapshots = useCallback(async () => {
+ const agentId = currentAgent?.id;
+ if (!agentId) return;
+ setSnapshotsLoading(true);
+ setSnapshotsError(null);
+ try {
+ const result = await intelligenceClient.identity.getSnapshots(agentId, 20);
+ setSnapshots(result);
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : String(err);
+ setSnapshotsError(`加载快照失败: ${msg}`);
+ } finally {
+ setSnapshotsLoading(false);
+ }
+ }, [currentAgent?.id]);
+
+ const handleRestoreSnapshot = useCallback(async (snapshotId: string) => {
+ const agentId = currentAgent?.id;
+ if (!agentId) return;
+ setRestoringSnapshotId(snapshotId);
+ setSnapshotsError(null);
+ setConfirmRestoreId(null);
+ try {
+ await intelligenceClient.identity.restoreSnapshot(agentId, snapshotId);
+ await loadSnapshots();
+ } catch (err) {
+ const msg = err instanceof Error ? err.message : String(err);
+ setSnapshotsError(`回滚失败: ${msg}`);
+ } finally {
+ setRestoringSnapshotId(null);
+ }
+ }, [currentAgent?.id, loadSnapshots]);
+
+ // Load snapshots when agent tab is active and agent changes
+ useEffect(() => {
+ if (activeTab === 'agent' && currentAgent?.id) {
+ loadSnapshots();
+ }
+ }, [activeTab, currentAgent?.id, loadSnapshots]);
+
const userMsgCount = messages.filter(m => m.role === 'user').length;
const assistantMsgCount = messages.filter(m => m.role === 'assistant').length;
const toolCallCount = messages.filter(m => m.role === 'tool').length;
@@ -479,6 +529,118 @@ export function RightPanel() {
)}
+
+ {/* 历史快照 */}
+
+
+
+ {snapshotsExpanded && (
+
+ {snapshotsError && (
+
+ )}
+
+ {snapshotsLoading ? (
+
+
+ 加载中...
+
+ ) : snapshots.length === 0 ? (
+
+ 暂无快照记录
+
+ ) : (
+ snapshots.map((snap) => {
+ const isRestoring = restoringSnapshotId === snap.id;
+ const isConfirming = confirmRestoreId === snap.id;
+ const timeLabel = formatSnapshotTime(snap.timestamp);
+
+ return (
+
+
+
+
+
+
+
{timeLabel}
+ {isConfirming ? (
+
+
+
+
+ ) : (
+
+ )}
+
+
+ {snap.reason || '自动快照'}
+
+
+
+ );
+ })
+ )}
+
+ )}
+
) : activeTab === 'files' ? (
@@ -791,3 +953,15 @@ function AgentToggle({
);
}
+
+function formatSnapshotTime(timestamp: string): string {
+ const now = Date.now();
+ const then = new Date(timestamp).getTime();
+ const diff = now - then;
+
+ if (diff < 60000) return '刚刚';
+ if (diff < 3600000) return `${Math.floor(diff / 60000)} 分钟前`;
+ if (diff < 86400000) return `${Math.floor(diff / 3600000)} 小时前`;
+ if (diff < 604800000) return `${Math.floor(diff / 86400000)} 天前`;
+ return new Date(timestamp).toLocaleDateString('zh-CN');
+}
diff --git a/desktop/src/components/VikingPanel.tsx b/desktop/src/components/VikingPanel.tsx
index 28811fa..2d663c1 100644
--- a/desktop/src/components/VikingPanel.tsx
+++ b/desktop/src/components/VikingPanel.tsx
@@ -12,12 +12,14 @@ import {
CheckCircle,
FileText,
Database,
+ Sparkles,
} from 'lucide-react';
import {
getVikingStatus,
findVikingResources,
listVikingResources,
readVikingResource,
+ storeWithSummaries,
} from '../lib/viking-client';
import type { VikingStatus, VikingFindResult } from '../lib/viking-client';
@@ -32,6 +34,9 @@ export function VikingPanel() {
const [expandedUri, setExpandedUri] = useState(null);
const [expandedContent, setExpandedContent] = useState(null);
const [isLoadingL2, setIsLoadingL2] = useState(false);
+ const [isGeneratingSummary, setIsGeneratingSummary] = useState(false);
+ const [summaryUri, setSummaryUri] = useState('');
+ const [summaryContent, setSummaryContent] = useState('');
const loadStatus = async () => {
setIsLoading(true);
@@ -292,6 +297,61 @@ export function VikingPanel() {
)}
+ {/* Summary Generation */}
+ {status?.available && (
+
+
智能摘要
+
+ 存储资源并自动通过 LLM 生成 L0/L1 多级摘要(需配置摘要驱动)
+
+
+ setSummaryUri(e.target.value)}
+ placeholder="资源 URI (如: notes/project-plan)"
+ className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-900 text-gray-900 dark:text-white text-sm focus:ring-2 focus:ring-blue-500 focus:border-transparent"
+ />
+
+
+ )}
+
{/* Info Section */}
关于语义记忆
diff --git a/desktop/src/lib/api-fallbacks.ts b/desktop/src/lib/api-fallbacks.ts
index c521aa5..174307f 100644
--- a/desktop/src/lib/api-fallbacks.ts
+++ b/desktop/src/lib/api-fallbacks.ts
@@ -69,6 +69,7 @@ export interface SecurityLayerFallback {
}
export interface SecurityStatusFallback {
+ _isFallback?: true;
layers: SecurityLayerFallback[];
enabledCount: number;
totalCount: number;
@@ -107,8 +108,10 @@ interface TriggerForTasks {
* Default quick config when /api/config/quick returns 404.
* Uses sensible defaults for a new user experience.
*/
-export function getQuickConfigFallback(): QuickConfigFallback {
+export function getQuickConfigFallback(): QuickConfigFallback & { _isFallback: true } {
+ console.warn('[fallback] 使用降级数据: getQuickConfigFallback');
return {
+ _isFallback: true as const,
agentName: '默认助手',
agentRole: 'AI 助手',
userName: '用户',
@@ -127,13 +130,15 @@ export function getQuickConfigFallback(): QuickConfigFallback {
* Default workspace info when /api/workspace returns 404.
* Returns a placeholder indicating workspace is not configured.
*/
-export function getWorkspaceInfoFallback(): WorkspaceInfoFallback {
+export function getWorkspaceInfoFallback(): WorkspaceInfoFallback & { _isFallback: true } {
+ console.warn('[fallback] 使用降级数据: getWorkspaceInfoFallback');
// Try to get a reasonable default path
const defaultPath = typeof window !== 'undefined'
? `${navigator.userAgent.includes('Windows') ? 'C:\\Users' : '/home'}/workspace`
: '/workspace';
return {
+ _isFallback: true as const,
path: defaultPath,
resolvedPath: defaultPath,
exists: false,
@@ -145,7 +150,8 @@ export function getWorkspaceInfoFallback(): WorkspaceInfoFallback {
/**
* Calculate usage stats from session data when /api/stats/usage returns 404.
*/
-export function getUsageStatsFallback(sessions: SessionForStats[] = []): UsageStatsFallback {
+export function getUsageStatsFallback(sessions: SessionForStats[] = []): UsageStatsFallback & { _isFallback: true } {
+ console.warn('[fallback] 使用降级数据: getUsageStatsFallback — 基于本地 session 数据计算');
const stats: UsageStatsFallback = {
totalSessions: sessions.length,
totalMessages: 0,
@@ -173,14 +179,15 @@ export function getUsageStatsFallback(sessions: SessionForStats[] = []): UsageSt
}
}
- return stats;
+ return { ...stats, _isFallback: true as const };
}
/**
* Convert skills to plugin status when /api/plugins/status returns 404.
* ZCLAW uses Skills instead of traditional plugins.
*/
-export function getPluginStatusFallback(skills: SkillForPlugins[] = []): PluginStatusFallback[] {
+export function getPluginStatusFallback(skills: SkillForPlugins[] = []): Array
{
+ console.warn('[fallback] 使用降级数据: getPluginStatusFallback — 从 Skills 列表推断');
if (skills.length === 0) {
// No skills loaded — return empty rather than fabricating fake builtins
return [];
@@ -197,7 +204,8 @@ export function getPluginStatusFallback(skills: SkillForPlugins[] = []): PluginS
/**
* Convert triggers to scheduled tasks when /api/scheduler/tasks returns 404.
*/
-export function getScheduledTasksFallback(triggers: TriggerForTasks[] = []): ScheduledTaskFallback[] {
+export function getScheduledTasksFallback(triggers: TriggerForTasks[] = []): Array {
+ console.warn('[fallback] 使用降级数据: getScheduledTasksFallback — 从 Triggers 列表推断');
return triggers
.filter((t) => t.enabled)
.map((trigger) => ({
@@ -214,7 +222,8 @@ export function getScheduledTasksFallback(triggers: TriggerForTasks[] = []): Sch
* Returns honest minimal response — only includes layers that correspond
* to real ZCLAW capabilities, no fabricated layers.
*/
-export function getSecurityStatusFallback(): SecurityStatusFallback {
+export function getSecurityStatusFallback(): SecurityStatusFallback & { _isFallback: true } {
+ console.warn('[fallback] 使用降级数据: getSecurityStatusFallback — 返回静态安全层状态');
const layers: SecurityLayerFallback[] = [
{ name: 'device_auth', enabled: true, description: '设备认证' },
{ name: 'rbac', enabled: true, description: '角色权限控制' },
@@ -228,6 +237,7 @@ export function getSecurityStatusFallback(): SecurityStatusFallback {
const securityLevel = calculateSecurityLevel(enabledCount, layers.length);
return {
+ _isFallback: true as const,
layers,
enabledCount,
totalCount: layers.length,
diff --git a/desktop/src/lib/viking-client.ts b/desktop/src/lib/viking-client.ts
index 96fd597..edbe098 100644
--- a/desktop/src/lib/viking-client.ts
+++ b/desktop/src/lib/viking-client.ts
@@ -65,13 +65,15 @@ export async function addVikingResource(
}
/**
- * Add a resource with inline content
+ * Add a resource with metadata (keywords + importance)
*/
-export async function addVikingResourceInline(
+export async function addVikingResourceWithMetadata(
uri: string,
- content: string
+ content: string,
+ keywords: string[],
+ importance?: number
): Promise {
- return invoke('viking_add_inline', { uri, content });
+ return invoke('viking_add_with_metadata', { uri, content, keywords, importance });
}
/**
@@ -136,41 +138,16 @@ export async function getVikingTree(
return invoke>('viking_tree', { path, depth });
}
-// === Server Functions ===
-
-export interface VikingServerStatus {
- running: boolean;
- port?: number;
- pid?: number;
- error?: string;
-}
+// === Summary Generation Functions ===
/**
- * Get Viking server status
+ * Store a resource and auto-generate L0/L1 summaries via configured LLM driver
*/
-export async function getVikingServerStatus(): Promise {
- return invoke('viking_server_status');
-}
-
-/**
- * Start Viking server
- */
-export async function startVikingServer(): Promise {
- return invoke('viking_server_start');
-}
-
-/**
- * Stop Viking server
- */
-export async function stopVikingServer(): Promise {
- return invoke('viking_server_stop');
-}
-
-/**
- * Restart Viking server
- */
-export async function restartVikingServer(): Promise {
- return invoke('viking_server_restart');
+export async function storeWithSummaries(
+ uri: string,
+ content: string
+): Promise {
+ return invoke('viking_store_with_summaries', { uri, content });
}
// === Memory Extraction Functions ===
diff --git a/docs/README.md b/docs/README.md
index d720f9f..65556d5 100644
--- a/docs/README.md
+++ b/docs/README.md
@@ -77,7 +77,7 @@ docs/
## Crate 架构
-ZCLAW 核心由 8 个 Rust Crate 组成:
+ZCLAW 核心由 10 个 Rust Crate 组成:
| Crate | 层级 | 职责 |
|-------|------|------|
@@ -85,9 +85,12 @@ ZCLAW 核心由 8 个 Rust Crate 组成:
| `zclaw-memory` | L2 | 存储层 (SQLite, 会话管理) |
| `zclaw-runtime` | L3 | 运行时 (LLM 驱动, 工具, Agent 循环) |
| `zclaw-kernel` | L4 | 核心协调 (注册, 调度, 事件, 工作流) |
-| `zclaw-skills` | - | 技能系统 (SKILL.md 解析, 执行器) |
-| `zclaw-hands` | - | 自主能力 (Hand/Trigger 注册管理) |
-| `zclaw-protocols` | - | 协议支持 (MCP, A2A) |
+| `zclaw-skills` | L5 | 技能系统 (SKILL.md 解析, 执行器) |
+| `zclaw-hands` | L5 | 自主能力 (Hand/Trigger 注册管理) |
+| `zclaw-protocols` | L5 | 协议支持 (MCP, A2A) |
+| `zclaw-pipeline` | L5 | Pipeline DSL (v1/v2, 模板) |
+| `zclaw-growth` | L5 | 记忆增长 (FTS5 + TF-IDF) |
+| `zclaw-saas` | 独立 | SaaS 后端 (Axum + PostgreSQL) |
### 依赖关系
@@ -100,7 +103,12 @@ zclaw-runtime (→ types, memory)
↑
zclaw-kernel (→ types, memory, runtime)
↑
-desktop/src-tauri (→ kernel, skills, hands, channels, protocols)
+┌───┴───┬───────┬───────────┬──────────┐
+│ │ │ │ │
+skills hands protocols pipeline growth
+
+desktop/src-tauri (→ kernel, skills, hands, protocols)
+zclaw-saas (独立运行于 8080 端口)
```
## 支持的 LLM 提供商
@@ -113,13 +121,17 @@ desktop/src-tauri (→ kernel, skills, hands, channels, protocols)
| zhipu | `https://open.bigmodel.cn/api/paas/v4` | 智谱 GLM |
| openai | `https://api.openai.com/v1` | OpenAI |
| anthropic | `https://api.anthropic.com` | Anthropic Claude |
+| gemini | `https://generativeai.googleapis.com/v1beta` | Google Gemini |
| local | `http://localhost:11434/v1` | Ollama/LMStudio |
## 项目状态
- **架构迁移**: Phase 5 完成 - 内部 Kernel 集成
- **Agent 智能层**: Phase 1-3 完成
-- **测试覆盖**: 161 E2E tests passing, 26 Rust tests passing
+- **Rust Crates**: 10 个 (171 Tauri 命令, 383 单元测试)
+- **SaaS 平台**: 131 API 路由, 12 模块, 34 数据表
+- **前端**: React 19 + Zustand 18 Stores, 135 组件
+- **安全审计**: V1 通过 (B+)
## 贡献指南
@@ -130,4 +142,4 @@ desktop/src-tauri (→ kernel, skills, hands, channels, protocols)
---
-**最后更新**: 2026-03-22
+**最后更新**: 2026-04-03
diff --git a/docs/TRUTH.md b/docs/TRUTH.md
index 5a5d1a1..cf6567e 100644
--- a/docs/TRUTH.md
+++ b/docs/TRUTH.md
@@ -1,7 +1,7 @@
# ZCLAW 系统真相文档
-> **更新日期**: 2026-04-02
-> **数据来源**: V11 全面审计 + 二次审计 + 代码全量扫描
+> **更新日期**: 2026-04-03
+> **数据来源**: V11 全面审计 + 二次审计 + 2026-04-03 代码全量扫描验证
> **规则**: 此文档是唯一真相源。所有其他文档如果与此冲突,以此为准。
---
@@ -12,18 +12,21 @@
|------|--------|----------|
| Rust Crates | 10 个 (编译通过) | `cargo check --workspace` |
| Rust 代码行数 | ~66,000 | wc -l |
-| Rust 单元测试 | 584 个 | `cargo test --workspace` |
+| Rust 单元测试 | 383 个 | `grep '#\[test\]' crates/` |
| Tauri 命令 | 171 个 | grep `#[tauri::command]` + 注释排除 |
| **Tauri 命令有前端调用** | **147 个** | @connected 标注(经二次审计修正) |
| **Tauri 命令无前端调用** | **24 个** | @reserved 标注 |
| SKILL.md 文件 | 75 个 | `ls skills/*.md \| wc -l` |
| Hands 启用 | 9 个 | Browser/Collector/Researcher/Clip/Twitter/Whiteboard/Slideshow/Speech/Quiz |
| Hands 禁用 | 2 个 | Predictor, Lead |
-| SaaS API 端点 | 93 个(含 2 个 dev-only mock) | 路由注册全量统计 |
+| SaaS API 端点 | 131 个(含 2 个 dev-only mock) | 路由注册 handler 引用全量统计 |
+| SaaS 路由模块 | 12 个 | account/agent_template/auth/billing/knowledge/migration/model_config/prompt/relay/role/scheduled_task/telemetry(scheduled_task: 后端 5 CRUD + Admin V2 前端 service/page/route/nav) |
+| SaaS 数据表 | 34 个(含 saas_schema_version) | CREATE TABLE 全量统计 |
+| SaaS Workers | 7 个 | log_operation/cleanup_rate_limit/cleanup_refresh_tokens/record_usage/update_last_used/aggregate_usage/generate_embedding |
| LLM Provider | 8 个 | Kimi/Qwen/DeepSeek/Zhipu/OpenAI/Anthropic/Gemini/Local |
| Zustand Store | 18 个 | ls desktop/src/store/ (含 chat/ 子目录) |
-| React 组件 | ~50 个 | ls desktop/src/components/ |
-| 前端 TypeScript 测试 | 21 个文件 | 8 单元 + 12 E2E spec + 1 源码内 |
+| React 组件 | ~135 个 | find desktop/src/components/ (*.tsx/*.ts) |
+| 前端 TypeScript 测试 | 23 个文件 | 1 单元 + 22 E2E spec |
| Admin V2 页面 | 13 个 | admin-v2/src/pages/ 全量统计 |
| Admin V2 测试 | 322 个 | vitest 统计 |
| 中间件层 | 11 层 | 运行时注册 |
@@ -63,22 +66,18 @@
| 功能 | Rust 状态 | 前端状态 |
|------|-----------|----------|
-| Pipeline 执行 | DSL 引擎完整 | 无 invoke 调用 |
-| Viking 适配 | FTS5 + TF-IDF | 11 个命令无前端调用 |
+| Pipeline 执行 | DSL 引擎完整 | **已接通前端** (8 个 invoke 调用匹配 8 个 Rust 命令,已确认可用) |
+| Viking 适配 | FTS5 + TF-IDF | 5 个孤立 invoke 已清理,新增 addWithMetadata/storeWithSummaries 方法 + UI |
| Classroom | 27 个命令 | 7 个命令无前端调用 |
| Browser Hand | 22 个命令 | 部分无前端调用 |
| Multi-agent Director | 912 行 (feature-gated) | 未启用 |
-### 2.4 前端孤立 invoke 调用(无 Rust 后端实现)
+### 2.4 前端孤立 invoke 调用(已清理)
-以下 5 个前端 `invoke()` 调用在 Rust 端无对应命令,运行时将返回 "command not found":
+Viking 5 个孤立 invoke 调用已于 2026-04-03 清理移除:
+- `viking_add_inline`, `viking_server_start`, `viking_server_status`, `viking_server_stop`, `viking_server_restart`
-| 命令 | 前端文件 | 说明 |
-|------|----------|------|
-| `viking_add_inline` | `viking-client.ts` | 无 Rust 实现,| `viking_server_start` | `viking-client.ts` | Viking 服务器生命周期管理未实现 |
-| `viking_server_status` | `viking-client.ts` | 同上 |
-| `viking_server_stop` | `viking-client.ts` | 同上 |
-| `viking_server_restart` | `viking-client.ts` | 同上 |
+当前无已知前端孤立 invoke 调用。
---
@@ -140,17 +139,33 @@
---
+## 4.5 近期前端改进 (2026-04-03)
+
+| 改进 | 说明 |
+|------|------|
+| Pipeline 前端接通 | 8 个前端 invoke 调用匹配 8 个 Rust 命令,完整可用 |
+| Viking 孤立调用清理 | 5 个无后端实现的 invoke 已移除 |
+| Viking 新方法 | `addWithMetadata`, `storeWithSummaries` 新增,含 UI |
+| api-fallbacks 标记 | `_isFallback` markers + `console.warn` logging |
+| MessageSearch 恢复 | ChatArea 头部搜索按钮,功能完整 |
+| scheduled_task Admin V2 | 后端 5 CRUD 端点完成,Admin V2 前端 service + page + route + nav 已添加 |
+
+---
+
## 5. 文档漂移记录
-以下文档中的数字已与实际不符,需要校准:
+以下文档中的数字已与实际不符,需要校准(2026-04-03 已全部修正):
-| 文档 | 过时内容 | 正确值 |
-|------|----------|--------|
-| CLAUDE.md (旧版) | "React 18" | React 19 |
-| CLAUDE.md (旧版) | "Tailwind CSS" | Tailwind 4 |
-| CLAUDE.md (旧版) | "Next.js (admin/)" | Vite + Ant Design Pro (admin-v2/) |
-| roadmap.md | Skills: 75 | 76 |
-| roadmap.md | Tauri 命令: 58+/130+ | 175 |
+| 文档 | 过时内容 | 正确值 | 状态 |
+|------|----------|--------|------|
+| CLAUDE.md (旧版) | "React 18" | React 19 | ✅ 已修正 |
+| CLAUDE.md (旧版) | "Tailwind CSS" | Tailwind 4 | ✅ 已修正 |
+| CLAUDE.md (旧版) | "Next.js (admin/)" | Vite + Ant Design Pro (admin-v2/) | ✅ 已修正 |
+| features/README.md | SaaS API: 58 | 131 | ✅ 已修正 |
+| features/README.md | Tauri 命令: 175 | 171 | ✅ 已修正 |
+| features/README.md | SaaS Workers: 5 | 7 | ✅ 已修正 |
+| features/README.md | SKILL: 76 | 75 | ✅ 已修正 |
+| docs/README.md | Crates: 8 | 10 | ✅ 已修正 |
---
@@ -164,3 +179,5 @@
| 2026-04-02 | 深度审计后修正:8 个 Tauri 标注误标、4 处 SaaS let _ = 清理、TRUTH.md 路由数 58→93 |
| 2026-04-02 | 二次深度审计:(1) 再修正 11 个 Tauri 标注 (147 connected / 24 reserved = 171) (2) 修正文档数字 SKILL 75/Stores 18/Admin 13 (3) relay extract_token_usage + current_key_id 防御性修复 (4) 记录 5 个前端孤立 invoke 调用 |
| 2026-04-02 | 构建验证通过:cargo check ✅ + tsc --noEmit ✅ |
+| 2026-04-03 | 数字全面验证校准:SaaS API 93→131 (新增 knowledge 23 + billing 10 + role 11 等模块增长)、Rust 测试 584→383、React 组件 ~50→~135、前端测试 21→23、SaaS Workers 5→7 (新增 aggregate_usage/generate_embedding)、SaaS 路由模块 10→12、数据表 25→34 |
+| 2026-04-03 | 前端改进记录:(1) Pipeline 8 invoke 接通前端 (2) Viking 5 孤立 invoke 清理 + 2 新方法+UI (3) api-fallbacks _isFallback 标记 + console.warn 日志 (4) MessageSearch 恢复到 ChatArea (5) scheduled_task Admin V2 完整接入 (service+page+route+nav) |
diff --git a/docs/superpowers/specs/2026-04-03-production-readiness-design.md b/docs/superpowers/specs/2026-04-03-production-readiness-design.md
new file mode 100644
index 0000000..78ca138
--- /dev/null
+++ b/docs/superpowers/specs/2026-04-03-production-readiness-design.md
@@ -0,0 +1,310 @@
+ ZCLAW 生产就绪收尾设计文档
+
+> **日期**: 2026-04-03
+> **状态**: 已批准
+> **预估总工时**: 12h(3 批次)
+> **策略**: 分层收敛 — 个人端优先、企业端跟进
+
+---
+
+## 1. 背景与动机
+
+ZCLAW 经过 3 周密集开发,已修复全部 P0/P1 缺陷,核心功能完成度 90-98%。功能全景审计发现:
+
+- **12 个前后端一致性问题**: 5 个孤立 invoke、Pipeline 文档过时、14 个 SaaS 端点无前端调用
+- **9 个功能缺失**: WASM/Native 执行未实现、Identity 回滚无 UI、MessageSearch 被禁用
+- **10 个可用性风险**: api-fallbacks 静默掩盖、MessageSearch 被禁用、Viking 孤立调用运行时崩溃
+- **7 处文档漂移**: SaaS API 数量差距最大(文档 58,实际 132)
+
+本设计旨在通过 3 个批次高效收尾,使 ZCLAW 达到产品级可用状态。
+
+---
+
+## 2. 关键决策
+
+| 决策 | 选择 | 理由 |
+|------|------|------|
+| 功能冻结状态 | 全面解冻 → 修复 → 再冻结 | P0/P1 已全部修复,审计发现的断链需要新增前端代码 |
+| 目标用户优先级 | 个人优先,企业跟进 | 桌面端核心体验(聊天、Pipeline、Hand、记忆)先保障 |
+| 未接入端点策略 | 分批处理 | 个人端断链先接通,企业端(Scheduled Task/Config)先标注 @reserved |
+| Viking 发展方向 | 优化现有原生实现 | 原生 SqliteStorage 优于外部 sidecar,删除孤立 invoke |
+| Pipeline 状态 | 验证而非重连 | 代码审计显示前后端已完全连接,可能是文档过时 |
+
+---
+
+## 3. 执行计划
+
+### Batch 1: 用户直接感知 (5h)
+
+**目标**: 修复个人端用户能直接感知的问题
+
+#### B1-1: Pipeline 端到端验证 (1h)
+
+**问题**: TRUTH.md 记录"Pipeline DSL 引擎完整但无前端 invoke 调用",但代码审计显示前端 `pipeline-client.ts` 有 8 个 invoke 调用(pipeline_list/get/run/progress/result/cancel/runs/refresh)、Rust 端 `discovery.rs` 有完整 `#[tauri::command]` 注册。
+
+**操作**:
+1. 启动 Tauri 开发环境,在 PipelinesPanel 中触发一个 education 模板
+2. 确认 `pipeline_list` → `pipeline_run` → `pipeline_progress` → `pipeline_result` 完整流程
+3. 如果不工作,排查断链点并修复
+4. 更新 TRUTH.md 中过时的 Pipeline 记录
+
+**关键文件**:
+- `desktop/src/components/PipelinesPanel.tsx` — 使用 `usePipelines()` hook
+- `desktop/src/lib/pipeline-client.ts` — 8 个 Tauri invoke 调用 (list/get/run/progress/result/cancel/runs/refresh)
+- `desktop/src-tauri/src/pipeline_commands/discovery.rs` — `#[tauri::command]` 注册
+- `docs/TRUTH.md` — 修正过时记录
+
+#### B1-2: MessageSearch 恢复 (1h)
+
+**问题**: DeerFlow 重设计期间 MessageSearch 被注释掉(ChatArea.tsx 第 21 行)。组件本身完整,支持 session 搜索和 global 记忆搜索。
+
+**操作**:
+1. 取消 `ChatArea.tsx` 第 21 行注释,恢复 MessageSearch 导入
+2. 在 DeerFlow 极简布局中找到合适的搜索入口位置(建议放在 TopBar 中)
+3. 确认 `intelligence-backend.ts` 的 `searchGlobalMemory()` 仍正常工作
+4. 验证 session 搜索和 global 搜索均可触发
+
+**关键文件**:
+- `desktop/src/components/ChatArea.tsx` — 第 21 行注释
+- `desktop/src/components/MessageSearch.tsx` — 完整的搜索组件
+- `desktop/src/lib/intelligence-backend.ts` — global 搜索后端
+
+#### B1-3: Viking 清理与优化 (2h)
+
+**问题**: 5 个前端 invoke 调用在 Rust 端无对应命令,运行时必然返回 "command not found"。2 个有 Rust 后端的命令(`viking_add_with_metadata`、`viking_store_with_summaries`)无前端调用。
+
+**操作**:
+1. 删除 `viking-client.ts` 中 5 个孤立方法:`viking_add_inline`、`viking_server_start/stop/status/restart`
+2. 删除相关的 `VikingServerStatus` 类型定义
+3. 在 `viking-client.ts` 中添加 `addWithMetadata()` 方法(调用已有的 `viking_add_with_metadata`)
+4. 在 `viking-client.ts` 中添加 `storeWithSummaries()` 方法(调用已有的 `viking_store_with_summaries`)
+5. 在 VikingPanel 中添加"生成摘要"按钮,调用 `storeWithSummaries()`
+6. 更新 TRUTH.md 中 Viking 命令的前端连接标注
+
+**关键文件**:
+- `desktop/src/lib/viking-client.ts` — 删除 5 个孤立方法,添加 2 个新方法
+- `desktop/src/components/VikingPanel.tsx` — 添加摘要生成触发
+- `desktop/src-tauri/src/viking_commands.rs` — 已有 Rust 命令,无需修改
+- `docs/features/03-context-database/00-openviking-integration.md` — 更新架构描述
+
+#### B1-4: api-fallbacks 透明化 (1h)
+
+**问题**: `api-fallbacks.ts` 在后端返回 404 时静默返回假数据,用户无法区分真实功能和降级。
+
+**操作**:
+1. 每个 fallback 函数返回数据中添加 `_isFallback: true` 标记
+2. 添加 `console.warn('[fallback] 使用降级数据: <函数名>')` 日志
+3. 在消费 fallback 数据的 Store 中检测标记,设置 `isDegraded: true` 状态
+4. UI 组件根据 `isDegraded` 显示黄色提示条"该功能需要连接后端服务"
+
+**关键文件**:
+- `desktop/src/lib/api-fallbacks.ts` — 添加标记和日志
+- `desktop/src/store/configStore.ts` — 检测降级状态
+- `desktop/src/store/handStore.ts` — 检测降级状态
+- 相关 UI 组件 — 显示降级提示
+
+---
+
+### Batch 2: 系统健康 (4h)
+
+**目标**: 校准文档真相源,标注企业端断链
+
+#### B2-1: 文档漂移校准 (1.5h)
+
+**问题**: 7 处文档数字与实际代码不符。
+
+**操作**:
+更新以下文档中的过时数字:
+
+| 文档 | 过时值 | 正确值 |
+|------|--------|--------|
+| `docs/features/README.md` | SaaS API: 58 | 132 |
+| `docs/features/README.md` | Zustand Store: 15 | 18 |
+| `docs/features/README.md` | SQL Schema: v6 | v8 |
+| `docs/features/README.md` | Admin 页面: 11 | 13 |
+| `docs/README.md` | 8 Rust Crates | 10 |
+| `docs/features/roadmap.md` | Tauri 命令: 175 | 171 (TRUTH) |
+| `docs/TRUTH.md` | SaaS API: 93 | 132 (含 Knowledge Base 模块 23 个新端点: category CRUD + item CRUD + search + recommend + analytics 5 端点 + 版本管理) |
+
+同步更新 `docs/features/README.md` 中所有模块的成熟度评估。
+
+**关键文件**:
+- `docs/TRUTH.md`
+- `docs/features/README.md`
+- `docs/features/roadmap.md`
+- `docs/README.md`
+
+#### B2-2: 无前端端点标注 (0.5h)
+
+**问题**: 14 个 SaaS 端点无前端调用,但代码中无任何标注。
+
+**操作**:
+在以下 handler 函数上添加 `// @reserved - no frontend caller` 注释:
+
+| 端点 | 模块 |
+|------|------|
+| `POST /api/v1/config/items` | migration |
+| `GET /api/v1/config/items/:id` | migration |
+| `DELETE /api/v1/config/items/:id` | migration |
+| `GET /api/v1/config/analysis` | migration |
+| `POST /api/v1/config/seed` | migration |
+| `GET /api/v1/config/sync-logs` | migration |
+| `POST /api/v1/keys/:id/rotate` | model_config |
+| `GET /api/v1/knowledge/items/:id/versions/:v` | knowledge |
+| `GET /api/scheduler/tasks` | scheduled_task |
+| `POST /api/scheduler/tasks` | scheduled_task |
+| `GET /api/scheduler/tasks/:id` | scheduled_task |
+| `PATCH /api/scheduler/tasks/:id` | scheduled_task |
+| `DELETE /api/scheduler/tasks/:id` | scheduled_task |
+
+**关键文件**:
+- `crates/zclaw-saas/src/migration/handlers.rs`
+- `crates/zclaw-saas/src/model_config/handlers.rs`
+- `crates/zclaw-saas/src/knowledge/handlers.rs`
+- `crates/zclaw-saas/src/scheduled_task/handlers.rs`
+
+#### B2-3: Scheduled Task Admin UI (1.5h)
+
+**问题**: Scheduled Task 后端 5 个 CRUD 端点完整,但桌面端和 Admin 端均无 UI。
+
+**操作**:
+1. 在 `admin-v2/src/services/` 添加 `scheduled-tasks.ts` 服务文件
+2. 在 `admin-v2/src/pages/` 添加 ScheduledTasks 页面(列表+创建/编辑/删除)
+3. 在 `admin-v2/src/router/index.tsx` 添加路由
+4. 在 `admin-v2/src/layouts/AdminLayout.tsx` 侧边栏添加导航入口
+5. 复用 Admin 现有的 Ant Design Pro 组件模式
+
+**关键文件**:
+- `admin-v2/src/services/scheduled-tasks.ts` — 新建
+- `admin-v2/src/pages/ScheduledTasks.tsx` — 新建
+- `admin-v2/src/router/index.tsx` — 添加路由
+- `admin-v2/src/layouts/AdminLayout.tsx` — 添加侧边栏导航
+
+#### B2-4: TRUTH.md Pipeline 记录修正 (0.5h)
+
+**问题**: TRUTH.md 记录"Pipeline 无前端 invoke 调用",但代码审计显示已完全连接。
+
+**操作**:
+1. 将 Pipeline 从"已实现但未接通前端"移到"确认可用"列表
+2. 添加 Pipeline 验证结果记录
+
+**关键文件**:
+- `docs/TRUTH.md`
+
+---
+
+### Batch 3: 长期质量 (3h)
+
+**目标**: 验证功能性缺陷,清理 P2 代码质量问题
+
+#### B3-1: hand_run_status 端到端验证 (0.5h)
+
+**问题**: TRUTH.md 和审计报告记录 `hand_run_status` 和 `hand_run_list` 为 stub 命令,但代码审计显示它们已在 `desktop/src-tauri/src/kernel_commands/hand.rs`(第 358-416 行)完整实现,前端 `desktop/src/lib/kernel-hands.ts`(第 105-153 行)已有 invoke 调用。与 Pipeline 情况类似,可能需要的是验证而非实现。
+
+**操作**:
+1. 验证 hand_run_status/hand_run_list 的端到端流程
+2. 如果工作正常,更新 TRUTH.md 修正过时记录
+3. 如果有问题,修复断链
+
+**关键文件**:
+- `desktop/src-tauri/src/kernel_commands/hand.rs` — 已有完整实现(第 358-416 行)
+- `desktop/src/lib/kernel-hands.ts` — 已有 invoke 调用(第 105-153 行)
+- `docs/TRUTH.md` — 修正过时记录
+
+#### B3-2: Identity 快照回滚 UI (1h)
+
+**问题**: `identity_get_snapshots` 和 `identity_restore_snapshot` API 存在,但前端无回滚入口。
+
+**操作**:
+1. 在 RightPanel 的 identity tab 中添加"历史快照"区域
+2. 调用 `identityClient.getSnapshots(agentId)` 显示快照列表
+3. 每个快照显示时间戳和变更摘要
+4. 添加"回滚到此版本"按钮,调用 `identityClient.restoreSnapshot(agentId, snapshotId)`
+
+**关键文件**:
+- `desktop/src/components/RightPanel.tsx` — 添加快照区域
+- `desktop/src/lib/intelligence-client/` — 已有 identity 方法
+
+#### B3-3: P2 代码质量清理 (1h)
+
+**问题**: TRUTH.md 记录 10 个 P2 代码质量问题。
+
+**操作**:
+根据 TRUTH.md 中的 SEC2-P2-01~10 清单,逐项修复。具体项目需在执行时确认。
+
+#### B3-4: Config HTTP 方法对齐 (0.5h)
+
+**问题**: Admin `config.ts` 使用 PATCH 更新,SaaS 后端定义 PUT。
+
+**操作**:
+1. 确认 SaaS 后端是否同时支持 PUT 和 PATCH
+2. 如果只支持 PUT,更新 Admin 服务文件使用 PUT
+3. 如果同时支持,无需修改
+
+**关键文件**:
+- `admin-v2/src/services/config.ts`
+
+---
+
+## 4. 验证方案
+
+### Batch 1 完成标准
+
+- [ ] Pipeline: 能在 UI 中成功执行一个模板
+- [ ] MessageSearch: 在聊天界面能搜索消息(session + global)
+- [ ] Viking: VikingPanel 不再触发 "command not found",摘要生成可触发
+- [ ] api-fallbacks: 降级数据有明确提示
+
+### Batch 2 完成标准
+
+- [ ] 文档: TRUTH.md 和 README.md 数字与代码一致
+- [ ] 端点标注: 14 个无前端端点有 @reserved 注释
+- [ ] Scheduled Task: Admin 中能创建/查看/删除定时任务
+
+### Batch 3 完成标准
+
+- [ ] hand_run_status: 端到端验证通过,返回真实执行状态数据
+- [ ] Identity: 能查看历史快照并执行回滚
+- [ ] P2: 10 个代码质量问题已处理
+- [ ] Config: Admin 和 SaaS HTTP 方法一致
+
+### 自动化验证
+
+```bash
+# TypeScript 编译
+cd desktop && pnpm tsc --noEmit
+
+# Rust 编译
+cargo check --workspace
+
+# 单元测试
+cargo test --workspace
+pnpm vitest run
+cd ../admin-v2 && pnpm vitest run
+```
+
+---
+
+## 5. 风险评估
+
+| 风险 | 概率 | 影响 | 缓解 |
+|------|------|------|------|
+| Pipeline 实际有隐藏断链 | 中 | B1-1 时间翻倍 | 先验证再修复 |
+| DeerFlow 布局不适配 MessageSearch | 低 | 需调整 CSS | 复用现有搜索 UI |
+| Viking 摘要生成需要 LLM 配置 | 中 | 用户需先配置模型 | 显示配置引导 |
+| Scheduled Task Admin 页面超出预估 | 低 | 复用 Ant Design 模板 | 控制复杂度 |
+| P2 清理发现新问题 | 中 | 时间增加 | 按优先级截断 |
+
+---
+
+## 6. 不在本设计范围内
+
+以下功能明确**不在**本次收尾范围内:
+
+- WASM/Native Skill 执行模式(中期计划 M1)
+- 智能路由 Phase 3 多技能编排
+- Active Learning Phase 2 SQLite+向量化
+- Predictor/Lead Hands 实现
+- A2A 协议完整实现
+- Agent 持久化优化
+- 云同步服务