Files
mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md
T
Agent Board b798f628ee chore: land tree view-state, vault, Pi module split, and repo hygiene
Persist PageTree expand state via control-plane view-state and align
chevron/DOM with restored expansion; keep Sidex-style shallow page-tree
scan and drop the unused recursive scanner that only added cargo noise.

Add password vault workbench routes/runtime/skill/CLI, split page_ai_pi
into a module package, and retire Hermes/ACP/OpenHub recycle + root
harness evidence from the index while gitignoring recycle and local
diag dumps.

Archive superseded design/bugs docs under old/, point architecture at
ARCHITECTURE.md, and refresh smokes for Pi S1–S7, vault, and editor
regressions so the working tree can stay clean.
2026-07-21 05:13:05 +08:00

722 lines
15 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.
# 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 KernelMindmap 只是其中一种挂件、投影和操作器。**
这意味着:
- 页面树、文件树、Mindmap、RAG 结构索引、AI 结构操作,本质上都应收口到同一结构内核
- `BlockNote` 不再是系统定义页面的唯一方式
- Rust 最终不只是承接 API 或导图对象,而是承接整个统一结构真相
如果后续继续推进,真正该优先做的不是“先重写导图 UI”,而是:
1. 定义统一 kernel node / edge 模型
2. 定义 subtree / projection / reference 查询协议
3. 让 Sidebar、搜索、AI、Mindmap 开始直接消费 kernel
4. 最后再逐步边缘化 `BlockNote`