Files
mnote/design/04-tree-domain/process/4-16-tree-rust-family-remaining-final-runtime-checklist-v1.md
T
lix-2026 4ab36a9386 feat(tree): complete rust family runtime checklist
- add tree shell runtime artifact contracts and page/filetree/picker runtime reducers
- sink tree.subtree.move write operation through Rust and formalize command event plans
- harden file tree search projection contract and route thin-proxy boundaries
- record completed harness tasks and move design docs into process/done
2026-04-27 10:27:15 +08:00

216 lines
12 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.
# 4-16 [process] 树域 Rust 家族剩余 final runtime checklist v1
> 创建时间:2026-04-27
>
> 来源:`4-9 / 4-10 / 4-11` 中仍未完成的后续目标,以及 `4-12` 到 `4-15` 完成后的剩余边界。
>
> 本文只规划后续目标,不回滚已完成的 3000 inline host、Rust initial DOM、rendererInput/state family 与现有 smoke 覆盖。
## 0. 当前执行状态(2026-04-27
`harness` 本轮从本文拆出的 `task-001``task-009` 已全部执行完成,`harness-progress.txt` 记录为 `completed=9 / pending=0 / in_progress=0 / failed=0`
### 已完成
- Phase K 已完成 `rust_tree_shell_runtime_artifact_v1` artifact 边界,以及 page / filetree / picker 的 Rust-side runtime reducer contract。
- Phase K 已固定 3000 inline host 与 `mnote-web /tree` debug shell 都输出同名 runtime artifact3000 主路径继续使用 same-origin inline host`/api/tree/shell -> mnote-web:3104` debug 直连默认关闭。
- Phase L 已引入 Rust `treeWriteOperation`Convex `documents.move` 优先执行 Rust write operation,并保留 `normalizedMove` 作为兼容 fallback。
- Phase M 已将 `page.body.saved``block.patched``block.moved``block.embedded` 切到 formal `domainEventPlan` payload schema,复合命令 stream delta 使用 `resync_required` 保守策略。
- Phase N 已新增 route thinning manifest 与 boundary 测试,明确 `/api/tree/commands``/api/tree/stream``/api/tree/shell` 的 thin proxy / debug / compat 边界。
- Phase O 已完成 `file_tree` 搜索 hardening`maxResults=80`、祖先补全/排序/异步可见性元数据、空结果文案,以及 `index / asset-folder / asset / mindmap child / book / pdf` fixture 覆盖。
### 仍剩余
- `TreeShellIframeHost` 内联模板中的运行时执行层仍是 compat JS 镜像;已完成的是 Rust artifact/reducer contract,不是完整 wasm/Rust DOM runtime 替换。
- `normalizedMove` fallback 仍保留;后续可在确认所有调用方都稳定传入 `treeWriteOperation` 后删除兼容 fallback。
- `document.snapshot.saved` 仍未作为独立 event type 固定;当前 snapshot 信息随 `page.body.saved` payload 进入 formal schema。
- `tree.node.embed``pageReference` block 组装仍在 3000 route compat 边界内,后续应进入 Page Aggregate / Rust artifact。
- Phase O 的异步索引可见性目前是 projection request meta / move-embed picker 搜索路径契约,不是完整索引指标平台。
## 1. 当前基线
- `harness` task-001 至 task-009 已完成。
- `page tree / file tree / picker` 默认主路径已使用 3000 same-origin inline host,不再请求 `/api/tree/shell -> mnote-web:3104`
- 首屏 DOM 已由 Rust initial renderer 输出:
- `data-rust-page-renderer="initial_v1"`
- `data-rust-filetree-renderer="initial_v1"`
- `data-rust-picker-renderer="initial_v1"`
- 主路径已统一为 `state.items + rendererInput`,不再通过 `__MNOTE_TREE_SHELL_OVERRIDE__` 注入第二份 items。
- page focus、filetree selection、picker state 已暴露并消费 reducer contract;运行时执行仍主要是 compat JS 镜像。
- 3000 inline host 与 `mnote-web /tree` debug shell 已同步输出 `rust_tree_shell_runtime_artifact_v1`,供后续真正 Rust runtime / wasm 替换执行层。
- tree command move 写路径已优先使用 Rust `treeWriteOperation`Convex 继续作为 substrate 与一致性校验层。
- block/save 复合命令已具备 formal `domainEventPlan``resync_required` 保守 delta 合同。
## 2. 后续总目标
把树域从“Rust 持有语义 + compat JS 持有运行时 DOM/state machine”的过渡态,推进到:
- [x] Rust family 持有 renderer runtime / state machine contract。
- [ ] Rust family 真正持有 renderer runtime / DOM 执行层,不再依赖 `TreeShellIframeHost` compat JS 镜像。
- [x] 3000 host 收薄为挂载、认证、transport bridge、artifact writer 与浏览器能力边界。
- [x] Convex compat mutation 不再优先承担 tree command 的核心 legality / normalize / write truth。
- [x] block/save 复合命令进入正式 Rust artifact / domain-event contract。
- [ ] snapshot 独立事件与 Page Aggregate 深层收口继续后续推进。
## 3. Phase K:正式 Rust runtime / wasm 承接 tree shell 运行时
### 目标
完整替换 `TreeShellIframeHost` 内联模板中的主要 compat JS runtime,至少先把 page/filetree/picker 的核心状态机从字符串模板 JS 迁到 Rust runtime/wasm 或等价正式 Rust family runtime。
### checklist
- [x] 定义 runtime artifact 边界:
- [x] 输入:`rendererInput`、projection items、expanded ids、selected row ids、active picker item、focused id。
- [x] 输出:DOM patch / intent event / command dispatch event。
- [x] 事件:focus、keyboard、expand/collapse、selection、context menu、drag/drop、pick。
- [x] 为 page tree runtime 建立 Rust-side 状态机:
- [x] focus normalize / next / previous / home / end。
- [x] expand / collapse / open / context-menu intent。
- [x] drag move intent 与 drop feedback state。
- [x] 为 file tree runtime 建立 Rust-side 状态机:
- [x] selection / range / context selection / normalize visible rows。
- [x] drag row ids / copy-move effect / drop target feedback。
- [x] asset-folder / asset / index / doc 的打开与菜单 intent。
- [x] 为 picker runtime 建立 Rust-side 状态机:
- [x] next / previous / home / end / focus / pick。
- [x] excluded ids 与 root pick。
- [x] 搜索态输入框焦点不被 iframe/runtime 抢走。
- [x] 3000 inline host 与 `mnote-web /tree` debug shell 输出并消费正式 runtime artifact contract。
- [ ] 3000 host 不再维护主路径 JS 镜像状态机;仍需把 `TreeShellIframeHost` 内联模板 compat JS 执行层迁到 Rust wasm/runtime 或等价正式 runtime。
- [x] `mnote-web /tree` debug shell 只保留 debug/internal runtime 验证入口。
### 验收
- [x] `pnpm vitest run src/components/sidebar/tree-shell-iframe-host.test.tsx src/components/sidebar/tree-shell-surface.test.tsx`
- [x] `cargo test -p mnote-web page_renderer filetree_renderer picker_renderer`
- [x] `node scripts/task112-tree-rust-family-regression-smoke.js`
- [x] `node scripts/task113-picker-keyboard-regression-smoke.js`
- [x] smoke 中 `direct_tree_shell_debug_disabled` 仍成立,3000 主路径不请求 3104。
### 当前保留边界
- 这里的完成口径是 artifact / reducer contract / debug 边界完成,不代表 `TreeShellIframeHost` 的 DOM runtime 已完全从 JS template 替换为 Rust wasm。
## 4. Phase Ltree.subtree.move 最终写路径下沉 Rust kernel
### 目标
`tree.subtree.move` 的 legality、target parent、position normalize、canonical sort plan 与最终写入从 Convex compat mutation 继续回收到 Rust kernel / Rust write path。
### checklist
- [x] 梳理当前 `normalizedMove` 写入链:
- [x] `/api/tree/commands` preflightData。
- [x] `bridge-runtime` canonical order plan。
- [x] Convex `documents.move` optional validation。
- [x] Rust kernel 输出最终 write operation
- [x] parent_id。
- [x] sort_order patch set。
- [x] workspace_id / updated_at。
- [x] self / descendant / missing-parent legality error。
- [x] Convex mutation 优先执行 Rust `treeWriteOperation`,退为 substrate 写入执行器与一致性断言层。
- [x] 前端 Rust runtime / command adapter 已透传 `treeWriteOperation`,不再以 documents move compat 语义作为主路径。
- [x] domain event 与 streamDelta 使用 Rust move result,而不是 TS/Convex 再拼。
- [ ] 删除 `normalizedMove` fallback,并把无 `treeWriteOperation` 的旧 compat move 降级为显式 legacy/debug 路径。
### 验收
- [x] `cd rust && cargo test -p bridge-runtime tree_subtree_move_command`
- [x] `cd wolai-frontend && pnpm vitest run src/app/api/tree/commands/route.test.ts src/lib/documents/tree-command-client.test.ts src/lib/tree-stream/tree-delta.test.ts`
- [x] 增加或复用 Convex 层测试,证明 Convex 优先接受 Rust `treeWriteOperation` 并校验当前排序状态。
### 当前保留边界
- `normalizedMove` 仍作为旧调用链 fallback 保留;这不是第二份主排序真相,但仍是后续可删除的 compat 面。
## 5. Phase Mblock/save-snapshot 复合命令 formal artifact 与 domain-event contract
### 目标
`page.body.save / documents.save / blocks.patch|move|embed / snapshot save` 等复合命令补齐最终 formal Rust artifact / domain-event contract,避免停留在 noop 或过渡 hint。
### checklist
- [x] 固定复合命令 event type
- [x] `page.body.saved`
- [ ] `document.snapshot.saved`
- [x] `block.patched`
- [x] `block.moved`
- [x] `block.embedded`
- [x] 固定 payload schema
- [x] document id / page id。
- [x] block ids / patch summary / move source-target。
- [x] snapshot version / content hash / updated_at 作为 `page.body.saved` payload 的一部分。
- [x] Rust command plan 输出正式 `domainEventPlan``streamDeltaHint`,不再只用 noop 占位。
- [x] 3000 adapters 与 Rust artifact writer 按同一 schema 落 `command_logs / domain_events`
- [x] SSE reducer 对这些事件有明确 delta 或保守 resync 策略。
- [ ] 将 snapshot save 是否需要独立 `document.snapshot.saved` 事件定稿,并避免与 `page.body.saved` payload 重叠。
### 验收
- [x] `cd rust && cargo test -p bridge-runtime documents_save_command_plans_include_formal_domain_event_contract block_commands_include_formal_domain_event_contract`
- [x] `cd wolai-frontend && pnpm vitest run src/lib/documents/rust-runtime.test.ts src/lib/documents/page-write-command-adapter.test.ts src/lib/blocks/block-command-adapter.test.ts`
- [x] 至少一个非 noop 复合命令事件可在 command log 与 domain event 中稳定关联同一 `command_id`
### 当前保留边界
- `document.snapshot.saved` 未独立落地;当前完成的是 `page.body.saved` formal payload 中包含 snapshot 摘要。
## 6. Phase N3000 Next route 过渡职责继续收薄
### 目标
`3000` 保持唯一浏览器公开入口,但 Next route 只做薄代理、认证/浏览器能力桥和兼容边界,不继续承担树域主语义、主 delta 或主 renderer runtime。
### checklist
- [x] 盘点 3000 route 中仍在拼树域主语义的入口。
- [x] 将 route 内 action switch 收敛到 Rust command result / artifact writer。
- [x] 对 polling / SSE / snapshot route 标注 Rust 主体与 Next 薄代理边界。
- [x] 隔离只服务旧 compat host 的 runtime 分支,`/api/tree/shell` 默认关闭 debug 直连。
- [x] 保留文件字节读取、upload URL、cookie/auth 等浏览器入口必须职责。
- [ ]`tree.node.embed``pageReference` block 组装从 3000 compat 边界迁到 Page Aggregate / Rust artifact。
### 验收
- [x] `cd wolai-frontend && pnpm vitest run src/app/api/tree/commands/route.test.ts src/lib/tree-stream/tree-delta.test.ts`
- [x] `node scripts/task112-tree-rust-family-regression-smoke.js`
- [x] 新增文档说明哪些 route 是 thin proxy,哪些仍是待迁移 compat`design/04-tree-domain/process/4-17-tree-3000-route-thin-proxy-boundary-v1.md`
### 当前保留边界
- 3000 仍是唯一浏览器公开入口;thin proxy 不等于删除浏览器能力桥。
- `tree.node.embed` 的目标读取与 `pageReference` block 组装仍是明确标注的 compat 待迁移项。
## 7. Phase O:搜索语义 hardening
### 目标
`file_tree` 搜索过滤主链已在 Rust projection query;后续只补更丰富搜索语义和稳定性,不作为当前 renderer/runtime gate。
### checklist
- [x]`index.md / asset / asset-folder / mindmap child / book / pdf` 搜索命中补更多 fixture。
- [x] 明确 `maxResults` 与祖先补全的排序/截断规则。
- [x] 增加异步索引可见性元数据,特别是 move/embed picker 搜索结果路径。
- [x] 空结果与 fallback 文案保持稳定。
- [ ] 如后续需要完整索引平台,再补真实异步索引延迟、刷新和可见性指标,而不是只依赖 projection request meta。
### 验收
- [x] `cd wolai-frontend && pnpm vitest run src/lib/tree-stream/tree-delta.test.ts`
- [x] 搜索 route / projection fixture 覆盖新增资源类型与边界。
### 当前保留边界
- 本阶段完成的是 file tree projection 搜索契约 hardening,不是独立搜索服务或完整索引指标平台。
## 8. 非目标
- 不拆除 Convex substrate。
- 不把 OnlyOffice 嵌入 BlockNote 画布。
- 不恢复旧 React PageTree/FileTree 作为 rust_family 主路径 fallback。
- 不把 3104 重新暴露为默认前端入口。
- 不在前端新增第二套树结构真相或排序真相。