Files
mnote/design/03-rust-web/done/3-2-tree-first-graph-kernel-phase3-task-breakdown-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

467 lines
13 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.
# 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 3Rust 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 主路径切换。**