Files
zclaw_openfang/docs/superpowers/plans/2026-04-05-pre-launch-functional-audit.md
iven 0a3ba2fad4
Some checks failed
CI / Lint & TypeCheck (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Build Frontend (push) Has been cancelled
CI / Rust Check (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
docs: add pre-launch functional audit test execution plan (T1-T12, 5 chunks, 112 TCs)
2026-04-05 17:53:39 +08:00

2402 lines
68 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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-mcpRust 用 cargo testAdmin 用 Playwright + vitestSaaS 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=NoneLLM 分析从未生效
- [ ] **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 manifestKernel 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_locktokio 可能死锁
- [ ] **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_errP1
**V12 问题:** Stage 0/1 LLM 调用无 map_errdriver 未配置时可能 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 bodyP1
**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 误映射为 triggersP1
**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