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
Update audit tracker, roadmap, architecture docs, add admin-v2 Roles page + Billing tests, sync CLAUDE.md, Cargo.toml, docker-compose.yml, add deep-research / frontend-design / chart-visualization skills Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
297 lines
10 KiB
Markdown
297 lines
10 KiB
Markdown
# ZCLAW V11 差距分析报告
|
||
|
||
> **生成日期**: 2026-04-02
|
||
> **审计基线**: V10 AUDIT_TRACKER + V11 全面扫描
|
||
|
||
---
|
||
|
||
## 1. 五种差距模式总览
|
||
|
||
| 模式 | 数量 | 最高严重度 |
|
||
|------|------|-----------|
|
||
| 写了没接 | 8 项 | P3 |
|
||
| 接了没传 | 2 项 | **P1** |
|
||
| 传了没存 | 2 项 | P3 |
|
||
| 存了没用 | 3 项 | **P2** |
|
||
| 双系统不同步 | 5 项 | P3 |
|
||
|
||
---
|
||
|
||
## 2. 模式 1: "写了没接" (Wrote but Not Connected)
|
||
|
||
### 2.1 audit-logger.ts — 170 行完全孤立
|
||
|
||
**文件**: `desktop/src/lib/audit-logger.ts`
|
||
**严重度**: P3
|
||
|
||
完整的前端审计日志系统,包含 `FrontendAuditEntry` 类型、`AuditLogger` 类(log/logSuccess/logFailure/getLogs/clearLogs/exportLogs)、导出单例。
|
||
|
||
**验证**:
|
||
```bash
|
||
grep -rn "from.*audit-logger\|import.*audit-logger" desktop/src/ --include="*.ts" --include="*.tsx"
|
||
# 结果: 0 匹配
|
||
```
|
||
|
||
**影响**: 审计日志功能完全不可用,用户无法追溯操作历史。
|
||
|
||
**建议**:
|
||
- 方案 A: 在关键组件(ApprovalsPanel, AutonomyConfig, SecurityStore)中接入
|
||
- 方案 B: 如果当前不需要,标记为 `@internal reserved` 并从 barrel export 中移除
|
||
|
||
---
|
||
|
||
### 2.2 OFP 能力 — 类型定义无消费者
|
||
|
||
**文件**: `crates/zclaw-types/src/capability.rs:28-32`
|
||
**严重度**: P4
|
||
|
||
```rust
|
||
OfpDiscover,
|
||
OfpConnect { peer: String },
|
||
OfpAdvertise,
|
||
```
|
||
|
||
`Capability::grants()` 方法将这些变体匹配到 `_ => false`,意味着它们无法被授予或验证。
|
||
|
||
**建议**: 移除或添加 `// Reserved for OpenFang Protocol` 注释。
|
||
|
||
---
|
||
|
||
### 2.3 Director (multi-agent) — Feature-gated 912 行
|
||
|
||
**文件**: `crates/zclaw-kernel/src/director.rs`
|
||
**严重度**: P4 (保持 V10 DEAD-04)
|
||
|
||
22 个 `cfg(feature = "multi-agent")` 条目,完整的 Director 实现(5 种调度策略)。未在 Cargo.toml 中启用。
|
||
|
||
**建议**: 延后到产品路线图中多 Agent 功能启动时启用。
|
||
|
||
---
|
||
|
||
### 2.4 saas-admin.ts — 30 方法零消费者
|
||
|
||
**文件**: `desktop/src/lib/saas-admin.ts`
|
||
**严重度**: P2
|
||
|
||
30 个 Admin API 包装方法(providers/models/keys/accounts/tokens/roles/permissions),但:
|
||
- Desktop 前端不调用这些方法
|
||
- Admin-v2 有自己的 Axios service 层,不使用 saas-admin.ts
|
||
|
||
**文件头注释** (line 7-9):
|
||
> "Reserved for future admin UI (Next.js admin dashboard)."
|
||
|
||
**建议**: 删除整个文件,admin-v2 已有独立实现。避免维护两套代码。
|
||
|
||
---
|
||
|
||
### 2.5 Feature-gated 代码汇总
|
||
|
||
| 特性 | Crate | 代码量 | 状态 |
|
||
|------|-------|--------|------|
|
||
| multi-agent | zclaw-kernel | 22 cfg sites | 未启用 |
|
||
| a2a | zclaw-protocols | 2 cfg sites | 未启用 |
|
||
| wasm | zclaw-skills | 4 cfg sites | 未启用 |
|
||
|
||
---
|
||
|
||
### 2.6 62 个 Tauri 命令无前端调用
|
||
|
||
**分布**:
|
||
|
||
| 模块 | 未调用命令数 | 备注 |
|
||
|------|-------------|------|
|
||
| viking_commands | 11 | 完整 Viking 模块无 UI |
|
||
| pipeline_commands | 11 | 完整 Pipeline 模块无直接 invoke |
|
||
| gateway::commands | 11 | Gateway 连接管理 |
|
||
| classroom_commands | 7 (8 中仅 1 个被调用) | Classroom 功能 |
|
||
| LLM commands | 3 | llm_complete, embedding_create, embedding_providers |
|
||
| memory extractor | 2 | extract_session_memories, extract_and_store_memories |
|
||
| agent commands | 3 | export, import, agent_chat |
|
||
| kernel lifecycle | 2 | kernel_init, kernel_shutdown |
|
||
| 其他 | 12 | health, hand_run_cancel, scheduled_task 等 |
|
||
|
||
**注意**: pipeline 和 classroom 的 invoke 调用可能通过 store 或 client lib 间接调用,但 grep 未找到匹配。需手动验证。
|
||
|
||
---
|
||
|
||
## 3. 模式 2: "接了没传" (Connected but Not Passed)
|
||
|
||
### 3.1 trigger_update 参数嵌套问题 ⚠️ P1
|
||
|
||
**前端**: `desktop/src/lib/kernel-triggers.ts:99`
|
||
```typescript
|
||
return await invoke<TriggerItem>('trigger_update', { id, updates });
|
||
// updates = { name, enabled, handId, triggerType }
|
||
```
|
||
|
||
**Rust**: `desktop/src-tauri/src/kernel_commands/trigger.rs:183-189`
|
||
```rust
|
||
pub async fn trigger_update(
|
||
state: State<'_, KernelState>,
|
||
id: String,
|
||
name: Option<String>, // 期望扁平参数
|
||
enabled: Option<bool>,
|
||
hand_id: Option<String>,
|
||
) -> Result<TriggerResponse, String>
|
||
```
|
||
|
||
**问题**: 前端传递 `{ id, updates: { name, ... } }` 嵌套结构,但 Rust 期望 `{ id, name, enabled, hand_id }` 扁平参数。Tauri 的 serde 反序列化会忽略嵌套的 `updates` 对象,导致 name/enabled/hand_id 始终为 `None`。
|
||
|
||
**此外**: Rust 硬编码 `trigger_type: None`(trigger.rs:198),前端传递的 `triggerType` 永远被丢弃。
|
||
|
||
**影响**: Trigger 更新功能静默失败 — 用户修改 trigger 配置后不会生效。
|
||
|
||
**修复方案**: 前端改为扁平传递:
|
||
```typescript
|
||
await invoke('trigger_update', { id, name: updates.name, enabled: updates.enabled, handId: updates.handId });
|
||
```
|
||
|
||
---
|
||
|
||
### 3.2 hand_execute 参数名映射
|
||
|
||
**前端**: `desktop/src/lib/kernel-hands.ts:82`
|
||
```typescript
|
||
const result = await invoke('hand_execute', {
|
||
id: name, // 前端字段名 "id"
|
||
input: params || {},
|
||
...(autonomyLevel ? { autonomyLevel } : {}),
|
||
});
|
||
```
|
||
|
||
需验证 Rust 端是否接受 `id` 还是 `hand_name`。Tauri 自动做 camelCase ↔ snake_case 转换,但如果 Rust 使用 `name` 而前端使用 `id`,可能导致映射失败。
|
||
|
||
---
|
||
|
||
## 4. 模式 3: "传了没存" (Passed but Not Stored)
|
||
|
||
### 4.1 定时任务执行结果未持久化
|
||
|
||
**文件**: `crates/zclaw-saas/src/scheduler.rs:147-225`
|
||
|
||
`execute_scheduled_task` 执行任务后只更新 `last_run_at`、`next_run_at`、`run_count`,但不存储执行结果(成功/失败、输出、错误消息)。
|
||
|
||
`scheduled_tasks` 表 schema 缺少 `last_result`/`last_error` 列。
|
||
|
||
**影响**: 无法查看定时任务历史执行结果,无法诊断失败原因。
|
||
|
||
**建议**: 添加 `last_result TEXT` 和 `last_error TEXT` 列到 scheduled_tasks 表。
|
||
|
||
---
|
||
|
||
### 4.2 前端审计日志滞留 localStorage
|
||
|
||
`audit-logger.ts` 写入 localStorage,但无路径发送到后端或展示在 UI。数据在 `MAX_LOCAL_LOGS = 500` 条后循环覆盖。
|
||
|
||
---
|
||
|
||
## 5. 模式 4: "存了没用" (Stored but Not Used)
|
||
|
||
### 5.1 prompt_sync_status 表 — 零读取
|
||
|
||
**迁移**: `20260329000001_initial_schema.sql:244`
|
||
|
||
数据由 OTA 同步流程写入,但全代码库中无 `SELECT FROM prompt_sync_status`。
|
||
|
||
**可能原因**: OTA check 端点直接比较版本号而不查询此表。
|
||
|
||
**建议**: 移除死表,或实现读取路径。
|
||
|
||
---
|
||
|
||
### 5.2 telemetry_reports 表 — 零读取
|
||
|
||
**迁移**: `20260329000001_initial_schema.sql:305`
|
||
|
||
数据通过 telemetry 批量上报写入,但无查询路径。
|
||
|
||
**可能原因**: Admin dashboard 统计数据从 usage_records 聚合,不从此表读取。
|
||
|
||
**建议**: 实现读取端点供 admin-v2 telemetry 页面使用。
|
||
|
||
---
|
||
|
||
### 5.3 key_usage_window 表 — 零读取
|
||
|
||
**迁移**: `20260329000001_initial_schema.sql:274`
|
||
|
||
写入用于限流窗口追踪,但无 SELECT 查询。限流中间件可能使用内存中的 DashMap 而非数据库查询。
|
||
|
||
**建议**: 确认是否仍需要此表,或改用纯内存方案。
|
||
|
||
---
|
||
|
||
## 6. 模式 5: "双系统不同步" (Dual System Out of Sync)
|
||
|
||
### 6.1 Desktop ↔ Admin-v2 类型名称不一致(13+ 组)
|
||
|
||
| Admin-v2 名称 | Desktop 名称 | 实际差异 |
|
||
|---------------|-------------|----------|
|
||
| `AccountPublic` | `SaaSAccountInfo` | 命名 + llm_routing required/optional |
|
||
| `Provider` | `ProviderInfo` | 仅命名 |
|
||
| `Model` | `ModelInfo` | 仅命名 |
|
||
| `RelayTask` | `RelayTaskInfo` | 仅命名 |
|
||
| `ConfigItem` | `SaaSConfigItem` | 仅命名 |
|
||
| `OperationLog` | `OperationLogInfo` | 仅命名 |
|
||
| `PromptTemplate` | `PromptTemplateInfo` | 仅命名 |
|
||
| `PromptVersion` | `PromptVersionInfo` | 仅命名 |
|
||
| `AgentTemplate` | `AgentTemplateFull` | 命名 + 字段差异(admin 多 5 个字段) |
|
||
| `ApiError` | `SaaSErrorResponse` | 命名 + admin 多 status 字段 |
|
||
| `LoginResponse` | `SaaSLoginResponse` | 结构差异(cookie vs token) |
|
||
| `TokenInfo` | `TokenInfo` | nullability 差异 |
|
||
| `PaginatedResponse` | `PaginatedResponse` | **一致** |
|
||
|
||
### 6.2 有意义的字段差异
|
||
|
||
**AccountPublic.llm_routing**:
|
||
- Desktop: `llm_routing?: 'relay' | 'local'` (optional)
|
||
- Admin: `llm_routing: 'relay' | 'local'` (required)
|
||
|
||
**TokenInfo nullability**:
|
||
- Desktop: `last_used_at: string | null`, `expires_at: string | null`
|
||
- Admin: `last_used_at?: string`, `expires_at?: string`
|
||
|
||
**PromptVariable.type**:
|
||
- Desktop: `type: string`
|
||
- Admin: `type: 'string' | 'number' | 'select' | 'boolean'`
|
||
|
||
**AgentTemplate 字段差异**:
|
||
- Admin 额外: `visibility`, `status`, `current_version`, `version`, `capabilities`
|
||
- Desktop 缺少以上字段
|
||
|
||
### 6.3 文档数字不一致
|
||
|
||
| 指标 | 实际值 | 文档值 | 差异文件 |
|
||
|------|--------|--------|----------|
|
||
| Skills | 76 | 66/75/77 | SYSTEM_ARCHITECTURE.md, roadmap.md, troubleshooting.md |
|
||
| Hands | 9 目录 | 11 (CLAUDE.md) | CLAUDE.md 列出 11 个 Hand 配置 |
|
||
| Tauri 命令 | 175 | 58+ / 130+ | 06-tauri-backend/00-backend-integration.md |
|
||
| SaaS 路由 | 58 | 72+ | 08-saas-platform/00-saas-overview.md |
|
||
| Stores | 15 | 14 | 00-architecture/02-state-management.md |
|
||
|
||
---
|
||
|
||
## 7. Dead Code 完整清单
|
||
|
||
| 项 | 位置 | 行数 | 严重度 | 建议 |
|
||
|----|------|------|--------|------|
|
||
| audit-logger.ts | desktop/src/lib/ | 170 | P3 | 接入或删除 |
|
||
| saas-admin.ts | desktop/src/lib/ | 234 | P2 | 删除(admin-v2 已替代) |
|
||
| extract_structured_facts() | crates/zclaw-runtime/src/growth.rs:224 | ~30 | P4 | 删除 deprecated 方法 |
|
||
| secure-storage sync 方法 | desktop/src/lib/secure-storage.ts:309-325 | ~20 | P4 | 删除 |
|
||
| OFP 能力变体 | crates/zclaw-types/src/capability.rs:28-32 | 5 | P4 | 注释或移除 |
|
||
| Director feature-gated | crates/zclaw-kernel/src/director.rs | 912 | P4 | 保持,等路线图激活 |
|
||
| A2A feature-gated | crates/zclaw-protocols/src/a2a.rs | ~400 | P4 | 保持,等路线图激活 |
|
||
| WASM feature-gated | crates/zclaw-skills/src/wasm_runner.rs | ~200 | P4 | 保持,等路线图激活 |
|
||
|
||
---
|
||
|
||
## 8. Deprecated 代码状态
|
||
|
||
| 函数 | 位置 | 调用者 | 操作 |
|
||
|------|------|--------|------|
|
||
| `extract_structured_facts()` | growth.rs:224 | 0 | 删除 |
|
||
| `getStoredGatewayToken()` | gateway-storage.ts:129 | **3 活跃调用** | 先迁移调用者再删除 |
|
||
| `setStoredGatewayToken()` | gateway-storage.ts:196 | **1 活跃调用** | 先迁移调用者再删除 |
|
||
| `getSync()/setSync()/deleteSync()` | secure-storage.ts:309-325 | 0 | 删除 |
|