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
2402 lines
68 KiB
Markdown
2402 lines
68 KiB
Markdown
# 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。
|