Files
mnote/design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.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

474 lines
20 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.
# 3-1 [process] Rust Web 长期架构实施清单 v2
> 更新时间:2026-04-16
>
> 基于以下实际状态重写:
> - 当前未提交代码
> - `/mnt/Data1T/mnote/harness-tasks.json` 中 `task-059` ~ `task-069`
> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md`
> - `/mnt/Data1T/mnote/design/old/03-rust-web/process/rust-web-long-term-checklist-v1.md`
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/process/1-tree-first-graph-kernel-v1.md`
## 1. 这版为什么要重写
这次重写的原因很明确:
- `task-059` ~ `task-069` 目前在 `harness-tasks.json` 里已经被标为 `completed`
- 但从当前未提交代码实际看,很多项只证明了:
- 文档已补
- 骨架已建
- 局部组件已拆
- `eslint` / `cargo check` 可过
- **并不能证明对应长期阶段已经真正完成**
因此这版 checklist 的目标不是重复愿景,而是:
> **把长期路线重新落回“真实代码状态”,明确哪些已经落地、哪些只是最小接缝、哪些仍未开始。**
> 说明(2026-04-22):
> 这份清单仍保留为 Rust Web 分阶段全景参考,但当前最近一步不再是泛化推进全部 `Phase`,
> 而是优先推进 `Page Aggregate`、`tree command cutover`、`tree realtime event stream`。
> 当前执行优先级请先看 `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md`。
---
## 2. 当前总判断
从当前代码看,长期路线的真实状态是:
### 2.1 已有明确进展
- [x] `Phase 0` 的文档化边界梳理已经完成
- [x] `Phase 1` 已落了一个最小 `axum` Web 骨架:`rust/crates/mnote-web/`
- [x] `Phase 1` 已不再只是空骨架,现已包含 kernel / bridge / compat sidebar 的真实查询接缝
- [x] `Phase 2` 文档阅读态分离已经有实质代码
- [x] `Phase 3` 主 Sidebar 已出现 `kernelSidebarTree` 消费接缝
- [x] `Phase 4` 搜索已做 host/runtime 拆分,并开始返回 `nodeId` / `subtreeRootId` / `evidence`
- [x] `Phase 5` AI 面板已做 host/runtime 拆分,并开始向 Hermes bridge 传递 `node` / `subtree` / `outline` / `evidence`
- [x] `Phase 6` Mindmap 独立页已去掉 `editorStub` 主入口
- [x] `Phase 7` 阅读态已直接消费 `pageSubtree``BlockNote` 也已不是文档页默认唯一入口
### 2.2 但大部分阶段都只是“部分落地”
- [ ] `Phase 1` 还不是主 Web 路径,只是 Rust Web skeleton
- [ ] `Phase 3` Sidebar 仍是超大客户端组件,其他树域也未统一切到 kernel projection
- [ ] `Phase 4` 搜索仍是前端 runtime 主导,不是 server-first 搜索页
- [ ] `Phase 5` AI runtime 仍然很重,只是懒挂载了
- [ ] `Phase 6` Mindmap 仍然是重前端交互壳,不是独立对象页壳
- [ ] `Phase 7` 文档页外围面板仍集中在 `DocumentContent`
- [ ] `Phase 8` 旧 Next/React 主路径完全没有完成切换
### 2.3 结论
> **当前真实状态不是“Phase 0 ~ 8 已全部完成”,而是“Phase 0 基本完成,Phase 1/2/4/5/6/7 处于不同程度的部分落地,Phase 3 和 Phase 8 仍远未完成”。**
---
## 3. 重新定义状态口径
为了避免再次把“有骨架”写成“已完成”,v2 统一使用下面三种状态:
### `DONE`
定义:
- 代码主路径已经切换
- 不是只有文档或骨架
- 用户可感知行为已经变了
- 后续只剩清理和补强
### `PARTIAL`
定义:
- 已有真实代码改动
- 但仍是局部接缝、最小骨架、阶段性拆分
- 主路径尚未彻底切换
### `NOT_STARTED`
定义:
- 还停留在设计或口径层
- 或只有零散基础,不足以算阶段开始
---
## 4. 基于真实代码的阶段总览
| 阶段 | v1 口径 | 当前真实状态 | 说明 |
| --- | --- | --- | --- |
| Phase 0 | 边界冻结 | `DONE` | 文档、候选模块、边界口径已经成形,但性能基线更多还是文档定义,不是完整观测系统 |
| Phase 1 | Rust Web 基础层 | `PARTIAL` | `mnote-web` 已创建,`axum` 骨架已存在,且已补 bridge route、通用 query transport 与 Sidebar compat 切流入口,但仍不是整个产品的主 Web 入口 |
| Phase 2 | 文档阅读页 server-first 化 | `PARTIAL` 接近 `DONE` | 阅读态/编辑态已明显分离,但仍有旧链回退和大量客户端状态集中在 `DocumentContent` |
| Phase 3 | Sidebar / 树结构 Rust 化 | `PARTIAL` 偏早期 | 主 Sidebar 已以 `kernelSidebarTree` 作为主树来源,但整体仍是超大客户端组件 |
| Phase 4 | 搜索 Rust 化与 island 化 | `PARTIAL` | host/runtime 懒加载拆分已做,结果形状也开始带 `nodeId` / `subtreeRootId` / `evidence`,但仍未完成 server-first 搜索页 |
| Phase 5 | AI 面板 bridge island 化 | `PARTIAL` | host/runtime 拆分已做,且已开始把 `node` / `subtree` / `outline` / `evidence` 送入 Hermes,但 runtime 仍重,协议也未统一到真正“最小壳” |
| Phase 6 | Mindmap 独立对象化 | `PARTIAL` | 独立页脱离 editor stub 主入口,并补出 `standalone` / `documentBridge` 边界,但仍是客户端重壳 |
| Phase 7 | BlockNote 孤岛化 | `PARTIAL` | 阅读态已直接消费 `pageSubtree`,编辑器按需挂载,但外围 drawer/panel 仍集中在同一内容组件 |
| Phase 8 | 旧前端壳下线 | `NOT_STARTED` | 当前主入口仍是 Next/React,不能宣称主路径切换完成 |
---
## 5. Phase 0:基线与边界冻结
**当前状态:`DONE`**
### 5.1 已有事实
- [x] 已有长期架构文档
- [x] 已有长期 checklist 文档
- [x] 已有 `tree-first graph kernel` 文档
- [x] 已对文档页、Sidebar、Search、AI、Mindmap、OnlyOffice、`BlockNote` 做了模块级边界识别
### 5.2 当前仍不足的地方
- [ ] 真正可自动回归的性能基线系统仍未建立
- [ ] 统一 performance trace 采样点仍未进入运行时
- [ ] “冻结旧壳继续膨胀”目前更多靠文档与人工约束,不是代码级 guardrail
### 5.3 v2 完成判定
- [x] 设计层边界冻结已完成
- [ ] 运行时观测层冻结仍未完成
---
## 6. Phase 1Rust Web 基础层落地
**当前状态:`PARTIAL`**
### 6.1 已落地事实
- [x] Rust workspace 已并入 `mnote-web`
- [Cargo.toml](/mnt/Data1T/mnote/rust/Cargo.toml)
- [x] 已存在 `axum` Web 骨架
- [Cargo.toml](/mnt/Data1T/mnote/rust/crates/mnote-web/Cargo.toml)
- [x] 已有统一 app/router 骨架
- [app.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/app.rs)
- [mod.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/mod.rs)
- [x] 已有 request context / middleware
- [context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/context.rs)
- [request_context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/middleware/request_context.rs)
- [x] 已有最小 Hermes bridge route
- [hermes.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes.rs)
- [x] 已有 SSE / WS / compat route 骨架
- [x] 已有真实 bridge / compat 接缝
- [bridge.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/bridge.rs)
- [compat.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/compat.rs)
- [x] kernel sidebar route 已通过 `sidebar.dataset.list` runtime plan + 通用 query transport 读取数据集
- [kernel.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/kernel.rs)
### 6.2 明确还没完成
- [ ] `mnote-web` 还不是主 Web 服务入口
- [ ] 还没有主页面壳 SSR
- [ ] 还没有主 API 大面积从 Next route 切到 Rust Web
- [ ] 当前 `compat_next_base_path` 仍说明它还带有兼容层属性,不是唯一承载层
- [ ] fixture 已收口到测试/开发边界,但这还不等于整个产品流量已经全面切到 Rust Web
- [ ] 还不能说“后续页面迁移已不依赖 Next API route 作为唯一入口”,只能说“已经开始脱钩”
### 6.3 v2 后续任务
- [ ]`mnote-web` 从 skeleton 提升为真实服务入口
- [ ] 先把 sidebar kernel route 上的 fixture fallback 收到测试/开发边界,再承接一条真实页面壳或真实查询主链
- [ ] 明确 Next -> Rust Web 的流量切换边界
- [ ] 增加主 API / 页面壳级集成验证,而不只是 `cargo check`
---
## 7. Phase 2:文档阅读页 server-first 化
**当前状态:`PARTIAL`,但已经是最实的进展之一**
### 7.1 已落地事实
- [x] 文档页已在服务端预取 `meta + content`
- [page.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/documents/[id]/page.tsx)
- [x] `DocumentShell` 已去掉 mounted gating
- [document-shell.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-shell.tsx)
- [x] `DocumentReadView` 已作为阅读态渲染器落地
- [document-read-view.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-read-view.tsx)
- [x] `DocumentContent` 已有 `isEditing` / `keepEditorMounted`
- [document-content.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-content.tsx)
- [x] `BlockNoteEditor` 已不是默认唯一入口
### 7.2 当前还没完成
- [ ] 服务端读链失败时仍回退旧链
- [ ] 阅读态与编辑态虽已分开,但大量页面状态仍集中在 `DocumentContent`
- [ ] 评论、历史、回链、AI、页面选项虽然不是首屏阻塞,但仍在同一组件层集中管理
- [ ] 阅读页还不是一个真正极薄的 server-first 页面壳
### 7.3 v2 完成判定
- [x] “先阅读、后编辑”的主行为已经出现
- [ ] “阅读页已经彻底轻壳化”还不能成立
---
## 8. Phase 3Sidebar / 页面树 / 文件树 Rust 化与 island 化
**当前状态:`PARTIAL` 偏早期**
### 8.1 已落地事实
- [x] Sidebar 数据 query 契约此前已经有 Rust 化前进
- [x] 布局服务端会先加载 `sidebarInitialData`
- [layout.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/layout.tsx)
- [x] `sidebar-data.ts` 已生成 `kernel_sidebar_projection``kernelSidebarTree`
- [sidebar-data.ts](/mnt/Data1T/mnote/wolai-frontend/src/lib/sidebar-data.ts)
- [x] 主 Sidebar 已以 `sidebarData.kernelSidebarTree` 作为初始树与同步来源
- [sidebar.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx)
- [x] 已补统一 `page_tree` projection protocol,并让 `PrivateTree` / 文件树 / move-embed picker 共用
- [tree-projection.ts](/mnt/Data1T/mnote/wolai-frontend/src/lib/tree-projection.ts)
### 8.2 当前真实问题
- [ ] `Sidebar` 仍然是超大客户端组件
- [sidebar.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx)
- [ ] 页面树 / 文件树虽然已统一协议,但整体执行面仍主要在客户端
- [ ] `buildDocumentTree(...)` 仅剩兼容 helper 与旧单测,不再位于树域主路径
- [ ] 主布局仍然默认常驻挂载 Sidebar
- [ ] 还不能叫“服务端输出 + 局部 island”,现在更像“服务端首包 + 超大客户端壳”
### 8.3 v2 后续任务
- [ ] 先拆 Sidebar 自身为 host / runtime 或分片 island
- [ ] 把树结构首包与交互态严格分层
- [x] 把主 Sidebar 之外的 page tree、file tree、embed/move picker 也统一切到 kernel projection
- [ ] 把局部刷新协议显式化
- [ ] 给 Sidebar 建立真正的切页重渲染基线
---
## 9. Phase 4:搜索系统 Rust 化与 island 化
**当前状态:`PARTIAL`**
### 9.1 已落地事实
- [x] `SearchPalette` 已收口为轻量 host
- [search-palette.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/search/search-palette.tsx)
- [x] 搜索 runtime 已按需动态加载
- [SearchPaletteHost.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/search/SearchPaletteHost.tsx)
- [search-palette.runtime.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/search/search-palette.runtime.tsx)
- [x] 搜索结果契约已开始带 `nodeId` / `subtreeRootId` / `evidence`
- [search-query-adapter.ts](/mnt/Data1T/mnote/wolai-frontend/src/lib/search/search-query-adapter.ts)
- [search.ts](/mnt/Data1T/mnote/wolai-frontend/src/types/search.ts)
### 9.2 当前还没完成
- [ ] 主布局仍然默认挂载搜索 host
- [ ] 搜索仍主要是纯前端 runtime
- [ ] 没有真正的 server-first 搜索页
- [ ] 没有看到搜索 UI 直接接入 Rust Web 页面壳
- [ ] 结果形状虽已开始 kernel-aware,但检索真相层仍不是 Rust Web / kernel 真正主链
- [ ] 不能宣称“搜索系统 Rust 化”已完成,只能说“搜索 UI 体量开始拆分,结果契约开始收口”
### 9.3 v2 后续任务
- [ ] 把搜索页与浮层分开
- [ ] 先建立服务端搜索结果页壳
- [ ] 让 host 只保留热键与打开逻辑
- [ ] 减少全局常驻 store 对搜索的依赖
- [ ]`nodeId` / `subtreeRootId` / `evidence` 结果形状继续推进到更真实的 Rust/kernel 检索主链
---
## 10. Phase 5AI 面板进一步收口为纯桥接 island
**当前状态:`PARTIAL`**
### 10.1 已落地事实
- [x] 文档页 AI 已拆为 host + runtime
- [DocumentAiAgentPanel.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.tsx)
- [DocumentAiAgentPanel.runtime.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx)
- [x] Mindmap / OnlyOffice 也有类似 runtime 拆分
- [x] `GlobalAiAgentHost` 已不在 `(app)/layout.tsx` 主布局中挂载
- [x] 文档页 AI 已开始把 `node` / `subtree` / `outline` / `evidence` 传给 Hermes bridge
- [DocumentAiAgentPanel.runtime.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx)
- [route.ts](/mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts)
### 10.2 当前还没完成
- [ ] runtime 组件仍然非常重
- [ ] “最小会话协议、统一流式协议、页面上下文协议”还更多体现在组件内部,不是系统级协议层
- [ ] 还不能说 AI 面板已经变成“纯桥接壳”
- [ ] 页面级 AI adapter 仍然很大,只是改成了懒加载
- [ ] AI 已能消费 `node` / `subtree` / `outline` / `evidence` 上下文,但还不是统一的 kernel-first tool 协议
### 10.3 v2 后续任务
- [ ] 继续下沉 runtime 内状态与协议
- [ ] 把会话、tool event、client action 收口到共享协议层
- [ ] 让 runtime 再减重,而不只是拆文件
- [ ] 把当前上下文注入进一步收口为更稳定的 kernel node / subtree / edge bridge
---
## 11. Phase 6Mindmap 独立对象化与独立页面化
**当前状态:`PARTIAL`**
### 11.1 已落地事实
- [x] Rust 侧已有 Mindmap 对象协议与操作
- [x] 独立页已先在服务端抓 initial projection,再交给客户端页面壳
- [x] 独立页已直接使用 `StandaloneMindmapView`
- [page.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx)
- [x]`editorStub` 依赖已经不在独立页入口上
- [x] `MindmapBlock.tsx` 中已有 `standalone` / `documentBridge` 边界
- [MindmapBlock.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx)
- [x] 文档内嵌导图已默认走 preview-first 入口
### 11.2 当前还没完成
- [ ] 独立导图页仍是客户端页面,不是独立对象页壳
- [ ] 仍然直接复用同一个重前端组件
- [ ] 文档内嵌导图虽然已经 preview-first,但进入编辑/沉浸态后仍复用同一套重组件
- [ ] Mindmap 还没有脱离“重交互前端壳优先”的事实
- [ ] 导图数据真相仍未通过 kernel subtree / command 形成稳定主链
### 11.3 v2 后续任务
- [ ] 把独立导图页壳和导图操作壳分离
- [ ] 让文档内嵌导图先变成轻预览/轻入口
- [ ] 继续把对象真相留在 Rust,而不是留在前端组件状态
---
## 12. Phase 7:文档编辑态与 BlockNote 孤岛化
**当前状态:`PARTIAL`**
### 12.1 已落地事实
- [x] `DocumentContent` 已存在阅读态/编辑态切换
- [x] `BlockNoteEditor` 已变成按需挂载
- [x] `keepEditorMounted` 说明已开始按进入编辑态再保留编辑器
- [document-content.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-content.tsx)
- [x] 阅读态已直接消费 `pageSubtree`
- [document-content.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-content.tsx)
- [document-read-view.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/document-read-view.tsx)
### 12.2 当前还没完成
- [ ] `DocumentContent` 仍然同时管理:
- `DocumentAiAgentPanel`
- `DocumentHistoryDrawer`
- `DocumentCommentsDrawer`
- `PageBacklinksPanel`
- `PageOptionsSidebar`
- [ ] `pageSubtree` 当前仍在前端内容层生成和消费,不是更薄的 Rust/kernel 输出边界
- [ ] 搜索/AI/阅读态虽然开始共享 `node` / `subtree` / `outline` / `evidence` 口径,但还没有回到统一的 kernel projection / subtree 真相协议面
- [ ] 这说明外围能力虽然不再阻塞首屏,但仍未真正完全从编辑器宿主层拆开
- [ ] `BlockNote` 还不能算“完全孤岛化”,只能算“默认不再首屏强挂”
### 12.3 v2 后续任务
- [ ] 把外围 drawer/panel 再次拆层
- [ ] 让编辑宿主只负责编辑
- [ ] 让阅读宿主只负责阅读
- [ ]`pageSubtree` 的生成与消费继续下沉到更稳定的 server/kernel 边界
---
## 13. Phase 8:旧前端壳下线与兼容清理
**当前状态:`NOT_STARTED`**
### 13.1 直接证据
- [x] 当前主应用入口仍是 Next App Router
- [layout.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/layout.tsx)
- [x] 当前主文档页仍是 Next 页面
- [page.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/documents/[id]/page.tsx)
- [x] 当前主搜索、主 Sidebar、主 Mindmap 页都仍在旧前端壳内
### 13.2 因此不能成立的说法
- [ ] “Rust Web 主路径切换已完成”
- [ ] “双栈收缩已完成”
- [ ] “旧 Next/React 页面壳已清理”
### 13.3 v2 后续任务
- [ ] 先定义哪条真实流量先切到 `mnote-web`
- [ ] 先建立一条真实主路径,而不是只有 compat bridge
- [ ] 等真正有主路径后,再谈 Phase 8 清理
---
## 14. 与 task-059 ~ task-069 的关系重定义
这组任务不应再被理解成:
- “长期 Phase 0 ~ 8 已全部完成”
更准确的理解应是:
- `task-059` ~ `task-061`
- 主要完成了长期路线的**设计与口径定义**
- `task-062`
- 完成了 `mnote-web` 的**最小骨架落地**
- `task-063`
- 完成了文档阅读态分离的**核心第一步**
- `task-064`
- 只证明 Sidebar 主树已出现 kernel projection 消费接缝,不代表 Sidebar 重构完成
- `task-065`
- 只证明搜索运行时开始拆重,不代表搜索系统完成 server-first 重构
- `task-066`
- 只证明 AI host/runtime 拆分,不代表最小协议壳已经完成
- `task-067`
- 只证明独立导图页切走 editor stub 主入口,并补出 `standalone` / `documentBridge` 边界,不代表 Mindmap 独立对象页完成
- `task-068`
- 只证明 BlockNote 默认首屏强挂已解除,不代表完整孤岛化完成
- `task-069`
- 只能算“统一回写了阶段口径”,不能算“Phase 8 真完成”
---
## 15. v2 推荐执行顺序
如果从真实代码继续往前推进,建议顺序改成:
1. `Phase 1` 继续做实
- 先让 `mnote-web` 承接一条真实页面壳或真实查询主链
2. `Phase 2` 收尾
- 把文档阅读页进一步轻壳化
3. `Phase 3`
- 先打 Sidebar 本体,而不是继续写“已完成”
4. `Phase 4` / `Phase 5`
- 继续减 Search / AI runtime 重量
5. `Phase 6`
- 让 Mindmap 真正从“重前端壳”中继续独立
6. `Phase 7`
- 再拆 `DocumentContent` 外围面板
7. 最后才进入 `Phase 8`
---
## 16. 最终结论
当前未提交代码的真实含义是:
> **长期架构方向是对的,且已经开始进入真实代码;但 59-69 当前被标记为 `completed` 的口径明显偏乐观。**
更准确的结论应是:
- `Phase 0`:基本完成
- `Phase 1`:已开始,骨架已落
- `Phase 2`:已明显落地,但未完全收尾
- `Phase 3`:仍远未完成
- `Phase 4`:只完成轻量拆分
- `Phase 5`:只完成轻量拆分
- `Phase 6`:只完成独立页去耦第一步
- `Phase 7`:只完成阅读/编辑分离第一步
- `Phase 8`:尚未开始
因此,从当前实际代码出发,接下来最需要的不是继续宣布完成,而是:
> **把 v1 的“愿景式 checklist”,改成 v2 的“基于真实代码状态的 checklist”,并据此重排后续 harness 任务状态。**