416 lines
11 KiB
Markdown
416 lines
11 KiB
Markdown
# [recycle] mnote Rust 内核替换总路线图 v1
|
||
|
||
> 更新时间:2026-04-15
|
||
>
|
||
> 关联文档:
|
||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-plan.md`
|
||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-phase-checklist.md`
|
||
> - `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-missing-targets.md`
|
||
> - `/mnt/Data1T/mnote/ARCHITECTURE.md`
|
||
|
||
## 1. 目标定义
|
||
|
||
本路线图对应的最终目标只有一句话:
|
||
|
||
> **用 Rust 内核取代当前 TypeScript/Next route 主导的业务执行面,让 Web、CLI、AI 共享同一套 Rust Command / Query / Tool 内核。**
|
||
|
||
这里包含三个同时成立的条件:
|
||
|
||
- Rust 成为唯一业务执行平面
|
||
- 绝大部分核心能力都能通过 CLI 调用
|
||
- AI 编辑能力建立在与 CLI 同源的 Rust 工具面上
|
||
|
||
如果只完成其中一部分,都不能算“Rust 内核已经替换原有内核”。
|
||
|
||
---
|
||
|
||
## 2. 当前阶段判断
|
||
|
||
当前仓库已经完成的是:
|
||
|
||
- 单仓收口
|
||
- Rust workspace 落位
|
||
- P0 crate 与核心设计文档落位
|
||
- 首批 bridge 协议接缝
|
||
- 首批日志与事件落账
|
||
|
||
当前仓库还没有完成的是:
|
||
|
||
- Rust 真实执行入口
|
||
- `mnote-cli`
|
||
- 全域能力域建模
|
||
- AI/CLI 共用 Tool 面
|
||
- 旧 TS 执行面的系统性退役
|
||
|
||
因此当前阶段应定义为:
|
||
|
||
> **Phase 0 完成,Phase 1 即将开始。**
|
||
|
||
其中:
|
||
|
||
- `Phase 0` = 单仓收口 + 协议奠基
|
||
- `Phase 1` 以后才是“真正的内核替换”
|
||
|
||
---
|
||
|
||
## 3. 总体迁移原则
|
||
|
||
整个替换过程必须遵守下面六条原则。
|
||
|
||
### 3.1 Web 不再承载业务真规则
|
||
|
||
Next route 可以保留 transport、auth、session、streaming、SSR/BFF 职责,但不再长期承载核心业务执行规则。
|
||
|
||
### 3.2 CLI 与 AI 必须共用同一执行面
|
||
|
||
不能出现:
|
||
|
||
- CLI 走一套实现
|
||
- AI 走一套实现
|
||
- Web 再走第三套实现
|
||
|
||
最终只能保留一套 Rust 内核,三种入口共享。
|
||
|
||
### 3.3 Convex 继续是事实层,不是业务规则层
|
||
|
||
Convex 继续负责主事实保存,但对象规则、命令语义、查询聚合、索引、工具协议应逐步收回 Rust。
|
||
|
||
### 3.4 先做执行面替换,再做旧面退役
|
||
|
||
不能先删旧链路再补 Rust,也不能长期停留在双内核并行。
|
||
|
||
正确顺序是:
|
||
|
||
1. 建立 Rust 执行链
|
||
2. 双入口对齐
|
||
3. 完成回归
|
||
4. 退役旧 TS 业务执行逻辑
|
||
|
||
### 3.5 先覆盖高频主链路,再覆盖对象域
|
||
|
||
优先级应是:
|
||
|
||
1. 页面系统
|
||
2. 块系统
|
||
3. Sidebar / 搜索 / 索引
|
||
4. AI 写入工具面
|
||
5. Mindmap / OnlyOffice / Media / Table
|
||
|
||
### 3.6 每一阶段都必须有割接标准
|
||
|
||
每个阶段都要明确:
|
||
|
||
- 哪些功能已由 Rust 接管
|
||
- 哪些 TS route 仍是临时面
|
||
- 哪些旧实现可退役
|
||
|
||
---
|
||
|
||
## 4. 分阶段路线
|
||
|
||
## Phase 1:建立真实 Rust 执行入口
|
||
|
||
目标:
|
||
|
||
- 在主仓内建立最小 Rust bridge/runtime
|
||
- Web route 能调用真实 Rust 执行器
|
||
- 不再只是在 TypeScript 中构造 Rust 风格 request
|
||
|
||
优先覆盖:
|
||
|
||
- `documents.meta`
|
||
- `documents.content`
|
||
- `documents.save`
|
||
- `documents.title`
|
||
- `documents.options`
|
||
- `documents.stats`
|
||
- `sidebar.dataset.list`
|
||
- `search.documents`
|
||
|
||
阶段产出:
|
||
|
||
- `/mnt/Data1T/mnote/rust/bridge/`
|
||
- 最小 runtime executor
|
||
- Web -> Rust -> Convex 的真实样板链
|
||
|
||
阶段完成标准:
|
||
|
||
- 至少 1 条读链和 2 条写链真实经过 Rust 执行
|
||
- 对应 TS route 不再直接持有业务拼装逻辑
|
||
|
||
## Phase 2:引入 `mnote-cli` 并冻结 JSON 协议
|
||
|
||
目标:
|
||
|
||
- 把 CLI 变成一等入口
|
||
- 定义稳定的 machine-readable 输出
|
||
- 为后续 AI 共用工具面打基础
|
||
|
||
首批 CLI 面:
|
||
|
||
- `page`
|
||
- `block`
|
||
- `search`
|
||
- `sidebar`
|
||
- `tool`
|
||
|
||
阶段产出:
|
||
|
||
- `rust/crates/mnote-cli/`
|
||
- 统一 exit code 约定
|
||
- `--json` 输出契约
|
||
- `dry-run` / `validate-only` 基础能力
|
||
|
||
阶段完成标准:
|
||
|
||
- 核心页面和块操作能脱离浏览器完成
|
||
- CLI 与 Web 调用同一 Rust 执行面
|
||
|
||
## Phase 3:页面系统 Rust 化
|
||
|
||
目标:
|
||
|
||
- 页面创建、移动、复制、删除、恢复、回收站等能力收口到 Rust
|
||
- 页面树、父子关系、排序、引用更新不再由 TS route 零散实现
|
||
|
||
优先覆盖:
|
||
|
||
- `documents.create`
|
||
- `documents.move`
|
||
- `documents.delete`
|
||
- `documents.restore`
|
||
- `documents.duplicate`
|
||
- `documents.empty-trash`
|
||
- `documents.copy-tree`
|
||
|
||
阶段完成标准:
|
||
|
||
- 页面生命周期操作统一走 Rust command
|
||
- 旧 TS route 只保留 transport 包装
|
||
|
||
## Phase 4:块系统 Rust 化
|
||
|
||
目标:
|
||
|
||
- 把 BlockNote 正文相关的结构化编辑命令真正变成 Rust 内核能力
|
||
- AI/CLI 可直接调用块操作,不依赖浏览器交互细节
|
||
|
||
优先覆盖:
|
||
|
||
- `blocks.get`
|
||
- `blocks.patch`
|
||
- `blocks.move`
|
||
- `blocks.embed`
|
||
- `doc_insert_blocks`
|
||
- `doc_replace_range`
|
||
|
||
阶段完成标准:
|
||
|
||
- Rust 拥有稳定的 block ops 协议
|
||
- Web 编辑器只负责快照采集、渲染与交互
|
||
|
||
## Phase 5:搜索、索引与派生视图 Rust 化
|
||
|
||
目标:
|
||
|
||
- 把搜索、排序、snippet、Sidebar 数据集聚合统一移入 Rust
|
||
- 建立索引重建和派生视图回放能力
|
||
|
||
优先覆盖:
|
||
|
||
- `search.documents`
|
||
- `search.recent`
|
||
- `sidebar.dataset.list`
|
||
- 索引重建与校验命令
|
||
|
||
阶段完成标准:
|
||
|
||
- TS route 不再做核心召回和 ranking
|
||
- `index-fts` 真正进入产品主路径
|
||
|
||
2026-04-15 Phase 5 第一刀补记:`search.documents`、`search.recent`、`sidebar.dataset.list` 已补齐到主仓 Rust query/runtime 主链。`rust/crates/core-protocol` 新增 `SearchDocuments/SearchRecent` 契约,`storage-convex-bridge` 新增 query name -> Convex function 映射,`bridge-runtime` 现同时支持 query plan 输出与“携带原始 dataset 时直接在 Rust 内执行并返回 result”。其中 `search.documents` 的召回后排序、snippet、高亮、OCR 待补队列决策已迁入 `rust/crates/index-fts` 的 `evaluate_search_documents`;`/api/search/documents` route 现仅保留参数归一化、Convex 原始数据拉取与 HTTP 回传,不再持有标题/正文/思维导图/表格/附件的打分合并逻辑。`/api/sidebar` 也已改为先经 Rust runtime 生成 `sidebar.dataset.list` plan,再通过统一 query transport 调用 `sidebar:datasetList`,不再只是挂一个 queryName 元信息。
|
||
|
||
## Phase 6:AI 与 CLI 共用 Rust Tool 面
|
||
|
||
目标:
|
||
|
||
- 让 AI 直接调用 Rust tool protocol
|
||
- Web 中的 AI Agent 只成为对话和流式展示层
|
||
|
||
能力要求:
|
||
|
||
- `Tool` 注册表
|
||
- 统一权限与对象目标
|
||
- 统一错误码
|
||
- 统一审计
|
||
- `dry-run` / `validate-only` / `explain-plan`
|
||
|
||
阶段完成标准:
|
||
|
||
- AI 与 CLI 调用同一 Tool 面
|
||
- AI 编辑结果可追踪到 command、event、trace
|
||
|
||
2026-04-15 Phase 6 补记:已把统一观测面补进 Rust `Tool` 注册表与 `bridge-runtime`。当前 `bridge_request_get`、`bridge_trace_get`、`bridge_command_get` 三条观测查询,以及 `event_replay`、`index_rebuild` 两条恢复/重建任务,已经成为 Rust 正式能力面;`/api/bridge/request`、`/api/bridge/trace` 也已改为先经 Rust runtime 生成 query plan,再由 TS 仅做 Convex transport。后续 CLI 与 AI 若要稳定运行,必须以这组能力为统一回查/恢复前置,不再允许各入口各自手写 trace 查询与索引恢复脚本。
|
||
|
||
## Phase 7:对象域 adapter 接入
|
||
|
||
目标:
|
||
|
||
- 在不改变当前前端形态的前提下,把对象域执行层移入 Rust adapter
|
||
|
||
优先对象域:
|
||
|
||
- `adapter-mindmap`
|
||
- `adapter-onlyoffice`
|
||
- 后续再扩展 media / table
|
||
|
||
阶段完成标准:
|
||
|
||
- Mindmap 与 OnlyOffice 都可由 CLI / AI 直接操作核心对象能力
|
||
- 前端 route 不再是对象域业务真入口
|
||
|
||
## Phase 8:旧内核退役与总割接
|
||
|
||
目标:
|
||
|
||
- 明确哪些旧 TS route 只剩 transport
|
||
- 明确哪些旧业务实现可删除
|
||
- 正式宣布 Rust 成为唯一业务执行平面
|
||
|
||
阶段完成标准:
|
||
|
||
- Web、CLI、AI 全部指向同一 Rust 内核
|
||
- 核心域不再存在第二套业务执行实现
|
||
|
||
2026-04-15 Phase 8 补记:当前主仓已新增 `/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md` 作为最终割接文档。后续 Phase 8 不再接受“按感觉判断是否可以退役”的说法,而统一按该文档中的四组 gate 执行:页面/块/查询主链全部 Rust 持有,对象域只剩 transport 壳,AI/CLI 共用同一 Tool 面,以及旧 TS 兼容接口完成物理退役或明确降级。
|
||
|
||
---
|
||
|
||
## 5. 建议的切换顺序
|
||
|
||
为了降低风险,建议按下面顺序切换,而不是全面铺开。
|
||
|
||
### 批次 A:文档基础链
|
||
|
||
- `documents.meta`
|
||
- `documents.content`
|
||
- `documents.save`
|
||
- `documents.title`
|
||
- `documents.options`
|
||
- `documents.stats`
|
||
|
||
### 批次 B:页面结构链
|
||
|
||
- `documents.create`
|
||
- `documents.move`
|
||
- `documents.delete`
|
||
- `documents.restore`
|
||
- `documents.duplicate`
|
||
- `documents.copy-tree`
|
||
|
||
### 批次 C:块编辑链
|
||
|
||
- `blocks.get`
|
||
- `blocks.patch`
|
||
- `blocks.move`
|
||
- `blocks.embed`
|
||
|
||
### 批次 D:查询聚合链
|
||
|
||
- `sidebar.dataset.list`
|
||
- `search.documents`
|
||
- `search.recent`
|
||
|
||
### 批次 E:AI/CLI 工具链
|
||
|
||
- `doc_get`
|
||
- `doc_find`
|
||
- `doc_insert_blocks`
|
||
- `doc_replace_range`
|
||
- `slash_run`
|
||
|
||
### 批次 F:对象域链
|
||
|
||
- Mindmap
|
||
- OnlyOffice
|
||
- Media
|
||
- Table
|
||
|
||
---
|
||
|
||
## 6. 每阶段统一验收口径
|
||
|
||
无论哪个阶段,验收都应统一看下面六项。
|
||
|
||
### 6.1 执行入口是否真的进了 Rust
|
||
|
||
不是“TS 构造了 Rust 风格对象”,而是“Rust 真正执行了这条链”。
|
||
|
||
### 6.2 Web/CLI/AI 是否同源
|
||
|
||
如果一个能力还存在两套或三套实现,就不算完成。
|
||
|
||
### 6.3 是否具备 JSON 级输出与错误码
|
||
|
||
没有稳定 JSON 和错误码,就无法支撑 CLI 与 AI。
|
||
|
||
### 6.4 是否具备审计与回放
|
||
|
||
没有 command/event/trace,就无法长期稳定运行。
|
||
|
||
这里的“具备”不是指只落了一批日志表,而是至少同时满足:
|
||
|
||
- 任一写链都能回查 `request_id`、`trace_id`、`command_id`
|
||
- 命令、事件、冲突、失败态使用统一状态语义
|
||
- 至少有一条正式的 `event_replay` / `index_rebuild` 命令可被 CLI / AI / Web 复用
|
||
- TS route 不再私有维护第二套排障与恢复入口
|
||
|
||
### 6.5 是否补了自动化验证
|
||
|
||
每阶段都必须至少补:
|
||
|
||
- Rust 单测
|
||
- Web smoke
|
||
- 必要时的浏览器回归
|
||
- 对应 CLI smoke
|
||
|
||
### 6.6 是否明确了可退役旧面
|
||
|
||
必须显式标注:
|
||
|
||
- 哪些 TS 逻辑只剩壳
|
||
- 哪些逻辑仍是临时态
|
||
- 哪些代码已允许删除
|
||
|
||
---
|
||
|
||
## 7. 风险与防漂移要求
|
||
|
||
整个路线最容易失败的点有四个。
|
||
|
||
### 7.1 长期停留在“桥接完成即算完成”
|
||
|
||
这会导致项目永远停留在半替换状态。
|
||
|
||
### 7.2 CLI 迟迟不建立
|
||
|
||
如果不尽早建立 CLI,AI 最终还是会绕回 Web 私有逻辑。
|
||
|
||
### 7.3 对象域长期例外化
|
||
|
||
Mindmap、OnlyOffice、Media、Table 如果一直被当例外处理,最终不会形成统一内核。
|
||
|
||
### 7.4 旧 TS 执行面没有退役时点
|
||
|
||
如果不定义退役清单,旧逻辑会持续存活并反向污染新内核。
|
||
|
||
---
|
||
|
||
## 8. 一句话结论
|
||
|
||
这条路线不是“继续补几条 bridge”就能结束,而是要完成一次完整的执行面替换:
|
||
|
||
> **先把 Rust 变成真实执行器,再把 CLI 变成一等入口,最后让 AI 与 Web 共同收口到这套 Rust 内核。**
|
||
|
||
在这三个条件同时成立之前,都还不能宣布“Rust 内核已经替换原有内核”。
|