68 KiB
ZCLAW 上线前功能审计 — 测试执行计划
For agentic workers: REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: 系统性验证 ZCLAW 全部 12 个功能模块(T1-T12),发现并修复所有 P0/P1 缺陷,达到上线标准。
Architecture: 基于 V12 模块化审计框架,12 模块按风险排序(HIGH→MEDIUM→LOW),分 4 阶段执行。测试工具:Tauri 端用 tauri-mcp,Rust 用 cargo test,Admin 用 Playwright + vitest,SaaS API 用 HTTP + cargo test。
Tech Stack: Tauri 2.x + React 19 + Zustand + Rust Workspace (10 crates) + Axum + PostgreSQL + tauri-mcp
Spec: docs/superpowers/specs/2026-04-05-pre-launch-functional-audit-design.md
⚠️ 执行注意: 计划中的
execute_js代码块使用window.__TAURI_INTERNALS__.invoke()调用 Tauri 命令。V12 审计后代码已发生变更,部分命令名称/参数可能已更新。执行前必须:
- 验证每个 Tauri 命令名是否存在于
desktop/src-tauri/src/lib.rs的invoke_handler注册列表中- 验证参数签名是否匹配 Rust 函数定义
- V12 审计发现的部分问题(如 M4-01 双数据库、M4-02 反思 LLM)可能已在后续提交中修复,测试时应以实际代码为准
文件结构
测试结果输出
docs/test-results/
├── TEST_PLAN.md # 本文件
├── DEFECT_LIST.md # 缺陷汇总清单
├── RELEASE_READINESS.md # 上线评估
├── baseline/ # 基线测试结果
│ ├── cargo-test.txt
│ ├── desktop-vitest.txt
│ └── admin-vitest.txt
├── T1-hands/ # 每个 T 模块一个目录
│ ├── REPORT.md
│ └── screenshots/
├── T2-intelligence/
├── T3-agent/
├── ... (T3-T12 同理)
└── T12-e2e/
V12 审计报告(测试基线)
docs/features/audit-v12/
├── M1-intelligent-chat.md # T8 (91/100)
├── M2-agent-clones.md # T3 (67/100)
├── M3-hands-system.md # T1 (58/100) ⚠️ 最高风险
├── M4-intelligence-layer.md # T2 (61/100) ⚠️ 含 P0
├── M5-skill-ecosystem.md # T7 (85/100)
├── M6-pipeline-workflow.md # T5 (72/100)
├── M7-saas-desktop.md # T6 (85/100)
├── M8-admin-v2.md # T9 (82/100)
├── M9-communication-security.md # T10 (86/100)
└── M11-classroom.md # T4 (70/100)
关键源码文件
# Hands (T1)
desktop/src/store/handStore.ts
desktop/src/store/browserHandStore.ts
desktop/src/lib/kernel-hands.ts
desktop/src/lib/browser-client.ts
desktop/src/lib/autonomy-manager.ts
desktop/src/components/Automation/
desktop/src-tauri/src/kernel_commands/hand.rs
desktop/src-tauri/src/kernel_commands/approval.rs
crates/zclaw-hands/src/hands/ (9 .rs)
crates/zclaw-kernel/src/kernel/hands.rs
crates/zclaw-kernel/src/kernel/approvals.rs
hands/*.HAND.toml (9 配置)
# Intelligence (T2)
desktop/src/store/memoryGraphStore.ts
desktop/src/lib/intelligence-client/ (memory/identity/reflection/heartbeat)
desktop/src-tauri/src/intelligence/ (memory/identity/reflection/heartbeat/compactor.rs)
crates/zclaw-growth/src/
crates/zclaw-runtime/src/middleware/memory.rs
crates/zclaw-runtime/src/middleware/compaction.rs
# Agent (T3)
desktop/src/store/agentStore.ts
desktop/src/lib/kernel-agent.ts
desktop/src/components/AgentSelector.tsx
desktop/src-tauri/src/kernel_commands/agent.rs
crates/zclaw-kernel/src/kernel/agents.rs
# Classroom (T4)
desktop/src/store/classroomStore.ts
desktop/src/components/Classroom/
desktop/src-tauri/src/kernel_commands/classroom.rs
desktop/src-tauri/src/intelligence/classroom/
# Pipeline (T5)
desktop/src/store/workflowStore.ts
desktop/src/components/WorkflowBuilder/
crates/zclaw-pipeline/src/
# SaaS Desktop (T6)
desktop/src/lib/saas-client.ts
desktop/src/store/saasStore.ts
desktop/src/components/SaaS/
# Skills (T7)
desktop/src/lib/skill-discovery.ts
crates/zclaw-skills/src/
skills/ (75 SKILL.md)
# Chat (T8)
desktop/src/store/chat/ (streamStore, conversationStore, messageStore, artifactStore)
desktop/src/lib/kernel-chat.ts
desktop/src/components/ChatArea.tsx
# Admin V2 (T9)
admin-v2/src/pages/ (15 页面)
admin-v2/tests/ (~71 测试)
# Security (T10)
desktop/src/lib/secure-storage.ts
desktop/src/store/connectionStore.ts
crates/zclaw-saas/src/auth/
# SaaS API (T11)
crates/zclaw-saas/src/ (12 modules + workers)
crates/zclaw-saas/tests/
Chunk 1: Phase 1 环境准备 + T1 Hands 自主能力
Task 0: 环境准备 — 基线验证
Files:
-
Verify:
Cargo.toml,desktop/package.json,admin-v2/package.json -
Output:
docs/test-results/baseline/ -
Step 1: 创建测试结果目录
mkdir -p docs/test-results/baseline
mkdir -p docs/test-results/T1-hands/screenshots
mkdir -p docs/test-results/T2-intelligence/screenshots
mkdir -p docs/test-results/T3-agent/screenshots
mkdir -p docs/test-results/T4-classroom/screenshots
mkdir -p docs/test-results/T5-pipeline/screenshots
mkdir -p docs/test-results/T6-saas-desktop/screenshots
mkdir -p docs/test-results/T7-skills/screenshots
mkdir -p docs/test-results/T8-chat/screenshots
mkdir -p docs/test-results/T9-admin/screenshots
mkdir -p docs/test-results/T10-security/screenshots
mkdir -p docs/test-results/T11-saas-api
mkdir -p docs/test-results/T12-e2e/screenshots
- Step 2: 启动 PostgreSQL
docker compose up -d postgres
Expected: docker compose ps 显示 postgres healthy
- Step 3: 启动 SaaS 后端
cd crates/zclaw-saas && ZCLAW_SAAS_DEV=true cargo run
Expected: 服务监听 0.0.0.0:8080,日志无 ERROR
- Step 4: 启动 Tauri 桌面端
cd desktop && pnpm tauri dev
Expected: 窗口打开,无 panic
- Step 5: 验证 tauri-mcp 连接
manage_window(action='list')
Expected: 返回至少 1 个窗口,标题含 "ZCLAW"
- Step 6: 运行 Rust 基线测试
cargo test --workspace 2>&1 | tee docs/test-results/baseline/cargo-test.txt
Expected: 全部 pass,记录总测试数和通过数
- Step 7: 运行 Desktop 前端基线测试
cd desktop && pnpm vitest run 2>&1 | tee ../docs/test-results/baseline/desktop-vitest.txt
Expected: 全部 pass,记录总测试数
- Step 8: 运行 Admin 前端基线测试
cd admin-v2 && pnpm vitest run 2>&1 | tee ../docs/test-results/baseline/admin-vitest.txt
Expected: 全部 pass,记录总测试数
- Step 9: 确认 LLM Provider 可用
通过 tauri-mcp 在桌面端:
query_page(mode='map', interactive_only=True)
找到模型选择器,确认至少有 1 个模型可选。
或> 注: tauri-mcp 命令使用伪代码表示(Python kwarg 风格),实际执行时需转换为对应工具的 JSON 参数格式。execute_js 中 window.__TAURI_INTERNALS__.invoke(cmd, args) 为 Tauri WebView 内部调用约定,需在执行时验证确切签名。
Expected: 至少 1 个 LLM Provider 的 API Key 已配置
- Step 10: 记录基线结果
在 docs/test-results/baseline/README.md 记录:
-
cargo test: X/Y passed
-
desktop vitest: X/Y passed
-
admin vitest: X/Y passed
-
SaaS 后端: running/not running
-
LLM Provider: available/unavailable
-
Step 11: Commit 基线
git add docs/test-results/baseline/
git commit -m "test: add pre-launch audit baseline results"
git push
Task 1: T1 Hands 自主能力 — V12 已知问题验证
V12 健康度: 58/100 | 风险: HIGH | V12 问题: M3-01~M3-13
Files:
- Audit:
docs/features/audit-v12/M3-hands-system.md - Source:
desktop/src/store/handStore.ts,desktop/src/lib/kernel-hands.ts,desktop/src-tauri/src/kernel_commands/hand.rs - Config:
hands/*.HAND.toml - Rust impl:
crates/zclaw-hands/src/hands/
TC-1-01 | Hand 列举(正常)
- Step 1: 导航到自动化面板
query_page(mode='map', interactive_only=True)
找到 Automation/Hands 相关导航元素。
click(selector_type='ref', selector_value='{nav_ref}')
Expected: 自动化面板显示 9 个已启用的 Hand
- Step 2: 截图记录 Hand 列表
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-01-hand-list.png')
Expected: 截图显示 9 个 Hand 卡片(Browser/Researcher/Collector/Clip/Twitter/Whiteboard/Slideshow/Speech/Quiz),状态为 available
TC-1-02 | Hand 直接触发 — Researcher(正常)
- Step 3: 触发 Researcher Hand
在自动化面板点击 Researcher Hand:
click(selector_type='ref', selector_value='{researcher_ref}')
如有参数输入框,输入测试参数:
type_text(text='测试研究主题:AI Agent 框架对比')
点击执行:
click(selector_type='ref', selector_value='{execute_ref}')
Expected: Hand 进入 running 状态
- Step 4: 验证执行状态
wait_for(text=['completed', 'failed', 'Running', 'running'], timeout_ms=30000)
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-02-researcher-result.png')
Expected: Researcher Hand 完成执行,显示研究结果
TC-1-03 | M3-01 验证: run_id 丢失问题
V12 问题: hand.rs:184 丢弃 _run_id,前端无法跟踪执行状态
注意: 当前 Rust 代码 HandResult 已有 run_id 字段,但前端类型定义 kernel-hands.ts:94 仍使用 { instance_id, status } 与实际返回不匹配
- Step 5: 通过 tauri-mcp 检查 triggerHand 返回值
触发任意 Hand(如 Researcher),通过 execute_js 检查返回值结构:
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'quiz', input: { topic: 'run_id test' }, autonomyLevel: 'autonomous'
});
return JSON.stringify({ keys: Object.keys(result), hasRunId: 'run_id' in result || 'runId' in result, runIdValue: result.run_id || result.runId });
} catch (e) { return 'Error: ' + e; }
}
Expected: 返回值含 run_id 字段(Rust 端已修复),但前端 kernel-hands.ts 的类型定义可能仍不匹配
- Step 6: 截图记录
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-03-run-id-check.png')
记录结果到报告:run_id 是否存在、前端类型是否与 Rust 端对齐。
TC-1-04 | M3-07 验证: hand-execution-complete 事件监听
V12 问题: onHandExecutionComplete 未被调用,前端不更新执行结果
- Step 7: 触发 Hand 并观察 UI 是否自动更新
- 触发一个 Hand(如 Quiz)
- 不手动刷新页面
- 等待 30 秒
# 触发 Quiz Hand
click(selector_type='ref', selector_value='{quiz_ref}')
type_text(text='测试 Quiz 主题')
click(selector_type='ref', selector_value='{execute_ref}')
# 等待完成
wait_for(text=['completed', 'Complete', 'finished'], timeout_ms=60000)
Expected (如未修复): UI 不自动更新执行状态,需手动刷新 Expected (如已修复): UI 自动显示执行完成状态
- Step 8: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-04-event-listener.png')
TC-1-05 | M3-02 验证: Browser Hand 双路径断裂
V12 问题: Rust execute() 只返回结构化指令不执行实际操作
- Step 9: 通过 handStore 触发 Browser Hand
在自动化面板找到 Browser Hand 并触发:
click(selector_type='ref', selector_value='{browser_ref}')
配置参数(如打开网页):
type_text(text='https://example.com')
click(selector_type='ref', selector_value='{execute_ref}')
Expected (如未修复): 返回结构化指令 JSON 但不执行浏览器操作 Expected (如已修复): 实际打开/访问网页
- Step 10: 对比 browserHandStore 路径
通过 tauri-mcp 检查是否有独立的浏览器面板/功能:
query_page(mode='map', interactive_only=True)
Expected: browserHandStore 有独立的浏览器操作 UI,绕过 handStore 审批流程
- Step 11: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-05-browser-hand.png')
TC-1-06 | M3-03 验证: browserHandStore 绕过审批
V12 问题: 无视 TOML requires_approval = true
- Step 12: 设置自主级别为非自动
在自动化设置中,将自主级别设为"需审批"(非 autonomous)。
通过 tauri-mcp:
navigate(action='goto', url='tauri://localhost/settings/automation')
# 或点击设置页
click(selector_type='ref', selector_value='{settings_ref}')
找到自主级别滑块/下拉框,设置为"需审批"。
- Step 13: 通过 browserHandStore 执行操作
在浏览器面板执行一个操作(如导航到 URL)。
Expected (如未修复): 操作直接执行,不弹出审批确认 Expected (如已修复): 弹出审批确认对话框
- Step 14: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-06-bypass-approval.png')
TC-1-07 | 审批流程 — 完整闭环(正常)
- Step 15: 触发需审批的 Hand
确认有一个 Hand 配置了 requires_approval = true(检查 hands/*.HAND.toml)。
在自主级别为"需审批"模式下触发该 Hand。
Expected: 弹出审批队列/确认对话框
- Step 16: 审批通过
click(selector_type='ref', selector_value='{approve_ref}')
Expected: Hand 开始执行,完成后结果出现在 UI
- Step 17: 审批拒绝(重新触发)
再次触发需审批的 Hand,这次拒绝:
click(selector_type='ref', selector_value='{reject_ref}')
Expected: Hand 不执行,状态显示"已拒绝"
- Step 18: 截图记录审批流程
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-07-approval-flow.png')
TC-1-08 | M3-04 验证: max_concurrent 未实现(边界)
V12 问题: TOML 定义但运行时无检查
- Step 19: 并发触发同一 Hand
同时触发同一 Hand 3-5 次:
方式 A(如 UI 允许):快速多次点击执行按钮。 方式 B(通过 execute_js):
async () => {
// 连续触发同一 Hand 多次
for (let i = 0; i < 5; i++) {
await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'researcher',
input: { query: `test ${i}` },
autonomyLevel: 'autonomous'
});
}
return 'triggered 5 times';
}
Expected (如未修复): 5 个全部开始执行,无并发限制 Expected (如已修复): 达到 max_concurrent 后拒绝或排队
- Step 20: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-08-concurrent.png')
TC-1-09 | M3-05 验证: timeout_secs 未实现(边界)
V12 问题: Hand 可无限挂起
- Step 21: 触发可能长时间运行的 Hand
触发一个 Hand(如 Researcher 配合复杂查询),观察是否在 timeout_secs 内终止。
如果无法构造超时场景,检查 TOML 配置:
grep -r "timeout_secs" hands/*.HAND.toml
Expected (如未修复): Hand 无超时保护,可能无限运行 Expected (如已修复): 超过 timeout_secs 后 Hand 自动终止
- Step 22: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-09-timeout.png')
TC-1-10 | Hand 取消(正常)
- Step 23: 触发长时间 Hand 并中途取消
触发一个 Hand,在其 running 状态时点击取消:
click(selector_type='ref', selector_value='{cancel_ref}')
Expected: Hand 停止执行,状态变为 cancelled
- Step 24: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-10-cancel.png')
TC-1-11 | M3-09 验证: 重复审批路径(正常)
V12 问题: hand_approve vs approval_respond 两条重复路径
- Step 25: 验证两条审批路径
通过 Rust 日志或前端行为检查:
路径 A: hand_approve — 通过 handStore 直接审批
路径 B: approval_respond — 通过审批队列审批
检查两条路径是否行为一致(都触发执行,都 emit 事件)。
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-11-dual-approval.png')
Expected: 两条路径均能完成审批并触发执行
TC-1-12 | 不存在的 Hand 触发(异常)
- Step 26: 触发不存在的 Hand
通过 execute_js:
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'nonexistent-hand',
input: {},
autonomyLevel: 'autonomous'
});
return JSON.stringify(result);
} catch (e) {
return `Error: ${e}`;
}
}
Expected: 返回错误 "not found" 或类似
TC-1-13 | M3-08 验证: 审批条目永不过期(异常)
V12 问题: pending_approvals Vec 无限增长
- Step 27: 累积审批条目
触发多个需审批的 Hand,不审批它们。观察内存中 pending_approvals 是否持续增长。
通过 execute_js 检查:
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('approval_list', {});
return JSON.stringify(result);
}
Expected (如未修复): 列表持续增长,无过期清理 Expected (如已修复): 有过期机制自动清理 量化标准: 触发 5 次审批,等待 60 秒,检查是否执行了过期清理(列表长度应 <= 5)
TC-1-14 | 各 Hand 基础触发验证(正常)
- Step 28: 逐一触发 9 个已启用 Hand
对每个 Hand 执行基本触发测试:
| Hand | 测试输入 | 预期 |
|---|---|---|
| Researcher | 主题:"AI 测试" | 返回研究结果 |
| Collector | URL:"https://example.com" | 收集内容 |
| Quiz | 主题:"Rust 基础" | 生成测验 |
| Slideshow | 主题:"ZCLAW 介绍" | 生成幻灯片 |
| Speech | 文本:"你好世界" | TTS 朗读 |
| Whiteboard | 主题:"架构图" | 显示白板 |
| (需 OAuth 配置) | 检查是否正确报告配置缺失 | |
| Clip | (需 FFmpeg) | 检查是否正确报告依赖缺失 |
| Browser | URL:"https://example.com" | 返回操作结果 |
每个 Hand 截图一张:
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-14-{hand_name}.png')
Expected: 每个 Hand 至少能触发(成功或返回明确的配置缺失提示)
TC-1-15 | Hand 执行状态查询(正常)
- Step 29: 查询正在运行的 Hand 状态
触发一个 Hand,在其 running 时查询状态:
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('hand_run_status', {
handName: 'researcher',
runId: '{run_id_if_available}'
});
return JSON.stringify(result);
}
Expected: 返回 running/pending/completed 状态
- Step 30: 查询已完成 Hand 的状态
Expected: 返回 completed + 结果
TC-1-16 | M3-06 验证: hand_execute 返回值类型不匹配(正常)
V12 问题: 前端期望 { instance_id, status },实际返回 { success, output, error, durationMs }
- Step 31: 检查 triggerHand 完整返回值
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'quiz',
input: { topic: 'test' },
autonomyLevel: 'autonomous'
});
return JSON.stringify(Object.keys(result));
}
Expected (如未修复): 返回 ["success","output","error","durationMs"]
Expected (如已修复): 返回包含 runId 字段
- Step 32: 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-16-return-type.png')
TC-1-17 | M3-10 验证: tool_count/metric_count 硬编码为 0(正常)
- Step 33: 检查 hand_list 返回值
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('hand_list', {});
const counts = result.map(h => ({ name: h.name, toolCount: h.tool_count, metricCount: h.metric_count }));
return JSON.stringify(counts);
}
Expected (如未修复): 所有 Hand 的 tool_count 和 metric_count 均为 0 Expected (如已修复): 返回实际工具和指标数量
TC-1-18 | TOML 配置加载验证(正常)
- Step 34: 验证 TOML 配置被正确读取
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('hand_list', {});
// 检查每个 hand 的 enabled、requires_approval 等字段
return JSON.stringify(result.map(h => ({
name: h.name,
enabled: h.enabled,
requiresApproval: h.requires_approval,
timeoutSecs: h.timeout_secs,
maxConcurrent: h.max_concurrent
})));
}
对照 hands/*.HAND.toml 中的配置值验证一致性。
Expected: enabled/requires_approval 正确,timeout_secs/max_concurrent 定义但可能未生效
TC-1-19 | Hand 错误处理(异常)
- Step 35: 触发 Hand 传入无效参数
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'researcher',
input: null,
autonomyLevel: 'autonomous'
});
return JSON.stringify(result);
} catch (e) {
return `Error: ${e}`;
}
}
Expected: 返回明确错误信息(非 panic)
TC-1-20 | M3-12 验证: hand_trigger 永远不自动允许(边界)
V12 问题: autonomy-manager.ts:268 映射错误,hand_trigger 在 autonomous 模式下也不返回 allow
- Step 35b: 验证三个自主级别下 hand_trigger 的 canAutoExecute 结果
async () => {
// 检查 autonomy-manager 中 hand_trigger 映射
const levels = ['supervised', 'assisted', 'autonomous'];
const results = {};
for (const level of levels) {
// 模拟不同级别的 canAutoExecute 逻辑
results[level] = '需手动在 UI 中切换级别后验证';
}
return JSON.stringify(results);
}
实际操作:在 UI 中依次切换自主级别为 supervised → assisted → autonomous,每次触发一个 Hand(如 Quiz)。
Expected (如未修复): autonomous 模式下 Hand 仍需审批(canAutoExecute 不返回 allow) Expected (如已修复): autonomous 模式下 Hand 自动执行(canAutoExecute 返回 allow)
- 截图
take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-20-autonomy-mapping.png')
TC-1-21 | M3-13 验证: Clip Hand 路径含单引号(边界)
V12 问题: clip.rs:448 FFmpeg concat 文件路径单引号未转义
- Step 35c: 触发 Clip Hand 使用含单引号的路径
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'clip',
input: { files: ["C:\\User's Files\\video.mp4"], action: 'concat' },
autonomyLevel: 'autonomous'
});
return JSON.stringify(result);
} catch (e) { return 'Error: ' + e; }
}
Expected (如未修复): FFmpeg 解析失败或命令注入风险 Expected (如已修复): 正确转义单引号,返回正常结果或明确的路径错误
TC-1-22 | 无 LLM Provider 时触发 Hand(边界)
- Step 35d: 临时移除 LLM API Key 后触发 Researcher
- 进入设置,移除当前 Agent 的 API Key
- 触发 Researcher Hand
- 恢复 API Key
Expected: 返回明确错误提示("未配置 API Key" 等),非 panic/空结果
TC-1-23 | 超长输入触发 Hand(边界)
- Step 35e: 触发 Hand 传入超长字符串
async () => {
const longInput = 'A'.repeat(100000);
try {
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'quiz',
input: { topic: longInput },
autonomyLevel: 'autonomous'
});
return JSON.stringify({ status: 'returned', outputLen: JSON.stringify(result).length });
} catch (e) { return 'Error: ' + e; }
}
Expected: 拒绝超长输入或截断处理,非崩溃
- Step 36: Commit T1 测试结果
git add docs/test-results/T1-hands/
git commit -m "test(T1): hands system functional audit results"
git push
- Step 37: 生成 T1 测试报告
在 docs/test-results/T1-hands/REPORT.md 中记录:
- 执行用例数: 19/19
- 通过/失败数
- V12 已知问题验证结果(M3-01~M3-13)
- 新发现问题清单
- 健康度重新评估(基线 58/100)
git add docs/test-results/T1-hands/REPORT.md
git commit -m "test(T1): add hands system audit report"
git push
Chunk 2: T2 智能层 + T3 Agent 分身
Task 2: T2 智能层(记忆/反思/心跳/自主)— V12 已知问题验证
V12 健康度: 61/100 | 风险: HIGH | V12 问题: M4-01~M4-15 (含 2 个 P0)
Files:
- Audit:
docs/features/audit-v12/M4-intelligence-layer.md - Source:
- 记忆:
desktop/src/store/memoryGraphStore.ts,desktop/src/lib/intelligence-client/memory.ts,desktop/src-tauri/src/intelligence/memory.rs - 身份:
desktop/src/lib/intelligence-client/identity.ts,desktop/src-tauri/src/intelligence/identity.rs - 反思:
desktop/src/lib/intelligence-client/reflection.ts,desktop/src-tauri/src/intelligence/reflection.rs - 心跳:
desktop/src/lib/intelligence-client/heartbeat.ts,desktop/src-tauri/src/intelligence/heartbeat.rs - 自主:
desktop/src/lib/autonomy-manager.ts,desktop/src/components/AutonomyConfig.tsx - 压缩:
desktop/src/lib/intelligence-client/fallback-compactor.ts,desktop/src-tauri/src/intelligence/compactor.rs - Runtime 中间件:
crates/zclaw-runtime/src/middleware/memory.rs,crates/zclaw-runtime/src/middleware/compaction.rs - 存储:
crates/zclaw-growth/src/storage/sqlite.rs
- 记忆:
TC-2-01 | M4-01 验证: 双数据库问题(P0)
V12 问题: PersistentMemoryStore(LIKE) vs SqliteStorage(FTS5),数据不互通
- Step 1: 通过前端保存一条记忆
导航到记忆面板:
navigate(action='goto', url='tauri://localhost/memories')
# 或通过导航点击
手动保存一条记忆:"测试记忆条目 - 上线前审计"。
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-01a-save-memory.png')
- Step 2: 验证该记忆出现在对话注入中
进入对话界面,发送消息触发记忆搜索(发送与记忆相关的问题)。
type_text(text='你记得什么关于上线前审计的信息?')
click(selector_type='ref', selector_value='{send_ref}')
wait_for(text=['测试记忆', '审计'], timeout_ms=15000)
Expected (如未修复): 手动保存的记忆不出现在对话回复中(因为 Runtime 用 SqliteStorage,前端用 PersistentMemoryStore) Expected (如已修复): 对话回复引用了手动保存的记忆内容
- Step 3: 反向验证 — Agent 自动提取的记忆是否出现在前端面板
进行多轮对话,触发自动记忆提取。然后检查记忆面板是否显示新提取的记忆。
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-01b-memory-panel.png')
Expected (如未修复): Agent 提取的记忆不出现在前端记忆面板 Expected (如已修复): Agent 提取的记忆出现在前端面板
TC-2-02 | M4-02 验证: 反思 LLM 未接入(P0)
V12 问题: reflection_reflect 传入 driver=None,LLM 分析从未生效
- Step 4: 触发反思并检查是否使用 LLM
通过 execute_js 直接调用反思:
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('reflection_reflect', {
agentId: '{current_agent_id}',
force: true
});
return JSON.stringify({ keys: Object.keys(result), analysis: result.analysis?.substring(0, 200) });
}
Expected (如未修复): 返回规则分析结果(基于启发式规则),无 LLM 深度分析 Expected (如已修复): 返回包含 LLM 分析内容(更丰富的洞察)
- Step 5: 检查 Rust 端日志
查看日志中是否有 LLM 调用记录:
# 如果日志输出到文件
grep -i "reflection.*driver\|reflection.*llm\|reflect.*None" /tmp/zclaw-*.log 2>/dev/null || echo "No log file found"
Expected (如未修复): 日志显示 driver=None Expected (如已修复): 日志显示 driver=Some(...),有 LLM API 调用
- Step 6: 截图
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-02-reflection.png')
TC-2-03 | 记忆 CRUD(正常)
- Step 7: 创建记忆
navigate(action='goto', url='tauri://localhost/memories')
创建一条新记忆:
- 类型: fact
- 内容: "ZCLAW 上线前审计测试记忆"
- 重要性: 7
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-03a-create-memory.png')
- Step 8: 搜索记忆
搜索关键词 "上线前审计"。
type_text(text='上线前审计')
click(selector_type='ref', selector_value='{search_ref}')
wait_for(text=['ZCLAW 上线前审计'], timeout_ms=5000)
Expected: 搜索结果显示刚创建的记忆
- Step 9: 更新记忆
修改记忆内容为 "ZCLAW 上线前审计测试记忆 - 已更新"。
Expected: 记忆内容成功更新
- Step 10: 删除记忆
删除刚创建的记忆。
Expected: 记忆从列表中消失
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-03b-memory-crud.png')
TC-2-04 | M4-05 验证: 前端记忆搜索用 LIKE 非 FTS5(正常)
V12 问题: PersistentMemoryStore 用 LIKE 模糊匹配,非 FTS5
- Step 11: 测试搜索精度
- 创建多条记忆,内容包含 "机器学习"
- 搜索 "机器"
- 搜索 "学习"
Expected (LIKE): 两个搜索都返回结果(模糊匹配) Expected (FTS5): "机器" 返回结果,"学习" 可能不返回(分词差异)
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-04-search-like.png')
TC-2-05 | 身份演化(正常)
- Step 12: 查看当前 Agent 身份
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('identity_get', {
agentId: '{current_agent_id}'
});
return JSON.stringify({ hasSoul: !!result.soul, hasInstructions: !!result.instructions });
}
Expected: 返回当前 Agent 的 Soul 和 Instructions
- Step 13: 提出身份变更提案
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('identity_propose_change', {
agentId: '{current_agent_id}',
dimension: 'communication_style',
proposedValue: '更加技术性',
reason: '测试身份演化'
});
return JSON.stringify(result);
}
Expected: 创建变更提案
- Step 14: 审批/拒绝身份变更
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-05-identity.png')
TC-2-06 | M4-03 验证: 心跳不自动启动(正常)
V12 问题: 需前端手动初始化 heartbeat_init + heartbeat_start
- Step 15: 检查心跳是否自动运行
应用启动后,检查心跳状态:
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('heartbeat_status', {});
return JSON.stringify(result);
}
Expected (如未修复): 心跳未运行(需手动启动) Expected (如已修复): 心跳自动启动并运行
- Step 16: 手动启动心跳(如未自动启动)
async () => {
await window.__TAURI_INTERNALS__.invoke('heartbeat_init', { intervalMinutes: 5 });
await window.__TAURI_INTERNALS__.invoke('heartbeat_start', {});
const status = await window.__TAURI_INTERNALS__.invoke('heartbeat_status', {});
return JSON.stringify(status);
}
Expected: 心跳开始运行,显示下次巡检时间
- Step 17: 截图
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-06-heartbeat.png')
TC-2-07 | M4-04 验证: 自主授权后端无强制(正常)
V12 问题: 仅前端咨询层,后端不检查自主授权级别
- Step 18: 验证后端不检查自主级别
设置自主级别为 supervised,然后通过 execute_js 直接调用 Rust 命令绕过前端:
async () => {
// 前端 autonomy-manager 设为 supervised
// 但直接调用 Tauri 命令绕过前端检查
const result = await window.__TAURI_INTERNALS__.invoke('hand_execute', {
id: 'quiz',
input: { topic: 'autonomy test' },
autonomyLevel: 'supervised' // 后端是否检查?
});
return JSON.stringify({ executed: result.success });
}
Expected (如未修复): 后端直接执行,不检查自主级别 Expected (如已修复): 后端根据自主级别决定是否需要审批
TC-2-08 | 上下文压缩(正常)
- Step 19: 触发上下文压缩
进行多轮对话使上下文变长,然后触发压缩:
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('compaction_compact', {
agentId: '{current_agent_id}',
sessionId: '{current_session_id}'
});
return JSON.stringify({ success: result.success, originalTokens: result.original_tokens, compressedTokens: result.compressed_tokens });
}
Expected: 返回压缩结果,compressedTokens < originalTokens
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-08-compaction.png')
TC-2-09 | M4-06 验证: types 参数数组 vs 单值(边界)
V12 问题: 前端 types?: MemoryType[] vs 后端 memory_type?: string
- Step 20: 测试传入多种类型搜索
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('memory_search', {
query: 'test',
types: ['fact', 'procedure'] // 前端传数组
});
return JSON.stringify({ count: result?.length || 0 });
}
Expected (如未修复): 后端只接收第一个类型或报错 Expected (如已修复): 后端正确处理多类型搜索
TC-2-10 | 记忆内容无长度限制(异常)
V12 问题: M4-07 content 无长度限制
- Step 21: 保存超长记忆
async () => {
const longContent = 'A'.repeat(1000000); // 1MB
try {
const result = await window.__TAURI_INTERNALS__.invoke('memory_save', {
agentId: '{current_agent_id}',
memory: { content: longContent, memoryType: 'fact', importance: 5 }
});
return JSON.stringify({ saved: true, id: result.id });
} catch (e) { return 'Error: ' + e; }
}
Expected: 拒绝或截断(非无限制保存导致内存问题)
TC-2-11 | 心跳 interval 下限验证(边界)
V12 问题: M4-09 interval_minutes 无下限验证
- Step 22: 设置极短心跳间隔
async () => {
try {
await window.__TAURI_INTERNALS__.invoke('heartbeat_init', { intervalMinutes: 0.001 });
return 'No validation - accepted 0.001 minutes';
} catch (e) { return 'Blocked: ' + e; }
}
Expected (如未修复): 接受极短间隔,可能导致频繁心跳 Expected (如已修复): 拒绝低于最小值(如 1 分钟)
TC-2-12 | 反思引擎边界测试(边界)
- Step 23: 在无记忆的情况下触发反思
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('reflection_reflect', {
agentId: 'nonexistent-agent',
force: true
});
return JSON.stringify(result);
}
Expected: 返回空分析或明确的"无数据"提示,非 panic
TC-2-13 | 两套压缩实现验证(正常)
V12 问题: M4-13 Tauri 层和 Runtime 层各有独立压缩实现
- Step 24: 对比两套压缩配置
检查 Tauri 层 compactor.rs 和 Runtime 层 compaction.rs 的默认配置是否一致。
take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-13-compaction-dual.png')
- Step 25: Commit T2 测试结果
git add docs/test-results/T2-intelligence/
git commit -m "test(T2): intelligence layer functional audit results"
git push
- Step 26: 生成 T2 测试报告
在 docs/test-results/T2-intelligence/REPORT.md 中记录:
- 执行用例数: 13/13
- 通过/失败数
- V12 已知问题验证结果(M4-01~M4-15)
- 新发现问题清单
- 健康度重新评估(基线 61/100)
git add docs/test-results/T2-intelligence/REPORT.md
git commit -m "test(T2): add intelligence layer audit report"
git push
Task 3: T3 Agent 分身 — V12 已知问题验证
V12 健康度: 67/100 | 风险: HIGH | V12 问题: M2-01~M2-14 (含 2 个 P1)
Files:
- Audit:
docs/features/audit-v12/M2-agent-clones.md - Source:
desktop/src/store/agentStore.ts,desktop/src/lib/kernel-agent.ts,desktop/src/components/AgentSelector.tsx - Rust:
desktop/src-tauri/src/kernel_commands/agent.rs,crates/zclaw-kernel/src/kernel/agents.rs
TC-3-01 | Agent 列举(正常)
- Step 27: 查看 Agent 列表
query_page(mode='map', interactive_only=True)
找到 Agent 选择器/管理入口并点击。
Expected: 显示至少 1 个默认 Agent
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-01-agent-list.png')
TC-3-02 | M2-01 验证: KernelClient createClone 字段丢失(P1)
V12 问题: kernel-agent.ts 只传 name/description/model 3 字段,丢 7+ 人格字段
- Step 28: 通过 Kernel 模式创建 Agent(含完整人格字段)
在 Agent 管理界面创建新 Agent,填写所有字段:
- 名称: "审计测试 Agent"
- 描述: "用于测试字段传递"
- 表情: "🤖"
- 性格: "严谨、精确"
- 沟通风格: "技术导向"
- 备注: "测试备注"
type_text(text='审计测试 Agent')
# 依次填写其他字段
click(selector_type='ref', selector_value='{create_ref}')
- Step 29: 检查 SQLite 中 Agent 配置
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('agent_list', {});
const testAgent = result.find(a => a.name === '审计测试 Agent');
if (!testAgent) return 'Agent not found';
return JSON.stringify({
name: testAgent.name,
hasEmoji: !!testAgent.config?.emoji,
hasPersonality: !!testAgent.config?.personality,
configKeys: Object.keys(testAgent.config || {})
});
}
Expected (如未修复): config 中缺少 emoji/personality/communicationStyle 等字段 Expected (如已修复): config 包含所有传入的人格字段
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-02-field-loss.png')
TC-3-03 | M2-02 验证: 双通路创建不对等(P1)
V12 问题: Gateway 构建完整 TOML manifest,Kernel 仅 3 字段
- Step 30: 对比 Kernel 和 Gateway 两条通路的创建结果
创建两个 Agent:
- Agent A: 通过 Kernel 模式创建
- Agent B: 通过 Gateway 模式创建(如 Gateway 可用)
对比两个 Agent 的配置完整度。
Expected (如未修复): Kernel 创建的 Agent 缺少人格字段,Gateway 创建的完整 Expected (如已修复): 两条通路创建结果一致
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-03-dual-path.png')
TC-3-04 | Agent 更新(正常)
- Step 31: 更新 Agent 属性
修改刚创建的 Agent:
- 更新名称
- 更新描述
- 更新 system prompt
- 更新模型
click(selector_type='ref', selector_value='{edit_ref}')
type_text(text='审计测试 Agent - 已更新')
click(selector_type='ref', selector_value='{save_ref}')
Expected: 所有更新生效
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-04-update.png')
TC-3-05 | Agent 切换(正常)
- Step 32: 切换到新创建的 Agent
click(selector_type='ref', selector_value='{agent_selector_ref}')
click(selector_type='ref', selector_value='{test_agent_ref}')
Expected: Agent 切换成功,UI 显示新 Agent 名称
- Step 33: 发送消息验证 Agent 身份
type_text(text='你好,你是谁?')
click(selector_type='ref', selector_value='{send_ref}')
wait_for(text=['审计测试', 'Agent'], timeout_ms=15000)
Expected: AI 回复体现新 Agent 的身份/个性
TC-3-06 | M2-06 验证: Agent 切换不通知 Kernel(正常)
V12 问题: 切换 Agent 不更新 defaultAgentId
- Step 34: 切换 Agent 后检查 Kernel 状态
async () => {
// 切换到新 Agent 后检查
const agentId = await window.__TAURI_INTERNALS__.invoke('get_default_agent', {});
return JSON.stringify({ defaultAgentId: agentId });
}
Expected (如未修复): defaultAgentId 未更新为刚切换的 Agent Expected (如已修复): defaultAgentId 正确更新
TC-3-07 | M2-07 验证: 切换不取消流(正常)
V12 问题: 流式中切换 Agent,消息可能追到错误对话
- Step 35: 流式中切换 Agent
- 发送一条长消息(触发长时间流式响应)
- 在流式响应进行中,切换到另一个 Agent
type_text(text='请详细解释 Rust 的生命周期系统')
click(selector_type='ref', selector_value='{send_ref}')
# 立即切换 Agent
click(selector_type='ref', selector_value='{agent_selector_ref}')
click(selector_type='ref', selector_value='{another_agent_ref}')
Expected (如未修复): 原有流继续在后台运行,响应可能出现在错误的对话 Expected (如已修复): 切换前自动取消进行中的流
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-07-switch-during-stream.png')
TC-3-08 | Agent 删除(正常)
- Step 36: 删除测试 Agent
click(selector_type='ref', selector_value='{delete_ref}')
Expected: 删除成功,Agent 从列表消失
TC-3-09 | M2-05 验证: 删除不检查活跃状态(异常)
V12 问题: 删除正在使用的 Agent 无警告
- Step 37: 删除当前活跃的 Agent
切换到一个 Agent,然后直接删除它。
Expected (如未修复): 直接删除,无警告 Expected (如已修复): 弹出警告"该 Agent 正在使用中"
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-09-delete-active.png')
TC-3-10 | M2-08 验证: 无参数验证(异常)
V12 问题: 空 name、温度越界无验证
- Step 38: 创建空名 Agent
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('agent_create', {
name: '',
description: 'test',
model: 'gpt-4'
});
return JSON.stringify({ created: true, id: result.id });
} catch (e) { return 'Error: ' + e; }
}
Expected (如未修复): 成功创建空名 Agent Expected (如已修复): 拒绝空名称
- Step 39: 设置越界 temperature
async () => {
try {
const result = await window.__TAURI_INTERNALS__.invoke('agent_update', {
agentId: '{test_agent_id}',
updates: { temperature: 5.0 }
});
return JSON.stringify({ updated: true });
} catch (e) { return 'Error: ' + e; }
}
Expected (如未修复): 接受 temperature=5.0 Expected (如已修复): 拒绝越界值
TC-3-11 | M2-09 验证: 删除后 selectedAgent 引用(异常)
V12 问题: 删除当前选中 Agent 后引用可能悬挂
- Step 40: 删除当前选中 Agent 后检查状态
- 选中 Agent A
- 删除 Agent A
- 检查 conversationStore.currentAgent 是否有效
async () => {
// 删除后检查
const state = document.querySelector('[data-agent-name]')?.textContent;
return state || 'No agent selected';
}
Expected (如未修复): currentAgent 指向已删除 Agent Expected (如已修复): 自动切换到第一个可用 Agent
TC-3-12 | Agent 从模板创建(正常)
- Step 41: 从模板创建 Agent
检查是否有模板创建功能,如有则测试。
take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-12-template-create.png')
- Step 42: Commit T3 测试结果
git add docs/test-results/T3-agent/
git commit -m "test(T3): agent clones functional audit results"
git push
- Step 43: 生成 T3 测试报告
在 docs/test-results/T3-agent/REPORT.md 中记录:
- 执行用例数: 12/12
- 通过/失败数
- V12 已知问题验证结果(M2-01~M2-14)
- 新发现问题清单
- 健康度重新评估(基线 67/100)
git add docs/test-results/T3-agent/REPORT.md
git commit -m "test(T3): add agent clones audit report"
git push
Chunk 2 执行前必读: 所有
execute_js中的 Tauri 命令名需在执行时与desktop/src-tauri/src/lib.rs的invoke_handler注册列表核对。V12 审计后部分问题(M4-01/M4-02)可能已修复,以实际代码为准。
Chunk 3: T4 课堂系统 + T5 Pipeline 工作流
Task 4: T4 课堂系统 — V12 已知问题验证
V12 健康度: 70/100 | 风险: HIGH | V12 问题: M11-01~M11-08 (含 3 个 P1)
Files:
- Audit:
docs/features/audit-v12/M11-classroom.md - Source:
desktop/src/store/classroomStore.ts,desktop/src/components/Classroom/ - Rust:
desktop/src-tauri/src/kernel_commands/classroom.rs,desktop/src-tauri/src/intelligence/classroom/
TC-4-01 | 课堂生成(正常)
- Step 44: 触发课堂生成
导航到课堂功能,输入主题生成课堂:
type_text(text='Rust 所有权系统')
click(selector_type='ref', selector_value='{generate_ref}')
Expected: 显示生成进度,4 阶段 pipeline 逐步完成
- Step 45: 等待生成完成
wait_for(text=['completed', '生成完成', 'Complete'], timeout_ms=120000)
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-01-generation.png')
Expected: 课堂生成成功,显示场景列表
TC-4-02 | M11-01 验证: is_cancelled() blocking_lock 死锁(P1)
V12 问题: generate.rs:141-144 async 函数中使用 blocking_lock,tokio 可能死锁
- Step 46: 生成过程中取消课堂
- 开始生成一个课堂
- 在生成过程中点击取消
click(selector_type='ref', selector_value='{cancel_generation_ref}')
Expected (如未修复): 取消请求可能触发 tokio 死锁,应用卡住 Expected (如已修复): 取消成功,生成停止,无死锁
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-02-cancel-deadlock.png')
TC-4-03 | M11-02 验证: LLM 调用无 map_err(P1)
V12 问题: Stage 0/1 LLM 调用无 map_err,driver 未配置时可能 panic
- Step 47: 在无 LLM 配置时生成课堂
临时移除 LLM API Key,然后尝试生成课堂。
Expected (如未修复): 可能 panic 或返回空结果无错误提示 Expected (如已修复): 返回明确的错误信息
TC-4-04 | 场景播放(正常)
- Step 48: 播放已生成的课堂场景
click(selector_type='ref', selector_value='{scene_1_ref}')
Expected: 场景自动播放,显示 speech/whiteboard/quiz actions
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-04-scene-play.png')
TC-4-05 | TTS 朗读(正常)
- Step 49: 触发 TTS 朗读
在场景播放中点击朗读按钮。
Expected: 浏览器 TTS 以 zh-CN 语言朗读场景内容
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-05-tts.png')
TC-4-06 | 白板渲染(正常)
- Step 50: 查看白板场景
导航到含白板 action 的场景。
Expected: 白板内容正确渲染(SVG 或 Canvas)
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-06-whiteboard.png')
TC-4-07 | M11-03 验证: 课堂数据仅存内存(P1)
V12 问题: HashMap 存储,重启丢失
- Step 51: 重启应用后检查课堂数据
- 确认有已生成的课堂
- 重启 Tauri 应用
- 检查课堂是否还在
Expected (如未修复): 重启后所有课堂消失 Expected (如已修复): 课堂数据持久化,重启后仍存在
TC-4-08 | 课堂聊天(正常)
- Step 52: 在课堂中进行聊天
type_text(text='请解释一下这个概念')
click(selector_type='ref', selector_value='{chat_send_ref}')
wait_for(text=['解释'], timeout_ms=15000)
Expected: LLM 多 agent 响应课堂聊天
TC-4-09 | 课堂导出(正常)
- Step 53: 导出课堂为 JSON/Markdown
click(selector_type='ref', selector_value='{export_ref}')
Expected: 文件下载成功
take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-09-export.png')
TC-4-10 | M11-04 验证: LLM 失败静默 fallback(异常)
V12 问题: LLM 失败静默 fallback 到 placeholder
- Step 54: 制造 LLM 失败场景
在课堂聊天中,临时使 LLM 不可用。
Expected (如未修复): 回复是 placeholder 但用户无法区分 Expected (如已修复): 标记为 placeholder 或显示错误提示
TC-4-11 | M11-05 验证: 生成完成强制打开(正常)
V12 问题: 生成完成后强制打开 player
- Step 55: 生成期间关闭 player,观察完成后行为
Expected (如未修复): player 被强制重新打开 Expected (如已修复): 尊重手动关闭状态
TC-4-12 | 课堂历史列表(正常)
- Step 56: 检查课堂历史列表功能
Expected: 确认 classroom_list 前端集成状态
- Step 57: Commit T4 测试结果
git add docs/test-results/T4-classroom/
git commit -m "test(T4): classroom system functional audit results"
git push
Task 5: T5 Pipeline 工作流 — V12 已知问题验证
V12 健康度: 72/100 | 风险: MEDIUM | V12 问题: M6-01~M6-08 (含 2 个 P1)
Files:
- Audit:
docs/features/audit-v12/M6-pipeline-workflow.md - Source:
desktop/src/store/workflowStore.ts,desktop/src/components/WorkflowBuilder/ - Rust:
crates/zclaw-pipeline/src/
TC-5-01 | Pipeline 列举发现(正常)
- Step 58: 查看 Pipeline 列表
navigate(action='goto', url='tauri://localhost/pipelines')
Expected: 显示已有 Pipeline(含 10 行业模板)
take_screenshot(filePath='docs/test-results/T5-pipeline/screenshots/TC-5-01-pipeline-list.png')
TC-5-02 | M6-02 验证: v1/v2 解析器分裂(P1)
V12 问题: pipeline_list 只用 v1 解析器,v2 格式被静默丢弃
- Step 59: 检查 v2 格式 Pipeline 是否显示
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('pipeline_list', {});
return JSON.stringify({ count: result?.length, names: result?.map(p => p.name) });
}
Expected (如未修复): 仅显示 v1 格式 Pipeline Expected (如已修复): v1 和 v2 格式都正确列举
TC-5-03 | Pipeline 执行(正常)
- Step 60: 执行一个 Pipeline
click(selector_type='ref', selector_value='{pipeline_ref}')
click(selector_type='ref', selector_value='{execute_ref}')
wait_for(text=['completed', 'Running'], timeout_ms=60000)
take_screenshot(filePath='docs/test-results/T5-pipeline/screenshots/TC-5-03-execution.png')
TC-5-04 | Pipeline 监控(正常)
- Step 61: 查看执行进度
Expected: 返回进度信息(百分比、当前步骤)
TC-5-05 | M6-01 验证: route_intent 未注册(P1)
V12 问题: route_intent Tauri 命令未注册
- Step 62: 验证 IntentInput 组件
Expected (如未修复): IntentInput 报错或无响应 Expected (如已修复): IntentInput 返回推荐 Pipeline
TC-5-06 | Pipeline 取消(正常)
- Step 63: 执行中取消 Pipeline
Expected: Pipeline 停止执行
TC-5-07 | M6-03 验证: pipeline_create Action 类型丢失(正常)
V12 问题: 只映射 Hand 类型,丢失 LLM/Parallel/Condition
- Step 64: 创建包含多种 Action 类型的 Pipeline
Expected (如未修复): 非 Hand 类型步骤被映射为 Hand Expected (如已修复): 正确保留所有 Action 类型
TC-5-08 | Pipeline 导出(正常)
- Step 65: 导出 Pipeline 配置
Expected: 导出为 YAML/JSON 格式
- Step 66: Commit T5 测试结果
git add docs/test-results/T5-pipeline/
git commit -m "test(T5): pipeline workflow functional audit results"
git push
Chunk 4: T6 SaaS 集成 + T7 技能生态 + T8 智能对话
所有 execute_js 命令名需在执行时验证。
Task 6: T6 SaaS 桌面集成
V12 健康度: 85/100 | 风险: MEDIUM | V12 问题: M7-01~M7-06 (含 2 个 P1)
Files:
- Audit:
docs/features/audit-v12/M7-saas-desktop.md - Source:
desktop/src/lib/saas-client.ts,desktop/src/store/saasStore.ts,desktop/src/components/SaaS/
TC-6-01 | SaaS 登录(正常)
- Step 67: SaaS 登录流程
导航到 SaaS 登录页面,输入凭据登录。
Expected: 登录成功,JWT Cookie 设置,session 恢复
take_screenshot(filePath='docs/test-results/T6-saas-desktop/screenshots/TC-6-01-login.png')
TC-6-02 | M7-04 验证: refreshToken 未传 refresh_token body(P1)
V12 问题: Tauri 非浏览器可能无 cookie 自动附加
- Step 68: 验证 token 刷新
等待 JWT 过期(或手动触发刷新),检查是否成功获取新 token。
Expected (如未修复): 刷新失败(cookie 未附加) Expected (如已修复): 刷新成功
TC-6-03 | M7-02 验证: ConfigMigrationWizard PUT 路径参数错误(P1)
V12 问题: PUT 使用布尔值 exists 作为路径参数
- Step 69: 触发配置迁移向导
Expected (如未修复): PUT 请求发送错误参数 Expected (如已修复): PUT 请求发送正确的 config item ID
TC-6-04 | 模型列表 + 聊天中继(正常)
- Step 70: 通过 SaaS Relay 获取模型列表
Expected: 返回可用模型列表
- Step 71: 通过 SaaS Relay 发送聊天消息
Expected: SSE 流式响应正确
TC-6-05 | 配置同步(正常)
- Step 72: 配置 pull + diff + sync
Expected: 配置正确同步
TC-6-06 | M7-01 验证: 密码长度不一致(边界)
- Step 73: 验证前端密码最少 6 字符 vs 后端 8 字符
Expected (如未修复): 前端允许 6 字符密码但后端拒绝 Expected (如已修复): 前后端统一为 8 字符
- Step 74: Commit T6 测试结果
git add docs/test-results/T6-saas-desktop/
git commit -m "test(T6): SaaS desktop integration audit results"
git push
Task 7: T7 技能生态
V12 健康度: 85/100 | 风险: LOW | V12 问题: M5-01~M5-06 (含 1 个 P1)
Files:
- Audit:
docs/features/audit-v12/M5-skill-ecosystem.md - Source:
desktop/src/lib/skill-discovery.ts,crates/zclaw-skills/src/,skills/(75 SKILL.md)
TC-7-01 | M5-01 验证: tags 误映射为 triggers(P1)
V12 问题: convertFromBackend() 将 tags 映射为 triggers
- Step 75: 检查技能列表中 tags 和 triggers 字段
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('skill_list', {});
const sample = result.slice(0, 5).map(s => ({
name: s.name,
tags: s.tags,
triggers: s.triggers,
category: s.category
}));
return JSON.stringify(sample);
}
对照 skills/*.SKILL.md 中的 frontmatter 验证 tags 和 triggers 是否正确映射。
Expected (如未修复): tags 值出现在 triggers 字段,真实 triggers 丢失 Expected (如已修复): tags 和 triggers 各自正确
TC-7-02 | 技能加载 + 解析(正常)
- Step 76: 验证 75 个 SKILL.md 全部加载
async () => {
const result = await window.__TAURI_INTERNALS__.invoke('skill_list', {});
return JSON.stringify({ total: result.length });
}
Expected: 返回 75 个技能
TC-7-03 | 技能语义路由(正常)
- Step 77: 测试语义路由匹配
发送一条消息触发技能路由,验证是否正确匹配到相关技能。
TC-7-04 | M5-02 验证: SKILL.md tools 字段未解析(P2)
- Step 78: 检查 skill_list 返回值中是否有 tools 字段
Expected (如未修复): 技能对象中无 tools 字段 Expected (如已修复): 技能对象包含 tools 定义
TC-7-05 | M5-03 验证: Python 硬编码 python3(边界)
- Step 79: 在 Windows 上执行 Python 模式技能
Expected (如未修复): Windows 上 python3 不存在,执行失败
Expected (如已修复): 自动检测 python 或 python3
TC-7-06 | 技能采样执行(正常)
- Step 80: 采样执行 5 个不同执行模式的技能
| 执行模式 | 测试技能 | 预期 |
|---|---|---|
| PromptOnly | 任选 1 个 | LLM 处理 |
| Python | 任选 1 个 | Python 脚本执行 |
| Shell | 任选 1 个 | Shell 命令执行 |
每个技能截图一张
- Step 81: Commit T7 测试结果
git add docs/test-results/T7-skills/
git commit -m "test(T7): skill ecosystem audit results"
git push
Task 8: T8 智能对话
V12 健康度: 91/100 | 风险: LOW | V12 问题: M1-01~M1-11 (全部 P2/P3)
Files:
- Audit:
docs/features/audit-v12/M1-intelligent-chat.md
由于健康度最高(91/100),仅执行核心流程验证和已知 P2 问题抽样。
TC-8-01 | 流式聊天核心流程(正常)
- Step 82: 发送消息验证流式响应
type_text(text='你好,请介绍一下你自己')
click(selector_type='ref', selector_value='{send_ref}')
wait_for(text=['AI', '助手', '你好'], timeout_ms=15000)
Expected: 流式响应正常显示
take_screenshot(filePath='docs/test-results/T8-chat/screenshots/TC-8-01-streaming.png')
TC-8-02 | 模型切换(正常)
- Step 83: 切换模型并验证
在模型选择器中切换到不同的 Provider/模型,发送新消息。
Expected: 切换后使用新模型响应
TC-8-03 | 推理模式(正常)
- Step 84: 启用推理模式发送消息
Expected: 显示推理过程(ReasoningBlock)
TC-8-04 | 工具调用链(正常)
- Step 85: 触发工具调用的消息
Expected: 显示工具调用链(ToolCallChain)
TC-8-05 | 取消流(正常)
- Step 86: 流式中取消
Expected: 取消成功,部分结果显示
TC-8-06 | 多 Provider 连通(正常)
- Step 87: 逐一验证可用 Provider
对每个已配置的 Provider 发送一条测试消息。
Expected: 每个返回有效响应或明确的配置错误
TC-8-07 | Markdown 渲染(正常)
- Step 88: 请求 Markdown 格式回复
type_text(text='请用 Markdown 格式列出 5 个编程语言的特点')
Expected: 代码块、列表、表格等正确渲染
- Step 89: Commit T8 测试结果
git add docs/test-results/T8-chat/
git commit -m "test(T8): intelligent chat audit results"
git push
Chunk 5: T9 Admin V2 + T10 安全 + T11 SaaS API + T12 端到端
Task 9: T9 Admin V2 管理后台
V12 健康度: 82/100 | 风险: MEDIUM | V12 问题: M8-01~M8-08 (P2/P3)
Files:
- Audit:
docs/features/audit-v12/M8-admin-v2.md - Source:
admin-v2/src/pages/(15 页面),admin-v2/tests/(~71 测试) - Config:
admin-v2/vitest.config.ts
TC-9-01 | Admin 登录(正常)
- Step 90: 登录 Admin V2
在浏览器中打开 Admin V2(默认 http://localhost:5174),使用管理员凭据登录。
Expected: 登录成功,Cookie 设置正确
TC-9-02 | 15 页面 CRUD(正常)
- Step 91: 逐一验证 15 个页面加载
| 页面 | 测试操作 | 预期 |
|---|---|---|
| Dashboard | 查看概览 | 数据正常显示 |
| Accounts | 查看/编辑账户 | CRUD 正常 |
| ModelServices | CRUD 操作 | 模型配置正确保存 |
| Relay | 查看中继任务 | 列表显示 |
| Billing | 查看计费 | 信息显示 |
| Logs | 查看日志 | 分页正常 |
| Prompts | CRUD + 版本 | 版本历史正确 |
| Roles | CRUD | 角色权限正确 |
| Knowledge | CRUD + 搜索 | FTS5 搜索工作 |
| ScheduledTasks | CRUD | 调度配置正确 |
| AgentTemplates | CRUD | 模板保存正确 |
| Usage | 查看 | 统计图表显示 |
| Config | 查看/编辑 | 配置同步 |
| Login | 登录/登出 | 认证流程完整 |
每个页面截图一张。
TC-9-03 | M8-02 验证: Relay 缺 retry(正常)
- Step 92: 检查 Relay 页面是否有重试按钮
Expected (如未修复): Relay 任务只有查看,无重试操作 Expected (如已修复): 有重试按钮
TC-9-04 | 5 页缺失测试验证(正常)
- Step 93: 确认 5 个缺测试页面的状态
| 缺测试页面 | 验证方式 |
|---|---|
| Billing | 手动 CRUD 测试 |
| ConfigSync | 手动同步测试 |
| Knowledge | FTS5 搜索测试 |
| Roles | CRUD + 权限测试 |
| ScheduledTasks | CRUD 测试 |
TC-9-05 | TOTP 验证(正常)
- Step 94: Admin 账户设置 TOTP
Expected: QR 码显示,TOTP 验证通过
TC-9-06 | M8-03 验证: ROLE_PERMISSIONS 硬编码(边界)
- Step 95: 验证前端权限是否与后端同步
Expected (如未修复): 前端硬编码权限与后端可能不一致 Expected (如已修复): 权限从 API 动态获取
- Step 96: Commit T9 测试结果
git add docs/test-results/T9-admin/
git commit -m "test(T9): admin V2 audit results"
git push
Task 10: T10 通信与安全
V12 健康度: 86/100 | 风险: LOW | V12 问题: M9-01~M9-09 (P2/P3)
Files:
- Audit:
docs/features/audit-v12/M9-communication-security.md
TC-10-01 | 三模式连接验证(正常)
- Step 97: 验证 Kernel 模式连接
Expected: Tauri invoke 正常工作
- Step 98: 验证 SaaS Relay 模式连接
Expected: HTTP Cookie + SSE 正常
TC-10-02 | M9-01/M9-02 验证: require() 混用(P2)
- Step 99: 检查 SaaS Relay 分支是否使用 require()
在浏览器控制台观察是否有 CommonJS 错误。
Expected (如未修复): ESM+Vite 环境下 require() 报错 Expected (如已修复): 使用 await import() 替代
TC-10-03 | 安全基线验证(正常)
- Step 100: 运行安全相关 cargo test
cargo test --workspace -- security 2>&1 | tee docs/test-results/T10-security/cargo-security.txt
Expected: 安全测试全部通过
TC-10-04 | JWT/TOTP/限流验证(正常)
- Step 101: 验证 JWT password_version 机制
修改密码后,旧 JWT 应失效。
- Step 102: 验证登录限流(5次/分钟)
快速尝试 6 次登录。
Expected: 第 6 次被限流拒绝
- Step 103: Commit T10 测试结果
git add docs/test-results/T10-security/
git commit -m "test(T10): communication and security audit results"
git push
Task 11: T11 SaaS 后端 API
V12 健康度: N/A | 风险: MEDIUM | 无 V12 审计报告
Files:
- Source:
crates/zclaw-saas/src/(12 modules + workers),crates/zclaw-saas/tests/
TC-11-01 | SaaS 集成测试基线(正常)
- Step 104: 运行 SaaS 集成测试
cd crates/zclaw-saas && cargo test 2>&1 | tee ../../../docs/test-results/T11-saas-api/cargo-test.txt
Expected: 全部 pass
TC-11-02 | 核心 API 端点抽样验证(正常)
- Step 105: 验证关键端点
| 端点 | 方法 | 预期 |
|---|---|---|
| /api/v1/auth/login | POST | 返回 JWT |
| /api/v1/auth/me | GET | 返回用户信息 |
| /api/v1/relay/models | GET | 返回模型列表 |
| /api/v1/relay/chat/completions | POST | SSE 流 |
| /api/v1/admin/accounts | GET | 返回账户列表 |
| /api/v1/admin/dashboard/stats | GET | 返回统计数据 |
每个端点用 curl 验证:
# 示例
curl -s -X POST http://localhost:8080/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"test"}' | jq .
TC-11-03 | 权限检查验证(正常)
- Step 106: 验证非管理员无法访问 admin 端点
Expected: 返回 403 Forbidden
TC-11-04 | 数据库迁移验证(正常)
- Step 107: 验证数据库 schema 版本
PGPASSWORD=zclaw psql -h localhost -U zclaw -d zclaw -c "SELECT * FROM _schema_version;" 2>&1
Expected: schema_version = 14(当前版本)
- Step 108: Commit T11 测试结果
git add docs/test-results/T11-saas-api/
git commit -m "test(T11): SaaS backend API audit results"
git push
Task 12: T12 端到端用户场景
V12 健康度: N/A | 风险: HIGH | 跨模块集成
TC-12-01 | E2E-01: 新用户首次对话
- Step 109: 完整新用户对话流程
- 打开应用 → 首次引导
- 选择模型 → 发送消息
- 验证流式响应
涉及模块: T8, T3, T7
take_screenshot(filePath='docs/test-results/T12-e2e/screenshots/TC-12-01-first-chat.png')
TC-12-02 | E2E-02: Agent 创建与使用
- Step 110: 创建 Agent → 配置 → 切换 → 验证身份
涉及模块: T3, T8, T2
TC-12-03 | E2E-03: Hand 触发与审批
- Step 111: 对话中触发 Hand → 审批 → 查看结果
涉及模块: T1, T2, T8
TC-12-04 | E2E-04: SaaS 登录与订阅
- Step 112: SaaS 登录 → 订阅状态 → 配置同步
涉及模块: T6, T10
TC-12-05 | E2E-05: Pipeline 创建与执行
- Step 113: 创建 Pipeline → 配置 → 执行 → 导出
涉及模块: T5, T1
TC-12-06 | E2E-06: 记忆与反思闭环
- Step 114: 多轮对话 → 记忆提取 → 验证存储 → 反思触发
涉及模块: T2, T3, T8
TC-12-07 | E2E-07: Admin 管理全流程
- Step 115: Admin 登录 → 管理 → 配置 → 日志
涉及模块: T9, T11
TC-12-08 | E2E-08: 离线与重连
- Step 116: 断开 SaaS 后端 → 离线模式 → 恢复 → 重连
- 关闭 SaaS 后端进程
- 验证应用降级到 Kernel 模式
- 恢复 SaaS 后端
- 验证自动重连
涉及模块: T1, T2, T6, T8
TC-12-09 | E2E-09: 课堂场景播放
- Step 117: 进入课堂 → 播放 → TTS → 白板 → 笔记
涉及模块: T4, T1
TC-12-10 | E2E-10: 技能发现与执行
- Step 118: 浏览技能 → 安装 → 触发 → 验证结果
涉及模块: T7, T8
TC-12-11 | 回归验证
- Step 119: 重新运行基线测试
cargo test --workspace 2>&1 | tee docs/test-results/T12-e2e/regression-cargo.txt
cd desktop && pnpm vitest run 2>&1 | tee ../docs/test-results/T12-e2e/regression-vitest.txt
cd admin-v2 && pnpm vitest run 2>&1 | tee ../docs/test-results/T12-e2e/regression-admin.txt
Expected: 通过率不低于基线
- Step 120: 生成最终缺陷清单
在 docs/test-results/DEFECT_LIST.md 中汇总所有 T1-T12 发现的缺陷:
-
P0 缺陷数(目标: 0)
-
P1 缺陷数(目标: <= 2)
-
P2/P3/P4 缺陷列表
-
Step 121: 生成上线评估报告
在 docs/test-results/RELEASE_READINESS.md 中对照达标标准:
| 强制达标项 | 标准 | 结果 |
|---|---|---|
| P0 缺陷 | 0 | ? |
| P1 缺陷 | <= 2 | ? |
| 核心流程通过 | 100% | ? |
| 自动化测试 | 全部通过 | ? |
| 安全 | 无 HIGH 缺陷 | ? |
- Step 122: Commit 最终结果
git add docs/test-results/
git commit -m "test: complete pre-launch functional audit T1-T12"
git push
执行总结
测试用例统计
| 模块 | 风险 | 测试用例数 | 预计时间 |
|---|---|---|---|
| T0 环境准备 | - | 11 步 | 0.5 天 |
| T1 Hands | HIGH | 23 用例 | 1 天 |
| T2 智能层 | HIGH | 13 用例 | 1 天 |
| T3 Agent | HIGH | 12 用例 | 0.5 天 |
| T4 课堂 | HIGH | 12 用例 | 0.5 天 |
| T5 Pipeline | MEDIUM | 8 用例 | 0.5 天 |
| T6 SaaS 集成 | MEDIUM | 6 用例 | 0.5 天 |
| T7 技能 | LOW | 6 用例 | 0.5 天 |
| T8 对话 | LOW | 7 用例 | 0.5 天 |
| T9 Admin | MEDIUM | 6 用例 | 0.5 天 |
| T10 安全 | LOW | 4 用例 | 0.5 天 |
| T11 SaaS API | MEDIUM | 4 用例 | 0.5 天 |
| T12 E2E | HIGH | 11 用例 | 1.5 天 |
| 总计 | ~123 用例 | 8-10 天 |
注: 实际用例数 ~123 低于 spec 估计的 170-230,因为本计划聚焦于 V12 已知问题验证和核心流程测试,而非穷举测试。每个模块的边界和异常用例可在执行中根据发现的问题补充。
执行顺序
Phase 1: Task 0 (环境准备) → 阻塞门控
Phase 2: T1 → T2 → T3 → T4 (高风险模块)
Phase 3: T5 → T6 → T7 → T8 → T9 → T10 → T11 (中低风险)
Phase 4: T12 (E2E 集成)
最终: DEFECT_LIST.md + RELEASE_READINESS.md
上线达标门控
在 Phase 2 完成后(T1-T4),检查:
- P0 缺陷 = 0
- P1 缺陷 <= 2
- 聊天/Agent CRUD/Hand 触发/SaaS 登录 4 条主路径通过
如果未达标,暂停 Phase 3,优先修复 P0/P1。