Files
mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md
T
lix-2026 5f97800489 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
2026-05-23 23:38:42 +08:00

15 KiB
Raw Blame History

1 [reference] Tree-First Graph 内核方案 v1

更新时间:2026-04-22

当前状态:reference。本文是 tree-first graph kernel 的长期架构边界,不是当前可直接执行的 checklist;执行入口见 design/01-tree-first-graph-kernel/process/1-8-mvp-post-process-execution-order-v1.md

当前优先级入口:

  • /mnt/Data1T/mnote/design/01-05-current-priority-overview.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 更像重操作壳

当前:

同时承担:

  • 内嵌块
  • 独立页
  • 工具栏
  • 右键菜单
  • 导航器
  • 缩略图
  • 本地全屏视图

这说明它当前的本质更接近:

  • 一个前端重交互操作层

而不是:

  • 一个稳定、极简、内核级结构模型

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 KernelMindmap 只是其中一种挂件、投影和操作器。

这意味着:

  • 页面树、文件树、Mindmap、RAG 结构索引、AI 结构操作,本质上都应收口到同一结构内核
  • BlockNote 不再是系统定义页面的唯一方式
  • Rust 最终不只是承接 API 或导图对象,而是承接整个统一结构真相

如果后续继续推进,真正该优先做的不是“先重写导图 UI”,而是:

  1. 定义统一 kernel node / edge 模型
  2. 定义 subtree / projection / reference 查询协议
  3. 让 Sidebar、搜索、AI、Mindmap 开始直接消费 kernel
  4. 最后再逐步边缘化 BlockNote