From 0a3ba2fad4f35bc774b3d5088b9ffe36deff7b90 Mon Sep 17 00:00:00 2001 From: iven Date: Sun, 5 Apr 2026 17:53:39 +0800 Subject: [PATCH] docs: add pre-launch functional audit test execution plan (T1-T12, 5 chunks, 112 TCs) --- .../2026-04-05-pre-launch-functional-audit.md | 2401 +++++++++++++++++ 1 file changed, 2401 insertions(+) create mode 100644 docs/superpowers/plans/2026-04-05-pre-launch-functional-audit.md diff --git a/docs/superpowers/plans/2026-04-05-pre-launch-functional-audit.md b/docs/superpowers/plans/2026-04-05-pre-launch-functional-audit.md new file mode 100644 index 0000000..622e969 --- /dev/null +++ b/docs/superpowers/plans/2026-04-05-pre-launch-functional-audit.md @@ -0,0 +1,2401 @@ +# 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 审计后代码已发生变更,部分命令名称/参数可能已更新。**执行前必须**: +> 1. 验证每个 Tauri 命令名是否存在于 `desktop/src-tauri/src/lib.rs` 的 `invoke_handler` 注册列表中 +> 2. 验证参数签名是否匹配 Rust 函数定义 +> 3. 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: 创建测试结果目录** + +```bash +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** + +```bash +docker compose up -d postgres +``` + +Expected: `docker compose ps` 显示 postgres healthy + +- [ ] **Step 3: 启动 SaaS 后端** + +```bash +cd crates/zclaw-saas && ZCLAW_SAAS_DEV=true cargo run +``` + +Expected: 服务监听 `0.0.0.0:8080`,日志无 ERROR + +- [ ] **Step 4: 启动 Tauri 桌面端** + +```bash +cd desktop && pnpm tauri dev +``` + +Expected: 窗口打开,无 panic + +- [ ] **Step 5: 验证 tauri-mcp 连接** + +```python +manage_window(action='list') +``` + +Expected: 返回至少 1 个窗口,标题含 "ZCLAW" + +- [ ] **Step 6: 运行 Rust 基线测试** + +```bash +cargo test --workspace 2>&1 | tee docs/test-results/baseline/cargo-test.txt +``` + +Expected: 全部 pass,记录总测试数和通过数 + +- [ ] **Step 7: 运行 Desktop 前端基线测试** + +```bash +cd desktop && pnpm vitest run 2>&1 | tee ../docs/test-results/baseline/desktop-vitest.txt +``` + +Expected: 全部 pass,记录总测试数 + +- [ ] **Step 8: 运行 Admin 前端基线测试** + +```bash +cd admin-v2 && pnpm vitest run 2>&1 | tee ../docs/test-results/baseline/admin-vitest.txt +``` + +Expected: 全部 pass,记录总测试数 + +- [ ] **Step 9: 确认 LLM Provider 可用** + +通过 tauri-mcp 在桌面端: +```python +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 基线** + +```bash +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: 导航到自动化面板** + +```python +query_page(mode='map', interactive_only=True) +``` +找到 Automation/Hands 相关导航元素。 + +```python +click(selector_type='ref', selector_value='{nav_ref}') +``` + +Expected: 自动化面板显示 9 个已启用的 Hand + +- [ ] **Step 2: 截图记录 Hand 列表** + +```python +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: +```python +click(selector_type='ref', selector_value='{researcher_ref}') +``` + +如有参数输入框,输入测试参数: +```python +type_text(text='测试研究主题:AI Agent 框架对比') +``` + +点击执行: +```python +click(selector_type='ref', selector_value='{execute_ref}') +``` + +Expected: Hand 进入 running 状态 + +- [ ] **Step 4: 验证执行状态** + +```python +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 检查返回值结构: +```javascript +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: 截图记录** + +```python +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 是否自动更新** + +1. 触发一个 Hand(如 Quiz) +2. 不手动刷新页面 +3. 等待 30 秒 + +```python +# 触发 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: 截图** + +```python +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 并触发: +```python +click(selector_type='ref', selector_value='{browser_ref}') +``` + +配置参数(如打开网页): +```python +type_text(text='https://example.com') +click(selector_type='ref', selector_value='{execute_ref}') +``` + +Expected (如未修复): 返回结构化指令 JSON 但不执行浏览器操作 +Expected (如已修复): 实际打开/访问网页 + +- [ ] **Step 10: 对比 browserHandStore 路径** + +通过 tauri-mcp 检查是否有独立的浏览器面板/功能: +```python +query_page(mode='map', interactive_only=True) +``` + +Expected: browserHandStore 有独立的浏览器操作 UI,绕过 handStore 审批流程 + +- [ ] **Step 11: 截图** + +```python +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: +```python +navigate(action='goto', url='tauri://localhost/settings/automation') +# 或点击设置页 +click(selector_type='ref', selector_value='{settings_ref}') +``` + +找到自主级别滑块/下拉框,设置为"需审批"。 + +- [ ] **Step 13: 通过 browserHandStore 执行操作** + +在浏览器面板执行一个操作(如导航到 URL)。 + +Expected (如未修复): 操作直接执行,不弹出审批确认 +Expected (如已修复): 弹出审批确认对话框 + +- [ ] **Step 14: 截图** + +```python +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: 审批通过** + +```python +click(selector_type='ref', selector_value='{approve_ref}') +``` + +Expected: Hand 开始执行,完成后结果出现在 UI + +- [ ] **Step 17: 审批拒绝(重新触发)** + +再次触发需审批的 Hand,这次拒绝: +```python +click(selector_type='ref', selector_value='{reject_ref}') +``` + +Expected: Hand 不执行,状态显示"已拒绝" + +- [ ] **Step 18: 截图记录审批流程** + +```python +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): +```javascript +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: 截图** + +```python +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 配置: +```bash +grep -r "timeout_secs" hands/*.HAND.toml +``` + +Expected (如未修复): Hand 无超时保护,可能无限运行 +Expected (如已修复): 超过 timeout_secs 后 Hand 自动终止 + +- [ ] **Step 22: 截图** + +```python +take_screenshot(filePath='docs/test-results/T1-hands/screenshots/TC-1-09-timeout.png') +``` + +#### TC-1-10 | Hand 取消(正常) + +- [ ] **Step 23: 触发长时间 Hand 并中途取消** + +触发一个 Hand,在其 running 状态时点击取消: +```python +click(selector_type='ref', selector_value='{cancel_ref}') +``` + +Expected: Hand 停止执行,状态变为 cancelled + +- [ ] **Step 24: 截图** + +```python +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 事件)。 + +```python +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: +```javascript +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 检查: +```javascript +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 | 主题:"架构图" | 显示白板 | +| Twitter | (需 OAuth 配置) | 检查是否正确报告配置缺失 | +| Clip | (需 FFmpeg) | 检查是否正确报告依赖缺失 | +| Browser | URL:"https://example.com" | 返回操作结果 | + +每个 Hand 截图一张: +```python +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 时查询状态: + +```javascript +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 完整返回值** + +```javascript +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: 截图** + +```python +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 返回值** + +```javascript +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 配置被正确读取** + +```javascript +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 传入无效参数** + +```javascript +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 结果** + +```javascript +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) + +- [ ] **截图** + +```python +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 使用含单引号的路径** + +```javascript +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** + +1. 进入设置,移除当前 Agent 的 API Key +2. 触发 Researcher Hand +3. 恢复 API Key + +Expected: 返回明确错误提示("未配置 API Key" 等),非 panic/空结果 + +#### TC-1-23 | 超长输入触发 Hand(边界) + +- [ ] **Step 35e: 触发 Hand 传入超长字符串** + +```javascript +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 测试结果** + +```bash +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) + +```bash +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: 通过前端保存一条记忆** + +导航到记忆面板: +```python +navigate(action='goto', url='tauri://localhost/memories') +# 或通过导航点击 +``` + +手动保存一条记忆:"测试记忆条目 - 上线前审计"。 + +```python +take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-01a-save-memory.png') +``` + +- [ ] **Step 2: 验证该记忆出现在对话注入中** + +进入对话界面,发送消息触发记忆搜索(发送与记忆相关的问题)。 + +```python +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 自动提取的记忆是否出现在前端面板** + +进行多轮对话,触发自动记忆提取。然后检查记忆面板是否显示新提取的记忆。 + +```python +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 直接调用反思: +```javascript +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 调用记录: +```bash +# 如果日志输出到文件 +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: 截图** + +```python +take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-02-reflection.png') +``` + +#### TC-2-03 | 记忆 CRUD(正常) + +- [ ] **Step 7: 创建记忆** + +```python +navigate(action='goto', url='tauri://localhost/memories') +``` + +创建一条新记忆: +- 类型: fact +- 内容: "ZCLAW 上线前审计测试记忆" +- 重要性: 7 + +```python +take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-03a-create-memory.png') +``` + +- [ ] **Step 8: 搜索记忆** + +搜索关键词 "上线前审计"。 + +```python +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: 记忆从列表中消失 + +```python +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: 测试搜索精度** + +1. 创建多条记忆,内容包含 "机器学习" +2. 搜索 "机器" +3. 搜索 "学习" + +Expected (LIKE): 两个搜索都返回结果(模糊匹配) +Expected (FTS5): "机器" 返回结果,"学习" 可能不返回(分词差异) + +```python +take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-04-search-like.png') +``` + +#### TC-2-05 | 身份演化(正常) + +- [ ] **Step 12: 查看当前 Agent 身份** + +```javascript +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: 提出身份变更提案** + +```javascript +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: 审批/拒绝身份变更** + +```python +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: 检查心跳是否自动运行** + +应用启动后,检查心跳状态: +```javascript +async () => { + const result = await window.__TAURI_INTERNALS__.invoke('heartbeat_status', {}); + return JSON.stringify(result); +} +``` + +Expected (如未修复): 心跳未运行(需手动启动) +Expected (如已修复): 心跳自动启动并运行 + +- [ ] **Step 16: 手动启动心跳(如未自动启动)** + +```javascript +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: 截图** + +```python +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 命令绕过前端: +```javascript +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: 触发上下文压缩** + +进行多轮对话使上下文变长,然后触发压缩: +```javascript +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 + +```python +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: 测试传入多种类型搜索** + +```javascript +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: 保存超长记忆** + +```javascript +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: 设置极短心跳间隔** + +```javascript +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: 在无记忆的情况下触发反思** + +```javascript +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 的默认配置是否一致。 + +```python +take_screenshot(filePath='docs/test-results/T2-intelligence/screenshots/TC-2-13-compaction-dual.png') +``` + +- [ ] **Step 25: Commit T2 测试结果** + +```bash +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) + +```bash +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 列表** + +```python +query_page(mode='map', interactive_only=True) +``` + +找到 Agent 选择器/管理入口并点击。 + +Expected: 显示至少 1 个默认 Agent + +```python +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" +- 描述: "用于测试字段传递" +- 表情: "🤖" +- 性格: "严谨、精确" +- 沟通风格: "技术导向" +- 备注: "测试备注" + +```python +type_text(text='审计测试 Agent') +# 依次填写其他字段 +click(selector_type='ref', selector_value='{create_ref}') +``` + +- [ ] **Step 29: 检查 SQLite 中 Agent 配置** + +```javascript +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 包含所有传入的人格字段 + +```python +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: +1. Agent A: 通过 Kernel 模式创建 +2. Agent B: 通过 Gateway 模式创建(如 Gateway 可用) + +对比两个 Agent 的配置完整度。 + +Expected (如未修复): Kernel 创建的 Agent 缺少人格字段,Gateway 创建的完整 +Expected (如已修复): 两条通路创建结果一致 + +```python +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 +- 更新模型 + +```python +click(selector_type='ref', selector_value='{edit_ref}') +type_text(text='审计测试 Agent - 已更新') +click(selector_type='ref', selector_value='{save_ref}') +``` + +Expected: 所有更新生效 + +```python +take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-04-update.png') +``` + +#### TC-3-05 | Agent 切换(正常) + +- [ ] **Step 32: 切换到新创建的 Agent** + +```python +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 身份** + +```python +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 状态** + +```javascript +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** + +1. 发送一条长消息(触发长时间流式响应) +2. 在流式响应进行中,切换到另一个 Agent + +```python +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 (如已修复): 切换前自动取消进行中的流 + +```python +take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-07-switch-during-stream.png') +``` + +#### TC-3-08 | Agent 删除(正常) + +- [ ] **Step 36: 删除测试 Agent** + +```python +click(selector_type='ref', selector_value='{delete_ref}') +``` + +Expected: 删除成功,Agent 从列表消失 + +#### TC-3-09 | M2-05 验证: 删除不检查活跃状态(异常) + +**V12 问题:** 删除正在使用的 Agent 无警告 + +- [ ] **Step 37: 删除当前活跃的 Agent** + +切换到一个 Agent,然后直接删除它。 + +Expected (如未修复): 直接删除,无警告 +Expected (如已修复): 弹出警告"该 Agent 正在使用中" + +```python +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** + +```javascript +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** + +```javascript +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 后检查状态** + +1. 选中 Agent A +2. 删除 Agent A +3. 检查 conversationStore.currentAgent 是否有效 + +```javascript +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** + +检查是否有模板创建功能,如有则测试。 + +```python +take_screenshot(filePath='docs/test-results/T3-agent/screenshots/TC-3-12-template-create.png') +``` + +- [ ] **Step 42: Commit T3 测试结果** + +```bash +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) + +```bash +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: 触发课堂生成** + +导航到课堂功能,输入主题生成课堂: +```python +type_text(text='Rust 所有权系统') +click(selector_type='ref', selector_value='{generate_ref}') +``` + +Expected: 显示生成进度,4 阶段 pipeline 逐步完成 + +- [ ] **Step 45: 等待生成完成** + +```python +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: 生成过程中取消课堂** + +1. 开始生成一个课堂 +2. 在生成过程中点击取消 + +```python +click(selector_type='ref', selector_value='{cancel_generation_ref}') +``` + +Expected (如未修复): 取消请求可能触发 tokio 死锁,应用卡住 +Expected (如已修复): 取消成功,生成停止,无死锁 + +```python +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: 播放已生成的课堂场景** + +```python +click(selector_type='ref', selector_value='{scene_1_ref}') +``` + +Expected: 场景自动播放,显示 speech/whiteboard/quiz actions + +```python +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 语言朗读场景内容 + +```python +take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-05-tts.png') +``` + +#### TC-4-06 | 白板渲染(正常) + +- [ ] **Step 50: 查看白板场景** + +导航到含白板 action 的场景。 + +Expected: 白板内容正确渲染(SVG 或 Canvas) + +```python +take_screenshot(filePath='docs/test-results/T4-classroom/screenshots/TC-4-06-whiteboard.png') +``` + +#### TC-4-07 | M11-03 验证: 课堂数据仅存内存(P1) + +**V12 问题:** HashMap 存储,重启丢失 + +- [ ] **Step 51: 重启应用后检查课堂数据** + +1. 确认有已生成的课堂 +2. 重启 Tauri 应用 +3. 检查课堂是否还在 + +Expected (如未修复): 重启后所有课堂消失 +Expected (如已修复): 课堂数据持久化,重启后仍存在 + +#### TC-4-08 | 课堂聊天(正常) + +- [ ] **Step 52: 在课堂中进行聊天** + +```python +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** + +```python +click(selector_type='ref', selector_value='{export_ref}') +``` + +Expected: 文件下载成功 + +```python +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 测试结果** + +```bash +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 列表** + +```python +navigate(action='goto', url='tauri://localhost/pipelines') +``` + +Expected: 显示已有 Pipeline(含 10 行业模板) + +```python +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 是否显示** + +```javascript +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** + +```python +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 测试结果** + +```bash +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 恢复 + +```python +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 测试结果** + +```bash +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 字段** + +```javascript +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 全部加载** + +```javascript +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 测试结果** + +```bash +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: 发送消息验证流式响应** + +```python +type_text(text='你好,请介绍一下你自己') +click(selector_type='ref', selector_value='{send_ref}') +wait_for(text=['AI', '助手', '你好'], timeout_ms=15000) +``` + +Expected: 流式响应正常显示 + +```python +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 格式回复** + +```python +type_text(text='请用 Markdown 格式列出 5 个编程语言的特点') +``` + +Expected: 代码块、列表、表格等正确渲染 + +- [ ] **Step 89: Commit T8 测试结果** + +```bash +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 测试结果** + +```bash +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** + +```bash +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 测试结果** + +```bash +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 集成测试** + +```bash +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 验证: +```bash +# 示例 +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 版本** + +```bash +PGPASSWORD=zclaw psql -h localhost -U zclaw -d zclaw -c "SELECT * FROM _schema_version;" 2>&1 +``` + +Expected: schema_version = 14(当前版本) + +- [ ] **Step 108: Commit T11 测试结果** + +```bash +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: 完整新用户对话流程** + +1. 打开应用 → 首次引导 +2. 选择模型 → 发送消息 +3. 验证流式响应 + +涉及模块: T8, T3, T7 + +```python +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 后端 → 离线模式 → 恢复 → 重连** + +1. 关闭 SaaS 后端进程 +2. 验证应用降级到 Kernel 模式 +3. 恢复 SaaS 后端 +4. 验证自动重连 + +涉及模块: 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: 重新运行基线测试** + +```bash +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 最终结果** + +```bash +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。