23 KiB
4-16 [done] 树域 Rust 家族剩余 final runtime checklist v1
创建时间:2026-04-27
来源:
4-9 / 4-10 / 4-11中仍未完成的后续目标,以及4-12到4-15完成后的剩余边界。本文只规划后续目标,不回滚已完成的 3000 legacy inline host、Rust initial DOM、rendererInput/state family 与现有 smoke 覆盖。
口径修正(2026-04-28):本文记录的
harness task-001至task-009完成,只代表 Rust/WASM reducer runtime、artifact、route thinning、projection hardening 等阶段性目标完成;不代表 page tree / file tree / picker 已完成 final Rust DOM shell 切换。真正 final DOM shell 的硬门禁以../done/4-18-tree-final-dom-shell-cutover-hard-gate-v1.md为准。收口更新(2026-04-28):
harness task-010至task-013已完成 final DOM shell 默认路径切换。rust_family默认 host 已改为rust_wasm_dom_shell_host,默认 bridge 为dom_wasm;TreeShellIframeHost仅在显式NEXT_PUBLIC_TREE_SHELL_LEGACY_IFRAME_HOST=1下作为 legacy/debug host 进入。最终 runtime 剩余项收口(2026-04-28):
harness task-014至task-018已完成。normalizedMovefallback 已删除;page.body.saved与document.snapshot.saved已拆分为双 domain event plan;tree.node.embed的pageReference结构与插入位置已迁入 RustpageAggregateEmbedPlan;file_tree搜索索引可见性已成为 projection resultmeta.search.indexingVisibility。
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_v1artifact 边界,以及 page / filetree / picker 的 Rust-side runtime reducer contract。 - Phase K 历史阶段曾固定 3000 inline host 与
mnote-web /treedebug shell 都输出同名 runtime artifact;当前默认主路径已继续收口为rust_wasm_dom_shell_host,/api/tree/shell -> mnote-web:3104debug 直连默认关闭。 - Phase K 历史阶段曾把 3000 host implementation 从
rust_inline_compat_host收口为rust_runtime_artifact_host,并在 legacy runtime artifact manifest 中显式标注family=rust_family / version=1 / executionStrategy=browser_bridge / browserBridge=iframe_srcdoc;当前该 host 只代表显式 legacy/debug。 - Phase K 已新增 Rust
TreeShellRuntimeRequest / TreeShellRuntimeResultwire-safe facade:page / filetree / picker 三类 request 可serde_jsonroundtrip,输出统一分为TreeShellDomPatch、TreeShellHostEvent、TreeShellCommandEvent,并已在 runtime artifact manifest 中暴露 request/result contract、state snapshot、patch/event kind。 - Phase K 已新增
mnote-web POST /api/tree/runtime/reduce,并新增 3000 同源POST /api/tree/runtime/reducethin proxy;这是当前 browser bridge 调用 Rust runtime facade 的首个正式 HTTP seam。 - Phase K 已把 3000
TreeShellIframeHost的 filetree selection / normalize visible rows / drag row ids 路径接到 runtime reduce seam,保留本地 reducer fallback,避免 Rust runtime endpoint 不可用时破坏现有真实交互。 - Phase K 已把 3000
TreeShellIframeHost的 page focus / keyboard / expand / collapse / toggle / open / context menu 路径接到 runtime reduce seam,保留本地即时 fallback 与 runtime 对账。 - Phase K 已把 3000
TreeShellIframeHost的 picker focus / keyboard / pick 路径接到 runtime reduce seam,保留本地即时 fallback 与 runtime 对账。 - Phase K 已把 3000
TreeShellIframeHost的 page / filetree open-context 与 picker pick 路径接到 runtime hostEvent 回放器:主路径优先消费TreeShellRuntimeResult.hostEvents,endpoint 不可用或无 hostEvent 时才回退本地宿主事件。 - Phase K 已把 3000
TreeShellIframeHost的 filetree open / context menu 路径接到 runtime reduce seam,并已改为优先消费 runtime hostEvent。 - Phase K 已把 3000
TreeShellIframeHost的 filetree drop-target highlight 路径接到 runtime reduce seam:hydrated 与 fallback 两条 dragover/dragleave 链都会构造updateDropTarget请求,并把 runtime snapshot 回填到data-drop-targetDOM patch。 - Phase K 已落地正式 Rust/WASM reducer runtime artifact:新增
rust/crates/tree-shell-runtime-wasm,通过 wasm-bindgen 导出reduceTreeShellRuntime,固定产物为mnote-tree-shell-runtime.js与mnote-tree-shell-runtime_bg.wasm。 - Phase K 已新增 3000 同源
/api/tree-shell-runtime/*资源路由与build-tree-shell-runtime.js构建脚本,dev-server启动前会生成正式 tree shell wasm artifact。 - Phase K 已将 3000
TreeShellIframeHost的 page / filetree / picker reduce 执行器切为 wasm-first:默认优先调用 wasm artifact,HTTP/api/tree/runtime/reduce只作为 fallback/debug seam。 - Phase L 已引入 Rust
treeWriteOperation,Convexdocuments.move只接受 Rust write operation;normalizedMovefallback 已删除。 - Phase M 已将
page.body.saved、document.snapshot.saved、block.patched、block.moved、block.embedded切到 formaldomainEventPlan/domainEventPlanspayload 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、祖先补全/排序、projection resultmeta.search.indexingVisibility、空结果文案,以及index / asset-folder / asset / mindmap child / book / pdffixture 覆盖。
后续阶段已收口
- final DOM shell 默认路径已切到
rust_wasm_dom_shell_host:page / file tree / picker 不再通过TreeShellIframeHost的srcDoc内联模板承载默认 DOM shell。 - 默认 DOM host 通过
reduceTreeShellRuntimeWASM artifact 或同源/api/tree/runtime/reduceRust seam 消费state / hostEvents / commandEvents;旧本地 JS fallback reducer 只保留在 legacy iframe host。 - 默认真实流量已禁止
iframe_srcdoc作为 tree DOM shell 成功路径;对应负向门禁与 smoke 已覆盖。 normalizedMovefallback 已删除,无treeWriteOperation的 move 不再进入主写路径。document.snapshot.saved已作为独立 event type 固定;page.body.savedpayload 只保留 page 与 blocks,snapshot 版本/hash/updatedAt 进入独立事件。tree.node.embed的pageReferenceblock 组装已迁入 RustpageAggregateEmbedPlan;3000 route 只负责读取源/目标 substrate 快照并作为 preflight 传入。- Phase O 的索引可见性已从客户端 request meta 提升为 file_tree projection result meta;完整外部索引平台仍不是本树域 runtime 收口阶段目标。
1. 当前基线
harnesstask-001 至 task-009 已完成。page tree / file tree / picker默认主路径已使用 3000 same-originrust_wasm_dom_shell_host,不再请求/api/tree/shell -> mnote-web:3104,也不再依赖iframe_srcdocinline DOM shell。- 首屏 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;默认 DOM host 已通过 Rust/WASM runtime facade 驱动 page / picker / filetree 的 focus、expand、selection、open/context、drop 与 picker pick,HTTP reduce seam 保留为同源 Rust fallback/debug。
- 3000 legacy inline host 与
mnote-web /treedebug shell 已同步输出rust_tree_shell_runtime_artifact_v1manifest;默认 DOM host 已使用同源 tree-shell-runtime WASM artifact 或 HTTP reduce seam 执行 runtime。 - tree command move 写路径已优先使用 Rust
treeWriteOperation;Convex 继续作为 substrate 与一致性校验层。 - block/save 复合命令已具备 formal
domainEventPlan与resync_required保守 delta 合同。
2. 后续总目标
把树域从“Rust 持有语义 + compat JS 持有运行时 DOM/state machine”的过渡态,推进到:
- Rust family 持有 renderer runtime / state machine contract。
- 3000 主路径 host implementation 已从 compat 命名收口为
rust_wasm_dom_shell_host。 - Rust family 暴露可序列化的 runtime request/result facade,供后续 wasm/browser bridge 调用。
- Rust family 已通过 wasm artifact 持有默认 reducer runtime 执行层,不再默认依赖 HTTP bridge 执行 reduce。
- Rust family 默认持有 renderer DOM 执行层,不再依赖
TreeShellIframeHostbrowser bridge JS adapter 维护默认 DOM/state shell。 - 3000 host 收薄为挂载、认证、transport bridge、artifact writer 与浏览器能力边界。
- Convex compat mutation 不再优先承担 tree command 的核心 legality / normalize / write truth。
- block/save 复合命令进入正式 Rust artifact / domain-event contract。
- snapshot 独立事件与 Page Aggregate 深层收口继续后续推进。
最高优先级硬门禁
- 默认 page tree / file tree / picker 主路径不得再依赖
TreeShellIframeHost的srcDocinline DOM shell。 - 默认主路径不得再标注
data-tree-browser-bridge="iframe_srcdoc"。 TreeShellIframeHost必须降级为显式 legacy/debug host,不能作为rust_family默认执行面。task112/task113必须改为验证新 Rust/WASM DOM shell 主路径,而不是验证旧 inline iframe host 继续可用。
3. Phase K:正式 Rust runtime / wasm 承接 tree shell 运行时
目标
完整替换 TreeShellIframeHost 内联模板中的主要 compat JS runtime,至少先把 page/filetree/picker 的核心状态机从字符串模板 JS 迁到 Rust runtime/wasm 或等价正式 Rust family runtime。
checklist
- 定义 runtime artifact 边界:
- 输入:
rendererInput、projection items、expanded ids、selected row ids、active picker item、focused id。 - 输出:DOM patch / intent event / command dispatch event。
- 事件:focus、keyboard、expand/collapse、selection、context menu、drag/drop、pick。
- 输入:
- 为 page tree runtime 建立 Rust-side 状态机:
- focus normalize / next / previous / home / end。
- expand / collapse / open / context-menu intent。
- drag move intent 与 drop feedback state。
- 为 file tree runtime 建立 Rust-side 状态机:
- selection / range / context selection / normalize visible rows。
- drag row ids / copy-move effect / drop target feedback。
- asset-folder / asset / index / doc 的打开与菜单 intent。
- 为 picker runtime 建立 Rust-side 状态机:
- next / previous / home / end / focus / pick。
- excluded ids 与 root pick。
- 搜索态输入框焦点不被 iframe/runtime 抢走。
- 3000 legacy inline host 与
mnote-web /treedebug shell 输出并消费正式 runtime artifact contract。 - 历史 Phase K 主路径标识曾切到
rust_runtime_artifact_host,iframe 上显式标注data-tree-runtime-artifact-host=rust_tree_shell_runtime_artifact_v1与data-tree-browser-bridge=iframe_srcdoc;当前默认主路径已继续切到rust_wasm_dom_shell_host与data-tree-browser-bridge=dom_wasm。 - 定义 wire-safe runtime facade:
TreeShellRuntimeRequest统一承载 page / filetree / picker 的 environment、state、action。TreeShellRuntimeResult统一输出 state snapshot、domPatches、hostEvents、commandEvents。TreeShellDomPatch固定pageState / fileTreeState / pickerState。TreeShellHostEvent固定 page open/context menu、filetree open/context menu、picker pick root/document。TreeShellCommandEvent固定createNode / renameNode / moveSubtree / copyResource / moveResource / uploadResource。
- runtime artifact manifest 暴露
runtimeApi,让 3000 host 可识别 request/result 与 patch/event kind。 mnote-web暴露POST /api/tree/runtime/reduce,让 browser bridge 可调用 Rustreduce_tree_shell_runtime。- 3000 暴露同源
POST /api/tree/runtime/reducethin proxy,保留 cookie/auth/header 转发与no-store边界。 - 3000
TreeShellIframeHost的 filetree selection / visible row normalize / drag row ids 先接入 runtime reduce seam,并保留本地 fallback。 - 3000
TreeShellIframeHost的 page focus / keyboard / expand / collapse / toggle / open / context menu 已接入 runtime reduce seam,并保留本地 fallback。 - 3000
TreeShellIframeHost的 picker focus / keyboard / pick 已接入 runtime reduce seam,并保留本地 fallback。 - 3000
TreeShellIframeHost的 page / filetree open-context 与 picker pick 已开始消费 runtime hostEvent,并保留本地 fallback。 - 3000
TreeShellIframeHost的 filetree open / context menu 已接入 runtime reduce seam,并优先消费 runtime hostEvent。 - 3000
TreeShellIframeHost的 filetree drop-target highlight 已接入 runtime reduce seam,并保留本地 DOM fallback。 - 新增正式 wasm artifact:
rust/crates/tree-shell-runtime-wasm复用mnote-web/src/tree_shell/*runtime API 与 reducer。reduceTreeShellRuntime(request)wasm-bindgen API 已可在浏览器/Node 中执行TreeShellRuntimeRequest -> TreeShellRuntimeResult。build-tree-shell-runtime.js生成固定mnote-tree-shell-runtime.js与mnote-tree-shell-runtime_bg.wasm。- 3000 同源
/api/tree-shell-runtime/manifest.json、/api/tree-shell-runtime/mnote-tree-shell-runtime.js、/api/tree-shell-runtime/mnote-tree-shell-runtime_bg.wasm已覆盖。 TreeShellIframeHost已通过loadTreeShellWasmRuntime / reduceTreeShellRuntimeViaWasm / reduceTreeShellRuntimeWithArtifact默认优先使用 wasm artifact。
- 3000 默认 host 不再维护主路径 JS adapter 状态机;
TreeShellIframeHost内联模板 browser bridge JS DOM shell 已降级为显式 legacy/debug。 mnote-web /treedebug shell 只保留 debug/internal runtime 验证入口。
验收
pnpm vitest run src/components/sidebar/tree-shell-iframe-host.test.tsx src/components/sidebar/tree-shell-surface.test.tsxpnpm vitest run src/app/api/tree/runtime/reduce/route.test.ts src/app/api/tree/shell/route.test.ts src/components/sidebar/tree-shell-iframe-host.test.tsx src/components/sidebar/tree-shell-surface.test.tsx src/components/documents/move-embed-picker-dialog.test.tsxpnpm vitest run src/components/documents/move-embed-picker-dialog.test.tsxcargo test -p mnote-web page_renderer filetree_renderer picker_renderercargo test -p mnote-web tree_runtime_reduce_endpoint_returns_filetree_runtime_resultcargo test -p mnote-web tree_runtime_reduce_endpoint_returns_page_and_picker_runtime_resultscargo test -p mnote-web tree_shell_embeds_renderer_input_contractcargo test -p mnote-web tree_shell_renderer_input_exposes_runtime_artifact_boundarycargo test -p tree-shell-runtime-wasm -- --nocapturenode scripts/build-tree-shell-runtime.jspnpm vitest run src/app/api/tree-shell-runtime/[...asset]/route.test.ts src/components/sidebar/tree-shell-iframe-host.test.tsx- Node smoke:加载
generated/mnote-tree-shell-runtime.js+.wasm后调用reduceTreeShellRuntime(mode=page, action=moveNext),返回focusedId=doc:child。 node scripts/task112-tree-rust-family-regression-smoke.jsnode scripts/task113-picker-keyboard-regression-smoke.js- smoke 中
direct_tree_shell_debug_disabled仍成立,3000 主路径不请求 3104。
当前保留边界
- 这里的历史完成口径包含正式 Rust/WASM reducer runtime artifact 与默认 wasm-first reduce 执行;真正 final DOM shell 完成以
task-010至task-013和4-18硬门禁为准。 - 当前 DOM runtime 阶段已把 page/picker/filetree 默认 host 切到
TreeShellRustDomShellHost;后续已继续删除normalizedMovefallback、补document.snapshot.saved独立事件,并把tree.node.embed的 Page Aggregate / Rust artifact 边界收口。 - 后续阶段不得继续把“新增 runtime reducer action”或 legacy iframe 能力增强误写成 final renderer 主任务;默认路径必须保持
rust_wasm_dom_shell_host + dom_wasm。
4. Phase L:tree.subtree.move 最终写路径下沉 Rust kernel
目标
把 tree.subtree.move 的 legality、target parent、position normalize、canonical sort plan 与最终写入从 Convex compat mutation 继续回收到 Rust kernel / Rust write path。
checklist
- 梳理当前
normalizedMove写入链:/api/tree/commandspreflightData。bridge-runtimecanonical order plan。- Convex
documents.moveoptional validation。
- Rust kernel 输出最终 write operation:
- parent_id。
- sort_order patch set。
- workspace_id / updated_at。
- self / descendant / missing-parent legality error。
- Convex mutation 优先执行 Rust
treeWriteOperation,退为 substrate 写入执行器与一致性断言层。 - 前端 Rust runtime / command adapter 已透传
treeWriteOperation,不再以 documents move compat 语义作为主路径。 - domain event 与 streamDelta 使用 Rust move result,而不是 TS/Convex 再拼。
- 删除
normalizedMovefallback,并把无treeWriteOperation的旧 compat move 降级为显式 legacy/debug 路径。
验收
cd rust && cargo test -p bridge-runtime tree_subtree_move_commandcd 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- 增加或复用 Convex 层测试,证明 Convex 优先接受 Rust
treeWriteOperation并校验当前排序状态。
当前保留边界
normalizedMove不再作为旧调用链 fallback 保留;move 主写路径强制使用 RusttreeWriteOperation。
5. Phase M:block/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
- 固定复合命令 event type:
page.body.saveddocument.snapshot.savedblock.patchedblock.movedblock.embedded
- 固定 payload schema:
- document id / page id。
- block ids / patch summary / move source-target。
- snapshot version / content hash / updated_at 作为
document.snapshot.savedpayload 的一部分。
- Rust command plan 输出正式
domainEventPlan与streamDeltaHint,不再只用 noop 占位。 - 3000 adapters 与 Rust artifact writer 按同一 schema 落
command_logs / domain_events。 - SSE reducer 对这些事件有明确 delta 或保守 resync 策略。
- 将 snapshot save 是否需要独立
document.snapshot.saved事件定稿,并避免与page.body.savedpayload 重叠。
验收
cd rust && cargo test -p bridge-runtime documents_save_command_plans_include_formal_domain_event_contract block_commands_include_formal_domain_event_contractcd 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- 至少一个非 noop 复合命令事件可在 command log 与 domain event 中稳定关联同一
command_id。
当前保留边界
document.snapshot.saved已独立落地;page.body.savedformal payload 不再包含 snapshot 摘要。
6. Phase N:3000 Next route 过渡职责继续收薄
目标
3000 保持唯一浏览器公开入口,但 Next route 只做薄代理、认证/浏览器能力桥和兼容边界,不继续承担树域主语义、主 delta 或主 renderer runtime。
checklist
- 盘点 3000 route 中仍在拼树域主语义的入口。
- 将 route 内 action switch 收敛到 Rust command result / artifact writer。
- 对 polling / SSE / snapshot route 标注 Rust 主体与 Next 薄代理边界。
- 隔离只服务旧 compat host 的 runtime 分支,
/api/tree/shell默认关闭 debug 直连。 - 保留文件字节读取、upload URL、cookie/auth 等浏览器入口必须职责。
- 将
tree.node.embed的pageReferenceblock 组装从 3000 compat 边界迁到 Page Aggregate / Rust artifact。
验收
cd wolai-frontend && pnpm vitest run src/app/api/tree/commands/route.test.ts src/lib/tree-stream/tree-delta.test.tsnode scripts/task112-tree-rust-family-regression-smoke.js- 新增文档说明哪些 route 是 thin proxy,哪些仍是待迁移 compat:
design/04-tree-domain/done/4-17-tree-3000-route-thin-proxy-boundary-v1.md。
当前保留边界
- 3000 仍是唯一浏览器公开入口;thin proxy 不等于删除浏览器能力桥。
tree.node.embed的目标读取仍是 3000 浏览器公开入口的 substrate 职责;pageReferenceblock 结构与插入位置语义已由 RustpageAggregateEmbedPlan产出。
7. Phase O:搜索语义 hardening
目标
file_tree 搜索过滤主链已在 Rust projection query;后续只补更丰富搜索语义和稳定性,不作为当前 renderer/runtime gate。
checklist
- 为
index.md / asset / asset-folder / mindmap child / book / pdf搜索命中补更多 fixture。 - 明确
maxResults与祖先补全的排序/截断规则。 - 增加异步索引可见性元数据,特别是 move/embed picker 搜索结果路径。
- 空结果与 fallback 文案保持稳定。
- 如后续需要完整索引平台,再补真实异步索引延迟、刷新和可见性指标,而不是只依赖 projection request meta。
验收
cd wolai-frontend && pnpm vitest run src/lib/tree-stream/tree-delta.test.ts- 搜索 route / projection fixture 覆盖新增资源类型与边界。
当前保留边界
- 本阶段完成的是 file tree projection 搜索契约 hardening 与 projection result 可见性指标,不是独立搜索服务或外部索引平台。
8. 非目标
- 不拆除 Convex substrate。
- 不把 OnlyOffice 嵌入 BlockNote 画布。
- 不恢复旧 React PageTree/FileTree 作为 rust_family 主路径 fallback。
- 不把 3104 重新暴露为默认前端入口。
- 不在前端新增第二套树结构真相或排序真相。