# 1 [reference] Tree-First Graph 内核方案 v1 > 更新时间:2026-04-22 > > 当前状态:`reference`。本文是 tree-first graph kernel 的长期架构边界,不是当前可直接执行的 checklist;执行入口见 `design/10-review/process/21-mvp-post-architecture-closure-checklist-v1.md`。 > > 当前优先级入口: > - `/mnt/Data1T/mnote/design/10-review/process/21-mvp-post-architecture-closure-checklist-v1.md` > > 关联文档: > - `/mnt/Data1T/mnote/design/03-rust-web/reference/3-rust-web-long-term-architecture-v1.md` > - `/mnt/Data1T/mnote/design/03-rust-web/reference/3-1-rust-web-long-term-checklist-v2.md` > - `/mnt/Data1T/mnote/ARCHITECTURE.md` ## 1. 文档目的 本文回答的不是“页面如何加速”,而是更底层的问题: > **mnote 长期到底应该以什么作为统一对象内核。** 在前一轮讨论里,方向经历了一个重要修正: - 不是让 `Mindmap` 成为系统主投影 - 也不是让“导图页面”变成新的系统中心 - 而是让 **`tree-first graph` 成为统一结构内核** - `Mindmap` 只是这个内核的一种可视化挂件 这份文档的目标,是把这个判断正式固定下来。 --- ## 2. 先给结论 结论只有一句: > **mnote 的长期核心不应是 `BlockNote-first`,也不应是 `Mindmap-first`,而应是 `tree-first graph kernel`。** 也就是说: - **树** 是主骨架 - **图** 是横向引用扩展 - **Mindmap** 是树/图的一种空间化视图 - **Sidebar / 页面树 / 文件树 / 文档阅读页 / 搜索结果 / AI 面板** 都只是同一内核的不同投影 因此,长期正确方向不是: - “把所有东西都画成导图” 而是: - “让所有对象共享同一份结构内核,再让不同视图各自投影” --- ## 3. 为什么不是 Mindmap-first 虽然 Mindmap 在结构表达上很强,但它不适合被定义为主中心。 原因有四个。 ### 3.1 导图 UI 不是所有场景的最佳交互 下面这些场景不适合被强行导图化: - Sidebar 导航 - 文件树浏览 - 文档阅读 - 搜索结果浏览 - 历史版本查看 - AI 工具面板 这些场景里,很多时候: - 列表更合适 - 树表更合适 - 阅读流更合适 - 搜索结果卡片更合适 所以: > **导图是一种强表达能力的视图,不是所有结构都应默认进入的主视图。** ### 3.2 如果 Mindmap 成为主中心,系统会被导图交互绑架 一旦把 Mindmap 当主投影,后面很容易出现: - 结构建模被导图控件的数据形状反向约束 - 页面/文件/章节/引用都被迫适配导图编辑器 - 视图层规则污染对象层规则 这会让“结构内核”被“某种 UI 控件”夺走主导权。 ### 3.3 当前本地代码已经说明 Mindmap 更像重操作壳 当前: - [`MindmapBlock.tsx`](/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx) 同时承担: - 内嵌块 - 独立页 - 工具栏 - 右键菜单 - 导航器 - 缩略图 - 本地全屏视图 这说明它当前的本质更接近: - 一个前端重交互操作层 而不是: - 一个稳定、极简、内核级结构模型 ### 3.4 Mindmap 已经适合退到“挂件层” 真正更合理的位置是: - 它继续保留 - 但作为 `tree-first graph kernel` 的挂件和投影 - 而不是事实源 --- ## 4. 为什么是 Tree-First Graph 这是因为 mnote 当前最稳定、最通用、最可渐进迁移的共同语义,本质上是: - **父子层级** - **局部子树** - **对象引用** 这正对应: - 树 - 子树 - 图边 ### 4.1 树是最自然的主骨架 下面这些天然就是树: - 工作区结构 - 页面树 - 文件树 - 文档大纲 - PDF 章节结构 - 页面内部结构 - 导图节点结构 因此“树优先”不是一种美学偏好,而是数据现实。 ### 4.2 图是必须存在的扩展层 但系统又不可能只有树,因为还存在: - 双向引用 - 页面引用页面 - 块引用块 - 摘要引用原文 - PDF 章节引用页码/附件 - AI 生成节点引用证据节点 这些都不是父子关系,而是横向边。 所以系统最终一定是: - 树作为主骨架 - 图作为引用扩展 也就是: > **tree-first graph** ### 4.3 这种结构最适合 Rust 内核化 因为它天然适合: - typed node - typed edge - subtree query - graph traversal - object projection - CLI / AI tool 直接操作 这比“以某个前端编辑器数据格式为真相”更适合进入 Rust core。 --- ## 5. 内核定义 ## 5.1 统一内核 长期建议把 mnote 的结构真相定义为: - `WorkspaceKernel` - `Node` - `Edge` - `Projection` ### 5.1.1 当前已落地的 Rust 类型 2026-04-16 这轮已经在 Rust `core-protocol` 中补入统一 kernel 类型定义,入口文件为: - `/mnt/Data1T/mnote/rust/crates/core-protocol/src/kernel.rs` 当前已落下的主类型包括: - `KernelNode` - `KernelEdge` - `KernelProjectionRequest` - `KernelProjectionResult` - `KernelSubtreeRef` - `KernelSubtreeResult` - `KernelGetNode` - `KernelGetSubtree` - `KernelListChildren` - `KernelListEdges` - `KernelTraverseGraph` - `KernelCreateNode` - `KernelUpdateNode` - `KernelMoveSubtree` - `KernelAttachEdge` - `KernelDetachEdge` 这意味着这份文档里的 kernel 语义已经不再只是概念,而是进入了 Rust 可复用协议层。 ### 5.2 Node 每个对象都是带类型的节点。 候选节点类型包括: - `workspace` - `folder` - `page` - `section` - `paragraph` - `asset` - `book` - `pdf` - `mindmap` - `mindmap_node` - `table` - `query_view` - `summary` - `ai_note` - `reference_anchor` 当前 Rust 中的最小首批节点类型已经固定为: - `workspace` - `folder` - `page` - `section` - `asset` - `book` - `pdf` - `mindmap` - `mindmap_node` - `summary` - `ai_note` - `reference_anchor` - `content_node` - `index_node` 注意: > **这里的关键不是名字,而是“页面、文件、书籍、摘要、AI 结果不再分属不同系统,而是同一内核里的 typed node”。** ### 5.3 Edge 边分成两类: #### A. 骨架边 - `parent_of` - `child_of` - `contains` #### B. 扩展边 - `references` - `backlinks_to` - `source_of` - `derived_from` - `summarizes` - `indexes` - `points_to` 当前 Rust 中的最小首批边类型已经固定为: - `parent_of` - `child_of` - `contains` - `references` - `backlinks_to` - `source_of` - `derived_from` - `summarizes` - `indexes` - `points_to` 这样: - 树结构靠骨架边维持 - 网状关系靠扩展边表达 ### 5.4 Projection Projection 不是数据真相,只是同一内核的不同投影。 长期主要投影包括: - Sidebar tree - 页面树 - 文件树 - 文档阅读流 - Mindmap - 搜索结果页 - AI 操作视图 - 未来可能的关系图 / 时间线 / 表格视图 当前 Rust 中已经固定的投影种类包括: - `sidebar_tree` - `page_tree` - `file_tree` - `mindmap` - `read_view` - `search_results` - `rag_index` ### 5.5 四层边界 为了避免后续又把前端页面壳误当事实源,当前主线边界固定为四层: 1. **事实源** - 统一 `tree-first graph kernel` - 只承载 `node / edge / subtree / audit` - 不承载具体前端 UI 状态 2. **投影** - `sidebar tree` - `page tree` - `file tree` - `mindmap projection` - `read view` - `search / rag projection` 3. **编辑器** - `BlockNote` - `Mindmap canvas` - `OnlyOffice` - 未来其他专用内容编辑器 4. **外挂 / 挂件** - AI 面板 - 评论 - 历史 - 回链 - 右侧辅助信息面板 固定规则是: - 事实源只在 kernel - 投影不拥有对象真相 - 编辑器不等于对象模型 - 外挂只消费 kernel 或 projection,不再私自定义第二套对象真相 ### 5.6 术语冻结 这一轮同时把后续文档和任务要共用的术语冻结如下: - `node` 指统一内核中的 typed object - `edge` 指节点之间的 typed relation - `projection` 指从 kernel 派生出的视图结果,不是事实源 - `subtree` 指从某个 root node 出发的一段有界层级结构 - `content node` 指以正文载荷为主的节点,适合交给 BlockNote 之类编辑器处理 - `reference edge` 指非父子关系的引用边,例如页面引用、证据引用、来源引用 - `summary node` 指对某段 subtree 或 source node 做摘要后的节点 - `index node` 指为搜索/RAG 建立的结构索引节点 ### 5.7 现阶段并入策略 当前主线按下面的口径迁移: - 暂时继续存在,但应逐步并入 kernel 的对象: - 页面 - Sidebar 数据集 - 搜索结果对象 - 导图树数据 - 当前明确不是事实源、只保留为编辑或展示壳: - BlockNote 文档结构 - Mindmap 前端画布状态 - OnlyOffice 页面壳 - 各类 AI host / panel 本地状态 --- ## 6. 与当前系统的关系 ## 6.1 与 Sidebar / 页面树 / 文件树的关系 这些都不应再视为独立系统。 长期应改成: - 同一份结构内核 - 在 Sidebar 中投影为导航树 - 在文件页中投影为文件树 - 在某些对象页中投影为结构树 所以: > **Sidebar 不是“一个前端导航组件”,而是 kernel 的树投影。** ## 6.2 与 Mindmap 的关系 Mindmap 不再是中心,而是: - kernel 的空间化图形视图 - 适合做结构浏览、重组、章节展开、节点重排 但它不再是: - 唯一主视图 - 唯一对象真相 ### 6.3 与 BlockNote 的关系 长期上,`BlockNote` 应从“系统底座”降级为: - 内容编辑挂件 - 某类页面内容编辑器 而不是: - 页面结构本体 - 工作区结构内核 也就是说,未来不是: - 页面 = BlockNote 文档 而更接近: - 页面 = kernel 子树 - BlockNote = 某类内容节点的编辑器 ### 6.4 与 AI 的关系 AI 不应直接面对“页面壳”和“前端控件”,而应直接面对 kernel。 长期上 AI 更适合操作: - 节点 - 子树 - 引用边 - 结构索引 - 节点摘要 例如: - 创建节点 - 拆分章节为子树 - 为节点补 refs - 生成 summary 节点 - 把 PDF 章节树挂到 book 节点下 这比“模拟导图 UI 操作”或“模拟 BlockNote 操作”更稳定。 ### 6.5 与 RAG 的关系 RAG 不再只是: - 文本块检索 而应演进为: - 结构索引检索 + 正文证据回查 例如: - 一本书先变成书籍节点 - 再生成章节树 - 再生成章节子树摘要 - 再用节点 refs 指回原始页码、附件、正文块 这样检索时可以: 1. 先命中结构层 2. 再下钻子树 3. 再回查原文证据 这正适合复杂文档。 --- ## 7. 结合 BookRAG 的启发 用户提到的 `BookRAG` 给出的核心启发,不是“做一个导图页面”,而是: > **复杂文档应该先被抽成层级结构索引,再做检索与生成。** 这和 mnote 非常契合。 ### 7.1 书籍对象的建议形态 长期上可以采用: - 一个 `book` 节点 - 一个 canonical 章节树 - 每章是一个 subtree - 每小节是更深层节点 - 节点 refs 指向: - 页码 - PDF - 原文块 - 摘要 - AI 生成说明 ### 7.2 不建议直接复制很多份 chapter mindmap 实体 更好的方式是: - 逻辑上是一棵 canonical tree - 章节导图只是 subtree projection - 需要时再做缓存或派生视图 否则会出现: - 多份结构副本 - 同步成本 - 版本冲突 ### 7.3 这和当前 Rust Mindmap 协议是兼容的 当前 Rust 已经有: - `MindmapTreeNode` - `MindmapOp` - `mindmap_get_subtree` - `mindmap_outline_to_mindmap` 这意味着: - 以树为真相 - 以子树为检索和投影单位 并不是从零开始。 --- ## 8. 这条路线和“主 Mindmap”有什么本质差异 两者差异很大。 ### 8.1 错误路线 错误路线是: - 整个工作区变成一个超级导图页面 - 所有东西都围绕导图控件组织 - UI 形态决定对象语义 ### 8.2 正确路线 正确路线是: - 整个工作区共享一份结构内核 - Mindmap 只是可视化挂件 - 列表、树表、阅读流、搜索结果也都是合法投影 - 对象语义先于 UI 形态存在 --- ## 9. 长期分层建议 ## 9.1 Kernel Layer Rust 内核负责: - typed node - typed edge - subtree query - graph traversal - projection query - 权限 - trace - 版本 - 审计 ## 9.2 Service Layer Rust Web 层负责: - API - SSR 页面壳 - SSE / WS - 结构查询 - AI bridge - projection 请求分发 ## 9.3 Projection Layer 不同前端视图负责: - Sidebar tree projection - 阅读页 projection - Mindmap projection - 搜索 projection - AI 操作 projection ## 9.4 Editor Layer 编辑器只是挂件: - BlockNote - Mindmap canvas - OnlyOffice - 未来别的专用编辑器 它们都不再是系统底座。 --- ## 10. 为什么这条路线更适合替代 BlockNote 世界 因为它不是“再造一个更大的前端编辑器”,而是: - 先把页面结构、对象结构和引用结构收口 - 再让 BlockNote 退化成一个专用内容编辑挂件 长期上,页面不再被定义成: - 一个 block 文档 而更接近: - 一个子树容器 这样未来才可能逐步实现: - 页面结构独立于 BlockNote - 页面中的某些内容节点仍可用 BlockNote 编辑 - 某些结构节点则改用别的编辑/操作方式 这比一次性整体替掉 BlockNote 更现实。 --- ## 11. 风险与约束 ### 11.1 不要把整个 workspace 真存成一条超大 JSON 树 逻辑上统一成一棵树,不等于物理上只能是一条大对象。 长期更合理的是: - 逻辑统一 - 物理分片 - 子树加载 - 局部版本 - 局部缓存 ### 11.2 不要让 Projection 反向定义内核 例如: - Mindmap 控件的数据格式 - BlockNote 的块数据结构 - Sidebar 某次渲染需要的 rows 这些都不能反过来定义 kernel 真相。 ### 11.3 不要过早把所有内容节点都树化成同一种文本节点 结构树适合表达: - 层级 - 目录 - 引用 - 摘要 - 索引 但富文本正文仍然可能需要自己的内容模型。 所以长期更合理的是: - 树/图内核负责结构 - 内容节点负责正文 - 两者通过 typed node 接口连接 --- ## 12. 最终结论 最终结论可以固定成下面这句话: > **mnote 的长期方向不是 Mindmap-first,而是 Tree-First Graph Kernel;Mindmap 只是其中一种挂件、投影和操作器。** 这意味着: - 页面树、文件树、Mindmap、RAG 结构索引、AI 结构操作,本质上都应收口到同一结构内核 - `BlockNote` 不再是系统定义页面的唯一方式 - Rust 最终不只是承接 API 或导图对象,而是承接整个统一结构真相 如果后续继续推进,真正该优先做的不是“先重写导图 UI”,而是: 1. 定义统一 kernel node / edge 模型 2. 定义 subtree / projection / reference 查询协议 3. 让 Sidebar、搜索、AI、Mindmap 开始直接消费 kernel 4. 最后再逐步边缘化 `BlockNote`