docs: consolidate core integration cases

This commit is contained in:
Haitao Pan 2026-04-05 18:24:10 +08:00
parent b542229311
commit 0d31858cf2
11 changed files with 924 additions and 428 deletions

View File

@ -1,42 +1,27 @@
# Multi-Agent Cases
# 核心集成测试 Cases
这组案例用于手动验证 `XWorkmate` 当前的多 Agent 协作链路,覆盖:
`docs/cases/` 只保留当前项目主线需要长期维护的手动集成用例,不再承载旧的多 Agent / ARIS / 外部桥接历史 case。
- `单机智能体`
- `本地 OpenClaw Gateway`
- `远程 OpenClaw Gateway`
- `ARIS + 本地 Ollama`
- `Architect / Engineer / Tester`
- `Go core reviewer`
- `外部 Agent CLI / JSON-RPC session`
## 当前入口
## 推荐验证顺序
- [核心功能集成测试手动 Case](./core-integration-manual-cases.md)
1. [ARIS 本地 Ollama 功能交付](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/aris_local_ollama_feature_delivery.md)
2. [ARIS 缺陷修复与审阅循环](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/aris_bugfix_review_loop.md)
3. [外部 Agent CLI Bridge 会话](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/external_agent_bridge_session.md)
4. [模式切换与线程连续追问](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/thread_mode_switch_followup.md)
5. [Intent Router + Skill Resolver + Memory Injector 典型用例](/Users/shenlan/workspaces/cloud-neutral-toolkit/xworkmate/docs/cases/intent_router_skill_memory_typical_cases.md)
## 配套文档
## 相关设计文档
- [核心功能集成测试自动化规划](../testing/core-integration-auto-test-plan.md)
- [XWorkmate 测试规范模板与指南](../testing/xworkmate-test-spec.md)
- [XWorkmate 测试规范](../quality/xworkmate-test-spec.md)
- [Assistant 任务线程信息架构](/Users/shenlan/workspaces/cloud-neutral-toolkit/xworkmate.svc.plus/docs/architecture/assistant-thread-information-architecture.md)
## 使用建议
## 你应该重点观察的点
推荐顺序:
- Assistant 仍复用现有输入框、附件、技能和当前线程
- `ARIS` 模式下会显示框架状态,但不会改变主布局
- 协作任务应按 `Architect -> Engineer -> Tester` 顺序推进
- 本地 Ollama 可用时,即便缺失部分云端 CLI也应能退化运行
- 线程应可继续追问,不是一答即结束
- 任务列表仍保持极简,只显示名称、时间、归档
- `llm-chat``claude-review` 由 Go core 驱动,不依赖 `go run`
1. 先看自动化规划,确认当前能力树与测试落点
2. 再按手动 Case 执行设置页与任务线程验证
3. 执行后把证据记录回具体测试单或验收报告
## 建议记录项
## 维护边界
- 当前使用的框架:`原生` 或 `ARIS`
- 当前执行模式:`单机智能体` / `本地 OpenClaw Gateway` / `远程 OpenClaw Gateway`
- 参与角色的 CLI 组合
- 是否看到流式输出
- 是否发生自动回退
- 最终是否能继续在同一线程追问
- 这里不再新增历史回溯型 postmortem 或旧架构演示 case
- 与当前主线不匹配的多 Agent / ARIS / 外部 CLI bridge 案例已移除
- 如果新增长期手动用例,必须挂到当前“设置页配置”或“任务线程”能力树下

View File

@ -1,45 +0,0 @@
# ARIS 缺陷修复与审阅循环
## 目标
验证 `Tester` 低分时ARIS 会进入迭代审阅循环,而不是直接结束。
## 推荐配置
- 框架:`ARIS`
- 执行模式:`本地 OpenClaw Gateway`
- Ollama 端点:`http://127.0.0.1:11434`
- Architect`gemini`
- Engineer`claude` 或 `opencode`
- Tester`codex`
## 建议任务
```text
修复当前项目里一个设置页的小问题:
1. 找一个明显的 widget test 稳定性问题
2. 先解释问题根因
3. 再做最小修复
4. 必须补回归测试
5. 如果测试或评审认为还不稳,继续迭代直到通过
```
## 期望表现
- `Architect` 先做问题拆解
- `Engineer` 提交第一版修复
- `Tester` 如果认为不稳,应给出明确问题点
- 系统会继续推进修复,而不是停在第一次回答
## 重点看什么
- 是否真的出现第二轮或更多轮 review / fix
- `Tester` 的反馈是否具体
- `Engineer` 是否基于上一轮反馈继续修改
- 最终线程是否仍可继续追问
## 通过标准
- 至少看到一次明确的审阅反馈
- 如果第一次未达标,能看到迭代继续
- 最终产物包含测试状态说明

View File

@ -1,51 +0,0 @@
# ARIS 本地 Ollama 功能交付
## 目标
验证 `ARIS + 本地 Ollama` 在标准三角色链路下可以完成一条完整的小功能交付任务。
## 推荐配置
- 框架:`ARIS`
- 执行模式:`单机智能体` 或 `本地 OpenClaw Gateway`
- Ollama 端点:`http://127.0.0.1:11434`
- Architect`gemini`
- Engineer`opencode`
- Tester`codex`
## 建议任务
把下面这段话直接粘到 Assistant
```text
为当前 Flutter 工作区补一个「最近任务过滤器」:
1. 仅在现有任务列表顶部增加一个最近 24 小时过滤开关
2. 默认关闭,开启后只显示最近 24 小时更新过的任务
3. 不改变现有卡片布局
4. 补最小单测
5. 最后给出修改摘要和风险点
```
## 期望表现
- `Architect` 先给出拆解和约束
- `Engineer` 再进入实现
- `Tester` 最后做审阅和测试反馈
- 若 `Tester` 评分不足,会自动进入 review / fix 循环
- 线程保持 `open`,可以继续追问
## UI 观察点
- 顶部或会话状态中能看到当前是 `ARIS`
- 流程消息按阶段顺序出现
- 不会弹出独立 ARIS 页面
- 任务列表仍然是极简布局
## 通过标准
- 至少完成一轮 `Architect -> Engineer -> Tester`
- 会话能持续,不会一答即结束
- 最终结果里包含:
- 改动摘要
- 测试结果
- 风险或后续建议

View File

@ -0,0 +1,329 @@
# 核心功能集成测试手动 Case
## 1. 使用说明
这份文档只保留当前项目主线的核心手动用例:
- 设置页面配置功能
- 任务线程场景测试
每个 case 都要求记录统一证据,最少包含:
- 当前模式
- 当前 provider / endpoint
- 输入提示词或操作
- 结果摘要
- 产物路径或截图点
- 是否需要外部服务人工确认
## 2. 设置页面配置功能
### `MANUAL-ACP-001` 在线用户同步后默认值与本地 override 共存
- 前置条件
- 已登录在线账户
- 账户侧存在可同步的 Gateway / ACP 默认配置
- 本地有一项可区分的 override 值
- 操作步骤
1. 打开 `Settings -> Integrations -> Gateway`
2. 触发账户同步或重进设置页等待同步完成
3. 观察远程默认 endpoint 与本地 override 的展示
4. 返回主页面,再次进入设置页确认状态稳定
- 期望结果
- 远程默认配置被注入
- 本地 override 没有被覆盖
- 页面不显示 secret 明文
- 建议记录项
- 当前登录账户
- 同步前后 endpoint 对比
- 是否看到 secret 明文
- 截图点:同步完成后的设置页
### `MANUAL-ACP-002` selfhost ACP 远程接入
- 前置条件
- 有可访问的 selfhost ACP 基址
- 若服务需要 auth准备好 auth 值
- 操作步骤
1. 进入 `Settings -> Integrations -> Gateway`
2. 输入 selfhost 基址,例如 `https://host.example.com/opencode`
3. 如有需要,填写 auth
4. 点击 `测试连接`
5. 保存并生效,返回页面再次确认
- 期望结果
- 连接测试成功或失败信息明确
- 内部派生路径符合 `/acp``/acp/rpc`
- 保存后页面状态稳定,重新进入不会丢失 endpoint
- 建议记录项
- provider / endpoint
- auth 是否为空
- 测试连接结果摘要
- 截图点:测试连接结果
### `MANUAL-ACP-003` local ACP / local 模式接入
- 前置条件
- 本机已有 local / loopback ACP 服务
- 确认监听地址与端口
- 操作步骤
1. 输入 loopback endpoint例如 `http://127.0.0.1:9001/opencode`
2. 点击 `测试连接`
3. 保存并生效
4. 关闭设置页后重新进入确认仍然显示 local endpoint
- 期望结果
- local / loopback 非 TLS 允许通过
- 页面明确显示当前为本地配置
- 不会把 local endpoint 错误识别为 remote insecure endpoint
- 建议记录项
- 当前模式
- loopback endpoint
- 测试连接结果
- 是否需要本机服务日志人工对照
## 3. 本地执行型任务线程
### `MANUAL-LOCAL-001` `powerpoint-pptx`
- 前置条件
- `pptx` 技能可用
- 当前线程为空白或新建线程
- 操作步骤
1. 在 assistant 线程中选择 `powerpoint-pptx`
2. 输入“生成一个三页产品介绍演示稿”
3. 等待任务完成
4. 在同一线程继续追问“把第二页改成对比页”
- 期望结果
- 当前线程生成 `.pptx` 产物
- 产物显示在当前线程 artifact 区域
- 第二次追问延续同一线程上下文
- 建议记录项
- 线程 ID 或线程标题
- 输入提示词
- 产物路径
- 截图点artifact 列表与连续追问结果
### `MANUAL-LOCAL-002` `word-docx`
- 前置条件
- `word-docx` 技能可用
- 操作步骤
1. 选择 `word-docx`
2. 输入“生成一份包含标题、目录和表格的周报文档”
3. 等待结果生成
- 期望结果
- 当前线程返回 `.docx` 产物
- 结果归属当前线程
- 不会跳到其他 provider 或其他线程
- 建议记录项
- 当前模式
- provider
- 文档产物路径
- 结果摘要
### `MANUAL-LOCAL-003` `excel-xlsx`
- 前置条件
- `excel-xlsx` 技能可用
- 操作步骤
1. 选择 `excel-xlsx`
2. 输入“生成一个带汇总公式的销售表”
3. 等待结果完成
- 期望结果
- 当前线程中出现 `.xlsx` 产物
- 线程 workspace 有对应文件
- 结果摘要说明生成成功
- 建议记录项
- 提示词
- 文件名
- artifact 区域截图
### `MANUAL-LOCAL-004` `pdf`
- 前置条件
- `pdf` 技能可用
- 操作步骤
1. 选择 `pdf`
2. 输入“合并两个 PDF 并输出新文件”
3. 等待任务完成
- 期望结果
- 当前线程生成 PDF 结果
- 失败时线程中能看到错误摘要
- 不会只显示文本而没有产物
- 建议记录项
- 输入操作
- 产物路径
- 成功或失败摘要
### `MANUAL-LOCAL-005` `image-resizer`
- 前置条件
- `image-resizer` 技能可用
- 有可处理的本地图片
- 操作步骤
1. 选择 `image-resizer`
2. 输入“将图片缩放到 1200x800 并压缩”
3. 等待任务完成
- 期望结果
- 当前线程出现处理后的图片产物
- 结果归属当前线程 workspace
- 结果摘要包含尺寸或压缩信息
- 建议记录项
- 原图与结果图路径
- 输出尺寸
- 截图点:线程结果区
### `MANUAL-LOCAL-006` 本地浏览器自动化
- 前置条件
- 本地浏览器自动化技能可用
- 有可访问网页
- 操作步骤
1. 在当前线程选择浏览器自动化技能
2. 输入“打开示例页面并提取标题”
3. 等待结果返回
- 期望结果
- 线程内返回网页操作摘要
- 如有截图或日志产物,进入当前线程 artifact
- 切换到其他线程后不复用本线程结果
- 建议记录项
- 访问网址
- 返回摘要
- 是否生成截图或日志
## 4. 在线执行任务线程
### `MANUAL-ONLINE-001` `image-cog`
- 前置条件
- 在线 provider 可用
- `image-cog` 技能可用
- 操作步骤
1. 在 assistant 线程选择 `image-cog`
2. 输入“生成一张极简产品海报”
3. 等待任务状态完成
- 期望结果
- 线程中显示在线任务结果
- 产物图片回到当前线程 artifact
- provider 显示为在线执行
- 建议记录项
- 当前 provider / endpoint
- 任务状态变化
- 图片产物路径或截图
### `MANUAL-ONLINE-002` `image-video-generation-editting`
- 前置条件
- 在线视频/图片生成服务可用
- 操作步骤
1. 选择 `image-video-generation-editting`
2. 输入“基于这张图生成 5 秒镜头推近视频”
3. 等待任务轮询完成
- 期望结果
- 线程内可见任务处理中间状态或最终状态
- 最终产物回传到当前线程
- 失败时有明确错误摘要
- 建议记录项
- 任务开始与结束时间
- 视频或图片结果路径
- 是否需要外部服务后台确认
### `MANUAL-ONLINE-003` `video-translator`
- 前置条件
- 在线翻译/配音服务可用
- 准备一个待翻译视频
- 操作步骤
1. 选择 `video-translator`
2. 输入“将视频翻译成英文并输出字幕版”
3. 等待任务完成
- 期望结果
- 当前线程返回翻译后的视频或字幕产物
- 线程中可见任务成功或失败摘要
- 不会丢失当前线程上下文
- 建议记录项
- 输入视频来源
- 结果产物路径
- 错误信息或成功摘要
### `MANUAL-ONLINE-004` 资讯采集
- 前置条件
- 在线采集能力可用
- 操作步骤
1. 选择资讯采集能力
2. 输入“采集今天关于 AI Agent 的 5 条资讯”
3. 查看结果
- 期望结果
- 线程返回结构化资讯结果
- 标题、来源、摘要等字段完整
- 结果留在当前线程内
- 建议记录项
- 查询词
- 结果条数
- 结果摘要截图
### `MANUAL-ONLINE-005` 搜索
- 前置条件
- 在线搜索能力可用
- 操作步骤
1. 选择搜索能力
2. 输入“搜索 XWorkmate ACP 配置说明”
3. 查看结果后继续追问“把前 3 条结果做摘要”
- 期望结果
- 搜索结果结构完整
- 连续追问复用同一线程
- 不新建孤立线程
- 建议记录项
- 初始查询词
- 连续追问内容
- 搜索结果摘要
## 5. 通用线程场景
### `MANUAL-THREAD-001` 同线程连续追问
- 前置条件
- 任意一个本地执行或在线执行任务已经成功完成
- 操作步骤
1. 在原线程继续提问“继续基于刚才结果展开 3 点”
2. 观察回复
- 期望结果
- 沿用原线程
- 回答引用刚才的结果
- 建议记录项
- 原线程标识
- 连续追问内容
- 是否保留上下文
### `MANUAL-THREAD-002` 切换线程后的状态隔离
- 前置条件
- 至少准备两个不同线程
- 操作步骤
1. 在线程 A 完成一个任务
2. 切换到线程 B 执行不同任务
3. 再切回线程 A
- 期望结果
- A、B 两个线程的技能、provider、artifact 不串线
- 当前线程状态只反映当前线程
- 建议记录项
- 线程 A/B 标识
- 各自技能与产物
- 切换前后截图
### `MANUAL-THREAD-003` 失败回退观察
- 前置条件
- 准备一个可稳定触发失败的配置或任务
- 操作步骤
1. 使用错误 endpoint 或故意不可达的在线任务
2. 提交任务并观察线程结果
- 期望结果
- 线程中出现清晰失败信息
- 不会把失败误报为成功
- 保留当前线程,便于继续修正并重试
- 建议记录项
- 失败输入
- 错误摘要
- 是否能在同线程重试

View File

@ -1,43 +0,0 @@
# 外部 Agent CLI Bridge 会话
## 目标
验证 `Go core` 驱动的 reviewer / CLI 会话是持续的 session而不是一次 prompt 一次退出。
## 推荐配置
- 框架:`ARIS`
- 本地 Ollama 可用
- `llm-chat` / `claude-review` 走 Go core
- Assistant 使用现有线程,不切新页面
## 建议任务
```text
请按 reviewer 方式审阅当前工作区的最近代码变更:
1. 先给出主要风险
2. 然后我会继续追问每一条风险
3. 不要只给结论,要保留后续会话上下文
```
## 手动验证步骤
1. 发送第一轮任务
2. 等 reviewer 返回第一轮风险列表
3. 在同一线程继续追问:
- “展开第 1 条”
- “如果不修会怎样”
- “给最小修复建议”
## 期望表现
- 同一线程持续回答
- 能记住上一轮 reviewer 结果
- 不会退化成一次性 stateless 输出
- `abort/cancel` 后不会继续刷 delta
## 通过标准
- 第二轮、第三轮追问都能基于前文继续
- 没有出现会话上下文丢失
- 没有强制重新建任务

View File

@ -1,181 +0,0 @@
# Secure Local Persistence Postmortem
## 问题摘要
用户现场反馈很直接:
- 当前会话里 Gateway 可以正常连接
- App 一重启,本地配置和已保存凭证丢失
- `Gateway 访问` 页重新出现 `gateway token missing`
这不是单点 bug而是持久层设计里连续几处降级路径叠加后的结果。
## 用户可见症状
### 1. 重启后网关凭证丢失
表现:
- token / password 在当前会话内可用
- 退出再打开后不可用
- 首次连接提示重新输入 shared token
### 2. 本地配置或任务会话恢复不稳定
表现:
- settings snapshot 或 assistant threads 在某些路径下恢复失败
- backup 虽然存在,但仍可能是明文旧格式
### 3. 明文本地状态残留
表现:
- 旧版 `SharedPreferences` 和 SQLite 中存在明文 settings / threads
- backup 文件也可能保留明文副本
## 根因
## 根因 1`FlutterSecureStorage` 强制套了 400ms 超时
旧逻辑:
- secure storage 读写只要超过 `400ms`,就视为失败
- 一旦失败,直接退化成“仅内存”
结果:
- 当前进程内看起来一切正常
- 因为值实际上没持久化,进程退出后凭证全部丢失
这是这次“重启后 token 消失”的直接根因。
## 根因 2secure storage 失败时降级策略设计错了
旧策略把“可恢复 secret”误当成“会话临时缓存”处理
- token / password / API key 没写进 durable fallback
- 只保存在进程内存
这个策略对调试场景看似友好,但对桌面 App 的真实使用是灾难性的,因为用户天然预期“已经保存”的 secret 会跨重启存在。
## 根因 3legacy prefs 迁移把明文直接写回了主存储
迁移链路里存在一个关键缺口:
- 从 `SharedPreferences` 读取到旧版明文 settings / threads
- 直接调用数据库写入
- 没有经过 sealed local state
结果:
- 用户完成升级后,本地状态仍可能继续以明文形式存在 SQLite
- 旧的 pref key 也没有被及时清理
这让“升级到新版本后自动变安全”的承诺失效了。
## 根因 4本地状态密钥也被允许走普通 fallback
旧版把 `xworkmate.local_state.key` 当成普通 secret 处理。
结果:
- 一旦它掉进 fallback 文件secure storage 就不再是本地状态加密的真正前提
- 架构上变成“有 secure storage 更好,没有也能常态运行”
这违背了本次补丁要建立的安全模型。
## 根因 5线程状态异步保存存在覆盖竞态
Assistant 线程会话是异步落盘的。旧逻辑没有串行 flush
- 线程 A 的旧快照可能在稍后写入
- 覆盖线程 B 或更新后的新状态
在加密封装增加写入成本后,这个竞态更容易暴露。
## 修复策略
### 1. secure storage 不再 400ms 即判死刑
- 超时提高到 `5s`
- 对真实 `FlutterSecureStorage` 保留超时保护
- 对测试注入 client 不套这层超时
### 2. secure storage 失败时改为 durable fallback而不是仅内存
- Gateway token
- Gateway password
- AI Gateway API key
- Vault token
这些 secret 在 secure storage 异常时会写入持久化 fallback保证跨实例恢复。
### 3. 本地配置和任务会话统一 sealed
对以下状态统一改为 AES-GCM sealed payload
- `SettingsSnapshot`
- Assistant thread records
- `assistant-state-backup.json`
目标是消除明文 SQLite / 明文 JSON backup。
### 4. legacy 明文状态迁移时立即重写并清理旧 pref
新逻辑:
- 读旧 pref
- 若目标存储不存在,则按 sealed 路径写入
- 写入成功后删除旧 pref key
这样升级后不会继续遗留明文主副本。
### 5. 本地状态密钥升级为 primary secure storage only
`xworkmate.local_state.key` 现在的规则是:
- 必须优先保存在主 secure storage
- 不再纳入普通 secure fallback 白名单
- 对旧版 `local-state-key.txt` 仅做一次迁移,随后删除
### 6. Assistant 线程持久化改为串行队列
新增线程持久化 queue 和 flush 机制,保证:
- 新状态不会被晚到的旧写入覆盖
- clear / send / view-mode 切换前可以先 flush
### 7. dispose 后的异步通知保护
`SettingsController` 新增 dispose guard避免恢复链路异步完成后向已销毁对象 `notifyListeners()`
## 为什么旧方案会失效
旧方案的问题不在“没加密”,而在于它把三件不同的事混在了一起:
- 当前请求是否可用
- 是否已经持久化
- 是否已经安全持久化
一旦 secure storage 稍慢,系统就会把“当前连接可继续”错误地当成“数据已经保存”,这正是桌面应用里最危险的误导。
## 回归防线
这次新增的回归覆盖重点包括:
- secure storage 超时后 secret 仍能跨实例恢复
- SQLite 不可用时sealed 的 settings / threads 仍能恢复
- plaintext local state 能迁移为 sealed storage
- legacy `local-state-key.txt` 能迁移到主 secure storage 并被清理
- backup 文件不再泄露明文 settings / threads
## 后续约束
后续所有涉及本地状态持久化的修改,都必须继续满足:
- `.env` 仍是预填,不是持久化真值
- 当前用户发起连接时可直接用表单值握手,不依赖 secure-store 回读
- local state 不得重新落回 `SharedPreferences` 明文
- backup 不得重新变成明文副本
- 不能再让 `xworkmate.local_state.key` 走常态文件 fallback

View File

@ -1,70 +0,0 @@
# 模式切换与线程连续追问
## 目标
验证三种模式切换后,线程归属正确、模型随模式变化,并且现有线程还能继续追问。
相关设计说明:
- [Assistant 任务线程信息架构](/Users/shenlan/workspaces/cloud-neutral-toolkit/xworkmate.svc.plus/docs/architecture/assistant-thread-information-architecture.md)
## 需要覆盖的三种模式
- `单机智能体`
- `本地 OpenClaw Gateway`
- `远程 OpenClaw Gateway`
## 建议步骤
### 场景 A单机智能体
发送:
```text
用一句话介绍你当前的执行上下文。
```
确认:
- 顶部状态显示 `单机智能体`
- 不显示 `已连接 openclaw ...`
- 模型标签来自 AI Gateway 当前模型
然后继续追问:
```text
继续基于刚才的上下文,再展开说 3 点。
```
确认线程连续。
### 场景 B切到本地 OpenClaw Gateway
切模式后在新任务里发送:
```text
检查当前本地 Gateway 可用性,并说明你现在通过哪条链路工作。
```
确认:
- 顶部状态变成 `本地 OpenClaw Gateway`
- 模型标签跟随当前模式变化
### 场景 C切到远程 OpenClaw Gateway
在可连接远程网关时发送:
```text
说明当前远程链路状态,并等待我继续追问。
```
然后继续追问一轮,确认线程不丢上下文。
## 通过标准
- 切换模式后,模型显示会跟着变
- `单机智能体` 不会错误显示 OpenClaw 已连接
- 三种模式下线程都能继续追问
- 任务列表分组归属与实际提交模式一致
- 右上角状态只反映当前线程,不沿用别的线程连接结果

View File

@ -1,6 +1,6 @@
# XWorkmate 测试规范
> 适用范围: `xworkmate.svc.plus`
> 适用范围: `XWorkmate`
> 规范等级: 正式
> 用途: 统一一次变更的测试规划、执行、验收、归档口径。
@ -102,4 +102,9 @@
示例验收文档:
- `docs/releases/2026-03-23-single-agent-test-acceptance.md`
- `docs/reports/2026-03-23-single-agent-test-acceptance.md`
长期维护文档:
- `docs/testing/core-integration-auto-test-plan.md`
- `docs/cases/core-integration-manual-cases.md`

View File

@ -113,5 +113,4 @@
## 相关文档
- [Secure Local Persistence Architecture](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/architecture/secure-local-persistence-architecture.md)
- [Secure Local Persistence Postmortem](/Users/shenlan/workspaces/cloud-neutral-toolkit/XWorkmate.svc.plus/docs/cases/secure-local-persistence-postmortem.md)
- [Secure Local Persistence Architecture](../architecture/secure-local-persistence-architecture.md)

View File

@ -0,0 +1,566 @@
# 核心功能集成测试自动化规划
## 1. 文档目标
这份文档用于把当前项目主线整理成一套可直接落到现有测试 harness 的自动化规划,服务于后续增量实现,而不是重新设计新的测试框架。
覆盖范围只保留两大模块:
- 设置页面配置功能
- 任务线程场景测试
本文默认当前真实拓扑如下:
- 在线用户同步会向本地设置注入远程默认值
- ACP 支持 selfhost 远程服务端
- ACP 支持 local / loopback 模式
- 线程执行同时覆盖本地执行型任务与在线执行任务
## 2. 现有可复用测试基础
后续实现优先扩展现有测试,而不是新增平行体系。
### 2.1 runtime 层
- `test/runtime/settings_controller_account_sync_suite.dart`
- `test/runtime/external_acp_endpoint_settings_suite.dart`
- `test/runtime/acp_endpoint_paths_suite.dart`
- `test/runtime/gateway_endpoint_normalization_suite.dart`
- `test/runtime/app_controller_thread_skills_suite.dart`
- `test/runtime/app_controller_execution_target_switch_suite.dart`
- `test/runtime/desktop_thread_artifact_service_test.dart`
### 2.2 feature 层
- `test/features/settings_page_gateway_acp_messages_suite.dart`
- `test/features/settings_page_suite.dart`
- `test/features/web_settings_page_external_acp_suite.dart`
- `test/features/assistant_page_installed_skill_e2e_suite.dart`
### 2.3 integration 层
- `integration_test/desktop_settings_flow_test.dart`
- `integration_test/desktop_navigation_flow_test.dart`
### 2.4 已有 harness 结论
已存在的 installed-skill E2E harness 已验证:
- `pptx`
- `docx`
- `xlsx`
- `pdf`
参考:
- `docs/reports/2026-03-30-installed-skill-e2e-harness.md`
后续新增覆盖优先把这套 harness 扩展到:
- `image-resizer`
- 本地浏览器自动化
- `image-cog`
- `image-video-generation-editting`
- `video-translator`
- 资讯采集
- 搜索
## 3. 分层约束
### 3.1 runtime
用于验证:
- endpoint 规范化
- 账户同步与 settings snapshot
- 线程身份、技能绑定、artifact 写回、线程隔离
- local / remote 模式切换与 provider 选择
### 3.2 feature
用于验证:
- 设置页输入、提示语、错误分类
- assistant 页技能选择、提交、结果表面
- 已安装技能对 UI 壳层的最小可见性
### 3.3 integration
用于验证:
- 桌面端设置入口与关键 happy path 冒烟
- 页面切换后配置可见性
- 线程入口与设置入口的真实联通
## 4. 通用断言基线
所有首批自动化用例默认都要尽量覆盖以下断言:
- 线程 ID 连续且不会串线程
- 技能绑定到当前线程,不串 provider
- 结果写入当前线程 workspace 或 artifact snapshot
- 本地执行型与在线执行型都通过同一结果表面暴露产物
- secret 不进入普通 settings snapshot
- local 模式允许明确的非 TLS 边界remote 模式不允许静默降级
- 错误信息按配置错误、连接失败、鉴权失败、任务失败分层呈现
## 5. 设置页面配置功能
### `ACP-CONFIG-001` 在线用户同步成功且 secret 不落 settings snapshot
- 测试目标
- 验证在线用户同步会注入远程默认配置,但 secret 只留在 secure storage 或运行时态,不进入普通 snapshot。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- 复用 `SettingsController` 账户同步假服务
- 提供远程配置 payload包含 endpoint、provider、secret 引用位
- 关键断言
- 同步后 endpoint 与 provider 被注入本地设置
- settings snapshot 不包含 token/password/API key 明文
- 本地 override 仍可覆盖远程默认值
- 失败分类
- 同步失败
- snapshot 泄露 secret
- 远程默认值覆盖用户 override
- 后续实现建议文件落点
- 首选扩展 `test/runtime/settings_controller_account_sync_suite.dart`
- UI 显示补充到 `test/features/settings_page_suite.dart`
### `ACP-CONFIG-002` selfhost ACP 基址输入后正确派生 `/acp``/acp/rpc`
- 测试目标
- 验证设置页输入 selfhost 基址后,内部派生出的 websocket / RPC 路径符合当前 ACP 规则。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- 复用 endpoint normalization 与 external endpoint settings 相关 fixture
- 基址样例覆盖:
- `https://host.example.com/opencode`
- `https://host.example.com/codex`
- 关键断言
- 基址派生 `.../acp`
- RPC 派生 `.../acp/rpc`
- 不重复拼接已存在的 `/acp`
- UI 回显与内部值一致
- 失败分类
- path 重复拼接
- RPC 路径丢失
- 基址与回显不一致
- 后续实现建议文件落点
- 首选扩展 `test/runtime/acp_endpoint_paths_suite.dart`
- 兼并到 `test/runtime/external_acp_endpoint_settings_suite.dart`
- 设置页提示补充到 `test/features/settings_page_gateway_acp_messages_suite.dart`
### `ACP-CONFIG-003` local ACP loopback 模式允许非 TLSremote 模式不允许静默降级
- 测试目标
- 明确 local / loopback 与 remote transport trust boundary。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- endpoint normalization fixtures
- loopback host 样例:
- `http://127.0.0.1:9001/opencode`
- `ws://127.0.0.1:9001/codex`
- remote host 样例:
- `http://example.com/opencode`
- 关键断言
- loopback/local 模式可接受非 TLS
- remote 模式遇到非 TLS 时给出明确错误或阻止提交
- remote 模式不会 silently rewrite 成 insecure transport
- 失败分类
- loopback 被误拦截
- remote 静默降级
- 错误分类不清晰
- 后续实现建议文件落点
- 首选扩展 `test/runtime/gateway_endpoint_normalization_suite.dart`
- 连接策略落到 `test/runtime/external_acp_endpoint_settings_suite.dart`
- 表单提示补充到 `test/features/settings_page_gateway_acp_messages_suite.dart`
### `ACP-CONFIG-004` 设置页测试连接对 hosted base URL、自定义 auth、失败提示语分类正确
- 测试目标
- 验证设置页“测试连接”在 hosted、自定义 auth、空 auth、连接失败等路径下给出稳定反馈。
- 推荐测试层级
- `feature`
- `integration`
- 前置依赖与假服务
- fake gateway client
- hosted / selfhost / local 三类 endpoint fixture
- fake failure 分类:
- 鉴权失败
- 空响应
- 网络失败
- 关键断言
- 按配置类型显示正确提示文案
- 成功时状态更新为已连接或已验证
- 失败时文案可区分空响应、认证失败、网络失败
- 失败分类
- 所有失败收敛成同一文案
- 成功失败状态混乱
- UI 不回显当前配置来源
- 后续实现建议文件落点
- 首选扩展 `test/features/settings_page_gateway_acp_messages_suite.dart`
- Web 设置页差异补充到 `test/features/web_settings_page_external_acp_suite.dart`
- 桌面 happy path 冒烟补充到 `integration_test/desktop_settings_flow_test.dart`
## 6. 任务线程场景测试
### 6.1 通用 harness 规则
线程类测试优先复用 installed-skill E2E harness 与 thread skill runtime suite统一要求
- 当前线程内技能绑定正确
- prompt 进入真实 controller 提交路径
- 结果写入 thread workspace / artifact snapshot
- provider / mode / thread 三个维度相互隔离
首选落点:
- `test/features/assistant_page_installed_skill_e2e_suite.dart`
- `test/runtime/app_controller_thread_skills_suite.dart`
- `test/runtime/app_controller_execution_target_switch_suite.dart`
- `test/runtime/desktop_thread_artifact_service_test.dart`
### 6.2 本地执行型
#### `THREAD-LOCAL-001` `pptx` 在当前线程绑定、提交、产物回写
- 测试目标
- 验证 `pptx` 技能从当前线程选中、提交到结果产物落盘的完整链路。
- 推荐测试层级
- `feature`
- `runtime`
- 前置依赖与假服务
- 已安装技能共享根目录 fixture
- 确定性 artifact writer
- 关键断言
- 当前线程记录绑定 `pptx`
- 产物进入当前线程 workspace
- artifact snapshot 可见 `.pptx` 结果
- 失败分类
- 技能未绑定
- 结果写到错误线程
- artifact snapshot 不刷新
- 后续实现建议文件落点
- 扩展 `test/features/assistant_page_installed_skill_e2e_suite.dart`
- 必要时补到 `test/runtime/app_controller_thread_skills_suite_shared_roots.dart`
#### `THREAD-LOCAL-002` `docx`
- 测试目标
- 验证 `docx` 本地文档生成链路与线程绑定一致。
- 推荐测试层级
- `feature`
- `runtime`
- 前置依赖与假服务
- 同 `pptx` harness
- 关键断言
- 当前线程技能为 `docx`
- 产物后缀与 artifact metadata 正确
- 二次追问仍引用同一线程上下文
- 失败分类
- 技能/产物元信息不一致
- 连续追问丢线程
- 后续实现建议文件落点
- 扩展 `test/features/assistant_page_installed_skill_e2e_suite.dart`
- 线程连续性扩展 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
#### `THREAD-LOCAL-003` `xlsx`
- 测试目标
- 验证表格任务在当前线程生成并回写结果。
- 推荐测试层级
- `feature`
- `runtime`
- 前置依赖与假服务
- 同 installed-skill harness
- 关键断言
- 产物路径进入当前线程 workspace
- artifact snapshot 里能看到 `.xlsx`
- 不会误落到共享根目录或其他线程目录
- 失败分类
- 产物路径越界
- artifact snapshot 漏刷新
- 后续实现建议文件落点
- 扩展 `test/features/assistant_page_installed_skill_e2e_suite.dart`
- 产物归属补到 `test/runtime/desktop_thread_artifact_service_test.dart`
#### `THREAD-LOCAL-004` `pdf`
- 测试目标
- 验证 PDF 工具链在当前线程中以本地执行型方式完成。
- 推荐测试层级
- `feature`
- `runtime`
- 前置依赖与假服务
- 同 installed-skill harness
- 关键断言
- 当前线程与 `pdf` 技能绑定
- 结果作为 artifact 返回,而不是只停留在流式文本
- 失败时保留线程内错误摘要
- 失败分类
- 只返回文本不回写 artifact
- 失败状态丢失
- 后续实现建议文件落点
- 扩展 `test/features/assistant_page_installed_skill_e2e_suite.dart`
- 失败回写补到 `test/runtime/app_controller_thread_skills_suite_workspace_fallback.dart`
#### `THREAD-LOCAL-005` `image-resizer`
- 测试目标
- 把媒体类中的本地图片处理纳入已安装技能 harness。
- 推荐测试层级
- `feature`
- `runtime`
- 前置依赖与假服务
- 新增本地图片处理 skill fixture
- 确定性输出文件名
- 关键断言
- `image-resizer` 被识别为本地执行型
- 输出图片进入当前线程 artifact snapshot
- 输出 metadata 标识批处理或尺寸变化摘要
- 失败分类
- 媒体技能被误分到在线执行
- 结果文件未进入线程产物面
- 后续实现建议文件落点
- 首选扩展 `test/features/assistant_page_installed_skill_e2e_suite.dart`
- provider / mode 归类补到 `test/runtime/app_controller_execution_target_switch_suite_thread.dart`
#### `THREAD-LOCAL-006` 本地浏览器自动化
- 测试目标
- 验证本地浏览器自动化技能走本地执行路径,且结果仍回到线程 artifact / 文本摘要表面。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- browser automation skill fixture
- fake browser result payload
- 关键断言
- 当前线程内 mode 为本地执行
- 执行结果包含摘要与可选产物记录
- 切换线程后不会复用上一线程浏览器上下文
- 失败分类
- 浏览器自动化被归到远程 provider
- 线程切换后结果串线
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
- 壳层可见性补到 `test/features/assistant_page_installed_skill_e2e_suite.dart`
### 6.3 在线执行型
#### `THREAD-ONLINE-001` `image-cog`
- 测试目标
- 验证图像生成在线任务的提交、轮询、产物回传与线程归属。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- fake remote provider / ACP task status poller
- 远程图片 artifact fixture
- 关键断言
- 线程内 provider 标识为在线执行
- 任务状态从提交进入完成
- 图片产物进入当前线程 artifact snapshot
- 失败分类
- 状态轮询中断
- 产物回传到错误线程
- provider 标识错误
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_acp.dart`
- UI 壳层补到 `test/features/assistant_page_installed_skill_e2e_suite.dart`
#### `THREAD-ONLINE-002` `image-video-generation-editting`
- 测试目标
- 验证图片/视频在线生成编辑链路的长任务管理。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- fake long-running remote task
- image-to-video / text-to-video 结果 fixture
- 关键断言
- 长任务状态可轮询
- 最终视频或图片产物进入当前线程
- 失败状态会回写线程消息而不是静默结束
- 失败分类
- 长任务无状态
- 结束但无产物
- 失败静默
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_acp.dart`
- 必要时新增 sibling suite`test/runtime/app_controller_thread_skills_suite_media_remote.dart`
#### `THREAD-ONLINE-003` `video-translator`
- 测试目标
- 验证视频翻译/配音任务的在线提交与出片产物回传。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- fake remote translation job
- 带字幕/带配音结果 fixture
- 关键断言
- 线程内保留任务状态摘要
- 成功时回传视频或字幕产物
- 失败时线程中可见错误摘要与重试入口状态
- 失败分类
- 任务状态与线程消息脱节
- 只有文本结果无实际产物
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_acp.dart`
- 结果面一致性补到 `test/runtime/desktop_thread_artifact_service_test.dart`
#### `THREAD-ONLINE-004` 资讯采集
- 测试目标
- 验证资讯采集在在线执行模式下返回结构化结果,且与线程上下文绑定。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- fake fetch/search provider
- 结构化 article list fixture
- 关键断言
- 线程中保留查询条件与结果摘要
- article list 结构化字段完整
- 结果不会串到其他线程的搜索结果中
- 失败分类
- 结构化字段缺失
- 采集结果串线
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
- UI 结果面补到 `test/features/assistant_page_installed_skill_e2e_suite.dart`
#### `THREAD-ONLINE-005` 搜索
- 测试目标
- 验证搜索任务在线执行时的结果结构和线程归属。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- fake search provider
- top-N 搜索结果 fixture
- 关键断言
- 当前线程消息记录本次查询
- 搜索结果结构完整
- 后续追问复用同一线程而不是新建孤立任务
- 失败分类
- 查询记录缺失
- 连续追问断链
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_execution_target_switch_suite_thread.dart`
- 连续追问行为补到 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
## 7. 线程连续性与隔离
### `THREAD-CROSS-001` 同线程连续追问不丢上下文
- 测试目标
- 验证本地执行型与在线执行型在完成一次任务后,都能继续在同一线程追问。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- 已有 thread skill fixtures
- 至少一条本地执行与一条在线执行样例
- 关键断言
- 第二次提问复用原线程 ID
- 上下文引用到第一次任务结果
- 不会因 provider 切换而新建错误线程
- 失败分类
- 线程 ID 重置
- 上下文丢失
- provider 切换导致错绑
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
- UI 壳层最小补充到 `test/features/assistant_page_suite_core.dart`
### `THREAD-CROSS-002` 切换线程后技能、产物、状态不串线
- 测试目标
- 验证多线程场景下技能选择、artifact、provider 状态严格归属当前线程。
- 推荐测试层级
- `runtime`
- 前置依赖与假服务
- 多线程 fixture
- 每线程不同技能与不同 artifact
- 关键断言
- 线程 A 的 artifact 不出现在线程 B
- 线程 B 的 provider 状态不污染线程 A
- 当前线程右上角状态只反映当前线程
- 失败分类
- artifact 串线
- 状态面串线
- 技能选择残留
- 后续实现建议文件落点
- 首选扩展 `test/runtime/app_controller_thread_skills_suite_thread_isolation.dart`
- 如需状态面验证,补到 `test/runtime/app_controller_execution_target_switch_suite_thread.dart`
### `THREAD-CROSS-003` 本地执行型与在线执行型在 artifact / result surface 上表现一致
- 测试目标
- 保证用户无论走本地还是在线执行,结果面都遵循统一模型。
- 推荐测试层级
- `runtime`
- `feature`
- 前置依赖与假服务
- 一组本地执行 fixture
- 一组在线执行 fixture
- 关键断言
- 两类任务都能回写 artifact snapshot
- 消息摘要格式遵循统一 result surface
- 不要求用户切换不同浏览入口查看结果
- 失败分类
- 本地只有 artifact在线只有文本
- 结果面模型不一致
- 后续实现建议文件落点
- 首选扩展 `test/runtime/desktop_thread_artifact_service_test.dart`
- 壳层可见性补到 `test/features/assistant_page_installed_skill_e2e_suite.dart`
## 8. 实施顺序建议
### P0
- `ACP-CONFIG-001`
- `ACP-CONFIG-002`
- `ACP-CONFIG-003`
- `ACP-CONFIG-004`
- `THREAD-LOCAL-005`
- `THREAD-LOCAL-006`
- `THREAD-ONLINE-001`
- `THREAD-ONLINE-002`
- `THREAD-ONLINE-003`
- `THREAD-ONLINE-004`
- `THREAD-ONLINE-005`
- `THREAD-CROSS-001`
- `THREAD-CROSS-002`
- `THREAD-CROSS-003`
### 已有基础可复用项
以下能力优先在现有 harness 上扩断言,而不是重写:
- `THREAD-LOCAL-001`
- `THREAD-LOCAL-002`
- `THREAD-LOCAL-003`
- `THREAD-LOCAL-004`
## 9. 完成标准
这份自动化规划被视为可执行,需要满足:
- 每个首批 case 都有明确首选落点
- 不引入新的测试框架名词
- 能直接映射到 `runtime / feature / integration` 三层
- 每个 case 都有可实现的依赖与 fake service 提示
- 每个 case 都有可验证断言与失败分类

View File

@ -1,6 +1,6 @@
# XWorkmate 测试规范模板与指南
> 适用范围: `xworkmate.svc.plus`
> 适用范围: `XWorkmate`
> 目的: 提供可直接套用的验收写法,方便快速产出单次测试记录。
## 1. 这份文档的角色
@ -104,5 +104,7 @@
可参考现有验收文档:
- `docs/releases/2026-03-23-single-agent-test-acceptance.md`
- `docs/reports/2026-03-23-single-agent-test-acceptance.md`
- 正式规范: `docs/quality/xworkmate-test-spec.md`
- 长期自动化规划: `docs/testing/core-integration-auto-test-plan.md`
- 长期手动 case: `docs/cases/core-integration-manual-cases.md`