# 4-9 [recycle] 树域 Rust 家族化剩余架构事项与能力保留方案 v1 > 更新时间:2026-04-23 > > 回收说明(2026-04-28):本文是 Rust 家族化下一阶段的早期架构拆解稿,后续已由 `4-10` 执行清单、`4-11` final renderer / host thinning、`4-16` remaining final runtime、`4-18` final DOM shell hard gate 继续拆分和覆盖。本文保留为历史能力保留口径,不再作为当前活跃 `process` 入口。 > > 关联文档: > - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-sidebar-pagetree-filetree-rust-web-rebuild-v1.md` > - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-2-sidebar-pagetree-filetree-product-interaction-contract-v1.md` > - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-6-tree-command-protocol-cutover-stage2-v1.md` > - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-4-tree-projection-protocol-contract-v1.md` > - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-7-tree-shell-ui-state-boundary-v1.md` > - `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md` > - `/mnt/Data1T/mnote/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md` > - `/mnt/Data1T/mnote/ARCHITECTURE.md` ## 1. 文档目的 这份文档只回答两个问题: 1. 在当前长期方向已经固定为 `Rust kernel + Rust web + Leptos island + Convex substrate` 的前提下,树域继续朝 Rust 家族化推进,还剩哪些真正的架构事项。 2. 在 `page tree / file tree` 从当前 `TypeScript + Next + React` 主壳向 Rust 家族执行面迁移时,哪些现有能力必须被完整保留,不能为了“换语言”而退化。 这份文档不是为了重复证明: - `Convex` 是否还保留 - 树域是否已经具备 projection contract - `Page Aggregate` 是否应该存在 这些上位结论已经在关联文档中固定。 本文只做当前阶段最需要的补充收口: > **树域已经完成 truth / projection / command 边界的第一轮收口,但主渲染壳仍主要停留在 `TypeScript + Next + React`。下一阶段要解决的,不再是“树是不是 kernel projection”,而是“树域主执行面怎样继续向 Rust 家族迁移,同时不丢掉现有交互能力”。** --- ## 2. 当前判断 ## 2.1 已经成立的部分 当前已经成立且不应回退的事实: - `tree-first graph kernel` 继续是树域真相层。 - `Convex` 继续承担存储、实时同步、内容与协作底座。 - `mnote-web` 已经具备树域 projection / command / transport 的正式入口能力。 - `sidebar_tree / page_tree / file_tree` 已经形成同一 projection family。 - 树域主路径不应再回到“前端自己定义第二套树真相”。 也就是说,当前真正成立的结构是: - `Rust kernel` 持有树语义。 - `Convex` 提供 substrate。 - `Rust web` 已开始承接 route / projection / command / stream。 - 当前主站中的树 consumer 已经开始消费 projection family。 ## 2.2 仍未完成的部分 当前仍未完成、且正是下一阶段主任务的部分是: - `page tree / file tree / picker` 的主渲染壳仍主要是 `TypeScript + Next + React`。 - `file_tree` 的一部分 row 语义仍由前端 adapter 继续补齐,而不是完全由 Rust 直接输出。 - `tree.*` 的长期命令面虽已冻结,但主调用路径仍未完全退出 `documents.*` 兼容入口。 - 树域 realtime 仍未完全收口为 Rust Web 正式 `snapshot + delta + resync` 主链。 - Sidebar 整体仍是超大客户端壳,树域虽然已收 truth,但执行面与宿主边界还不够薄。 因此当前正确判断不是: - “树域 Rust 家族化已经完成” 而是: > **树域已经完成“语义与协议收口”,但还没有完成“主执行面 Rust 家族化”。** --- ## 3. 为什么继续 Rust 家族化有真实意义 ## 3.1 不是语言洁癖,而是减少第二套运行时语义 如果长期保持下面这种结构: - Rust 负责 kernel / query / command / projection - Next/React 继续负责主树 UI、主交互壳、主状态骨架 那么树域会长期同时维护两套复杂度: 1. Rust 侧的 projection / command / stream 语义 2. 前端壳里的 row model / selection / focus / keyboard / DnD / fallback / adapter 语义 这会带来: - 协议在两侧重复解释 - 调试时要同时跨 TS / Rust 两套执行面 - tree shell 的边界始终无法真正稳定 - 后续一切性能优化都要先穿过旧前端壳 因此这里的“继续 Rust 家族化”真正要减少的,不是文件后缀的种类,而是: > **树域存在两套长期执行语义的状态。** ## 3.2 对加载速度与运行成本有真实潜力 树域是高频常驻 UI,不是偶尔打开一次的边缘面板。 如果它继续作为大型 `use client` 组件族存在,就会长期保留这些成本: - 客户端组件挂载 - 虚拟列表初始化 - DnD 状态机初始化 - 菜单与选择状态初始化 - 浏览器侧 row model 构建 - 兼容 fallback 与 stream 选择逻辑 这些成本不会因为“数据真相已经交给 Rust”而自动消失。 把树域主壳继续迁向 Rust 家族,真实收益主要来自: - 进一步压低浏览器端常驻 JS - 让 projection -> renderer 的路径更短 - 减少 hydration 与挂载层数 - 降低 Sidebar 切页与刷新时的重渲染放大 - 为后续更彻底的 server-first 壳收口创造条件 这里必须强调: - Rust 化 **不自动等于** 更快 - 但在当前项目的长期方向里,Rust 家族化是“继续减轻旧前端壳”的必要手段 ## 3.3 对协作冲突与长期维护也有真实意义 这里的“冲突”不只指 git merge 冲突,更主要是: - projection contract 与 renderer 行为漂移 - TS adapter 与 Rust route 的边界反复变化 - 同一个交互在两侧同时维护 legality / normalization / fallback 当树域主执行面仍留在 React 壳里时: - Rust 改协议 - 前端就要继续补 adapter - 测试也要跨两族运行时拼接验证 继续 Rust 家族化的意义,是让下面这条链尽量收敛为一条语言家族更统一的主链: - kernel truth - projection - tree command - tree shell - renderer --- ## 4. 下一阶段剩余架构事项 下面这些事项,才是树域继续 Rust 家族化时真正还没完成的主任务。 ## 4.1 正式定义“树域主执行面”的完成标准 首先必须明确: - “树域已经吃 projection” 不等于 “树域已经 Rust 家族化完成” - “存在 Leptos scaffold / Rust tree_shell 模块” 不等于 “主路径 renderer 已迁完” 下一阶段完成标准应固定为: - 至少一条真实默认用户流量,主树 renderer 不再依赖当前 React `PrivateTree` / `FileTree` - `page tree / file tree / picker` 的核心交互骨架不再由 Next/React 主壳承担 - TS 宿主只保留挂载、局部桥接、页面路由与极薄 compat 如果这一标准不先冻结,后续很容易再次把“有 Rust route”误当成“已经 Rust 化完成”。 ## 4.2 把 page tree renderer 真正迁入 Rust 家族 `page tree` 下一阶段不是继续补前端 helper,而是把以下能力迁成 Rust 家族正式 renderer 能力: - 行渲染 - 展开/折叠 - 当前页高亮 - hover 动作区 - 键盘导航 - 拖拽反馈 - 上下文菜单入口 这里的重点不是“把视觉样式翻译一遍”,而是: - 把行级行为骨架从 React 组件迁走 - 让 page tree 只围绕正式 projection item 工作 - 不再由现有 TS 组件长期持有主路径交互状态机 ## 4.3 把 file tree 从“前端 adapter 文件树”收口为“Rust 直接输出 + Rust 家族 renderer” `file_tree` 是当前最关键也最容易退化的一段。 下一阶段必须同时做两件事: 1. Rust 侧继续把 `file_tree` 输出补完整。 2. renderer 不再依赖当前前端在 `pageRows + assets` 上继续拼 visible rows。 必须继续向 Rust 收口的内容包括: - `index.md` - 附件 - `mindmap` 文件夹 - 导图子附件 - 表格、书籍、PDF 等对象提示 - `resource_kind / asset_kind / icon_hint` 否则文件树即使换了新壳,也仍然只是: - “页面树 + 前端附件补丁” 这不符合长期目标。 ## 4.4 把树域交互骨架拆成可替换的正式模块 下一阶段不应继续把交互都堆在单一大组件里,而应显式收口为几类正式模块: - row model - selection model - focus model - keyboard model - DnD state machine - context action registry 无论这些模块最终落在: - `Leptos` - 或极薄 Rust/TS bridge 都必须满足两条: - 它们不再定义结构真相 - 它们可以独立测试与演进 ## 4.5 完成 tree command cutover Stage 2 树域继续 Rust 家族化时,命令面不能长期继续停在双轨。 下一阶段必须完成: - 主路径默认发 `tree.*` - `documents.*` 退到 compat - legality / normalize / move target 等树策略继续回收给 Rust 否则会出现一个长期问题: - UI 壳换成 Rust 家族了 - 但命令面仍主要经由旧 `documents.*` 兼容语义运行 这样并没有完成真正的主执行面收口。 ## 4.6 完成 Rust Web realtime contract 树域如果要继续往正式主链推进,realtime 必须从“可用”进入“单一正式合同”。 下一阶段需要补齐: - `snapshot` - `delta` - `resync` - cursor 漂移处理 - 局部 subtree 与 workspace scope 的统一 目标不是简单保住 fallback,而是让树域主路径不再依赖: - 查询快照 - 本地 freshness 选择 - React 侧补偿式同步 ## 4.7 收薄宿主边界 长期目标不是让主站彻底消失,而是让主站对树域只保留最小宿主职责: - 页面布局挂载位 - 路由跳转 - 样式容器 - 极薄 feature flag / compat - 与其他页面面板的最小桥接 不应继续保留在宿主中的内容: - 树结构重建 - 主交互状态骨架 - 文件树资源行语义补丁 - 主要 keyboard / DnD / selection 逻辑 --- ## 5. page tree 迁移时必须保留的能力 `page tree` 在迁移到 Rust 家族主执行面时,必须显式保证下面这些能力不退化。 ## 5.1 结构与导航 必须保留: - 稳定的层级展开/折叠 - 当前页高亮 - 祖先自动展开 - 搜索/过滤后层级仍可理解 禁止退化为: - 纯扁平列表 - 只有打开功能、没有层级语义的按钮组 ## 5.2 行级动作 必须保留: - 新建子页面 - 重命名 - 移动 - 归档/恢复类上下文操作入口 - 行级 hover 动作区 要求: - 不能为了换 renderer 把动作缩减到“点开页面 + 更多菜单” - 不能丢失当前工作区级高频动作入口 ## 5.3 键盘与焦点 必须保留: - 上下移动 - 左右展开/折叠 - Enter 打开 - 稳定的 focus 行 要求: - `focus` 不能重新混成 `selected` - 展开与选择变化后焦点归一化必须稳定 ## 5.4 拖拽与移动 必须保留: - 基础拖拽排序 - 父节点切换 - 非法拖拽校验 要求: - drop feedback 不能退化成不可预测的闪烁 - 目标父节点与位置推导必须有稳定、可测试的协议 ## 5.5 大树体验 必须保留: - 稳定滚动 - 大树下的可见区域性能 - 展开/折叠与切页不会出现明显回闪 这部分是迁移时的硬验收项,不是可选优化项。 --- ## 6. file tree 迁移时必须保留的能力 `file_tree` 比 `page tree` 更容易因迁移而退化。 下一阶段必须把“功能保留”明确写成硬门槛。 ## 6.1 资源层级 必须保留: - 页面 - `index.md` - 附件 - `mindmap` 文件夹 - 导图子附件 - 表格、书籍、PDF 等资源对象语义 禁止退化为: - 页面树下挂一个普通附件列表 - mindmap 资源被拍平成普通文件 ## 6.2 选择能力 必须保留: - 单选 - 多选 - Shift 范围选 - 右键选中 - 可见行变化后的选择归一化 这部分如果退化,文件树就不再是资源管理器语义,而会退回文档树换皮。 ## 6.3 打开与操作 必须保留: - 单击选择 - 双击打开资源 - 资源级右键菜单 - 按资源类型分支的动作入口 要求: - 资源图标语义必须稳定 - `asset_kind / icon_hint` 不允许再次回到壳内临时猜测 ## 6.4 拖放 必须保留: - 内部拖放 - 外部文件拖入上传 - copy / move 区分 - 非法投放校验 要求: - 文件树不能只保留视觉拖拽,没有正式动作协议 - 外部文件拖入必须继续是正式主路径能力 ## 6.5 文件树特有的可见行模型 必须保留: - `doc -> index -> asset-folder -> asset` 的可见行语义 - 扁平化 rows 与深度的稳定映射 - 可见行变化后的选择、焦点、拖放范围归一化 这里允许实现换掉,但不允许语义丢掉。 --- ## 7. 推荐迁移顺序 为了尽量保持体验不退化,推荐顺序如下: 1. 先补齐 `file_tree` 的 Rust 直接输出,避免迁 renderer 时还要继续背前端 adapter。 2. 再把 `page tree` renderer 迁入 Rust 家族,因为它对象更单纯、验收面更小。 3. 然后迁 `file tree` renderer,因为它依赖更多资源与交互语义。 4. 再迁 `picker` 轻量模式,让它复用同一套 renderer / state family。 5. 最后继续削薄宿主,收掉剩余主路径 React 树壳。 原因: - `page tree` 先迁可以先验证主行 renderer 与状态骨架。 - `file_tree` 后迁可以避免一开始就在最复杂对象面上同时处理 renderer 与 contract 漂移。 - `picker` 最适合作为共用 renderer 的轻量消费场景,而不是主线路的先导。 --- ## 8. 迁移阶段的验收门槛 只有同时满足下面几条,才可以把树域继续 Rust 家族化的某一阶段视为成立: - 页面树与文件树都没有因切流而减少已有能力。 - `page tree / file tree` 的关键能力有 smoke 覆盖: - 切页 - 展开/折叠 - 拖拽 - 右键菜单 - 多选与范围选 - 外部文件拖入 - `file_tree` 的对象投影不再依赖前端临时补丁维持主路径。 - 主调用路径默认走正式 `tree.*` 命令面。 - 正式 realtime 至少已经进入统一 `snapshot + delta + resync` 合同,而不是继续主要靠补偿式 freshness 选择。 - 主站宿主不再持有树结构真相,也不再承担主要树域交互状态机。 --- ## 9. 当前优先级建议 在当前总优先级下,树域继续 Rust 家族化的最近顺序建议固定为: 1. 继续推进 `4-6 tree command protocol cutover stage2` 2. 明确 `file_tree` 直接输出的剩余缺口,并以 Rust 侧补齐 3. 为 `page tree / file tree` 迁移补正式功能保留回归矩阵 4. 选择并落一条真实默认流量进入 Rust 家族 renderer 5. 再逐步收掉当前主路径 React 树壳 也就是说,当前下一步不是: - 继续在现有 React 树壳里堆更多交互补丁 而是: > **在功能不退化的前提下,把树域从“Rust 持有语义、React 持有主执行面”的过渡态,推进到“Rust 家族同时持有语义与主执行面”的下一阶段。** --- ## 10. 最终结论 当前树域继续往全 Rust 方向发展,是有真实意义的。 意义不在于: - 代码库里减少一种语言 而在于: - 收掉旧前端壳的长期主执行职责 - 减少第二套复杂运行时语义 - 为首屏与常驻交互链路继续减重 - 让 `tree-first graph kernel -> Rust Web -> Rust family shell` 形成更一致的长期主链 但这个推进必须满足一个前提: > **page tree / file tree 的功能能力不能因为迁移而退化。** 因此,下一阶段的正确目标不是“尽快把组件翻译成 Rust”,而是: > **先把剩余 projection / command / realtime / host 边界补齐,再以 page tree 与 file tree 的能力保留为硬约束,把树域主执行面稳步迁入 Rust 家族。**