Files
mnote/scripts/TESTING_REFERENCE.md
T
Agent Board bc6f8488ee feat: vault core/CLI/workbench, vaultd token path, filetree view-state cleanup
Land password-vault dedicated workbench and mnote-vault-core/CLI, agent token
read path design, vault transport split, and retire obsolete filetree smokes.
Ignore local vault reimport scripts that trip secret scanners.
2026-07-24 11:36:06 +08:00

540 lines
27 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.
# mnote 测试参考
## ⚡ 浏览器测试快速启动(AI agent 专用)
> **执行浏览器验证前,先确认此节,避免浪费时间。**
### 1. 检查服务是否已运行
```bash
ss -ltnp 'sport = :3000'
# 有输出 = 服务已运行,跳到步骤 3
# 无输出 = 服务未运行,继续步骤 2
```
### 2. 启动服务(后台模式)
```bash
nohup npm run dev:hot > /tmp/mnote-dev.log 2>&1 &
echo $!
# 等待 5-10 秒后检查日志
sleep 8 && grep -E 'gateway 已启动|Running' /tmp/mnote-dev.log
```
**关键点:**
- 启动命令是 `npm run dev:hot`(不是 desktop:hot
- `dev:hot` 默认启用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1`
- 使用 cargo-watch 自动重编译
- 端口固定为 3000
### 3. 浏览器验证步骤(Paseo
```bash
# 1. 新建标签页
paseo_browser_new_tab url=http://localhost:3000/auth
# 2. 等待页面加载
paseo_browser_wait url=localhost:3000 timeoutMs=15000
# 3. 截图(如果返回 "tab not painted",等 3 秒重试)
paseo_browser_screenshot
# 4. 快速登录(snapshot 找到 @e5 即"测试账号快速登录"按钮)
paseo_browser_click ref=@e5
# 5. 等待进入工作区
paseo_browser_wait url=localhost:3000 text=工作区
# 6. 截图
paseo_browser_screenshot
```
### 4. 测试账号
- 邮箱:`mnote.e2e@example.com`
- 密码:`MnoteE2E123!`
- 用户名:`mnote-e2e`
### 5. 常见问题
| 问题 | 原因 | 解决 |
|------|------|------|
| ERR_CONNECTION_REFUSED | 服务器未启动 | 先运行 `npm run dev:hot` |
| tab not painted | 页面未渲染完成 | 等待 3 秒后重试截图 |
| Paseo 终端无输出 | 前台进程阻塞 | 用 `nohup ... &` 后台启动 |
| `desktop:hot` vs `dev:hot` | 启动命令不同 | 浏览器测试用 `dev:hot` |
### 6. AI 密码本读密 / 登录态(12-2 · **不依赖 3000**
读密与 login/session 走本地 core + capability token**不要**为 resolve/login/session 启 mnote-web。
```bash
cd rust
cargo build -q -p mnote-vault
# 一次签发(写入 ~/.config/mnote/vault-tokens/default.token;默认 scope 含 login,session
./target/debug/mnote-vault issue-token --agent smoke --ttl 1d
./target/debug/mnote-vault doctor
# 可选常驻 UDS$XDG_RUNTIME_DIR/mnote-vaultd.sock 或 MNOTE_VAULT_SOCK
./target/debug/mnote-vault serve &
./target/debug/mnote-vault list # sock 优先,不可达则内嵌 core
./target/debug/mnote-vault resolve --id <cred_id> --field password
./target/debug/mnote-vault resolve --id <id> --field password --local # 强制内嵌
./target/debug/mnote-vault resolve --id <id> --field password --remote # 强制 UDS
# session 回写 + login 复用(无外站 HTTP
./target/debug/mnote-vault session --id <id> --cookie-header 'mnote_session=smoke; other=1' --local
./target/debug/mnote-vault login --id <id> --local # 期望 reused=true / mode=session
cargo test -p mnote-vault-core --lib
cargo test -p mnote-web --lib routes::vault::resolve_strategy_tests
cargo test -p mnote-web --lib routes::vault -- --nocapture 2>&1 | rg -n "login_reuses|ok"
```
- Crate`mnote-vault-core``mnote-vault`bin,含 `serve` + login/session)、`mnote-web` AI list/get/resolve/login/session thin-wrap core
- 设计:`design/12-vault/process/12-2-vaultd-local-token-agent-read-path-v1.md`
- Skill / 策略:`$mnote-vault``/home/lix/.agent-infra/vault-policy.md`
- Web UI / CRUD workbench 仍可走 3000**list/get/resolve/login/session 稳态禁止以 auth-e2e 为前置**
这份文档面向 `/mnt/Data1T/mnote/scripts` 目录下的现有测试脚本,目标不是重新设计测试体系,而是把当前已经在用的 smoke、回归脚本、截图取证和人工复核方式整理成一套可执行参考。
当前结论先说在前面:
- `scripts/` 里的主力仍然是 `Playwright smoke + Node 断言`
-`mnote` 来说,最有价值的不是把所有测试都换成“浏览器插件式控制”,而是把已有 smoke 的结果变得更可看、更易复核。
- `/doko` 适合作为 smoke 之后的“真实页面直观复核层”,不是用来替代 smoke。
- 2026-05-20 起,默认主入口固定按 `http://127.0.0.1:3000` 理解;历史记录里的 `3001` 只代表当时临时 mnote-web 实例,不再作为默认验收入口。
- 历史 smoke 分为 `current``retired/debug` 两类维护;退役脚本不应进入默认回归,除非脚本自身要求显式环境变量。
- 2026-05-27 起,默认 smoke 基线只覆盖 `3000 Rust SSR + leptos-tiptap + local-first` 主路径;Convex export、Convex 兼容、Next、3104、BlockNote 默认路径脚本不再放在默认候选里。
- 依赖 `/api/dev/seed` 的 browser smoke 默认使用 `npm run dev:hot``dev:hot` 默认启用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1``desktop:hot` 与生产启动仍默认关闭。修改 Node 启动脚本或环境变量后必须重启 `dev:hot` 主进程,不能只等待 cargo-watch 重载 Rust。
## 0. 当前 smoke 状态清单
这一节用于避免历史脚本被误当作当前架构主链验收。
### 0.0 2026-05-26 默认基线
建议日常 smoke 先跑这一组,确保当前主入口、认证、文档 island、Page Aggregate、local-first 和关键 runtime surface 没断:
```bash
node scripts/task114-rust-web-gateway-entry-smoke.js
node scripts/task159-auth-entry-smoke.js
node scripts/task164-desktop-hot-local-folder-main-entry-smoke.js
node scripts/task166-local-first-managed-workspace-no-convex-smoke.js
node scripts/task167-local-markdown-title-body-options-no-convex-smoke.js
node scripts/task490-runtime-surfaces-smoke.js
```
其中 `task490-runtime-surfaces-smoke.js` 是轻量浏览器 smoke,验证页面设置、浮动 Pi Lab 入口、旧 OpenHub/opencode 前端不再打开、slash menu、block handle menu 能在当前 leptos-tiptap 文档页工作;它不要求真实模型返回,也不替代更重的 Pi Lab/Page AI 或编辑器菜单专项脚本。
### 0.1 当前主链优先脚本
- 入口与认证:`task114-rust-web-gateway-entry-smoke.js``task159-auth-entry-smoke.js``task097-homepage-entry-smoke.js`
- Rust SSR 文档页 / Page Aggregatelocal-first 默认优先 `task167-local-markdown-title-body-options-no-convex-smoke.js`Page Aggregate browser conversion / compat fallback 改动补跑 `task522-page-aggregate-compat-fallback-contract.js`cloud/control-plane 文档可补跑 `task110-page-title-single-truth-smoke.js``task-page-aggregate-body-sync-smoke.js``task-page-aggregate-options-sync-smoke.js``task-page-aggregate-refresh-persistence-smoke.js`
- leptos-tiptap runtime surface`task490-runtime-surfaces-smoke.js`;需要验证保存回读可补跑 `task121-rust-web-editor-island-hydration-smoke.js`,但它仍使用 `/api/tree/commands create` 准备文档,不作为无 Convex 默认基线;需要验证浮层互斥和更多菜单状态时再跑 `task158-e30-menu-state-smoke.js`
- local-first 本地工作区:`task164-desktop-hot-local-folder-main-entry-smoke.js``task166-local-first-managed-workspace-no-convex-smoke.js``task167-local-markdown-title-body-options-no-convex-smoke.js``task436-local-markdown-open-document-external-change-smoke.js``task443-local-markdown-asset-upload-smoke.js``task451-local-markdown-conflict-resolution-ui-smoke.js``task452-local-search-index-browser-smoke.js``task453-local-folder-page-ai-changed-files-smoke.js`WorkspacePath / ObjectIdentity runtime 消费统一改动补跑 `task524-workspace-object-identity-matrix-smoke.js``task452` 只覆盖普通本地搜索、settings API、tag/backlink API 和旧 local-index UI 不复活;资料库问答、PDF/Office/image source ingestion 与引用回跳改跑 LightRAG / provider-neutral knowledge-rag 脚本。
- LightRAG / Knowledge RAG 资料库:LightRAG 是默认 provider。资料源、摄取、source scope 与 watcher 改动优先跑 `task532-knowledge-rag-docx-ingestion-smoke.js``task533-knowledge-rag-source-watcher-sync-smoke.js``task534-knowledge-rag-source-management-scope-smoke.js``task538-knowledge-rag-source-scope-api-smoke.js`;引用和 Page AI final answer 改动补跑 `task529-knowledge-rag-citation-resource-tab-smoke.js``task530-knowledge-rag-page-ai-final-answer-smoke.js`;真实 Pi + LightRAG 服务可用时补跑 `task-pi-lab-real-lightrag-smoke.js`。WeKnora 仅是历史/备用 provider,不进入默认回归。旧 OpenHub 专项资料库 smoke 已软归档到 `recycle/20260712-pi-ts-openhub-retirement/`;旧 `task526-local-folder-ocr-api-smoke.js` / OCR sidecar 链路已退役并软归档;`/api/search/documents` 不作为 LightRAG、LiteParse、OCR sidecar 或 evidence.sqlite 的资料库问答 fallback。
- local Markdown conflict regression`task510-local-markdown-conflict-regression-group.js` 串联真实冲突、连续上传、新建页面、外部恢复、多 tab CAS 与上传 409 孤儿策略;可用 `MNOTE_CONFLICT_REGRESSION_TASKS=a.js,b.js` 做定点子集。
- tree realtime / live cache`task446-tree-rename-dual-browser-live-smoke.js``task447-tree-move-order-dual-browser-live-smoke.js``task448-tree-resync-recovery-dual-browser-smoke.js``task449-tree-sse-reconnect-snapshot-recovery-smoke.js`
- 资源对象与 mindmap`task455-local-folder-mindmap-clean-smoke.js``task456-resource-object-shell-sync-smoke.js``task166-mindmap-phase6-block-smoke.js``task167-mindmap-kmind-parity-smoke.js``task168-mindmap-put-validator-smoke.js`Page AI mindmap skill / 资源生成改动补跑 `task503-mindmap-skill-capability-smoke.js`,真实 mindmap resource tab / Page AI target 改动补跑 `task525-page-ai-mindmap-resource-target-smoke.js`
- Page AI / agent history / ChatOnly`task502-page-ai-agent-selector-context-smoke.js` 覆盖 Page AI agent/context/target picker、skills source 和 run payloadraw local resource target 改动补跑 `task520-page-ai-raw-resource-target-smoke.js``task504-page-ai-history-agent-filter-smoke.js` 覆盖 Page AI 历史按 agent 过滤;ChatOnly / provider session 绑定改动优先跑 `task512-chatonly-doubao-sync-smoke.js`,跨 provider 同步补跑 `task513-chatonly-provider-sync-smoke.js``task763` / `task765` 是 OpenCode debug fallback 专项脚本,不属于默认回归,待 debug route 彻底移除时一并退役。
- Dev hot / OnlyOffice live bridgeSidebar dev hot reload 入口改动补跑 `task514-sidebar-dev-hot-reload-gating-smoke.js`OnlyOffice live bridge session / scope / HTTP 工具边界改动补跑 `task515-onlyoffice-live-scope-http-smoke.js`bridge session/token/queue/current/close 和 `docKey/pageOrigin` 元数据改动补跑 `task516-onlyoffice-bridge-multisession-browser-smoke.js`bridge plugin index / `Asc.plugin` direct loop / plugin 元数据透传改动补跑 `task517-onlyoffice-bridge-plugin-direct-smoke.js`;真实 ONLYOFFICE iframe / DocumentServer session、同文档双 tab、resource scope 和非 dry-run 写入落点改动补跑 `task518-onlyoffice-real-iframe-session-scope-smoke.js`Page AI 真实 UI 选择 Office target 并冻结 live bridge session 改动补跑 `task523-page-ai-onlyoffice-real-target-session-smoke.js`
- local resource lifecycle API`task437-local-folder-asset-trash-lifecycle-smoke.js`,现在只验证 `local-file:*` delete / restore / purge,不再依赖普通 `.txt` 是否出现在 UI 文件树。
### 0.2 需要退役或拆分的历史脚本
- `task444-convex-workspace-export-local-fixture-smoke.js``task455-convex-export-plan-rollback-smoke.js``export-convex-workspace-to-local.js`Convex export 迁移验证已退出默认 smoke,已归档到 `recycle/scripts/retired-convex-export-smokes-20260526/`
- 注意编号复用:`scripts/task444-filetree-create-mindmap-title-cache-smoke.js``scripts/task455-local-folder-mindmap-clean-smoke.js` 仍是当前本地 filetree / mindmap 脚本;退役的是带 `convex-export` 名称的 task444 / task455。
- 旧 Convex 兼容 smoke 已软删除到 `recycle/20260527-legacy-cleanup/convex/scripts/`,包括 `task163``task174``task175``task427``task428``task429``task430``task431``task432``task433``task434`
- `task179-tree-create-delete-no-reload-smoke.js`:覆盖 `/tree` debug shell。`/tree` 已是显式 debug/internal 边界,脚本默认阻断;只有设置 `MNOTE_ALLOW_DEBUG_TREE_SMOKE=1` 时才可执行。
- `task123-rust-web-tree-live-stream-consumer-smoke.js`:只证明 `/api/tree/events` SSE fallback 仍可用。当前 realtime 主链是 WebSocket push + SSE fallback;验证主链时优先使用 446 / 447 / 448,只有排查 fallback 时再跑 123。
- WeKnora 默认 provider 脚本(`task544``task769``task772``task777``task781``task783``task784``task785``task787``task788``task789``task790``task79x`)已退役;它们与 LightRAG 默认 provider 主线相反。
- Hermes/ACP/Reasonix 页面 AI 主流程 smoke 已退役;只保留 `task-hermes-page-ai-retirement-guard.js` 防止旧 runtime 复活。`task762-page-ai-board-first-smoke.js` 也已退役。
-`task019``task021``task022` 这类早期 UI regression 脚本已软删除到 `recycle/scripts/retired-ui-regressions/`,只作为历史对照;后续默认不要用于当前 Rust SSR / local-first 主路径验收。
- `task494-filetree-lazy-loading-dedup-smoke.js``task498-starred-page-tree-scope-and-local-edit-smoke.js``task499-sidebar-tree-view-state-smoke.js`2026-07-21 诊断为 fixture/契约过时(非 Playwright 安装问题),已迁到 `recycle/scripts/obsolete-tree-smokes-20260721/`。全局 Playwright 栈:`~/.agent-infra/playwright-stack`(见该目录 `use-in-project.md`)。树移动排序优先 `task447-tree-move-order-dual-browser-live-smoke.js` 或 Hermes tree QA。
### 0.3 其他 current 候选脚本
这些脚本不是最小默认基线,但仍属于当前 Rust SSR / leptos-tiptap / local-first 维护面,按改动范围选择性运行:
- `task426-mnote-web-main-no-reload-smoke.js`
- `task109-leptos-island-multipage-save-smoke.js`
- `task122-rust-web-create-page-ui-smoke.js`
- `task125-rust-web-search-server-first-smoke.js`
- `task165-rust-web-dual-pane-smoke.js`
- `task458-local-create-page-no-conflict-smoke.js`
- `task459-local-markdown-attachment-tab-smoke.js`
- `task484-local-folder-page-body-refresh-readback-smoke.js`
- `task486-local-markdown-save-error-editor-preserves-content-smoke.js`
- `task487-local-folder-tree-live-consumer-smoke.js`
## 1. 当前测试分层
按目录里的现状,脚本大致分成四层。
### 1.1 入口与网关层
这一层主要验证路由、网关、owner、认证入口、基础响应是否正确,特点是快、稳定、适合作为最早执行的守门测试。
代表脚本:
- `task097-homepage-entry-smoke.js`
- `task114-rust-web-gateway-entry-smoke.js`
- `task159-auth-entry-smoke.js`
适用场景:
- 刚切流 Rust Web
- 改了入口路由、鉴权、兼容代理
- 需要先判断“服务有没有活着、入口是不是对的”
### 1.2 页面交互 smoke 层
这一层是当前最核心的 UI 验证方式:启动页面、登录测试账号、进入真实文档页或工作区,然后通过 Playwright 操作页面并做断言。
代表脚本:
- `task110-page-title-single-truth-smoke.js`
- `task112-tree-rust-family-regression-smoke.js`
- `task120-rust-web-tree-integration-smoke.js`
- `task122-rust-web-create-page-ui-smoke.js`
- `task164-page-options-visible-effect-smoke.js`
- `task490-runtime-surfaces-smoke.js`
- `task165-rust-web-dual-pane-smoke.js`
- `task164-desktop-hot-local-folder-main-entry-smoke.js`
- `task166-local-first-managed-workspace-no-convex-smoke.js`
- `task455-local-folder-mindmap-clean-smoke.js`
这一层已经覆盖了当前主线里最重要的部分:
- tree / sidebar / create page
- document shell / island hydration
- 页面设置、双栏、AI、local folder
- Rust Web 主路径
### 1.3 Wolai 对标与视觉取证层
这一层不是单纯判断“是否通过”,而是要保留截图、矩阵、对比结论,方便和 Wolai 体验做真实核对。
代表脚本:
- `task119-rust-web-wolai-visual-regression-smoke.js`
- 已跟踪的对标基线:`task118-rust-web-wolai-ui-parity-smoke.js``task119-rust-web-wolai-visual-regression-smoke.js`
- `task128``task129``task137``task160``task162` 是 gitignored 的本地历史取证脚本,不属于默认回归。
- 页面 AI 旧 `/api/ai-agent/run` 视觉 smoke 已移入本机 gitignored `recycle/scripts/retired-ai-agent-run-smokes/`;当前页面 AI 验证优先使用 Pi Lab / opencode / Page AI smoke 与 `task-page-block-ai-tools-smoke.js`。Hermes 相关 smoke 只作为 legacy guard / 历史对照。
这一层最重要的原则不是“文案命中”,而是:
- 必须有截图
- 必须能说明视口
- 必须能说明对比对象
- 最终仍需要人工看图
### 1.4 共享 helper 与登录/临时文档支撑层
这部分决定了 smoke 是否能稳定复用。
关键文件:
- `tree-shell-smoke-helpers.js`
- `task114-rust-web-gateway-entry-smoke.js`
目前 helper 已经沉淀了几个稳定约定:
- 默认前端入口:`MNOTE_UI_BASE_URL`,缺省 `http://127.0.0.1:3000`
- 默认测试账号:
- 邮箱:`mnote.e2e@example.com`
- 密码:`MnoteE2E123!`
- 快捷按钮:`测试账号快速登录`
- 通过 API 或 UI 兜底完成认证
- 为 smoke 自动创建、重命名、清理临时页面
后续新脚本优先复用这些 helper,不要在每个任务里再复制一套登录和清理逻辑。
#### Dev seed 启动契约
- 需要 `setupWorkspaceAccess``seedAiPolicy``seedAiRuntime` 等测试数据准备能力时,先确认服务由 `npm run dev:hot` 启动。
- `npm run dev:hot` 默认开启 dev fixtures;可用 `MNOTE_WEB_ALLOW_DEV_FIXTURES=0 npm run dev:hot` 显式关闭。
- `npm run desktop:hot` 保持生产近似的安全默认,不自动开放 `/api/dev/seed`;确需复用时显式执行 `MNOTE_WEB_ALLOW_DEV_FIXTURES=1 npm run desktop:hot`
- smoke 遇到 `dev_seed_disabled` 时不得标记为“功能未验证后跳过”;应先按上述契约重启服务,再重新执行完整 smoke。
## 2. 当前推荐测试顺序
对本项目,推荐不要一上来就跑最重的 UI 对标脚本,而是按下面顺序推进。
### 2.1 第一步:入口守门
先跑入口和网关类 smoke,确认不是服务没起或路由错了。
建议优先:
```bash
node scripts/task114-rust-web-gateway-entry-smoke.js
node scripts/task159-auth-entry-smoke.js
node scripts/task097-homepage-entry-smoke.js
```
适用时机:
- 本地服务刚启动
- 刚切换分支
- 改了认证、入口、gateway、compat
### 2.2 第二步:主路径交互 smoke
入口没问题后,再跑和当前改动最相关的页面交互脚本。
例如:
- tree / sidebar 改动:`task112``task120``task122`
- document shell / island`task110``task121`
- local-first:优先使用 `task164-desktop-hot-local-folder-main-entry-smoke.js``task166-local-first-managed-workspace-no-convex-smoke.js``task167-local-markdown-title-body-options-no-convex-smoke.js``task455-local-folder-mindmap-clean-smoke.js`
- 页面设置:`task164-page-options-visible-effect-smoke.js`
- 双栏:`task165`
- AI:优先使用 Pi Lab / Page AI 当前主线 smoke、`task-page-block-ai-tools-smoke.js``task-hermes-page-ai-retirement-guard.js` 这类 legacy guard;其余 Hermes 页面 AI 主流程 smoke 已退役。Page AI history / skills / ChatOnly 相关改动补跑 `task503-mindmap-skill-capability-smoke.js``task504-page-ai-history-agent-filter-smoke.js``task512-chatonly-doubao-sync-smoke.js``task513-chatonly-provider-sync-smoke.js`OnlyOffice live bridge 改动补跑 `task515-onlyoffice-live-scope-http-smoke.js``task516-onlyoffice-bridge-multisession-browser-smoke.js``task517-onlyoffice-bridge-plugin-direct-smoke.js``task518-onlyoffice-real-iframe-session-scope-smoke.js`,其中 `task516/517` 覆盖 bridge session lifecycle 与 `docKey/pageOrigin` 元数据;Page AI 真实 target picker / Office live session 改动补跑 `task523-page-ai-onlyoffice-real-target-session-smoke.js``task155``task156``task161` 等旧 `/api/ai-agent/run` smoke 只保留在本机 gitignored `recycle/scripts/retired-ai-agent-run-smokes/` 做历史对照
原则:
- 只跑和当前改动相关的脚本
- 不要无差别全量跑
- 先窄后宽
### 2.3 第三步:截图证据复核
如果脚本本身已经输出:
- `screenshot`
- `screenshotDir`
- `measure`
- `matrixPath`
- `resultPath`
那这些产物不应只当“附带文件”,而应作为测试结果的一部分。
推荐做法:
- 成功时也保留关键截图
- 失败时至少保留失败前最后一张截图
- 重要 UI 任务保留整组截图目录
### 2.4 第四步:`/doko` 真实页面复核
当 smoke 已经告诉你“逻辑大体通过”,但你仍想确认页面是否真的像人看到的一样时,再补 `/doko`
`/doko` 更适合回答这类问题:
- 首屏布局是不是顺眼
- Sidebar 层级、图标、文案是否真可读
- 页面设置弹层是否真的展开到位
- 登录后工作区是否像预期渲染
`/doko` 不擅长替代:
- 稳定断言
- 自动点击链路
- 大量重复回归
所以推荐组合是:
`smoke 先筛出通过/失败 -> 看截图 -> 必要时再用 /doko 复核真实页面`
## 3. 为什么当前不建议把主线转成“浏览器插件测试”
当前讨论过 `codex cli + 浏览器插件` 的方向,但对 `mnote` 现阶段的主要收益并不明显。
原因有三点:
1. 你当前真正缺的是“页面直观证据”,不是“替换掉 Playwright”
2. `scripts/` 里的 smoke 已经能覆盖多数关键交互,只是证据层不够统一
3. 浏览器插件路线更适合复用真实 Chrome 当前标签页和真实登录环境,不是当前项目测试的首要瓶颈
因此,现阶段更推荐:
- 保留 Playwright smoke 作为自动化骨架
- 补足截图、trace、结果摘要
-`/doko` 做人工视角复核
## 4. 新增或修改 smoke 的写法建议
这里不是要求统一重构旧脚本,而是约束新增脚本尽量沿着同一条路走。
### 4.1 优先复用 helper
优先从下面两个文件拿能力:
- `tree-shell-smoke-helpers.js`
- `task114-rust-web-gateway-entry-smoke.js`
尤其是:
- 登录
- 创建临时文档
- 清理临时文档
- `fetchWithTimeout`
- `findFreePort`
- `waitForGateway`
### 4.2 让脚本输出结构化结果
推荐脚本结束时输出 JSON,至少包含:
```json
{
"ok": true,
"baseUrl": "http://127.0.0.1:3000",
"task": "taskxxx-name",
"screenshot": "/abs/path/to/file.png",
"screenshotDir": "/abs/path/to/dir"
}
```
如果没有截图,也应该至少输出:
- `ok`
- `baseUrl`
- `task`
- 关键对象 id(如 `documentId``workspaceId`
### 4.3 对 UI 任务默认保留截图
满足下面任一条件时,建议默认保留截图:
- 首屏入口变化
- Sidebar / tree 结构变化
- modal / popover / dropdown 变化
- editor block 行为变化
- Wolai 对标
推荐命名方式延续现有风格:
- `01-before-*`
- `02-after-*`
- `03-after-reload-*`
这样后续人工复核时不需要重新猜步骤。
### 4.4 失败信息要面向定位
断言报错要直接描述“哪个状态不对”,不要只写泛化失败。
推荐:
- `开启宽版后 htmlWide 应为 true,实际 false`
- `测试账号登录后仍停留在 /auth`
- `本地首屏未捕获工作区特征`
不推荐:
- `smoke failed`
- `assert error`
## 5. 针对当前 mnote 的推荐组合
如果后续只是做日常开发验证,推荐这样选:
### 5.1 快速检查
适合日常改完立刻看:
```bash
node scripts/task114-rust-web-gateway-entry-smoke.js
node scripts/task159-auth-entry-smoke.js
```
### 5.2 主路径回归
按当前改动挑 1 到 3 个最相关脚本,例如:
```bash
node scripts/task120-rust-web-tree-integration-smoke.js
node scripts/task122-rust-web-create-page-ui-smoke.js
node scripts/task164-page-options-visible-effect-smoke.js
```
### 5.3 视觉复核
如果任务明显涉及视觉或交互形态:
- 先看 smoke 产出的截图
- 再用 `/doko` 打开真实页面复核
### 5.4 Wolai 对标任务
对标任务不要只看断言结果,至少补:
- 本地 smoke
- Wolai 基线截图
- 本地截图
- 必要时 comparison matrix
## 6. 对后续演进的建议
这部分不是要求本轮立刻实现,而是后续维护时优先考虑。
### 6.1 在现有 smoke 上统一证据产物
优先级最高的增强不是“换工具”,而是统一输出:
- `tmp/.../screenshots`
- `tmp/.../trace.zip`
- `tmp/.../result.json`
这样 smoke 从“脚本 pass/fail”升级成“脚本 + 可看证据”。
### 6.2 把 `/doko` 固化成复核步骤
适合写进任务流程的话术是:
- 先跑 smoke
- 再看截图
- 仍有疑问时用 `/doko` 看真实渲染
不要让 `/doko` 承担自动化断言职责。
### 6.3 新脚本优先沿当前命名方式继续
目前 `taskNNN-...-smoke.js` 已经形成了可追踪的任务链,后续建议继续沿用,避免引入第二套命名体系。
---
如果后续要继续推进,最值得做的不是重写测试体系,而是:
1. 给最常用的 smoke 补统一截图/trace 产物
2. 再补一份“如何读取 smoke 结果”的轻量脚本或汇总器
这样能直接解决当前最真实的痛点:`A + C`,也就是“结果更直观、测试更像真的看过页面”。
## 7. 脚本纪律:不得直写 control-plane 数据库
所有测试和 smoke 脚本**不得直接通过 `sqlite3` CLI、`node:sqlite``better-sqlite3` 或任何本地 SQLite 库写 control-plane DB**。需要写入测试数据时,必须走以下批准路径:
### 7.1 通过 API seed(推荐)
使用 `scripts/lib/control-plane-dev-seed.js` 提供的 helper,通过 `POST /api/dev/seed` 写入:
```js
const { setupWorkspaceAccess, seedAiRuntime } = require("./lib/control-plane-dev-seed");
await setupWorkspaceAccess(requestContext, baseUrl, { ... });
```
该 helper 调用的是 Rust `/api/dev/seed` 端点,不直写数据库。
初始环境(测试账号 + workspace)也可通过 `control-plane-admin init --backend ...` 准备,见 `docs/operations/control-plane-turso.md`
### 7.2 通过统一环境变量构建
使用 `scripts/lib/control-plane-test-env.js``buildControlPlaneTestEnv()` 获取正确的控制面环境变量:
```js
const { buildControlPlaneTestEnv } = require("./lib/control-plane-test-env");
const controlPlaneEnv = buildControlPlaneTestEnv(dataRoot, process.env);
// 然后传给 spawn(cargo, args, { env: { ...controlPlaneEnv } })
```
### 7.3 例外
- `scripts/lib/control-plane-dev-seed.js``scripts/lib/control-plane-test-env.js` 本身是批准 helper。
- `scripts/desktop-hot.js``scripts/dev-hot.js``scripts/prod-build-start.js` 作为启动基础设施,设置环境变量路径是必要的。
- `rust/crates/` 下的 Rust 代码通过 `ControlPlaneStore` trait 访问数据库是正常路径。
- `scripts/task-control-plane-admin-libsql-roundtrip-smoke.js` 使用 `cargo run --bin control-plane-admin`,走 Rust admin CLI。
- `sqlite` fallback、admin CLI、legacy evidence/local_search 不在脚本纪律约束范围内。
- 已退役 AI host 自身 SQLite 不绑定本轮 control-plane Turso 切换;历史迁移说明保留在 recycle 归档中。
### 7.4 违规后果
- 直接 `sqlite3` 写 control-plane DB 会导致多个进程同时写同一个 SQLite 文件,增加 WAL 损坏和并发写入冲突的风险。
- 直接写库的脚本在切换到 Turso/libSQL 后端后将无法运行。
- 违反此纪律的脚本将被要求改用上述批准路径。
具体约束条目见 AGENTS.md 中"脚本纪律"一节。