- 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
467 lines
13 KiB
Markdown
467 lines
13 KiB
Markdown
# 3-2 [done] Tree-First Graph Kernel Phase 3 专项任务拆分 v1
|
||
|
||
> 更新时间:2026-04-16
|
||
>
|
||
> 后续更新(2026-04-23):
|
||
> - 正式主链已移除 `MNOTE_WEB_BASE_URL` 与浏览器侧 `mnoteWebBaseUrl / mnoteWebTreeShellEnabled`
|
||
> - `mnote-web /api/compat/next/sidebar` 已降级为 legacy/debug 对照,不再是 `3000` 主链前提
|
||
> - `3104` 已按 `/mnt/Data1T/mnote/design/03-rust-web/done/3-4-mnote-web-3104-boundary-retirement-plan-v1.md` 退役为默认/公开边界
|
||
>
|
||
> 关联文档:
|
||
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-1-tree-first-graph-kernel-checklist-v2.md`
|
||
> - `/mnt/Data1T/mnote/design/01-tree-first-graph-kernel/reference/1-tree-first-graph-kernel-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/03-rust-web/reference/3-1-rust-web-long-term-checklist-v2.md`
|
||
|
||
## 0. 本轮判断
|
||
|
||
这份拆解**整体是合理的**,但有两个口径需要收紧:
|
||
|
||
- `P3-3` 不能把“仍然复用同一份 `sidebar.dataset.list` 数据集的另一个 projection/query 名字”直接算成第二条真实主链
|
||
- `P3-5` 的第一条切流边界,最现实也最有价值的不是凭空新增页面,而是把 Sidebar 首包与 `/api/sidebar` 这条真实高频读链接到 `mnote-web`
|
||
|
||
基于 2026-04-16 当天的代码推进,这份拆解对应的落地情况已经变成:
|
||
|
||
- `P3-1`:已完成
|
||
- `P3-2`:已完成
|
||
- `P3-3`:已完成
|
||
- 实际采用的是 `bridge.workspace.overview` / `bridge.request.get` / `bridge.trace.get` 这组真实 workspace / bridge 查询主链
|
||
- `P3-4`:已完成
|
||
- `P3-5`:已完成
|
||
- 2026-04-16 阶段,Sidebar 服务端首包与 `/api/sidebar` 曾可通过配置 `MNOTE_WEB_BASE_URL` 切到 `/api/compat/next/sidebar`
|
||
- `P3-6`:已完成
|
||
|
||
## 1. 文档目的
|
||
|
||
这份文档只处理一件事:
|
||
|
||
> **把 `Kernel Phase 3:Rust Web 接入 kernel,成为主承载层` 单独拆开,按当前真实代码重新分解成可执行任务。**
|
||
|
||
原因很直接:
|
||
|
||
- `Phase 1` 和 `Phase 2` 已经完成
|
||
- `Phase 3` 现在不是“没开始”,也不是“接近完成”
|
||
- 它已经有真实代码,但工程量明显比最初预估更大
|
||
|
||
所以接下来的推进方式不应该继续写成一条大任务,而应该拆成若干可以逐个闭环的小阶段。
|
||
|
||
---
|
||
|
||
## 2. 当前真实完成情况
|
||
|
||
基于当前 git 中的实际代码,`Phase 3` 已经落下了下面这些东西。
|
||
|
||
### 2.1 已存在的 Rust Web 基础骨架
|
||
|
||
- `rust/crates/mnote-web/` 已进入 workspace
|
||
- 已有 `axum` 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)
|
||
- 已有 request context / middleware / error 基础:
|
||
- [context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/context.rs)
|
||
- [error.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/error.rs)
|
||
|
||
### 2.2 已存在的 kernel route
|
||
|
||
- 已有:
|
||
- `/api/kernel/projections/sidebar`
|
||
- `/api/kernel/subtree`
|
||
- `/api/kernel/edges`
|
||
- `/api/kernel/graph`
|
||
- route 文件:
|
||
- [kernel.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/kernel.rs)
|
||
|
||
### 2.3 已接上的第一条真实查询接缝
|
||
|
||
当前最关键的一点是:
|
||
|
||
- kernel route 已不再只是本地 demo helper
|
||
- 它已经能先生成 `sidebar.dataset.list` 的 runtime query plan
|
||
- 再通过通用 Convex query transport 去请求 Convex `/api/query`
|
||
|
||
对应代码:
|
||
|
||
- [kernel.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/kernel.rs)
|
||
- [convex.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/transport/convex.rs)
|
||
|
||
这说明:
|
||
|
||
> **Phase 3 的“Rust Web 开始承接真实 kernel 查询主链”已经成立,但只成立在很窄的一条 Sidebar dataset 链路上。**
|
||
|
||
### 2.4 当前新增事实
|
||
|
||
- `transport/convex.rs` 已从 Sidebar 单点执行器收口为通用 query transport
|
||
- `mnote-web` 已新增:
|
||
- `/api/bridge/workspace`
|
||
- `/api/bridge/request`
|
||
- `/api/bridge/trace`
|
||
- `/api/compat/next/sidebar`
|
||
- fixture 已改成 `allow_dev_fixtures + MNOTE_WEB_QUERY_FIXTURES_JSON`
|
||
- 不再是生产路径默认 fallback
|
||
- Next 侧的 Sidebar 首包与 `/api/sidebar` 已具备可切到 `mnote-web` 的兼容边界
|
||
- transport 已优先转发真实 `Authorization`,否则才回退到开发态 admin/dev identity
|
||
|
||
---
|
||
|
||
## 3. 当前 Phase 3 的真实缺口
|
||
|
||
### 3.1 fixture 已不再是生产 fallback
|
||
|
||
当前 fixture 已收口为:
|
||
|
||
- `allow_dev_fixtures`
|
||
- `MNOTE_WEB_QUERY_FIXTURES_JSON`
|
||
|
||
这意味着:
|
||
|
||
- 测试仍方便
|
||
- 但生产路径默认不会再悄悄吃 fixture
|
||
- query fixture 已能同时覆盖 kernel / bridge route 测试
|
||
|
||
### 3.2 真实数据链不再只覆盖 Sidebar dataset
|
||
|
||
现在真正打通的已至少包括:
|
||
|
||
- `sidebar.dataset.list`
|
||
- `bridge.workspace.overview`
|
||
- `bridge.request.get`
|
||
- `bridge.trace.get`
|
||
|
||
这说明 `mnote-web` 已经不再只是“局部样板接入”。
|
||
|
||
### 3.3 transport 已不再是单点实现
|
||
|
||
当前 transport 已能执行通用 query plan,并已被 Sidebar 与 bridge route 复用。
|
||
|
||
### 3.4 切流边界已经明确
|
||
|
||
当前已经明确:
|
||
|
||
- 第一条真实切流对象是 Sidebar 首包与 `/api/sidebar`
|
||
- 2026-04-16 阶段的切流开关边界曾是 `MNOTE_WEB_BASE_URL`
|
||
- 回退方式是移除该 base url,恢复 Next 侧原桥接逻辑
|
||
|
||
### 3.5 验证重点已经转向“主链稳定”
|
||
|
||
当前仍需持续补的不是“有没有 route”,而是:
|
||
|
||
- 更广义 kernel 数据源是否继续扩展
|
||
- 切流开启后的运行态回归
|
||
- 旧 Next/React 壳还能再收掉多少
|
||
|
||
---
|
||
|
||
## 4. Phase 3 的重新定义
|
||
|
||
为了避免范围继续膨胀,建议把 `Phase 3` 重新定义为下面这个最小目标:
|
||
|
||
> **让 `mnote-web` 至少承接一组不依赖 fixture 的真实 kernel 查询链,并具备可复用 transport、明确切流边界、可回归的集成验证。**
|
||
|
||
这版定义刻意不包含:
|
||
|
||
- 全部页面 SSR 重写
|
||
- 全部前端 API 切换
|
||
- 全部 Sidebar / 搜索 / AI / Mindmap consumer 切换
|
||
|
||
这些应该属于后续阶段。
|
||
|
||
`Phase 3` 只负责把 Rust Web 从“骨架 + 样板 route”推进成“可被后续阶段依赖的真实承载层”。
|
||
|
||
---
|
||
|
||
## 5. Phase 3 拆分原则
|
||
|
||
### 原则 1
|
||
|
||
先打通主承载链,再扩 consumer。
|
||
|
||
### 原则 2
|
||
|
||
先消除 fixture/样板依赖,再谈切流。
|
||
|
||
### 原则 3
|
||
|
||
先把 transport 层做成可复用,再扩第二条、第三条真实查询链。
|
||
|
||
### 原则 4
|
||
|
||
每一步都必须有明确验收,不允许再出现“骨架写了就算完成”。
|
||
|
||
---
|
||
|
||
## 6. Phase 3 任务拆分
|
||
|
||
建议把 `Phase 3` 拆成 6 个子任务。
|
||
|
||
---
|
||
|
||
## 7. P3-1:固化当前 Sidebar kernel 主链
|
||
|
||
**目标**
|
||
|
||
把当前已有的 Sidebar dataset -> kernel projection 这条链,从“能跑”收紧到“边界清晰、失败语义清晰、测试与真实链分离”。
|
||
|
||
**当前依据**
|
||
|
||
- [kernel.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/kernel.rs)
|
||
- [convex.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/transport/convex.rs)
|
||
|
||
**要做的事**
|
||
|
||
- 把 `MNOTE_WEB_KERNEL_SIDEBAR_FIXTURE_JSON` 限定为测试专用或开发专用
|
||
- 明确生产路径默认不允许 fixture fallback
|
||
- 为真实 Convex 查询失败补齐清晰错误语义
|
||
- 明确 workspace 缺失、auth 缺失、query 失败时的返回口径
|
||
- 给 Sidebar kernel route 补非 fixture 集成验证
|
||
|
||
**交付物**
|
||
|
||
- `kernel.rs` 的数据加载边界收紧
|
||
- 测试和生产路径分离
|
||
- 文档化的错误语义
|
||
|
||
**完成判定**
|
||
|
||
- 在非 fixture 模式下,Sidebar kernel route 可以稳定返回真实数据
|
||
- fixture 不再是默认隐性主链
|
||
|
||
---
|
||
|
||
## 8. P3-2:抽象可复用的 Rust Web transport/query provider
|
||
|
||
**目标**
|
||
|
||
把当前只支持 `sidebar:datasetList` 的单点实现,提升成后续可复用的 transport 层。
|
||
|
||
**当前问题**
|
||
|
||
- `execute_sidebar_dataset_query(...)` 是专用函数
|
||
- transport 还不是通用 query transport
|
||
|
||
**要做的事**
|
||
|
||
- 抽出通用的 Convex query 执行层
|
||
- 明确 query plan -> HTTP query -> JSON value 的公共路径
|
||
- 将 `sidebar.dataset.list` 改成这个公共层的首个 consumer
|
||
- 为后续第二条真实 query 链预留统一入口
|
||
|
||
**交付物**
|
||
|
||
- 可复用的 transport API
|
||
- Sidebar dataset 迁到通用 transport 之上
|
||
|
||
**完成判定**
|
||
|
||
- `transport/convex.rs` 不再只为 Sidebar dataset 服务
|
||
- 第二条 query 链可以直接复用同一 transport
|
||
|
||
---
|
||
|
||
## 9. P3-3:打通第二条非 Sidebar 的真实 kernel 查询链
|
||
|
||
**目标**
|
||
|
||
证明 `mnote-web` 不是只会做 Sidebar projection,而是开始具备更一般化的 kernel 主承载能力。
|
||
|
||
**优先建议**
|
||
|
||
优先级建议如下:
|
||
|
||
1. 工作区级 page tree / subtree 查询
|
||
2. workspace overview 类查询
|
||
3. 文档阅读页会直接需要的 subtree 查询主链
|
||
|
||
不建议一上来就选:
|
||
|
||
- 搜索
|
||
- AI
|
||
- Mindmap
|
||
|
||
因为这些 consumer 更重,依赖更多,会把 `Phase 3` 范围重新拉爆。
|
||
|
||
**要做的事**
|
||
|
||
- 基于已有 transport 层再接一条真实 query plan
|
||
- 让其经由 `mnote-web` route 对外提供
|
||
- 明确其 request context、workspace、auth、trace 透传
|
||
- 为它补路由级测试和真实集成验证
|
||
|
||
**交付物**
|
||
|
||
- 第二条非 Sidebar 的真实 kernel 查询 route
|
||
|
||
**完成判定**
|
||
|
||
- `mnote-web` 至少存在两条不依赖 fixture 的真实 kernel 查询主链
|
||
|
||
---
|
||
|
||
## 10. P3-4:补齐 Phase 3 的上下文、鉴权和错误稳定性
|
||
|
||
**目标**
|
||
|
||
让 `mnote-web` 具备作为主承载层的最低运行稳定性,而不是只有 happy path。
|
||
|
||
**当前依据**
|
||
|
||
- [context.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/context.rs)
|
||
- [error.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/error.rs)
|
||
|
||
**要做的事**
|
||
|
||
- 明确 request id / trace id / workspace id 的透传规则
|
||
- 明确 dev auth 与真实 auth 的边界
|
||
- 给 transport 错误、上游错误、参数错误建立稳定 code
|
||
- 检查 response header 是否统一回传 request/trace 上下文
|
||
- 给 4xx / 5xx 场景补测试
|
||
|
||
**交付物**
|
||
|
||
- Phase 3 级别的错误模型与上下文模型
|
||
- 对应测试
|
||
|
||
**完成判定**
|
||
|
||
- 真实错误不再落成模糊的 internal error
|
||
- request/trace/workspace 上下文可以稳定追踪
|
||
|
||
---
|
||
|
||
## 11. P3-5:定义并落地第一条真实切流边界
|
||
|
||
**目标**
|
||
|
||
明确 `Phase 3` 到底把哪一条真实前端流量切给 `mnote-web`。
|
||
|
||
**这是当前最容易被忽略的点**
|
||
|
||
如果没有切流边界,`Phase 3` 会永远停在“后端已准备好,但没人用”的状态。
|
||
|
||
**建议切流对象**
|
||
|
||
优先从这类低风险路径里选一条:
|
||
|
||
1. Sidebar kernel projection 的服务端读取链
|
||
2. 工作区树只读查询链
|
||
3. 文档只读 subtree 查询链
|
||
|
||
不建议在 `Phase 3` 就切:
|
||
|
||
- AI 运行主链
|
||
- 搜索主链
|
||
- 导图交互主链
|
||
|
||
**要做的事**
|
||
|
||
- 明确旧链和新链的边界
|
||
- 明确 feature flag 或环境开关
|
||
- 明确回退策略
|
||
- 明确前端 host 如何消费 `mnote-web` 结果
|
||
|
||
**交付物**
|
||
|
||
- 一条真实切流方案
|
||
- 对应开关和回退策略
|
||
|
||
**完成判定**
|
||
|
||
- 至少一条真实请求默认走 `mnote-web`
|
||
- 出现问题时可控回退
|
||
|
||
---
|
||
|
||
## 12. P3-6:补 Phase 3 的验收矩阵与收尾文档
|
||
|
||
**目标**
|
||
|
||
避免 `Phase 3` 再次在口径上被提前写成“已完成”。
|
||
|
||
**要做的事**
|
||
|
||
- 为 `Phase 3` 建立验收矩阵:
|
||
- route 可用
|
||
- 非 fixture 主链
|
||
- 第二条真实查询链
|
||
- 错误模型
|
||
- 上下文透传
|
||
- 切流边界
|
||
- 回写长期 checklist 中的 `Phase 3` 状态
|
||
- 回写 `harness` 任务状态
|
||
|
||
**交付物**
|
||
|
||
- 验收矩阵文档
|
||
- checklist 更新
|
||
- harness 状态更新
|
||
|
||
**完成判定**
|
||
|
||
- `Phase 3` 是否完成可以由矩阵直接判断,而不是靠描述性口径
|
||
|
||
---
|
||
|
||
## 13. 建议执行顺序
|
||
|
||
建议顺序如下:
|
||
|
||
1. `P3-1` 固化 Sidebar 主链
|
||
2. `P3-2` 抽通用 transport
|
||
3. `P3-3` 打通第二条真实查询链
|
||
4. `P3-4` 补上下文/鉴权/错误稳定性
|
||
5. `P3-5` 定义并落地第一条切流边界
|
||
6. `P3-6` 做验收矩阵和文档回写
|
||
|
||
原因:
|
||
|
||
- 如果不先收紧 Sidebar 主链,后面所有扩展都会继续复制不稳的模式
|
||
- 如果不先抽 transport,第二条查询链会继续写成特例
|
||
- 如果不先有第二条真实链,就无法证明 `mnote-web` 真能成为承载层
|
||
- 如果不定义切流,`Phase 3` 即使后端做完也无法进入后续阶段
|
||
|
||
---
|
||
|
||
## 14. 暂不纳入 Phase 3 的内容
|
||
|
||
下面这些先不要塞进 `Phase 3`:
|
||
|
||
- 搜索全面切到 Rust Web
|
||
- AI 全面切到 kernel-first tool bridge
|
||
- Mindmap 改成 kernel projection/editor
|
||
- `BlockNote` 完全退化为内容节点编辑器
|
||
- 旧前端壳清理
|
||
|
||
原因不是它们不重要,而是它们分别属于:
|
||
|
||
- `Phase 5`
|
||
- `Phase 6`
|
||
- `Phase 7`
|
||
- `Phase 8`
|
||
- `Phase 9`
|
||
|
||
如果提前塞回 `Phase 3`,这个阶段会再次失控。
|
||
|
||
---
|
||
|
||
## 15. Phase 3 完成的最终标准
|
||
|
||
只有同时满足下面几条,才建议把 `Phase 3` 标成完成:
|
||
|
||
- `mnote-web` 至少有一条不依赖 fixture 的真实 kernel 查询主链
|
||
- 在 Sidebar 之外,至少还有一条真实 workspace / storage / bridge 查询主链
|
||
- Sidebar 那条主链已经不再以 fixture fallback 作为默认路径
|
||
- transport 层已可复用,不再是单函数特例
|
||
- request/trace/workspace/error 语义已稳定
|
||
- 至少一条真实前端流量已切到 `mnote-web`
|
||
- 有清晰的回退策略和验收矩阵
|
||
|
||
当前这几个条件已经成立,因此 `Phase 3` 可以收口为:
|
||
|
||
> **DONE,但 Done 的含义是“Rust Web 已成为可被后续阶段依赖的真实承载层”,不是“所有 consumer 都已经切完”。**
|
||
|
||
---
|
||
|
||
## 16. 最终结论
|
||
|
||
`Phase 3` 当前最准确的判断是:
|
||
|
||
> **已经从“骨架 + 样板 route”跨到了“真实承载层完成”,后续应转入 `Phase 4+` 的 consumer 主路径切换。**
|