chore: batch a filetree smoke evidence

This commit is contained in:
lix-2026
2026-05-21 11:01:17 +08:00
parent 1569699fbb
commit 175b69db79
16 changed files with 1245 additions and 14 deletions
@@ -76,7 +76,36 @@ pnpm exec tsc --noEmit --pretty false 2>&1 | rg "convex/documents.ts\\((160|161|
结果:阶段 6 修改附近无新增 TypeScript 报错。全量 `tsc` 仍受仓库既有错误影响,未作为本阶段完成条件。
## 5. 待补
## 5. 待补Worker C 2026-05-21 追加 local folder restore focus 缺口)
- React Sidebar Drawer 的恢复后 DOM focus 仍需在 React 入口可稳定渲染页面树时补浏览器证据;当前 3000 主壳 smoke 已覆盖“恢复后无需刷新可见 / reveal”,fallback 提示仍由 React Drawer 代码路径负责。
### 5.1 Convex 页面(已有部分证据)
- React Sidebar Drawer 的恢复后 DOM focus 仍需在 React 入口可稳定渲染页面树时补浏览器证据;当前 3000 主壳 smoke(`task429`)已覆盖"恢复后无需刷新可见 / reveal"fallback 提示仍由 React Drawer 代码路径负责。
- 双浏览器 no-refresh:A 恢复页面后,B 不刷新即可看到位置变化;该项归入阶段 8 的实时刷新矩阵。
- 已知源码问题:`selectSidebarFileTreeDocument` 存在且工作(create / navigate 路径调用),但 restore 路径不调用。
### 5.2 Local folder 非 md 资源 restore focus(新发现缺口,Worker C 2026-05-21 审计)
当前状态:**完全未实现**。审计证据及源码对照:
| 检查项 | 状态 | 证据来源 |
|--------|------|----------|
| `selectSidebarFileTreeDocument` 是否从 restore 路径调用 | ❌ 否 | `layout.rs:1274,1296,1333,9278`(仅 create/navigate/activate 路径调用) |
| restore 后 filetree 行是否有 `data-active` / `data-selected` | ❌ 无 | `task473` gap smoke 结果:`data-active="false"``data-selected="false"` |
| restore 后是否 `scrollIntoView``focus()` | ❌ 无 | 同上 |
| trash workbench 的 restore 后 filetree 同步机制 | 轮询 1200ms | `layout.rs:1991-2004` (`startLocalFolderSidebarWatch`) |
| trash workbench 的 restore 后是否调用 `refreshLocalFolderSidebarSnapshot` | ❌ 否,只调 `refresh()`(自身 workbench | `gateway.rs:1064-1065` |
| `selectSidebarFileTreeDocument` 是否支持 `local-file:` row-id | ❌ 否,只查 `doc:` | `layout.rs:4138` |
### 5.3 下一步建议(供 Codex 参考,不在此阶段修改 Rust)
1. **短路径(仅 focus 现有行)**trash workbench inline script 的 restore `.then()` 中设置 `window.__mnoteRestoredDocumentId = entryId`;下一轮 filetree poll 检测此值并 focus 对应行。
2. **中路径**`gateway.rs` trash workbench script 中 restore 成功后也调用 `refreshLocalFolderSidebarSnapshot()` 并传入 focus 参数。
3. **长路径**:扩展 `selectSidebarFileTreeDocument` 支持 `local-file:` 行 IDrestore 完成后通过 `CustomEvent` 跨 trash 页 → 主页面通信。
4. **smoke 回归**`task473` 已记录当前缺口。后续实现后复跑 `task473` 应观察到 `data-selected="true"``data-active="true"` 出现。
### 5.4 2026-05-21 浏览器复核
- Codex 独立复跑 `node --check scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js``node scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js``ok:true``restoreNavFree.delta=0``fileReappearsInFiletree=true`
- Reasonix Browser Worker 输出目录:`tmp/reasonix-batch-a-browser-task473-2026-05-21/`,结论 `PASS_WITH_KNOWN_GAP`
- 复核结论:local folder 非 md 资源 restore 后已证明 no-refresh 与行恢复;focus/reveal 仍未实现,不能归档为完成。
@@ -93,8 +93,13 @@
- `LocalFolderWatcherRegistry` 使用 `notify` 递归监听 root,但事件发送前经过 `is_markdown_path`,只允许 `.md/.markdown`
- `/api/local-folder/events` 订阅该 watcher,主要服务打开的本地 Markdown document session。
- 主 tree 的 local folder 模式不接 `/api/tree/events`,而是轮询 `/api/tree/local-folder-watch`;revision 扫描可见条目,非 md 文件变化会改变 revision,但当前变化后触发 `window.location.reload()`
- 主 tree 的 local folder 模式不接 `/api/tree/events`,而是轮询 `/api/tree/local-folder-watch``startLocalFolderSidebarWatch`1200ms 间隔)。revision 变化时调用 `refreshLocalFolderSidebarSnapshot()` 重渲染 filetree**不触发 `window.location.reload()`**。Rust 单元测试 `sidebar_tree_runtime_polls_local_folder_without_browser_reload` 验证了 SSR template 中不含 reload 语句
- trash workbench 的 local folder restore/purge 使用 `refresh()`gateway.rs:1040-1060):`fetch` + `DOMParser` 替换 workbench `innerHTML`,不触发浏览器导航。但 restore/purge 完成后不调用 `refreshLocalFolderSidebarSnapshot()`,filetree 更新依赖下次轮询触发。
- `task163-local-folder-unified-tree-browser-smoke.js` 已覆盖外部新增 Markdown、外部新增 / 删除 `watcher-asset.txt` 的可见性;尚未覆盖外部 Markdown 重命名 / 删除、非 md rename、非 md trash / restore / purge。
- `task435-local-folder-watch-no-reload-smoke` 已通过:外部非 md 文件(`.txt``.png`)的 create / rename / delete 在 filetree 中无刷新可见更新,全程无 `framenavigated`。(结果:`tmp/task435-local-folder-watch-no-reload-smoke/result.json`
- `task437-local-folder-asset-trash-lifecycle-smoke` 已通过(API-only):`tree.resource.archive` / `restore` / `purge` 的 canonicalCommand 与文件系统一致性。(结果:`tmp/task437-local-folder-asset-trash-lifecycle-smoke/result.json`
- `task464-local-folder-resource-trash-ui-smoke` 已通过(Browser UI):trash 页中 delete→visible / restore→file restored / purge→file gone 完整 UI 流程。(结果:`tmp/task464-local-folder-resource-trash-ui-smoke/result.json`
- `task473-local-folder-trash-restore-no-refresh-focus-gap-smoke` 新增并已由 Codex + Reasonix Browser Worker 实跑:验证 trash workbench 的 restore 操作为 fetch 型 `refresh()``restoreNavFree.delta=0`,不触发浏览器导航),restore 后 filetree 通过轮询显示恢复行(`fileReappearsInFiletree=true`)。同时记录 restore 后无 focus/active/selected 属性(`data-active="false"``data-selected="false"`、无 `data-focused`)——本缺口已明确记录。(结果:`tmp/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke/result.json`;浏览器证据:`tmp/reasonix-batch-a-browser-task473-2026-05-21/`
通过后才允许在 10-review 中把 local folder 阶段 8 子项勾选;如果仍发生 reload,只能标为“reload 型刷新可见”,不能标为 no-refresh。
@@ -39,8 +39,8 @@
- [x] `cargo test -p mnote-web layout -- --test-threads=1`
- [x] `cargo test -p mnote-web tree_command_local_folder -- --test-threads=1`
- [ ] `node scripts/task430-vscode-explorer-stage7-smoke.js`
- [ ] `node scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- [x] `node scripts/task430-vscode-explorer-stage7-smoke.js` — 2026-05-21 实跑通过,结论 `PASS_WITH_KNOWN_GAPS`workspace bootstrap、F2 rename、cut/paste move、DnD preflight guard 通过;FileTree `data-active`、Open Editors、`Paste Into` 菜单与 readonly/重名冲突矩阵仍作为后续缺口记录。
- [x] `node scripts/task471-local-folder-bulk-resource-trash-smoke.js` — 2026-05-21 实跑通过,全部断言成功:多选两个资源行、确认文案含附件数、双 archive command、trash index 含两项、DOM 记录 `bulk-delete`/`archived`/触发 row。
- [ ] 如新增 smoke`node scripts/task47*-filetree-action-layer-smoke.js`
## 5.1 本轮执行记录
@@ -49,6 +49,8 @@
- 已合入:右键 `paste-into` 使用菜单触发 row,不再只能靠 focused row。
- 本轮追加:`layout.rs` 为 filetree projection row 暴露 `data-capabilities`,新增 `ensureFileTreeWritableTarget` / `blockReadonlyFileTreeAction`paste 与内部 drop 在执行前复用 `/api/tree/filetree/drop-preflight`readonly 目标统一写入 `data-mnote-filetree-last-action-status=blocked``data-mnote-filetree-readonly-blocked``data-mnote-filetree-readonly-message` 与目标 row 标记,并沿用 `alert` fallback 提示。
- 本轮追加:`task471-local-folder-bulk-resource-trash-smoke.js` 增加语义断言,覆盖 bulk-delete 的 action 名、触发 row 与 `archived` undo 状态;未修改 `task430` 的隔离 workspaceId 前置条件,避免把环境准备失败误判为业务回归。
- 2026-05-21 Reasonix Worker B 实跑:`node scripts/task471-local-folder-bulk-resource-trash-smoke.js` 通过,所有断言成功,无业务语义改动;更新验收 checklist 标记为 `[x]`
- 2026-05-21 Codex 与 Reasonix Browser Worker 复核:`task430` / `task471` 均可在当前 3000 环境实跑。`task430` 的 Open Editors 与 active row 只记录现状,不作为本阶段业务失败;`task471` 的多选资源删除链路有截图与 JSON 证据。
## 6. 非目标
@@ -25,15 +25,16 @@
## 4. Checklist
- [ ] 跑或修复 `task430` / `task471` 的可复现前置条件。
- [ ] 明确哪些 smoke 已过、哪些因环境阻塞。
- [ ] 补充 open editor / filetree active row / lifecycle 状态断言建议。
- [ ] 更新 4-44 checklist 执行记录。
- [x] 跑或修复 `task430` / `task471` 的可复现前置条件。
- [x] 明确哪些 smoke 已过、哪些因环境阻塞。
- [x] 补充 open editor / filetree active row / lifecycle 状态断言建议。
- [x] 更新 4-44 checklist 执行记录。
## 5. 验收
- `node --check scripts/task430-vscode-explorer-stage7-smoke.js`
- `node --check scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- `node scripts/task430-vscode-explorer-stage7-smoke.js`
- `node scripts/task471-local-folder-bulk-resource-trash-smoke.js`
## 6. 非目标
@@ -46,4 +47,13 @@
- 2026-05-21Reasonix Worker D 识别到 `task430` 的前置问题:新注册用户在 `workspaces:fetchWorkspaceSummaries` 前可能还没有 workspace,需要先通过 `/api/tree/commands` create action 触发 workspace bootstrap。
- 2026-05-21Worker D 还建议将 `task471` 的验证记录同步到 `4-44`,并补 open editor / lifecycle 状态断言。
- 2026-05-21Worker D 进程停留在计划提交阶段,没有生成 `final.md`,也没有实际修改 smoke 或 checklist;本轮不把 4-45 checklist 标记为完成。
- 后续建议:先修 `task430` workspace bootstrap,再新增 filetree active row 与 open editors snapshot 的联合断言,避免只验证树动作、不验证打开编辑器状态。
- **2026-05-22Worker A 实际修改:**
-`task430` 的 workspace bootstrap 添加 fallback:当 `workspaces:fetchWorkspaceSummaries` 无返回时,通过 `/api/tree/commands` create(不带 workspaceId)触发 Rust 端 `workspaces:ensureDefaultWorkspace` 自举 workspace。
- 添加 `result.phases` 阶段追踪(auth-signin → auth-navigate → workspace-bootstrap),让失败可区分环境阻塞 vs 业务回归。
- 添加 `filetree-active-row` 断言:检查当前打开页对应的 FileTree row 是否有 `[data-active="true"]`
- 添加 `filetree-selected-row` 记录:记录选中行 ID(不做强制断言,因选中语义随点击变化)。
- 添加 `open-editors-section` 记录:确认 MNote 当前无 Open Editors DOM sectionVS Code 对比的已知缺口),只记录不报错。
- 所有新增断言均使用 `runOptional` 包装,环境缺口标记为 skipped 而不阻塞整体结果。
- 2026-05-21Codex 独立复跑 `node --check scripts/task430-vscode-explorer-stage7-smoke.js` / `node scripts/task430-vscode-explorer-stage7-smoke.js`,结果 `ok:true``result.phases``auth-signin``auth-navigate``workspace-bootstrap` 均通过;`f2-inline-rename-doc``f2-inline-rename-asset``cut-paste-move``dnd-preflight-guard` 均通过。
- 2026-05-21Reasonix Browser Worker 复跑 task430,输出目录 `tmp/reasonix-batch-a-browser-task430-2026-05-21/`,结论 `PASS_WITH_KNOWN_GAPS`。已知缺口保留为:FileTree row 未同步 `data-active="true"`、Open Editors section 未实现、右键菜单缺 `Paste Into`、DnD readonly/重名冲突仍需后续端到端矩阵。
- 2026-05-21Codex 独立复跑 `node --check scripts/task471-local-folder-bulk-resource-trash-smoke.js` / `node scripts/task471-local-folder-bulk-resource-trash-smoke.js`,结果 `ok:true`。Reasonix Browser Worker 输出目录 `tmp/reasonix-batch-a-browser-task471-2026-05-21/`,确认两个 local folder 资源行可 Ctrl 多选、确认文案含 `2 个附件`、DOM 状态写入 `bulk-delete` / `archived``.mnote/trash-index.json` 包含两项。
@@ -0,0 +1,134 @@
# 4-46 [process] Batch A FileTree Action / Trash Smoke Execution Checklist v1
> 创建时间:2026-05-21
>
> 上位入口:`design/01-tree-first-graph-kernel/process/1-8-mvp-post-process-execution-order-v1.md`
>
> 阶段:Batch A / P0 清验证阻塞
>
> 当前状态:`PROCESS`
## 1. 目标
`1-8` 中 Batch A 的四个入口文档拆成可执行小阶段,优先清除会干扰后续判断的 FileTree action、Open Editors lifecycle、Trash no-refresh 与 restore focus smoke 红灯。
本阶段不扩新产品面,不做大规模 tree command 重构;只修复或明确验证阻塞,并产出可复核 smoke 证据。
## 2. 上游入口
- `design/04-tree-domain/process/4-45-filetree-open-editors-lifecycle-link-checklist-v1.md`
- `design/04-tree-domain/process/4-44-filetree-action-layer-paste-drop-delete-v1.md`
- `design/04-tree-domain/process/4-34-filetree-trash-dual-browser-no-refresh-v1.md`
- `design/04-tree-domain/process/4-28-trash-restore-location-reveal-focus-v1.md`
## 3. 不做事项
- 不改变 delete 默认进入垃圾箱的语义。
- 不把 reload 型刷新伪装成 no-refresh。
- 不把浏览器环境准备失败标记为业务通过。
- 不提交 gitReasonix worker 只能改文件并报告,最终由 Codex 复核提交。
- 不改 `design/old/**`
## 4. Reasonix Worker 拆分
### Worker Atask430 Explorer / Open Editors 前置与断言
Owner
- `scripts/task430-vscode-explorer-stage7-smoke.js`
- `design/04-tree-domain/process/4-45-filetree-open-editors-lifecycle-link-checklist-v1.md`
目标:
- 修复或明确 `task430` 的 workspace bootstrap 前置条件。
- 补 FileTree active row / Open Editors / lifecycle 相关断言,至少让 smoke 结果能区分“环境阻塞”和“业务回归”。
- 不修改 Rust 核心文件。
验收:
- `node --check scripts/task430-vscode-explorer-stage7-smoke.js`
- 能实跑则运行 `node scripts/task430-vscode-explorer-stage7-smoke.js` 并记录结果;不能实跑必须写明缺失服务或环境前置。
### Worker Btask471 local folder bulk resource trash
Owner
- `scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- `design/04-tree-domain/process/4-44-filetree-action-layer-paste-drop-delete-v1.md`
目标:
- 实跑或修复 `task471`,确认 local folder 多选资源 delete 走 archive tree command、资源进入 `.mnote/trash`、DOM action 状态可观测。
- 如果缺少 3000 服务或 auth 前置,必须记录为环境阻塞,不改业务语义。
验收:
- `node --check scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- 能实跑则运行 `node scripts/task471-local-folder-bulk-resource-trash-smoke.js` 并记录 stdout / result。
### Worker C4-34 / 4-28 local folder no-refresh 与 restore focus 缺口
Owner
- `design/04-tree-domain/process/4-34-filetree-trash-dual-browser-no-refresh-v1.md`
- `design/04-tree-domain/process/4-28-trash-restore-location-reveal-focus-v1.md`
- 可新增或修改一个 `scripts/task47*-local-folder-*.js` smoke;如需改 Rust/SSR,先在最终报告中给建议,不直接改核心 Rust 文件。
目标:
- 盘点 local folder 非 md 资源 trash / restore / purge 的真实 UI 支持状态。
- 盘点 restore 后 DOM reveal / focus 的现有证据缺口。
- 如能小范围新增 browser smoke,则新增;否则更新 checklist,明确未完成能力与下一步。
验收:
- 新增脚本必须 `node --check` 通过。
- 若实跑浏览器 smoke,结果必须落到 `tmp/task47*/result.json` 或报告具体阻塞。
## 5. Codex 复核项
- [x] 逐个读取 Reasonix `final.md` / `result.json`
- [x] 检查 `git diff`,确认 worker 没有越权修改。
- [x] 运行所有被修改脚本的 `node --check`
- [x] 运行相关 Rust targeted tests(如 worker 修改 Rust)。
- [x] 对能实跑的 smoke 进行 Codex 独立复跑。
- [x] 更新本 checklist 的执行记录。
## 6. 浏览器测试阶段
Batch A 代码 / smoke 修复完成后,再拆分浏览器测试 worker:
- Browser Worker 1:实跑 `task430`,输出截图、控制台错误、result.json。
- Browser Worker 2:实跑 `task471`,输出截图、stdout、result.json。
- Browser Worker 3:实跑 local folder restore/no-refresh 相关 smoke 或人工步骤,输出截图和阻塞点。
Codex 必须复核浏览器测试结果;不能只相信 worker 文字总结。
## 7. 完成条件
- `task430` / `task471` 至少完成语法检查,且实跑结果为通过或有明确环境阻塞记录。
- `4-44` / `4-45` 的执行记录与真实 smoke 状态一致。
- `4-34` local folder 子项和 `4-28` restore focus 子项有明确证据:完成、未完成或环境阻塞,不能再是模糊 TODO。
- `git diff --check` 通过。
- `codegraph sync .` 已运行。
- 本阶段完成后由 Codex 提交 git。
## 8. 本轮执行记录
- 2026-05-21Codex 建立 Batch A 小 checklist,并准备派发 Reasonix Worker A/B/C。
- 2026-05-21Reasonix Coding Worker A/B/C 完成第一轮;Codex 读取 `.codex/reasonix-tasks/results/batch-a-worker-*.md` 并复核 diff。Worker A 修改 `task430``4-45`Worker B 更新 `4-44`Worker C 新增 `task473` 并更新 `4-34` / `4-28`
- 2026-05-21Codex 结束已完成的 Reasonix 残留进程,避免旧线程干扰后续 worker。
- 2026-05-21Codex 独立运行:
- `node --check scripts/task430-vscode-explorer-stage7-smoke.js`
- `node --check scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- `node --check scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js`
- `node scripts/task430-vscode-explorer-stage7-smoke.js`
- `node scripts/task471-local-folder-bulk-resource-trash-smoke.js`
- `node scripts/task473-local-folder-trash-restore-no-refresh-focus-gap-smoke.js`
- 2026-05-21:发现 `task473` 初版把 `file://` rootUri 再次传给 `trashUrl()`,导致 `/trash?rootUri=file://file://...` 等不到 local-folder workbench;已修为传入本地 root path。
- 2026-05-21:发现 `task473` 初版把 `data-active="false"` / `data-selected="false"` 当作 focus 证据;已修为只有值为 `"true"` 或明确 active/selected/focused class 才算 focus。修正后 `task473``ok:true`,但步骤 9 正确记录为 `ok:false` 的已知缺口。
- 2026-05-21:派发 Reasonix Browser Worker 1/2/3
- `task430` 输出 `tmp/reasonix-batch-a-browser-task430-2026-05-21/`,结论 `PASS_WITH_KNOWN_GAPS`
- `task471` 输出 `tmp/reasonix-batch-a-browser-task471-2026-05-21/`,结论 `PASS`
- `task473` 输出 `tmp/reasonix-batch-a-browser-task473-2026-05-21/`,结论 `PASS_WITH_KNOWN_GAP`
- 2026-05-21Codex 复核 Reasonix 截图和 JSONtask471 的多选删除截图与 DOM / trash index 断言一致;task430/task473 截图只作为浏览器可打开佐证,最终状态以 smoke `result.json` 为准。