Files
mnote/design/03-rust-web/done/3-18-local-folder-tree-live-consumer-convergence-checklist-v1.md
T

6.7 KiB
Raw Blame History

3-18 [done] Local Folder Tree Live Consumer 收敛 checklist v1

创建时间:2026-05-21

当前状态:DONE

上位入口:

  • design/01-tree-first-graph-kernel/process/1-8-mvp-post-process-execution-order-v1.md
  • design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md

目标:把 local-first 默认路径的 Sidebar / FileTree 从 local-folder-watch 轮询补拉 projection,收敛到与 cloud / sync path 相同的 tree live consumer 事件口径;完成后再判断 3-3 是否可归档。

1. 当前事实

  • 3000 cloud / compat 工作区已通过 TREE_LIVE_CONTROLLER_JS 优先连接 /api/realtime/ws,失败后回退 /api/tree/events
  • sourceKind=local_folder 时,TREE_LIVE_CONTROLLER_JS 当前直接标记 data-mnote-tree-live-transport="local-folder-static" 并返回,不进入 WS / SSE tree live consumer。
  • local_folder Sidebar / FileTree 当前由 startLocalFolderSidebarWatch() 轮询 /api/tree/local-folder-watch,发现 revision 变化后再调用 refreshLocalFolderSidebarSnapshot() 分别拉 /api/tree/projections/sidebar/api/tree/projections/file
  • web_shell.rs 已有 /api/local-folder/events SSE,用于 tiptap 文档外部变更刷新,但它还没有统一到 Sidebar / FileTree 的 tree:snapshot / tree:delta / tree:resync consumer。

2. 不做事项

  • 不恢复 Convex 正文主存储。
  • 不把 local_folder 变化写回 Convex command log。
  • 不重开旧 Next / BlockNote 默认路径。
  • 不一次性重写所有 Sidebar/FileTree 逻辑;本轮只替换轮询补拉链路的 transport 和 consumer 入口。

3. Worker 拆分

Worker A:后端 local_folder tree live stream

Owner

  • rust/crates/mnote-web/src/routes/local_folder_events.rs
  • rust/crates/mnote-web/src/routes/stream_support.rs
  • rust/crates/mnote-web/src/routes/mod.rs
  • 必要时只读 rust/crates/mnote-web/src/local_folder_watcher_registry.rs

目标:

  • 给 local_folder 提供 tree live 事件形状:tree:snapshot / tree:resync 至少携带 kernel_sidebar_projectionkernel_file_tree_projection
  • 复用现有 LocalFolderWatcherRegistry,不新增第二套 watcher。
  • 事件 payload 必须保留 sourceKind=local_folderrootUriworkspaceIdrevision
  • 若无法可靠生成细粒度 delta,允许先统一发 resync,但必须走同一个前端 renderSidebarSnapshot() consumer。

验收:

  • cargo test --manifest-path rust/Cargo.toml -p mnote-web local_folder_events -- --test-threads=1
  • cargo test --manifest-path rust/Cargo.toml -p mnote-web stream_support -- --test-threads=1

Worker B:前端 tree live controller 接入 local_folder

Owner

  • rust/crates/mnote-web/src/ssr/pages/layout.rs

目标:

  • 移除 sourceKind=local_folder 直接 local-folder-static 返回的长期阻塞。
  • local_folder 进入 tree live controller 后,应使用新后端事件流,并把 snapshot/resync 统一 dispatch 到 tree:snapshot / tree:resync
  • 保留 editor 文档外部变更的 /api/local-folder/events 用法,不破坏 tiptap conflict / external change 逻辑。
  • 尽量让 startLocalFolderSidebarWatch() 退为 fallback,不再是默认主链。

验收:

  • cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_tree_runtime -- --test-threads=1
  • cargo test --manifest-path rust/Cargo.toml -p mnote-web web_shell -- --test-threads=1

Worker C:浏览器 smoke 与证据

Owner

  • scripts/task435-local-folder-watch-no-reload-smoke.js
  • 可新增 scripts/task487-local-folder-tree-live-consumer-smoke.js
  • design/03-rust-web/process/3-18-local-folder-tree-live-consumer-convergence-checklist-v1.md

目标:

  • 增加或更新 smoke,验证 local_folder 文档页 HTML / DOM 不再显示 data-mnote-tree-live-transport="local-folder-static" 作为默认主链。
  • 验证 local_folder Sidebar / FileTree 的外部文件变化最终通过 data-mnote-tree-live-applied="snapshot|resync" 或等价 tree live 标记刷新,而不是只依赖 data-mnote-local-folder-watch-applied="projection"
  • smoke 必须可在 http://127.0.0.1:3000 环境运行,并输出 JSON 证据和截图路径。

验收:

  • node --check scripts/task435-local-folder-watch-no-reload-smoke.js
  • 若新增脚本:node --check scripts/task487-local-folder-tree-live-consumer-smoke.js

4. Codex 复核项

  • 复核 Worker A diff,确认没有新增第二套 watcher 或 Convex 写回。
  • 复核 Worker B diff,确认 local_folder 进入统一 tree live consumer,旧 polling 只保留 fallback。
  • 复核 Worker C smoke,确认断言覆盖真实 UI/DOM 状态。
  • 运行 targeted Rust tests。
  • 运行相关 smoke 或记录环境阻塞。
  • 更新 3-31-8 状态。

5. 本轮执行记录

  • 2026-05-21Codex 复核 3-3 发现 local_folder 默认路径仍是 local-folder-static + /api/tree/local-folder-watch 轮询补拉 projection,因此 3-3 暂不能归档,拆出本 checklist。
  • 2026-05-21Worker C(本批次)
    • 新增 scripts/task487-local-folder-tree-live-consumer-smoke.js
    • 未修改 scripts/task435-local-folder-watch-no-reload-smoke.js,该脚本保持 GREEN(覆盖 no-reload 语义,与 tree live consumer 正交)
    • 先前使用旧进程和首页入口时 smoke 呈 RED;切换到新编译的 3000 进程并改为 documents/local-md:README.md?sourceKind=local_folder... 后,task487 变为 GREENdata-mnote-tree-live-transport=local-folder-eventsdata-mnote-tree-live-status=connected、外部创建/删除后 data-mnote-tree-live-applied=resync
    • 本记录

Worker C smoke 覆盖点

# 断言 当前状态 期望状态(Workers A+B 后)
1 page tree 加载后 data-mnote-tree-live-transport 不是 "local-folder-static" GREEN — 当前为 "local-folder-events" 已满足
2 page tree 加载后 data-mnote-tree-live-status 不是 "static" GREEN — 当前为 "connected" 已满足
3 外部创建 .mddata-mnote-tree-live-applied"snapshot""resync" GREEN — 当前为 "resync" 已满足
4 外部删除 .mddata-mnote-tree-live-applied"snapshot""resync" GREEN — 当前为 "resync" 已满足
5 FileTree 视图加载后 transport/status 非 "local-folder-static" / "static" GREEN — 当前为 "local-folder-events" / "connected" 已满足
6 FileTree 外部创建后 tree-live-applied 为 snapshot/resync GREEN — 当前为 "resync" 已满足
7 data-mnote-local-folder-watch-applied 不再是唯一刷新证据 GREEN — 当前同时存在 data-mnote-tree-live-applied 已满足