chore: align local-first control plane and editor fixes

- wire SQLite control-plane access/session paths into Rust web local-folder routes

- preserve local Markdown attachment semantics across upload, reload, and secondary-pane resource tabs

- refresh design governance docs, Reasonix task templates, and bug records

- retire root .mcp.json local MCP config
This commit is contained in:
lix-2026
2026-05-23 23:38:42 +08:00
parent 42fb58310c
commit 5f97800489
110 changed files with 5344 additions and 889 deletions
@@ -0,0 +1,499 @@
# 3-1 [reference] Rust Web 长期架构实施清单 v2
> 更新时间:2026-04-29
>
> 当前状态:`reference`。本文保留 Rust Web 分阶段全景,不再作为 active implementation checklist。
>
> 基于以下实际状态重写:
> - 当前未提交代码
> - `/mnt/Data1T/mnote/harness-tasks.json` 中 `task-059` ~ `task-069`
> - `/mnt/Data1T/mnote/design/03-rust-web/reference/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/reference/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`。
>
> 复核补充(2026-04-29):`3000` 默认 owner 已是 `mnote-web`,根页 / 文档页 / `tree events` / `leptos-tiptap` island 已进入 Rust Web 主链;本清单继续保留在 `process/`,因为主 API 全量迁移、旧 Next/React 链清理、Search/AI/Mindmap 轻壳化仍未完成。
---
## 2. 当前总判断
从当前代码看,长期路线的真实状态是:
### 2.1 已有明确进展
- [x] `Phase 0` 的文档化边界梳理已经完成
- [x] `Phase 1` 已落了一个最小 `axum` Web 骨架:`rust/crates/mnote-web/`
- [x] `Phase 1` 已不再只是空骨架,现已包含 kernel / bridge / compat sidebar 的真实查询接缝
- [x] `Phase 1` 已成为 `3000` 主 Web 入口 owner,根页、文档页、tree stream 与主要 shell marker 均由 `mnote-web` 输出
- [x] `Phase 2` 文档阅读态分离已经有实质代码
- [x] `Phase 3` 主 Sidebar 已出现 `kernelSidebarTree` 消费接缝
- [x] `Phase 4` 搜索已做 host/runtime 拆分,并开始返回 `nodeId` / `subtreeRootId` / `evidence`
- [x] `Phase 5` AI 面板已做 host/runtime 拆分,并开始向 AI bridge 传递 `node` / `subtree` / `outline` / `evidence`2026-05-13 起长期方向改为 Hermes 页面内客户端 + mnote Hermes skill/plugin,旧 CLI host 只保留为历史/兼容证据
- [x] `Phase 6` Mindmap 独立页已去掉 `editorStub` 主入口
- [x] `Phase 7` 阅读态已直接消费 `pageSubtree``BlockNote` 也已不是文档页默认唯一入口
### 2.2 但大部分阶段都只是“部分落地”
- [x] `Phase 1` 已不再只是 skeleton`3000` 默认 owner 已是 Rust Web,根页 / 文档页 SSR 产品壳已进入主路径
- [ ] `Phase 1` 的主 API 全量迁移与 legacy compat 清理仍未完成
- [ ] `Phase 3` legacy Sidebar 仍是超大客户端组件;当前 Rust Web 3000 已有页面树 / 文件树 SSR tab host,但 live stream 消费侧还未完全闭环
- [ ] `Phase 4` 搜索仍是前端 runtime 主导,不是 server-first 搜索页
- [ ] `Phase 5` AI runtime 仍然很重,只是懒挂载了
- [ ] `Phase 6` Mindmap 仍然是重前端交互壳,不是独立对象页壳
- [ ] `Phase 7` 文档页外围面板仍集中在 `DocumentContent`
- [x] `Phase 8` 主入口已切到 `mnote-web`Next App Router 降为 legacy compat / island bundle source;彻底删除旧链仍留给后续清理
### 2.3 结论
> **当前真实状态不是“Phase 0 ~ 8 已全部完成”,而是“Phase 0 的 Rust Web 主入口和页面壳目标已完成,但主 API 迁移仍处于部分落地;Phase 2/4/5/6/7 仍处于不同程度的部分落地,Phase 3 的 3000 SSR 树壳已补实但 legacy Sidebar 与 live stream 消费侧仍需继续收口;Phase 8 已完成主入口 owner cutover,但旧 Next/React 链仍作为 legacy compat / island source 保留”。**
---
## 3. 重新定义状态口径
为了避免再次把“有骨架”写成“已完成”,v2 统一使用下面三种状态:
### `DONE`
定义:
- 代码主路径已经切换
- 不是只有文档或骨架
- 用户可感知行为已经变了
- 后续只剩清理和补强
### `PARTIAL`
定义:
- 已有真实代码改动
- 但仍是局部接缝、最小骨架、阶段性拆分
- 主路径尚未彻底切换
### `NOT_STARTED`
定义:
- 还停留在设计或口径层
- 或只有零散基础,不足以算阶段开始
---
## 4. 基于真实代码的阶段总览
| 阶段 | v1 口径 | 当前真实状态 | 说明 |
| --- | --- | --- | --- |
| Phase 0 | 边界冻结 | `DONE` | 文档、候选模块、边界口径已经成形,但性能基线更多还是文档定义,不是完整观测系统 |
| Phase 1 | Rust Web 基础层 | `PARTIAL` 接近 `DONE` | `mnote-web` 已成为 `3000` 主 Web 入口 owner,根页 / 文档页 SSR 产品壳、tree stream 与关键 API 接缝已落地;主 API 全量迁移、compat 清理与 legacy island source 清理仍未完成 |
| Phase 2 | 文档阅读页 server-first 化 | `PARTIAL` 接近 `DONE` | 阅读态/编辑态已明显分离,但仍有旧链回退和大量客户端状态集中在 `DocumentContent` |
| Phase 3 | Sidebar / 树结构 Rust 化 | `PARTIAL` | 主 Sidebar 已以 `kernelSidebarTree` 作为主树来源;Rust 3000 主文档壳已完成 Page Tree / File Tree create/delete 与页面内 mindmap asset create 的 no-refresh 验收,但整体仍是超大客户端组件 |
| Phase 4 | 搜索 Rust 化与 island 化 | `PARTIAL` | host/runtime 懒加载拆分已做,结果形状也开始带 `nodeId` / `subtreeRootId` / `evidence`,但仍未完成 server-first 搜索页 |
| Phase 5 | AI 面板 Hermes client island 化 | `PARTIAL` | host/runtime 拆分已做,且已开始把 `node` / `subtree` / `outline` / `evidence` 送入 AI bridge;后续应把 Web 面板退成 Hermes 页面内客户端,把 mnote 能力注册为 Hermes skill/plugin,但 runtime 仍重,协议也未统一到 Hermes session/run/tool contract |
| Phase 6 | Mindmap 独立对象化 | `PARTIAL` | 独立页脱离 editor stub 主入口,并补出 `standalone` / `documentBridge` 边界,但仍是客户端重壳 |
| Phase 7 | BlockNote 孤岛化 | `PARTIAL` | 阅读态已直接消费 `pageSubtree`,编辑器按需挂载,但外围 drawer/panel 仍集中在同一内容组件 |
| Phase 8 | 旧前端壳下线 | `PARTIAL` 接近 `DONE` | 3000 gateway / 文档 shell / tree realtime / Search / AI bridge / Mindmap object shell 已由 `mnote-web` 持有;Next App Router 降为 legacy compat / island bundle source,旧链彻底删除仍待后续 |
---
## 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` 接近 `DONE`;主入口和页面壳已完成,主 API 迁移与 compat 清理仍未完成**
### 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;当前仅按兼容 AI bridge 记录,不作为长期 agent 执行面
- [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)
- [x] `3000` 默认 owner 已是 `mnote-web``GET /` 返回 Rust Web workspace shell
- [gateway.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/gateway.rs)
- [home.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/home.rs)
- [x] 已有主页面壳 SSR`/documents/:id` 输出 Rust Web document shell、Page Aggregate marker 与 `leptos_tiptap_island` marker
- [web_shell.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/web_shell.rs)
- [document.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/document.rs)
- [x] Rust Web 已承接 tree commands、tree events、page aggregate、document save/title/options 等当前 3000 主链关键接缝
- [x] 已用 task114/task115/task118/task119/task120/task121/task122 建立页面壳级和树 / 编辑器 runtime smoke 验证
### 6.2 仍未完成
- [ ] 主 API 还没有大面积全量从 Next route / legacy compat 迁出
- [ ] 当前 `compat_next_base_path` 仍说明它还带有兼容层属性,不是唯一承载层
- [ ] Next App Router / React islands 仍作为 legacy compat 与部分 bundle source 保留
- [ ] 复杂 runtime、OnlyOffice、历史 debug 链与旧前端代码还未完全清理
### 6.3 v2 后续任务
- [x]`mnote-web` 从 skeleton 提升为真实服务入口
- [x] 把 sidebar kernel route 上的 fixture fallback 收到测试/开发边界,并承接真实页面壳与真实查询主链
- [x] 明确 Next -> Rust Web 的流量切换边界:`3000``mnote-web`Next 降为 legacy compat / island source
- [x] 增加页面壳级集成验证,而不只是 `cargo check`
- [ ] 继续迁移剩余主 API,收缩 `compat_next_base_path` 与 legacy upstream 依赖
---
## 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`3000 主文档壳 no-refresh 主链已闭环,Sidebar 瘦身仍未完成**
### 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)
- [x] Rust Web 3000 workspace shell 已接入真实页面树 / 文件树 tab host、真实 row、UI 新建页面和 active page 链路
- [workspace_shell.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/workspace_shell.rs)
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs)
- [x] Rust Web 3000 主文档壳已监听 `tree:local-command` 与同页 mindmap asset 写入,页面 create/delete 与页面内 mindmap create 均可在 Page Tree / File Tree 无刷新回显
- [layout.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/ssr/pages/layout.rs)
- [task426-mnote-web-main-no-reload-smoke.js](/mnt/Data1T/mnote/scripts/task426-mnote-web-main-no-reload-smoke.js)
### 8.2 当前真实问题
- [ ] `Sidebar` 仍然是超大客户端组件
- [sidebar.tsx](/mnt/Data1T/mnote/wolai-frontend/src/components/sidebar/sidebar.tsx)
- [x] 页面树 / 文件树在 3000 主文档壳下的 create/delete 与页面内 mindmap create 无刷新链路已验证;后续不能再用 3001/Next 或 `/tree` debug route 替代主链验收
- [x] `buildDocumentTree(...)` 仅剩兼容 helper 与旧单测,不再位于树域主路径
- [ ] 主布局仍然默认常驻挂载 Sidebar
- [ ] 还不能叫“服务端输出 + 局部 island”,现在更像“服务端首包 + 超大客户端壳”
### 8.3 v2 后续任务
- [ ] 先拆 Sidebar 自身为 host / runtime 或分片 island
- [ ] 把树结构首包与交互态严格分层
- [x] 把主 Sidebar 之外的 page tree、file tree、embed/move picker 也统一切到 kernel projection
- [x] 把 3000 主文档壳内页面 create/delete 与页面内 mindmap create 的局部刷新协议显式化;后续新增资产类型时继续复用同一主入口验收口径
- [ ] 给 Sidebar 建立真正的切页重渲染基线
---
## 9. Phase 4:搜索系统 Rust 化与 island 化
**当前状态:`GREEN`**
### 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 面板收口为 Hermes 页面内客户端 / mnote plugin bridge
**当前状态:`PARTIAL`**
> 2026-05-14 口径更新:
> - 本阶段原先把页面 AI 继续收口为 `mnote-cli host / client`,现在已被 `design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md` 覆盖。
> - 新长期方向是:页面 AI 面板使用 Leptos 实现 ACP/Hermes 页面内客户端;产品层运行态索引、权限和审计默认落 SQLite control-planemnote 通过 Hermes skill/plugin 暴露页面、树、artifact、edge 等业务能力。Hermes/Reasonix runtime 的内部 session/message/tool event/usage/model 不等同于 MNote 产品层会话真相。
> - `mnote-cli` 只能作为 plugin 内部适配器或调试入口,不能再被写成页面 AI 唯一长期执行面。
> - `design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.md` 已把页面 AI 主链推进到 Hermes session/run/events,并完成 `mnote.page.get`、正文写入、标题/页面设置、artifact、legacy guard、持久化审计和正式 `3000` smoke 矩阵;本节后续只跟踪 Rust Web 侧长期边界,不再保留旧 `/api/ai-agent/run` 待办作为当前状态。
### 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 主链已改为 mnote-web Hermes client proxy:创建/恢复 Hermes session,发起 Hermes run,消费 events,并从 Hermes session detail 刷新恢复
- [hermes_client.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_client.rs)
- [x] mnote 业务能力已通过 mnote Hermes tool routes 暴露,写入回到 Rust runtime / Page Aggregate command family / kernel
- [hermes_tools.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/hermes_tools.rs)
- [hermes_tools](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/mod.rs)
- [x]`/api/ai-agent/run` 在 mnote-web 中已退役为 `410 legacy_ai_agent_run_retired` guard,不再作为页面 AI 主入口
- [compat.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/compat.rs)
### 10.2 当前还没完成
- [ ] legacy React 文档页 AI runtime 文件仍然偏重,但它不再代表 Rust Web 3000 页面 AI 主链。
- [ ] node / subtree / edge 工具面还需要继续从页面上下文扩展成更稳定的 kernel-first Hermes plugin contract。
- [ ] Mindmap / OnlyOffice / generic AI 面板的旧域调用点仍需分别按各自 domain 拆迁移,不纳入“页面 AI Hermes 面板”完成定义。
### 10.3 v2 后续任务
- [x] 移除页面 AI 对旧 `/api/ai-agent/run` 主路径的长期依赖,改走正式 Hermes client proxy
- [x] 把会话、message、tool event、usage、model 选择交给 Hermes session 存储
- [x] 把 mnote 页面、树、artifact、edge 第一批能力注册为 Hermes skill/plugin tools
- [ ] 把当前上下文注入进一步收口为 Hermes run context + 稳定 kernel node / subtree / edge tool 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:旧前端壳下线与兼容清理
**当前状态:`PARTIAL`,主入口 owner cutover 已完成**
### 13.1 直接证据
- [x] `3000` 默认 owner 已是 `mnote-web` Rust gateway。
- [x] `/auth``/documents/:id``/api/tree/events``/search``/api/hermes/bridge``/mindmap/:docId/:mindmapId` 已具备 Rust Web owner / shell / transport contract。
- [x] `SKIP_NEXT_LEGACY=1` 可证明核心 shell 不依赖 Next legacy upstream。
- [x] Next App Router 已降为 legacy compat / React island bundle source,不再是主 Web 入口。
### 13.2 仍不能成立的说法
- [ ] “旧 Next/React 代码已经删除”
- [ ] “所有重交互 runtime 都已迁出 React island”
- [ ] “OnlyOffice、复杂编辑器与历史 debug 链都已完全退役”
### 13.3 v2 后续任务
- [ ] 继续清理 legacy compat route 与旧 Next 页面。
- [ ] 为仍保留的 React islands 建立更细的删除 / 替换清单。
- [ ] 保持 `3104` 只在显式 legacy/debug 场景可见,不恢复为公开入口。
---
## 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`:主入口 owner cutover 已完成,旧链清理继续推进
因此,从当前实际代码出发,接下来最需要的不是继续宣布完成,而是:
> **把 v1 的“愿景式 checklist”,改成 v2 的“基于真实代码状态的 checklist”,并据此重排后续 harness 任务状态。**
@@ -1,151 +0,0 @@
# 3-17 Convex Export Web Entry v1
状态:reference
归档说明(2026-05-21):CLI 迁移闭环已具备并有 smoke 证据;本文只保留为后续 Web 管理入口设计参考,当前不作为 active implementation checklist。若决定短期落地 Web UI,应新建执行 checklist。
## 目标
旧 Convex workspace 迁移到本地 workspace 时,用户应能在 Web 控制台完成:
1. 选择 Convex workspace。
2. 选择目标本地 root。
3. 先 dry run,查看计划、冲突和预计写入。
4. apply 后得到 manifest、冲突报告、索引重建结果。
5. 需要时按 manifest rollback。
## 当前基础
CLI 已具备最小迁移闭环:
- `scripts/export-convex-workspace-to-local.js --fixture <fixture.json> --out <dir>`
- `--dry-run`
- `--manifest <file>`
- `--conflict-report <file>`
- `--rollback <manifest.json>`
验证:
- `node scripts/task444-convex-workspace-export-local-fixture-smoke.js`
- `node scripts/task455-convex-export-plan-rollback-smoke.js`
## Web 入口设计
入口位置:管理员控制台 `/admin` 新增“Convex 迁移”面板。
字段:
- `workspaceId`
- `targetRootUri`
- `mode=dryRun | apply | rollback`
- `manifestPath`rollback 时必填
- `conflictPolicy=stop`,默认只支持 stop,不覆盖目标文件
## API 设计
### `GET /api/admin/convex-export/workspaces`
返回当前可导出的 Convex workspace 列表。
最小返回:
```json
{
"ok": true,
"workspaces": [
{ "workspaceId": "ws_1", "name": "默认空间", "documentCount": 12 }
]
}
```
### `POST /api/admin/convex-export/plan`
输入:
```json
{
"workspaceId": "ws_1",
"targetRootUri": "file:///mnt/Data1T/Mnote_data/users/user_1/workspaces/imported"
}
```
行为:
- 导出 Convex workspace fixture / snapshot 到临时计划。
- 调用迁移 planner,等价于 CLI `--dry-run`
- 写入 `<target>/.mnote/migration-plan.json` 或控制面 job 目录。
- 不写正文文件。
### `POST /api/admin/convex-export/apply`
输入:
```json
{
"workspaceId": "ws_1",
"targetRootUri": "file:///mnt/Data1T/Mnote_data/users/user_1/workspaces/imported",
"manifestPath": "/mnt/Data1T/Mnote_data/users/user_1/workspaces/imported/.mnote/migration-manifest.json"
}
```
行为:
- 默认 `conflictPolicy=stop`
- 目标文件存在时返回 409 和 conflict report。
- 成功后写 `.mnote/migration-manifest.json``.mnote/index/search-index.json`
### `POST /api/admin/convex-export/rollback`
输入:
```json
{
"manifestPath": "/mnt/Data1T/Mnote_data/users/user_1/workspaces/imported/.mnote/migration-manifest.json"
}
```
行为:
- 按 manifest 删除本次新增文件。
- 如 manifest 存在备份文件,则恢复备份。
- 不删除 manifest 本身,追加 rollback report。
## 权限
- 只有 admin 可以从任意 Convex workspace 导出。
- 普通用户只能导出自己拥有的 workspace 到自己有 write grant 的本地 root。
- 所有 `targetRootUri` 必须通过 local access policy 校验。
- Web API 不能接受任意 shell 命令;CLI 迁移逻辑应抽成 Rust/Node 可调用模块或由受控 job runner 调用固定脚本和固定参数。
## 状态与报告
任务状态包含:
- `queued`
- `planning`
- `blocked_by_conflict`
- `applying`
- `indexing`
- `completed`
- `failed`
- `rolled_back`
报告包含:
- `documentCount`
- `resourceCount`
- `aiSessionCount`
- `operationCount`
- `createdFiles`
- `conflicts`
- `indexRefresh`
- `manifestPath`
- `conflictReportPath`
## 后续落码顺序
1. 把 CLI planner/apply/rollback 拆成可被 Web route 复用的模块。
2. 新增 admin API 的 dry-run route。
3. 新增 admin UI “Convex 迁移”面板。
4. 新增 apply / rollback route。
5. 补 browser smokedry-run 不写文件、冲突 409、不覆盖、rollback 后 root 恢复。
@@ -0,0 +1,598 @@
# 3 [reference] Rust Web 长期架构方案 v1
> 更新时间:2026-05-09
>
> 当前状态:`reference`。本文保留 Rust Web 长期架构边界;当前实现队列以 `design/01-tree-first-graph-kernel/process/1-8-mvp-post-process-execution-order-v1.md` 和对应 `done/` 证据为准。
>
> 相关文档:
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md`
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/document-access-performance-root-cure-v1.md`
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/ai-frontend-simplification-plan-v1.md`
## 1. 文档目的
本文回答的是长期架构问题,而不是短期优化问题:
> **当 mnote 要继续沿着 Rust 主导路线演进时,Web 层到底应不应该一起 Rust 化;如果要 Rust 化,应该如何分层,而不是只说一句“改成 Rust”。**
本文重点不是:
- 再做几处懒加载
- 再精简几个前端面板
- 再给现有 Next 页面补一些缓存
本文重点是:
- Rust 内核和 Web 承载层如何分工
- 前端哪些部分应该退出当前重 React 壳
- `axum``Leptos` 这类 Rust Web 方案是否值得采用
- 页面 AI 应如何作为 Hermes 页面内客户端接入,并让 mnote 通过 Hermes skill/plugin 暴露业务能力
- 默认主编辑器已经切到页面内 `leptos-tiptap` island 后,剩余重编辑兼容链应如何继续收口
---
## 2. 先给结论
结论分三句:
### 2.1 不能只说“用 Rust”
如果只说“以后 Web 也改成 Rust”,但不明确:
- 谁负责 HTTP / SSE / WebSocket / 路由
- 谁负责 SSR 页面壳
- 谁负责 islands / hydration 模型
- 谁负责保留必须存在的浏览器重交互模块
那么最后大概率只是:
- Rust 内核继续存在
- 旧前端继续承担页面运行时主负担
这不叫根治。
### 2.2 长期推荐方案不是“只上 `axum`”,而是分层方案
长期推荐采用:
- **业务执行面:现有 Rust workspace 继续作为唯一业务真执行面**
- **Web 承载层:`axum`**
- **页面渲染模型:`Leptos Islands`**
- **AI 会话与编排面:Hermes**
- **mnote AI 能力面:Hermes skill/plugin -> Rust runtime / kernel**
- **最后保留的重编辑兼容孤岛:少量编辑器 runtime(当前默认主编辑器已是页面内 `leptos-tiptap` island`BlockNote` 仅保留为 `recycle/` 历史参考副本)**
一句话概括:
> **mnote 的长期正确方向不是“Next 外壳上继续打补丁”,也不是“只把 API 改成 Rust”,而是“Rust 内核 + Rust Web 壳 + server-first 页面 + 少量交互孤岛”。**
### 2.3 重编辑兼容链不是第一刀,而是最后一刀
当前真正难替代的主要是:
- 以旧 `BlockNote` 编辑器副本、转换链和剩余兼容保存链为代表的重编辑 runtime
而下面这些能力,从长期看都可以先退出当前大前端壳:
- Sidebar / 页面树 / 文件树
- 搜索面板
- Mindmap
- AI 面板
- 评论 / 回链 / 历史 / 页面选项
- 大部分页面级壳与详情面板
所以长期路线应当是:
> **先把能 Rust 化、能 server-first 化、能 island 化的东西全部迁走,最后再处理重编辑兼容链。**
---
## 3. 为什么当前问题不能靠“只做 Rust 内核”解决
结合当前仓库状态,可以确认一个关键事实:
- `/mnt/Data1T/mnote/rust/` 已经是业务协议、桥接、CLI、Convex bridge 的 Rust workspace
- 但它现在还不是 Web 页面承载层
- 它没有直接接管文档页、页面树、搜索壳、阅读页 SSR、浏览器交互分层
这意味着当前 Rust 已经影响了:
- 业务命令面
- 查询面
- AI tools / bridge 的真执行面
- CLI 化能力
但它**还没有从根上决定“网页怎么加载”**。
所以之前用户体感到的页面切换卡顿,本质仍然主要来自:
- 页面运行模型
- 客户端挂载链
- 重编辑器与周边面板的初始化方式
而不是“后端是不是 Rust”这一件事本身。
换句话说:
> **Rust 内核已经在替换业务执行平面,但网页访问性能要根治,还必须补上 Rust Web 层与页面运行模型重构。**
---
## 4. 为什么长期要引入 Rust Web 层,而不是停在现状
如果继续维持现在的分工:
- Rust 只负责业务执行
- Next/React 继续负责几乎全部页面壳和交互壳
那么会长期存在三个问题。
### 4.1 页面访问链仍然受制于重前端应用模型
即使业务调用已经走 Rust,页面还是会在浏览器里经历:
- 布局挂载
- 客户端组件挂载
- 动态导入
- 面板初始化
- 编辑器初始化
这类成本不会因为底层业务改成 Rust 自动消失。
### 4.2 Web 层仍然会保留第二套复杂运行语义
如果页面系统继续主要靠当前大前端维护,那么:
- 页面壳逻辑
- 面板装配逻辑
- 浏览器状态拼装逻辑
- 部分对象读取与表现层规则
仍会长期留在现有前端系统里。
这会让“Rust 已成为唯一主线”变成一句不完整的话。
### 4.3 很难把页面访问做成真正的 server-first
用户真正想要的是:
- 页面先出来
- 阅读先可用
- 交互只在局部发生
如果继续沿用大范围客户端 hydration 的页面模型,这个目标很难彻底实现。
---
## 5. `axum` 在这个体系里的正确位置
根据 `axum` 官方文档,它非常适合承担:
- Router
- Handler
- Middleware
- JSON / Form / Query 提取
- WebSocket
- SSE
- 基于 `tokio` 的服务承载
这使它非常适合 mnote 长期担任:
- 主 API 层
- 文档查询与聚合层
- 树结构装配层
- 搜索服务层
- Hermes client proxy 与 mnote tool bridge 层;页面 AI 会话真相归 Hermes,mnote 业务工具最终回到 Rust runtime / kernel
- 页面 SSR 外壳承载层
- 流式更新、通知、事件推送层
但也必须明确一件事:
> **`axum` 是优秀的 Rust Web 服务框架,但它不是页面交互模型本身。**
也就是说,`axum` 可以很好地承接:
- HTTP
- API
- 页面响应
- 流式接口
但它并不会直接回答:
- 哪些页面内容不该 hydrate
- 哪些交互应该变成 island
- `BlockNote` 之外还有多少东西需要进浏览器
所以:
> **长期方案不能只有 `axum`,还必须有“页面如何 server-first 输出、如何只给少量模块 hydration”的明确答案。**
---
## 6. 为什么推荐 `Leptos Islands`
根据 Leptos 官方 Islands 文档,它最重要的特征是:
- 默认可以让大量内容保持服务端输出
- 只有显式声明为 island 的部分进入客户端 hydration
- 父级服务端组件可以保留纯服务端逻辑
- 页面可以由少量交互岛包住,而不是整页一起变成大前端应用
这和 mnote 现在想解决的问题高度匹配。
因为 mnote 现在最需要的不是“再换一个前端框架”,而是:
- 把页面阅读恢复成轻页面
- 把交互缩到真正必要的模块
- 把大块浏览器运行时代码压缩成少量孤岛
Leptos Islands 很适合承接下面这类长期目标:
- 页面树 / 文件树作为轻交互 island
- 搜索输入与结果面板作为轻交互 island
- AI 面板作为独立 island
- 文档工具栏作为轻交互 island
- `BlockNote` 作为最后的重交互 island
- 其余阅读内容保持服务端输出
所以它的价值不是“因为它是 Rust 前端”,而是:
> **它天然支持 server-first + 少量 islands 的页面运行模型,这正是 mnote 当前最缺的东西。**
---
## 7. 为什么不建议只说“就 Rust”,也不建议直接押注别的 Rust 前端路线
### 7.1 不建议只说“就 Rust”
因为这句话缺少架构含义。
如果没有 Web 承载层和页面模型的明确选型,最后通常只会得到:
- Rust 业务内核
- 旧网页壳继续不变
这解决不了根因。
### 7.2 不建议把 `axum` 单独当成完整答案
`axum` 很强,但它解决的是:
- 服务承载
- HTTP / 流式能力
- 路由与 middleware
它不直接解决:
- islands
- 页面 hydration 边界
- 大前端退场策略
所以单独采用 `axum`,只够完成“Rust BFF / Rust API 化”,不够完成“页面运行模型重构”。
### 7.3 不把 Dioxus / Yew 作为当前主推荐
不是说它们不能用,而是它们不是当前最贴合目标的第一选择。
原因很简单:
- mnote 当前最核心的问题不是“缺一个 Rust UI 框架”
- 而是“如何让绝大多数页面不再变成整页重 hydration 应用”
从这个目标出发,`Leptos Islands` 比较直接地支持:
- server-first 页面
- 局部 hydration
- 少量交互孤岛
因此当前更适合作为第一推荐。
---
## 8. mnote 长期推荐分层
## 8.1 总体结构
长期推荐结构如下:
1. **Rust Core**
- `core-domain`
- `core-protocol`
- `bridge-runtime`
- `storage-convex-bridge`
- `index-fts`
2. **Rust Web**
- `axum` 作为主 HTTP / SSE / WS / API / SSR 承载
3. **Rust View Shell**
- `Leptos Islands` 作为页面壳、阅读态、轻交互 islands
4. **Browser Islands**
- 搜索框
- Sidebar 树
- AI bridge panel
- Mindmap 交互页
- `BlockNote` 编辑岛
5. **外挂或外部编辑器**
- OnlyOffice
- 后续可替换的在线表格 / 飞书文档插件
### 8.2 运行原则
长期运行原则应改成:
- 阅读优先
- 服务端先输出
- 浏览器只接必要交互
- 重交互能力单独孤岛化
- 业务规则全部留在 Rust 内核
### 8.3 实施治理口径
为了避免长期路线再次滑回“Rust 内核 + 重前端页面壳”的临时态,实施时必须额外固定四个治理口径:
1. **阶段边界固定**
- `Phase 0` 先冻结旧壳扩张、产出基线和 islands 候选
- `Phase 1` 先把 Rust Web 承载层立起来
- `Phase 2` ~ `Phase 6` 迁阅读页、Sidebar、搜索、AI、Mindmap
- `Phase 7` 最后处理 `BlockNote`
- `Phase 8` 再清理旧壳
2. **依赖顺序固定**
- 没有 `Phase 1` 的 Rust Web 入口,就不算真正进入长期主线
- 没有阅读态/编辑态分离,就不允许继续扩大编辑器默认挂载链
- 没有横向能力(trace、缓存、权限、回归脚本),就不允许每个模块各自发明运行语义
3. **横向能力固定**
- 统一 `request_id` / `trace_id`
- 统一缓存与预取口径
- 统一页面壳、对象、AI bridge 的权限边界
- 统一回归脚本和性能采样口径
4. **最终验收固定**
- 文档打开先看到阅读态,而不是编辑器 loading
- Sidebar/搜索/AI/Mindmap 已退出当前重前端主壳
- Rust Web 已能承接主 API、页面壳和主流式链路
- `BlockNote` 已降级为最后的重交互孤岛
对应的执行细节、逐阶段清单和可验证项,当前应先以 `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md` 确认优先级;`/mnt/Data1T/mnote/design/03-rust-web/reference/3-1-rust-web-long-term-checklist-v2.md` 保留为 Rust Web 分阶段全景参考。
### 8.4 当前已落地的最小里程碑(2026-05-09)
到目前为止,长期路线里已经有几条可以被源码直接证明的最小里程碑:
- `mnote-web` 已经不是只停留在 crate 骨架;`3000` 公开入口已由 Rust Web 主壳承接,`3104` 已退到仅显式 debug / internal 边界。
- Rust Web 主壳已经接入 `/api/tree/events` snapshot / delta / resync consumer,双 pane 也已复用同一条 tree realtime 主链,而不是每个页面壳各自维护第二条流。
- 文档页读取已收口到 Rust `/api/page-aggregate/:id``mnote.page_aggregate.v1` snapshot`/api/documents/page` 已降级为显式退场的 compat 边界,不再参与运行时主路径。
- 默认主编辑区已经切到页面内 `leptos-tiptap` island;阅读态、页头、页面设置和页面内 AI 面板都在 `3000` 主壳上继续收口,`BlockNote` 只保留为 `recycle/` 历史参考 / 对照材料。
- Sidebar 已形成“服务端首包 + 客户端局部 island”的最小边界,导航数据聚合契约不再散落在布局层。
- SearchPalette 与页面级 AI 面板都已经收成轻 host + 按需 runtime island,重量运行态不再默认跟随主布局常驻。
- Global AI 继续保留为实验入口,但不再回到 app layout 主链,避免长期路线再次滑回“全局大面板常驻”模式。
- Mindmap 已经具备独立页能力,文档内嵌形态也已降为轻预览/轻交互入口。
---
## 9. 各模块长期归位建议
### 9.1 文档阅读页
目标:
- 先直接返回可阅读页面
- 不等待编辑器初始化
- 不让评论、历史、AI、回链等阻塞正文出现
归位:
- 页面壳迁到 `axum + Leptos`
- 文档阅读内容默认服务端输出
- 编辑入口点击后才挂载编辑 island
### 9.2 Sidebar / 页面树 / 文件树
目标:
- 从当前大布局中的重量级客户端组件,变成轻交互 island
归位:
- 数据查询与聚合走 Rust
- 页面壳服务端输出
- 展开、拖拽、快捷过滤、局部刷新才在 island 内运行
### 9.3 搜索系统
目标:
- 搜索框与搜索结果只做局部交互
- 不再把整个页面切换都拖进搜索运行时
归位:
- 索引、召回、聚合全部 Rust 化
- 搜索输入与结果列表作为 island
- 搜索页本身保持 server-first
### 9.4 AI 面板
目标:
- 作为 Hermes 页面内客户端运行
- 不再承担前端本地 orchestration 或私有会话存储
- 不再成为常驻大壳的一部分
归位:
- 面板只保留 Hermes chat/session/run/tool event 的页面内子集 UI 与当前页面上下文桥接
- ACP/Hermes runtime 持有执行层 session / message / usage / modelMNote 产品层运行态索引、权限和审计默认由 SQLite control-plane 持有
- mnote 通过 Hermes skill/plugin 暴露页面、树、artifact、edge 工具,最终执行回到 Rust runtime / kernel
- 面板按页面需要懒挂载成单独 island
### 9.5 Mindmap
目标:
- 从 BlockNote 自定义块逻辑中进一步解耦
- 变成独立对象和独立页面能力
归位:
- 对象读写继续走 Rust
- 独立页面优先改成 Rust Web 壳 + 独立交互岛
- 文档内嵌版本退化为预览卡片或轻交互嵌入
### 9.6 OnlyOffice
目标:
- 维持外挂页面定位
归位:
- 继续独立页面或外部容器打开
- 只保留必要的签名、代理、回调
- 不参与主文档访问性能判断
### 9.7 `BlockNote`
目标:
- 最终变成单独的重交互编辑岛
归位:
- 阅读页不默认依赖它
- 编辑态按需挂载
- 它之外的能力尽量不再绑在同一前端运行时里
---
## 10. 为什么这是“根治路线”,不是“临时路线”
因为它改的不是几个组件,而是四个底层前提:
### 10.1 改的是页面运行模型
从:
- 先进入前端应用
变成:
- 先进入页面
### 10.2 改的是业务归属
从:
- Web 层和业务层长期混写
变成:
- 业务规则只留在 Rust
### 10.3 改的是浏览器职责
从:
- 浏览器承担整页大运行时
变成:
- 浏览器只承担必要的交互岛
### 10.4 改的是迁移顺序
从:
- 一上来就想替掉最难的 `BlockNote`
变成:
- 先清走外围大块能力
- 最后再处理 `BlockNote`
---
## 11. 推荐迁移顺序
长期上推荐按下面顺序推进,而不是乱序推进。
### Phase A:先把 Rust Web 层立起来
目标:
- 建立 `axum` 主承载层
- 建立 Rust 侧统一 Web 入口
- 接住 API、SSE、WS、文档 SSR 壳
此阶段不追求一次性替换全部页面,只追求:
- 先把“Rust 也能承接 Web 层”这件事落地
### Phase B:先迁轻页面与高频结构页
优先对象:
- Sidebar
- 页面树 / 文件树
- 搜索页
- 文档阅读页壳
- AI 面板壳
这些东西的特点是:
- 高频访问
- 强烈影响页面切换体感
- 又不像 `BlockNote` 那么难替换
### Phase C:把 Mindmap 独立化
目标:
- 让 Mindmap 从当前 BlockNote 共生结构里进一步脱离
- 独立页面优先 Rust 化
- 文档内嵌形态缩成轻版本
### Phase D:最后处理 `BlockNote`
只有当前三阶段基本稳定后,才建议处理:
- `BlockNote` 编辑器本体
- 文档编辑态与阅读态的最终分离
- 自定义 block 的最终重构边界
---
## 12. 最终建议
如果只问一句“是不是要参考 Rust 的 Web 框架,比如 `axum`,还是只要 Rust 就行”,最终答案是:
> **要参考,而且必须明确采用 Rust Web 分层;不能只说“就 Rust”。**
更具体的推荐是:
- **不是**“只保留现有 Rust 内核,网页继续主要靠当前重前端”
- **不是**“只引入 `axum` 做 API,然后页面模型不变”
- **而是**“Rust 内核 + `axum` Web 承载 + `Leptos Islands` 页面壳 + `BlockNote` 最后孤岛化”
这是当前最符合 mnote 长期目标的路线,因为它同时满足:
- 真正减少页面访问时的前端运行负担
- 继续强化 Rust 作为唯一业务执行平面
- 支持绝大部分功能逐步 CLI 化、服务化、AI 可编辑化
- 不要求一开始就碰最难替换的 `BlockNote`
---
## 13. 官方依据
本方案涉及的 Rust Web 判断,主要基于以下官方资料方向:
- `axum` 官方文档与 README
- 重点能力:Router、Handler、Middleware、JSON、WebSocket、SSE、`tokio` 服务承载
- Leptos 官方文档的 Islands 章节
- 重点能力:只有显式 island 进入客户端 hydration,其余内容可保持服务端输出
因此本文的判断不是“因为 Rust 很快所以推荐 Rust”,而是:
> **因为 mnote 需要的是 server-first 页面模型、少量交互孤岛、统一业务执行面,而 `axum + Leptos Islands + Rust Core` 正好能形成这套长期结构。**