# 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 家族。**
