diff --git a/AGENTS.md b/AGENTS.md index 96cd75df..bce55ac2 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -9,13 +9,13 @@ - 前端主路径应消费稳定 projection,不应在 UI 层重新拼出第二份对象真相。 - Next `documents/page` 读取主链已优先消费 Rust `mnote.page_aggregate.v1` 快照;TS `page-aggregate-builder` 仅保留为 fallback / adapter,不再把“前端手工拼 `meta + content`”描述为当前主路径。 - `3000` 当前主壳已接入 Rust Web `/api/tree/events` 的 snapshot / delta / resync consumer,并已有 browser smoke 验证;后续收口重点是统一 live cache 与减少补偿链,而不是把它描述成“还没接 live stream”。 -- 文档页默认主编辑器已切到页面内 `leptos-tiptap` island;`BlockNote` 当前是 fallback / 对照链,不再代表默认主编辑器方向。 +- 文档页默认主编辑器已切到页面内 `leptos-tiptap` island;`BlockNote` 已退出文档页默认主路径,只保留为历史参考实现 / 对照材料。 - 当前最优先的架构收口不是继续扩编辑器 UI,而是 `Page Aggregate`、`tree command cutover`、`tree realtime event stream` 三条主线。 ## 组件定位 - `leptos-tiptap` island 是当前文档页默认主编辑区 runtime,但不是系统事实源。 -- `BlockNote` 是迁移期 fallback / 对照编辑器,不是系统事实源。 +- `BlockNote` 是历史参考实现 / 对照材料,不再是运行时系统组件、默认回退编辑器或系统事实源。 - `Mindmap` 是 `tree-first graph` 的一种视图和编辑挂件,不是对象真相层。 - `OnlyOffice` 是独立页面型编辑器,不直接嵌入 `BlockNote` 画布;正文中通常通过附件块跳转进入。 diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 92d8e7b7..3fb62c85 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -18,7 +18,7 @@ 2. `Convex` 继续保留为当前自托管存储 / 实时 / 文件协作底座 3. `mnote-web` 是当前 Rust Web 主执行面,负责 3000 gateway、server-first shell、query / command / projection / transport 与 realtime stream;Next App Router 已降为 legacy compat / island bundle source,不再是当前主入口 4. 文档页默认主编辑器已切到页面内 `leptos-tiptap` island -5. `BlockNote` 当前保留为 fallback / 对照链,不再代表默认主编辑器方向 +5. `BlockNote` 已退出文档页默认主路径,仅作为历史参考实现 / 对照材料保留 一句话收口: @@ -82,16 +82,15 @@ ### 4.1 入口 -- `/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/page/route.ts` - `/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/page-aggregate-loader.ts` - `/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/documents/[id]/page.tsx` 当前文档页读取主链已经不再由页面入口手工拼若干独立字段,而是: -1. Next `GET /api/documents/page` 优先请求 Rust `/api/page-aggregate/:id` -2. 若返回可信的 `mnote.page_aggregate.v1` 快照,则直接作为 `PageAggregateProjection` -3. 只有在 snapshot 不可用或不可信时,才回退到 TS builder 组装 fallback projection -4. 页面入口与 `DocumentContent` 都消费这同一份聚合结果 +1. 页面 SSR 入口通过 `page-aggregate-loader.ts` 直接请求 Rust `/api/page-aggregate/:id` +2. `DocumentContent` 的内容重试补拉也直接请求同一条 `/api/page-aggregate/:id` 正式读链 +3. 读取主链不再回退到 TS builder;snapshot 不可用或不可信时直接显式失败 +4. Next `/api/documents/page` 已退场为明确 `410` 的 compat 边界,不再参与文档页运行时主路径 对应聚合类型定义: @@ -113,11 +112,7 @@ - `leptos_tiptap_island` -调试桥仍保留: - -- `leptos_tiptap_iframe_debug` - -兼容回退仍保留: +文档页主路径已不再暴露显式 debug host 选择;历史 `iframe_debug` 宿主仅剩源码参考,不再参与页面 host 选择面。 - `blocknote` @@ -135,12 +130,12 @@ ### 4.5 BlockNote 的当前位置 -- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocknote-editor.tsx` +- `/mnt/Data1T/mnote/recycle/wolai-frontend/src/components/editor/blocknote-editor.tsx` -`BlockNote` 当前仍保留,但其定位已变成: +`BlockNote` 当前仍保留回收副本,但其定位已变成: -- fallback / 对照链 -- 迁移期保险丝 +- 历史参考实现 +- 对照材料 / 调试素材 而不是默认主编辑器方向。 @@ -160,7 +155,7 @@ 1. Rust 侧虽已提供最小 `Page Aggregate` snapshot,但页面设置、页头标题与 AI 写入口还没有完整闭环到同一组聚合真相 2. 标题 / 正文 / 页面设置虽已开始收口到 `page.*` family,但 projection 回流与运行时语义仍未完全统一 -3. 客户端仍保留 fallback builder、preferred sidebar snapshot 与本地 aggregate state reducer,说明页面域单一真源仍在推进中 +3. 客户端仍保留 preferred sidebar snapshot 与本地 aggregate state reducer,说明页面域单一真源仍在推进中 因此当前正确表述应是: @@ -217,6 +212,10 @@ > **树域 realtime 主链由 Rust Web `/api/tree/events` 持有,前端只消费稳定 stream contract 与 projection。** +补充: + +> **`3000` 主壳当前已不再通过 `/api/tree/projections/*` 额外维护第二条 runtime live fallback;snapshot / delta / resync 直接消费 `/api/tree/events` 载荷。** + ## 7. Mindmap 与 OnlyOffice ### 7.1 Mindmap diff --git a/design/01-05-current-priority-overview.md b/design/01-05-current-priority-overview.md index 3ad51b22..e8502b27 100644 --- a/design/01-05-current-priority-overview.md +++ b/design/01-05-current-priority-overview.md @@ -38,7 +38,7 @@ - 文档页读取主链已优先消费 Rust `mnote.page_aggregate.v1` 快照 - 标题单一真源与页面写链都已经开始收口到 `page.*` family - 但页面设置运行时语义、页头标题回流与 AI 设置面仍未完全闭环 -- TS fallback / 页面本地 aggregate state 仍说明页面域尚未完全统一 +- 页面本地 aggregate state 与页头/子树补偿链仍说明页面域尚未完全统一;TS builder 已退出 runtime 主链 ### 2.2 Tree Command Cutover diff --git a/design/02-convex-rust-long-term-architecture/process/2-tree-first-graph-convex-rust-long-term-architecture-v1.md b/design/02-convex-rust-long-term-architecture/process/2-tree-first-graph-convex-rust-long-term-architecture-v1.md index cc7ead33..09cc9831 100644 --- a/design/02-convex-rust-long-term-architecture/process/2-tree-first-graph-convex-rust-long-term-architecture-v1.md +++ b/design/02-convex-rust-long-term-architecture/process/2-tree-first-graph-convex-rust-long-term-architecture-v1.md @@ -334,7 +334,7 @@ Rust Web 不是第二套业务内核。 - `documents.restore` - `documents.purge` -其中 `create / rename / move` 已进一步收成共享 `tree-command-client`,并被 Sidebar、DocumentContent、CustomSideMenu 等主入口复用。 +其中 `create / rename / move` 已进一步收成共享 `tree-command-client`,并被 Sidebar、DocumentContent 等主入口复用;`CustomSideMenu` 已退到 `recycle/` 历史参考区。 ### 6.1.5 Rust Web 正式实时树事件流已经有方案文档,但还不是运行中主链 @@ -397,7 +397,7 @@ Rust Web 不是第二套业务内核。 当前相关 lint 均为 `0 error`,但仍保留一些历史 warning,主要集中在: - `sidebar.tsx` -- `CustomSideMenu.tsx` +- `recycle/wolai-frontend/src/components/editor/menus/CustomSideMenu.tsx` 这些不是本批必须修复的主链 bug,但后续仍应继续压缩。 diff --git a/design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md b/design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md new file mode 100644 index 00000000..3124857f --- /dev/null +++ b/design/03-rust-web/process/3-15-runtime-fallback-retirement-checklist-v1.md @@ -0,0 +1,155 @@ +# 3-15 [process] Runtime Fallback 退场 Checklist v1 + +> 更新时间:2026-05-09 +> +> 关联: +> - `/mnt/Data1T/mnote/ARCHITECTURE.md` +> - `/mnt/Data1T/mnote/design/01-05-current-priority-overview.md` +> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-1-rust-web-long-term-checklist-v2.md` +> - `/mnt/Data1T/mnote/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md` +> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md` +> - `/mnt/Data1T/mnote/design/05-editor-mainline/process/5-6-page-aggregate-alignment-checklist-v1.md` +> - `/mnt/Data1T/mnote/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md` + +## 1. 目标 + +这份 checklist 只回答一件事: + +> **把已经不该继续充当系统组件的 runtime fallback、compat、legacy 与对照链,尽快退出主路径。** + +本轮采用激进退场口径: + +- 能退场的先退场 +- 退场对象同时退出运行时、默认入口与活跃设计口径 +- `/mnt/Data1T/mnote/recycle` 只保留参考物,不再参与系统主路径 + +## 2. 主路径白名单 + +下面这些属于必须保活的主路径: + +- [x] 文档页打开链继续可用 +- [x] Sidebar 继续可用 +- [x] `/api/tree/events` realtime 主链继续可用 +- [x] 页面标题保存继续可用 +- [x] 页面设置保存继续可用 +- [x] 正文保存继续可用 + +下面这些不再享有默认兼容资格,可直接进入退场名单: + +- [x] `BlockNote` fallback / 对照链 +- [x] AI provider 直连分支(`Hermes` / `Codex` / 旧 orchestrator compat) +- [x] legacy Next compat / alias / debug 壳 +- [x] TS page aggregate builder fallback +- [x] 仍以旧 owner / 旧 fallback 作为默认系统组件的活跃文档表述 + +## 3. 总原则 + +- [x] 不再把“开发态”作为保留 fallback 的理由 +- [x] 不再把“以后可能参考”作为继续挂在主路径上的理由 +- [x] 凡移入 `recycle/` 的对象,都必须先断开主路径 import / route / fallback 选择 +- [x] 主路径缺口优先补 Rust-first 正式链,不恢复 legacy fallback +- [x] 次要入口允许直接 404 / 410 / 501,不再静默降级 + +## 4. 第一波:立即退场 + +### 4.1 `BlockNote` fallback / 对照链 + +- [x] 删除页面壳里“显式切回 BlockNote”的默认入口 +- [x] 删除 `leptos-tiptap` host 中仅用于切回 `BlockNote` 的 fallback 触发链 +- [x] 把 `BlockNote` 从“系统默认可退回编辑器”降为 `recycle` 参考实现 +- [x] 活跃设计稿中不再把 `BlockNote` 写成系统 fallback,只允许写成历史对照链 + +### 4.2 AI provider 直连分支 + +- [x] 删除 Next `/api/ai-agent/run` 中 `provider=codex` 直连分支 +- [x] 删除 Next `/api/ai-agent/run` 中 `provider=hermes` 直连分支 +- [x] 删除 Rust `compat` 中代理到 legacy Next AI route 的优先分支 +- [x] 删除 Rust `compat` 中 direct Hermes 分支 +- [x] 删除 Rust `compat` 中 document AI orchestrator fallback 分支 +- [x] 统一只保留 `mnote-cli` host 作为默认主执行入口 +- [x] 次要 provider 请求改为明确失败,不再静默降级 + +### 4.3 legacy Next compat / alias / debug 壳 + +- [x] 删除 `/api/mnote-web/stream` 这类 tree stream compat alias +- [x] 删除 `legacy_next_proxy` 默认 fallback +- [x] 删除仅为 legacy Next upstream 保留的 route fallback +- [x] 删除默认可见 debug shell / compat shell 入口 +- [x] 仅在明确内部调试需要时,才允许保留隔离后的 debug 文件到 `recycle/` + +## 5. 第二波:主链清障后退场 + +### 5.1 `page aggregate` TS fallback + +- [x] 删除 `/api/documents/page` 读链里的 TS builder fallback +- [x] 文档页读取只保留 Rust `/api/page-aggregate/:id` 正式快照 +- [x] snapshot 不可用时直接显式失败,不再组装 fallback projection +- [x] 活跃设计稿不再写“Rust-first + TS fallback 混合态”,改成单一路径 + +### 5.2 页面域本地兼容状态 + +- [x] 识别 `page aggregate client state` 中仅为旧链兜底存在的字段 +- [x] 删除标题 / 页面设置 / 正文之间的兼容性双轨状态 +- [x] 删除只服务旧 fallback editor host 的状态同步分支 +- [x] 页面域只保留围绕正式 `page.*` command family 的状态回流 + +### 5.3 tree realtime / sidebar 补偿链 + +- [x] 删除 preferred snapshot 选择链中只为旧链存在的补偿分支 +- [x] 删除 Sidebar / page subtree / filetree 中旧 snapshot 回闪兜底 +- [x] `3000` 主壳只保留 `/api/tree/events` snapshot + delta + resync 主链 +- [x] 不再为 legacy route 额外维护第二条 live cache 语义 + +## 6. 第三波:统一归档到 `recycle/` + +### 6.1 设计稿与说明 + +- [x] 将已退场实现对应的设计稿移到 `design/old/` 或 `recycle/design/` +- [x] 活跃 `process/` 文档移除对已退场 runtime 的默认依赖描述 +- [x] `ARCHITECTURE.md` / `AGENTS.md` 不再把退场对象写成系统组件 + +### 6.2 参考实现与脚本 + +- [x] 将退场 runtime 的参考代码移动到 `recycle/` 对应目录 +- [x] 将只服务旧链的 smoke / fixture / helper 脚本移到 `recycle/` +- [x] 清除主路径中对这些参考实现的 import、route 注册和 UI 入口 + +## 7. 执行顺序 + +- [x] 先完成第一波:砍掉次要入口默认资格 +- [x] 再完成第二波:清掉主路径底下的假单一路径 +- [x] 最后完成第三波:统一归档文档、脚本和参考代码 + +## 8. 验收标准 + +### 8.1 必须成立 + +- [x] 文档页仍能打开 +- [x] Sidebar 仍能使用 +- [x] tree realtime 主链仍能工作 +- [x] 标题保存、页面设置保存、正文保存仍能工作 +- [x] 默认主路径不再出现“切回 legacy / fallback / compat”按钮或自动分支 + +### 8.2 必须消失 + +- [x] 默认运行时不再自动触发 `BlockNote` fallback +- [x] 默认 AI 运行时不再直连 `Hermes` / `Codex` / 旧 orchestrator compat +- [x] 默认 gateway 不再把 legacy Next 当作未迁路径的总兜底 +- [x] `/api/documents/page` 不再在 runtime 中组装 TS fallback projection + +### 8.3 允许接受 + +- [x] 次要入口直接报错 +- [x] 历史 debug 壳直接下线 +- [x] 某些只服务旧链的测试暂时删除后再按新主链重建 + +## 9. 禁止项 + +- [x] 不以“先保留一下,以后可能有用”为理由继续保活 fallback +- [x] 不把已移入 `recycle/` 的代码继续通过主路径 import 回来 +- [x] 不再新增任何新的 compat / fallback / legacy route +- [x] 不通过文档口径美化来掩盖 runtime 仍依赖 fallback 的事实 + +## 10. 一句话收口 + +> **这轮不是“继续整理兼容层”,而是“把不再属于系统组件的 fallback 全部赶出主路径,只保留主路径白名单”。** diff --git a/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md b/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md index 28986662..b2b5087c 100644 --- a/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md +++ b/design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md @@ -231,7 +231,7 @@ Rust Web 负责: - 首页不能再依赖 3104 实验壳 - `3000` 主入口必须可稳定进入 `/auth` 或文档页 -- 实时链路失败时,首屏仍要有稳定 snapshot fallback +- 首屏仍要有稳定 SSR snapshot,但不再通过第二条 runtime projection fallback 偷偷补拉 live 语义 也就是说: diff --git a/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md b/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md index fd86c85a..a166952f 100644 --- a/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md +++ b/design/03-rust-web/process/3-rust-web-long-term-architecture-v1.md @@ -58,7 +58,7 @@ - **Web 承载层:`axum`** - **页面渲染模型:`Leptos Islands`** - **AI 执行面:`mnote-cli`** -- **最后保留的重编辑兼容孤岛:少量编辑器 runtime(当前默认主编辑器已是页面内 `leptos-tiptap` island,`BlockNote` 仅保留为 fallback / 对照链)** +- **最后保留的重编辑兼容孤岛:少量编辑器 runtime(当前默认主编辑器已是页面内 `leptos-tiptap` island,`BlockNote` 仅保留为 `recycle/` 历史参考副本)** 一句话概括: @@ -68,7 +68,7 @@ 当前真正难替代的主要是: -- 以 `BlockNote` fallback、转换链和剩余兼容保存链为代表的重编辑 runtime +- 以旧 `BlockNote` 编辑器副本、转换链和剩余兼容保存链为代表的重编辑 runtime 而下面这些能力,从长期看都可以先退出当前大前端壳: @@ -359,8 +359,8 @@ Leptos Islands 很适合承接下面这类长期目标: - `mnote-web` 已经不是只停留在 crate 骨架;`3000` 公开入口已由 Rust Web 主壳承接,`3104` 已退到仅显式 debug / internal 边界。 - Rust Web 主壳已经接入 `/api/tree/events` snapshot / delta / resync consumer,双 pane 也已复用同一条 tree realtime 主链,而不是每个页面壳各自维护第二条流。 -- 文档页读取已经进入 Rust-first `page aggregate` 过渡态:`/api/documents/page` 优先消费 Rust `/api/page-aggregate/:id` 的 `mnote.page_aggregate.v1` snapshot,失败时才回退 TS builder。 -- 默认主编辑区已经切到页面内 `leptos-tiptap` island;阅读态、页头、页面设置和页面内 AI 面板都在 `3000` 主壳上继续收口,`BlockNote` 只保留为 fallback / 对照链。 +- 文档页读取已收口到 Rust `/api/page-aggregate/:id` 的 `mnote.page_aggregate.v1` snapshot;`/api/documents/page` 已降级为显式退场的 compat 边界,不再参与运行时主路径。 +- 默认主编辑区已经切到页面内 `leptos-tiptap` island;阅读态、页头、页面设置和页面内 AI 面板都在 `3000` 主壳上继续收口,`BlockNote` 只保留为 `recycle/` 历史参考 / 对照材料。 - Sidebar 已形成“服务端首包 + 客户端局部 island”的最小边界,导航数据聚合契约不再散落在布局层。 - SearchPalette 与页面级 AI 面板都已经收成轻 host + 按需 runtime island,重量运行态不再默认跟随主布局常驻。 - Global AI 继续保留为实验入口,但不再回到 app layout 主链,避免长期路线再次滑回“全局大面板常驻”模式。 diff --git a/design/05-editor-mainline/process/5-4-leptos-tiptap-mainline-correction-v1.md b/design/05-editor-mainline/process/5-4-leptos-tiptap-mainline-correction-v1.md index b55214df..4c9e6940 100644 --- a/design/05-editor-mainline/process/5-4-leptos-tiptap-mainline-correction-v1.md +++ b/design/05-editor-mainline/process/5-4-leptos-tiptap-mainline-correction-v1.md @@ -57,7 +57,7 @@ - `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/editor-host.tsx` - 但仍保留 TS converter、fallback host、兼容保存链与部分 host/runtime 过渡层 - `/mnt/Data1T/mnote/wolai-frontend/src/lib/documents/tiptap-content-converter.ts` - - `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocknote-editor.tsx` + - `/mnt/Data1T/mnote/recycle/wolai-frontend/src/components/editor/blocknote-editor.tsx` 这条线的问题不是“代码不能运行”,而是: @@ -397,27 +397,27 @@ 目标: - 正式把默认主编辑器从 `BlockNote` 切到页面内 `leptos-tiptap` island -- 让 `BlockNote` 退到显式 fallback / 兼容链,而不是继续承担默认主链 +- 让 `BlockNote` 退出运行时主路径,只保留 `recycle/` 历史参考副本,而不是继续承担默认主链 - 让默认主链不再依赖 `iframe runtime` 或 React `bridge runtime` 清单: -- [x] 收敛正式 host 命名:`leptos_tiptap_runtime` 改为“正式 island host”语义,`leptos_tiptap_inline` 仅保留为兼容别名,`leptos_tiptap_iframe_debug` 继续只保留给调试桥 +- [x] 收敛正式 host 命名:`leptos_tiptap_runtime` 改为“正式 island host”语义,`leptos_tiptap_inline` 仅保留为兼容别名;历史 `leptos_tiptap_iframe_debug` 已退出文档页 host 选择面,仅剩源码参考实现 - [x] 修改 `DocumentContent`、`page.tsx`、`runtime-config.ts` 的默认分发逻辑,使不带任何参数的 `/documents/[id]` 直接进入正式 `leptos-tiptap` island 主链 - [x] 删除默认主链对 `loadLeptosTiptapRuntime()` / `bridge.create()` / `bridge.document()` / `bridge.command()` 这种 React 控制面的依赖 -- [x] 保留 `blocknote` 显式回退开关:可以是 runtime config、query 参数或受控 feature flag,但必须做到“不改代码即可回退” -- [x] 把 `BlockNoteEditor` 降为 fallback / 对照链,不再继续承接新的长期 editor truth、save contract、AI contract 语义 +- [x] 历史 `blocknote` 显式回退链已退到 `recycle/`,不再作为当前 runtime config、query 参数或 feature flag 组成部分 +- [x] 把 `BlockNoteEditor` 降为 `recycle/` 历史参考实现,不再继续承接新的长期 editor truth、save contract、AI contract 语义 - [x] 为默认切流补齐真实 smoke:打开、输入、撤销、重做、引用插入、AI 改写、保存、刷新回填、异常回退 - [x] 为默认切流补齐观测项:runtime 加载失败、hydration 失败、Rust command 失败、保存失败、自动回退次数 - [x] 先完成开发环境默认切流,再进入受控范围的真实使用默认切流;每一步都保留 kill switch -- [x] 更新设计稿、运行时注释与口径,明确“默认主编辑器已切到页面内 `leptos-tiptap` island,`BlockNote` 为 fallback/兼容链” +- [x] 更新设计稿、运行时注释与口径,明确“默认主编辑器已切到页面内 `leptos-tiptap` island,`BlockNote` 仅保留 `recycle/` 历史参考副本” ### 6.5.1 当前验证记录(2026-04-21,2026-04-29 复核) - [x] `http://127.0.0.1:3000/documents/[id]` 在不带 `editorHost` 参数时默认进入页面内 `leptos_tiptap` island,而不是 `iframe` 或 React `bridge runtime` - [x] 侧边栏“新建页面”不再依赖 `edit=1`;当前 3000 Rust Web 侧栏 `+` 会通过 `/api/tree/commands` 新建页面并直接进入默认 `leptos-tiptap` 主链,`task122` 已覆盖 -- [ ] `node /mnt/Data1T/mnote/scripts/task108-document-default-editor-cutover-smoke.js` 已通过 -- [ ] `editorHost=blocknote` 显式回退在当前 3000 Rust Web shell 下尚未通过 `task108`;旧 Next/React fallback 只能作为 legacy/对照链,不能作为当前 3000 完成证据 +- [x] `task108-document-default-editor-cutover-smoke.js` 已移入 `recycle/scripts/`,不再作为当前 3000 主链验收项 +- [x] `editorHost=blocknote` 显式回退已退出当前 3000 Rust Web shell 的活跃验收范围;旧 Next/React fallback 只保留历史参考意义 - [x] `DocumentContent` 已暴露主链观测点:`runtime_load_failed`、`host_init_failed`、`command_failed`、`save_failed`、`fallback_count` - [x] 已修正 island `embedded` 模式判定,不再因为缺少 `?embedded=1` 而把 spike 页面壳误渲染进 3000 正式文档页 - [x] 已移除正式主链中的 spike 开发态壳元素:`hero`、重复标题、开发态提示文案、调试抽屉不再出现在 `/documents/[id]` 默认视图 @@ -427,7 +427,7 @@ - [x] 已修正正式主链中的本地草稿隔离:Rust island 不再使用全局单一 `localStorage` key,改为按 `workspaceId/documentId` 分桶 - [x] 已修正正式主链中的布局偏移:页面内 island 宿主不再额外施加横向 padding,编辑正文列、块手柄和 drop indicator 已回到同一几何基准 - [x] 已收敛切页期的 disposed signal 访问风险:窗口级 `mousemove/mouseup/keydown` listener 已改为 `try_get_untracked/try_set` 安全访问,避免在页面切换时继续触碰已释放 reactive value -- [ ] `task108` 当前仍未通过;2026-04-29 复核失败在 `?editorHost=blocknote` 后未出现 `data-editor-host-active="blocknote"`,因此不能把 blocknote fallback 计入当前 3000 Rust shell 完成项 +- [x] `task108` 已随 `BlockNote` fallback 退场移入 `recycle/`;不再用 blocknote fallback 证明当前 3000 Rust shell 完成度 - [x] `task121` / `task122` 已覆盖当前 3000 默认 island 的 hydrate、输入、保存、reload 读回和 UI 新建页面进入主链 - [ ] 当前 `slash / floating toolbar / drag handle / turn into` 仍是 island 内部的最小自制实现,尚未对齐官方 notion-like 模板的组件层级、视觉细节与菜单能力 @@ -440,9 +440,9 @@ 退出标准: - 不带参数的 `/documents/[id]` 默认进入 `leptos-tiptap` -- 出现问题时可通过显式开关快速回退到 `BlockNote`,而不是回滚代码 +- 出现问题时优先修正式 `leptos-tiptap` 主链,不再把回退到 `BlockNote` 作为默认策略 - 默认链路下的 Rust truth、AI contract、save contract 保持不变 -- `BlockNote` 不再是默认主编辑器,但仍保留为迁移期保险丝 +- `BlockNote` 不再是默认主编辑器,也不再是当前运行时保险丝;仅保留 `recycle/` 参考副本 --- diff --git a/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md b/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md index 0361a0d3..42f15e63 100644 --- a/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md +++ b/design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md @@ -34,7 +34,7 @@ 它现在更接近于: -> **`Rust snapshot 优先 + Convex-backed + 前端 fallback / 本地 state 仍存在` 的混合态。** +> **`Rust snapshot 主读链 + Convex-backed + 前端本地 state 仍存在` 的混合态。** 因此,当前看到的这些“小问题”: @@ -60,7 +60,7 @@ 但以下事实仍然成立: -- 读取主链虽已优先消费 Rust `mnote.page_aggregate.v1` snapshot,但 snapshot 不可用时仍保留 TS fallback +- 读取主链已固定为 Rust `mnote.page_aggregate.v1` snapshot,不再通过 TS builder 兜底 - 标题、正文、页面设置虽已开始收口到同一组 page aggregate command family,但 projection 回流与运行时语义还没完全闭环 - 页面树 / 文件树与页头标题的一致性已明显改善,但页头标题、页面设置与编辑器 runtime 还没有完全共享同一份聚合真相 - `pageOptions` 已部分进入 `leptos-tiptap` 运行时语义层,但还没有整体收口完成 @@ -109,10 +109,9 @@ ## 3.1 当前页面数据并不是一个统一聚合 -当前文档页读取主链已经优先走 Rust `mnote.page_aggregate.v1` 快照,再在 snapshot 不可用或不可信时回退到 TS builder: +当前文档页读取主链已经固定走 Rust `mnote.page_aggregate.v1` 快照: - Rust `/api/page-aggregate/:id` snapshot -- TS fallback builder - 页面本地 aggregate state reducer - preferred sidebar snapshot / 页头标题补偿链 diff --git a/design/05-editor-mainline/process/5-7-wolai-page-tree-main-editor-experience-restoration-v1.md b/design/05-editor-mainline/process/5-7-wolai-page-tree-main-editor-experience-restoration-v1.md index d040bcf6..0316a704 100644 --- a/design/05-editor-mainline/process/5-7-wolai-page-tree-main-editor-experience-restoration-v1.md +++ b/design/05-editor-mainline/process/5-7-wolai-page-tree-main-editor-experience-restoration-v1.md @@ -35,7 +35,7 @@ - 功能以“高频路径可用、复杂能力可降级”为原则。 - 当前项目保留“文件树 / Explorer”创新,不要求删除。 - 默认主编辑器继续是页面内 `leptos-tiptap` island。 -- `BlockNote` 只作为 fallback / 对照链,不重新变成默认方向。 +- `BlockNote` 只作为 `recycle/` 历史参考 / 对照材料,不重新变成默认方向。 - 树、页面结构、标题、正文、页面设置不能在 UI 层再拼第二份真相。 这份文档应放在 `05-editor-mainline/process`,因为它的核心不是 Rust Web 壳复刻,也不是单独的树命令合同,而是: @@ -384,8 +384,8 @@ Wolai / Notion-like 目标: 当前仓库已有可复用参考: -- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/blocknote-editor.tsx` 中,旧 `BlockNoteView` 通过 `SideMenuController` 注入自定义 `CustomSideMenu`。 -- `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/menus/CustomSideMenu.tsx` 中,`WolaiDragHandleWithInsert` 已实现上方插入、下方插入、手柄菜单、菜单冻结、空段落加号打开 slash、截图失焦状态重置。 +- `/mnt/Data1T/mnote/recycle/wolai-frontend/src/components/editor/blocknote-editor.tsx` 中,旧 `BlockNoteView` 通过 `SideMenuController` 注入自定义 `CustomSideMenu`。 +- `/mnt/Data1T/mnote/recycle/wolai-frontend/src/components/editor/menus/CustomSideMenu.tsx` 中,`WolaiDragHandleWithInsert` 已实现上方插入、下方插入、手柄菜单、菜单冻结、空段落加号打开 slash、截图失焦状态重置。 - `/mnt/Data1T/mnote/wolai-frontend/src/components/editor/leptos-tiptap-inline-editor-host.tsx` 当前已有较简化的块手柄和菜单,但没有复刻上 / 下短横线插入态。 - `/mnt/Data1T/mnote/rust/spikes/leptos-tiptap-spike/src/lib.rs` 已有 leptos/tiptap 手柄雏形,但当前样式偏重,并且 `insert_top_level_paragraph_after_html` 只支持 after 插入。 diff --git a/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md b/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md index 4ff9fc99..ca7a612c 100644 --- a/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md +++ b/design/07-ai/process/7-phase7-ai-kernel-projection-plan-v4.md @@ -504,7 +504,7 @@ CLI 要能明确限制: ### 8.7 外置 agent 接入顺序 - [x] 第 1 步:冻结 Codex 接入方式。 - - 结果:`/api/ai-agent/run` 已不再按 `provider=codex` 直入独立 bridge,统一走 `mnote-cli` host。 + - 结果:`/api/ai-agent/run` 已不再保留 `provider=codex` 默认系统入口;请求会明确失败,默认主链只保留 `mnote-cli` host。 - 验证命令: ```bash rg -n "provider === \"codex\"|runCodexBridge" /mnt/Data1T/mnote/wolai-frontend/src/app/api/ai-agent/run/route.ts @@ -636,7 +636,7 @@ CLI 要能明确限制: - CLI 是唯一长期执行面 - Web 面板只是 CLI 客户端 - `openai-agents-python` 是可插拔外置 agent -- Hermes / Codex / 后续 agent 都统一走 CLI +- Hermes / Codex / 后续 agent 不再拥有默认产品内入口;是否保留仅通过显式接线决定 ### 阶段 1:CLI 能力补齐 @@ -662,8 +662,8 @@ CLI 要能明确限制: 统一支持: -- Hermes -> `mnote-cli` -- Codex -> `mnote-cli` +- Hermes -> 显式外置接线或停用 +- Codex -> 显式外置接线或停用 - `openai-agents-python` -> `mnote-cli` ### 阶段 4:裁剪过渡层 diff --git a/design/03-rust-web/process/3-4-undo.md b/design/old/03-rust-web/process/3-4-undo.md similarity index 99% rename from design/03-rust-web/process/3-4-undo.md rename to design/old/03-rust-web/process/3-4-undo.md index 93eaa13a..e1bfa4aa 100644 --- a/design/03-rust-web/process/3-4-undo.md +++ b/design/old/03-rust-web/process/3-4-undo.md @@ -1,4 +1,4 @@ -# 3-4 [process] Rust Web 架构未完成项收口计划与执行清单 v1 +# 3-4 [recycle] Rust Web 架构未完成项收口计划与执行清单 v1 > **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` or `superpowers:executing-plans` when implementing this plan task-by-task. Steps use checkbox (`- [x]`) syntax for tracking. diff --git a/design/old/05-editor-mainline/process/5-editor-baseline-reset-v2.md b/design/old/05-editor-mainline/process/5-editor-baseline-reset-v2.md index 7d09e0e7..2167cbb9 100644 --- a/design/old/05-editor-mainline/process/5-editor-baseline-reset-v2.md +++ b/design/old/05-editor-mainline/process/5-editor-baseline-reset-v2.md @@ -48,8 +48,8 @@ - Rust `/document` 路由现在是 runtime/debug 壳,不是产品文档页 - [editor.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/routes/editor.rs) - 新 smoke 脚本已经把“看到 `Document Editor Shell` + `textarea[data-block-input-id]`”当成通过标准 - - [task103-document-shell-cutover-smoke.js](/mnt/Data1T/mnote/scripts/task103-document-shell-cutover-smoke.js) - - [task104-document-runtime-input-smoke.js](/mnt/Data1T/mnote/scripts/task104-document-runtime-input-smoke.js) + - [task103-document-shell-cutover-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task103-document-shell-cutover-smoke.js) + - [task104-document-runtime-input-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task104-document-runtime-input-smoke.js) 这说明问题不是“样式没做完”,而是默认交付口径已经被带偏。 @@ -138,11 +138,11 @@ Rust 侧不应优先承担: - `iframe` 挂载壳本身 - [mnote-web-document-shell-host.tsx](/mnt/Data1T/mnote/wolai-frontend/src/app/(app)/documents/[id]/mnote-web-document-shell-host.tsx) - 把 runtime debug 壳当默认验收的 smoke 脚本 - - [task103-document-shell-cutover-smoke.js](/mnt/Data1T/mnote/scripts/task103-document-shell-cutover-smoke.js) - - [task104-document-runtime-input-smoke.js](/mnt/Data1T/mnote/scripts/task104-document-runtime-input-smoke.js) - - [task105-document-runtime-transactions-smoke.js](/mnt/Data1T/mnote/scripts/task105-document-runtime-transactions-smoke.js) - - [task106-document-runtime-slash-reference-smoke.js](/mnt/Data1T/mnote/scripts/task106-document-runtime-slash-reference-smoke.js) - - [task107-document-runtime-save-smoke.js](/mnt/Data1T/mnote/scripts/task107-document-runtime-save-smoke.js) + - [task103-document-shell-cutover-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task103-document-shell-cutover-smoke.js) + - [task104-document-runtime-input-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task104-document-runtime-input-smoke.js) + - [task105-document-runtime-transactions-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task105-document-runtime-transactions-smoke.js) + - [task106-document-runtime-slash-reference-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task106-document-runtime-slash-reference-smoke.js) + - [task107-document-runtime-save-smoke.js](/mnt/Data1T/mnote/recycle/scripts/task107-document-runtime-save-smoke.js) 这些部分的问题不是“代码质量差”,而是: diff --git a/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md b/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md index 6371db21..a4ea669a 100644 --- a/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md +++ b/design/old/05-editor-mainline/process/ai-first-rust-block-editor-baseline-v1.md @@ -686,7 +686,7 @@ Rust-native minimal editor 更符合这一点。 - [x] `kode` / `kode-leptos` / `kode-doc` 的采用结论已冻结为“块内输入器与选择处理参考层”;当前基线先用 Rust shell + 最小 DOM 交互验证语义,不在第一版追求复杂 `contenteditable` 或整壳 Leptos 化。 - [x] 主文档页已经完成双路径切换:默认由 `mnoteWebDocumentShellEnabled` + `mnoteWebDocumentShellUrl` 驱动接入新壳,`?editor=compat` 保留旧 `BlockNote` 兼容入口。 - [x] 新 UI 壳首屏不依赖 `HocuspocusProvider`、`Yjs`、`comments`、旧 `BlockNoteView`;默认主路径只先加载文档壳 iframe,旧编辑器仅在 compat 路径进入。 -- [x] 最小浏览器回归链已经补齐并跑通,见 [`task103-document-shell-cutover-smoke.js`](/mnt/Data1T/mnote/scripts/task103-document-shell-cutover-smoke.js)。 +- [x] 最小浏览器回归链已经补齐并跑通,见 [`task103-document-shell-cutover-smoke.js`](/mnt/Data1T/mnote/recycle/scripts/task103-document-shell-cutover-smoke.js)。 ### 阶段 3 纠偏说明(2026-04-18) @@ -808,7 +808,7 @@ Rust-native minimal editor 更符合这一点。 - [x] 已完成 `BlockNote` 入口、依赖与内容格式迁移策略盘点,见 [`rust-block-editor-blocknote-migration-v1.md`](/mnt/Data1T/mnote/design/old/05-editor-mainline/process/rust-block-editor-blocknote-migration-v1.md)。 - [x] 主文档页默认路径已不再挂旧 `BlockNote`,而是切到 `mnote-web` 新文档壳;兼容入口仍保留 `?editor=compat` / debug 用途。 -- [x] 文档页测试基线已切到“默认新壳 + compat 回退”双路径,当前基线验证包括 `task103-document-shell-cutover-smoke.js`、`pnpm test`、`cargo test -p mnote-web`。 +- [x] 文档页测试基线已切到“默认新壳 + compat 回退”双路径,当前基线验证包括 `recycle/scripts/task103-document-shell-cutover-smoke.js`、`pnpm test`、`cargo test -p mnote-web`。 - 后续收尾:`task-068` 继续清理 `@blocknote/*`、Yjs、Mantine、旧 CSS 覆盖,以及 `mindmap` / `onlineTable` / 媒体块里仅供旧编辑器使用的残留耦合。 - 后续收尾:在 compat/debug 真正退场后,再删除 `blocknote-editor.tsx` 及其最终调用点,并完成包依赖瘦身。 diff --git a/design/old/05-editor-mainline/process/runtime-shell-to-wolai-page-correction-checklist-v1.md b/design/old/05-editor-mainline/process/runtime-shell-to-wolai-page-correction-checklist-v1.md index e4223ae1..c1db3e23 100644 --- a/design/old/05-editor-mainline/process/runtime-shell-to-wolai-page-correction-checklist-v1.md +++ b/design/old/05-editor-mainline/process/runtime-shell-to-wolai-page-correction-checklist-v1.md @@ -138,11 +138,11 @@ 相关脚本: -- `/mnt/Data1T/mnote/scripts/task103-document-shell-cutover-smoke.js:17` -- `/mnt/Data1T/mnote/scripts/task103-document-shell-cutover-smoke.js:25` -- `/mnt/Data1T/mnote/scripts/task104-document-runtime-input-smoke.js:29` -- `/mnt/Data1T/mnote/scripts/task104-document-runtime-input-smoke.js:46` -- `/mnt/Data1T/mnote/scripts/task106-document-runtime-slash-reference-smoke.js:34` +- `/mnt/Data1T/mnote/recycle/scripts/task103-document-shell-cutover-smoke.js:17` +- `/mnt/Data1T/mnote/recycle/scripts/task103-document-shell-cutover-smoke.js:25` +- `/mnt/Data1T/mnote/recycle/scripts/task104-document-runtime-input-smoke.js:29` +- `/mnt/Data1T/mnote/recycle/scripts/task104-document-runtime-input-smoke.js:46` +- `/mnt/Data1T/mnote/recycle/scripts/task106-document-runtime-slash-reference-smoke.js:34` 相关任务口径: diff --git a/docs/superpowers/plans/2026-05-10-mindmap-phase6-projection-editor-checklist.md b/docs/superpowers/plans/2026-05-10-mindmap-phase6-projection-editor-checklist.md new file mode 100644 index 00000000..b96dd637 --- /dev/null +++ b/docs/superpowers/plans/2026-05-10-mindmap-phase6-projection-editor-checklist.md @@ -0,0 +1,400 @@ +# Mindmap Phase 6 Projection Editor v1 Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 在不等待 `design/01-05` 全量收口的前提下,按 `design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.md` 的方向推进 `Mindmap Phase 6` 主线重构:让 Mindmap 从“独立对象中心 + blob 真相 + 前端重壳”降级成“kernel subtree / graph 的一种 projection 与 editor”,并适配当前已有的 Rust 主链;本轮优先收口文档内 `/` 命令插入的 `mindmap block` 最小读写真相链,再把独立导图页挂到同一套 truth / adapter 上。 + +**Architecture:** 这一版不重写画布,不替换 `simple-mind-map`,也不要求 page aggregate / tree realtime 彻底闭环。先建立 block 与独立页共用的 Rust projection + 最小 command adapter,让 `simple-mind-map` 降级成 renderer / editor adapter,再把 `/` 插入示例骨架、默认隐藏 chrome、hover 后显示工具栏 / 右侧面板 / 节点操作这些产品体验挂到这条新主链上。测试和截图验收只负责证明主线成立,不反向限制重构范围;本轮允许 blob 存储暂时作为 compat substrate 存在,但不再把它当长期对象真相。 + +**Tech Stack:** Next.js / React、Convex、Rust `core-protocol`、Rust `bridge-runtime`、Rust `mnote-web`、`simple-mind-map` + +--- + +## 方向确认 + +- [ ] 当前 Phase 6 的方向,明确是按 `design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.md` 推进 +- [ ] 目标明确是让 Mindmap 从“独立对象中心 + blob 真相 + 前端重壳”降级成“kernel subtree / graph 的一种 projection 与 editor” +- [ ] `design/01-05` 仍然是当前仓库的上位主线与优先级依据,但不是这轮 Mindmap Phase 6 的硬前置阻塞 +- [ ] 这轮只在不破坏 `Page Aggregate / tree command / tree realtime` 主线口径的前提下,收口 Mindmap 自身的 truth / projection / command 边界 +- [ ] 测试验收、截图留档、浏览器 smoke 只从属于主线重构,不反向决定主线方案 +- [ ] 独立导图页必须适配同一套 truth / adapter,但文档内 `/` 命令插入的 `mindmap block` 仍是本轮主验收入口 + +## 范围冻结 + +### 本计划明确要做 + +- [ ] 明确按 `6-mindmap-kernel-phase6-projection-editor-v1.md` 的口径推进,不把 Mindmap 再当独立对象真相层 +- [ ] 让 Mindmap 降级为 kernel subtree / graph 的一种 projection 与 editor,并接入当前 Rust 主链 +- [ ] 文档内 `/` 命令插入的 `mindmap block` 是本轮主验收面 +- [ ] 先收口 block 与独立页共用的最小读写真相链,再叠加产品体验 +- [ ] 独立导图页读链优先消费 Rust `mindmap.projection.get` +- [ ] 前端导图 projection 类型与 Rust projection contract 对齐 +- [ ] 为最小可用动作集建立 Rust command / op 适配层 +- [ ] 保留 `simple-mind-map` 作为 renderer / editor adapter +- [ ] 为独立页与内嵌块建立同一套“projection truth + adapter runtime”口径 +- [ ] `/` 插入后默认生成示例骨架:根节点 + 二级节点 + 两个分支主题 +- [ ] 默认只显示导图本体;hover block 后显示工具栏 / 右侧面板 / 节点 hover 操作 +- [ ] 补齐最小测试,确保 Phase 6 不回退成“前端摘要 + blob 真相” + +### 本计划明确不做 + +- [ ] 不要求先完成 `Page Aggregate` 全闭环 +- [ ] 不要求先完成 `tree realtime` 全域 live cache 统一 +- [ ] 不重写 `MindmapBlock.tsx` 的整套工具栏、动画、导入导出、图片工具 +- [ ] 不把 Convex `mindmaps` blob 存储在本轮强行改成 kernel node / edge 持久化 +- [ ] 不把所有 `simple-mind-map execCommand` 一次性收口到 Rust +- [ ] 不为了浏览器 smoke 或截图留档而保守维持旧的 blob-first 主路径 + +### 开工判定 + +- [ ] 确认当前主线口径仍是 `tree-first graph kernel` +- [ ] 确认当前方向是“Mindmap 降级成 kernel projection/editor 并适配 Rust 主链”,而不是继续补一套独立 blob 系统 +- [ ] 确认 `Page Aggregate` / `tree.*` / `/api/tree/events` 已是正式主链,而不是待验证方向 +- [ ] 确认本轮目标是 `projection/editor v1`,不是 `mindmap full kernel cutover` +- [ ] 确认测试验收从属于重构主线,而不是主线为测试妥协 +- [ ] 若任务被重新扩大到“顺手收口 page aggregate / realtime 尾项”,暂停并拆分 + +## 产品体验目标 + +- [ ] 主验收入口:文档页正文内通过 `/` 命令插入 `mindmap block` +- [ ] 插入后立即看到示例骨架,而不是空白画布或只有一个根节点 +- [ ] 默认只显示画布与导图本体,不常驻显示顶部工具栏、右侧面板、节点操作 +- [ ] 鼠标移入 block 区域后,显示顶部工具栏与右侧面板 +- [ ] 鼠标移入节点后,显示节点级 hover 操作 +- [ ] 独立页与 block 共享同一套 truth / adapter,只允许 chrome 壳层不同 + +## 参考对标 + +- [ ] 体验参考:`/mnt/Data1T/mnote/tmp/image copy 59.png` +- [ ] 更接近现有实现的参考:`/mnt/Data1T/mnote/tmp/image copy 60.png` +- [ ] 默认隐藏 chrome 的参考:`/mnt/Data1T/mnote/tmp/image copy 61.png` +- [ ] 外部参考实现: + - `https://github.com/suka233/siyuan-kmind-plugin` + - `https://github.com/wanglin2/mind-map` + - `https://github.com/wanglin2/mind-map-mcp` + - `https://github.com/wanglin2/lx-doc` +- [ ] 参考只用于体验与结构借鉴,不要求机械复刻外部产品 + +--- + +### Task 1: 冻结 Phase 6 执行边界 + +**Files:** +- Modify: `design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.md` +- Reference: `design/01-05-current-priority-overview.md` +- Reference: `ARCHITECTURE.md` + +- [ ] 在设计稿里补一段“本轮执行边界”,明确: + - 方向是把 Mindmap 降级成 kernel subtree / graph projection + editor + - 继续适配并复用当前已有的 Rust 主链 + - 先切 block / page 共用的最小读写真相链 + - 再把 `/` 插入、示例骨架、hover chrome 挂到新主链 + - 继续保留 `simple-mind-map` renderer + - 不把 `01-05` 尾项作为硬前置 +- [ ] 在设计稿里补一段“非目标说明”,明确: + - 本轮不是继续把 mindmap blob 打磨成长期对象真相 + - 本轮不是先做前端重壳再以后接 Rust + - 本轮不是一次性完成最终 kernel-native graph storage cutover +- [ ] 在设计稿里补一段“主验收面”,明确: + - 主验收入口是文档内 `/` 命令插入的 `mindmap block` + - 独立页必须共用同一真相链,但不是产品验收主画面 +- [ ] 在设计稿里补一段“测试从属关系”,明确: + - smoke / 截图用于证明主线成立 + - 不允许为了更好测而维持旧主路径 +- [ ] 在设计稿里补一段“阻塞条件”,明确只有以下情况才暂停: + - Rust projection contract 不可用 + - 现有 bridge 无法表达最小 MindmapOp + - 独立页与内嵌块入口无法共享 projection contract +- [ ] 在设计稿里补一段“延期项”,把以下内容显式标为后续阶段: + - blob 持久化移除 + - page aggregate 深度对齐 + - realtime delta 深度接入 + - 全量画布命令收口 +- [ ] 验证:设计稿读起来不会再误导执行者去先重写画布或等待 `01-05` 全完成 + +--- + +### Task 2: 建立 Mindmap Projection 真实合同 + +**Files:** +- Inspect/Modify: `rust/crates/core-protocol/src/mindmap.rs` +- Inspect/Modify: `rust/crates/bridge-runtime/src/lib.rs` +- Inspect/Modify: `rust/crates/mnote-web/src/routes/mindmap_shell.rs` +- Inspect/Modify: `wolai-frontend/src/lib/mindmap/mindmap-projection.ts` +- Test: `rust/crates/bridge-runtime/src/lib.rs` +- Test: `wolai-frontend/src/lib/mindmap/*.test.ts` + +- [ ] 盘点 Rust 侧现有 `MindmapProjection` 字段,列出前端真正需要消费的最小字段: + - `documentId` + - `mindmapId` + - `rootNodeId` + - `title` + - `nodeCount` + - `nodes` + - `raw/tree payload` + - `owner/source/meta` +- [ ] 判断前端 `MindmapProjection` 与 Rust contract 的差异,特别检查: + - 前端是否仍把 `projection: "mindmap_subtree"` 当私有摘要 + - 是否缺少 source / owner / version 语义 + - 是否把 `data` 原树和 projection 摘要混成一层 +- [ ] 冻结一份统一口径: + - Rust 输出什么 + - 前端只做什么适配 + - 哪些字段是 renderer 所需,哪些字段是系统真相 +- [ ] 在 contract 里显式区分三层: + - projection truth + - renderer input + - chrome / hover UI state +- [ ] 确认 block 和独立页都消费同一份 projection truth,不允许各自再拼一份摘要对象 +- [ ] 补测试,至少覆盖: + - Rust `mindmap.projection.get` 返回稳定 schema + - 前端 adapter 能解析 Rust projection + - 当原始 blob 字段缺失时,adapter 仍只做渲染兜底,不篡改 projection 语义 +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime mindmap` + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-projection` + +--- + +### Task 3: 建立最小 Command Adapter,只接本轮必须动作 + +**Files:** +- Inspect/Modify: `rust/crates/core-protocol/src/mindmap.rs` +- Modify: `rust/crates/bridge-runtime/src/lib.rs` +- Modify: `wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/route.ts` +- Create/Modify: `wolai-frontend/src/lib/mindmap/mindmap-command-client.ts` +- Test: `rust/crates/bridge-runtime/src/lib.rs` +- Test: `wolai-frontend/src/lib/mindmap/*.test.ts` + +- [ ] 冻结 v1 支持的最小动作集,只选: + - `rename/updateText` + - `addChild` + - `deleteNode` + - `addSiblingAfter` + - 节点 hover 操作所需的最小命令 + - `/` 插入后的示例骨架创建 +- [ ] `setRefs`、`move` 不作为本轮 block 主验收前置,除非实现时已在同一 adapter 中顺手闭环 +- [ ] 为这些动作建立前端 command client,不再默认整棵 `POST data blob` +- [ ] Rust bridge 明确区分: + - projection query + - command apply + - compat `mindmaps.put` +- [ ] 只有确实无法表达的动作,才回退到整棵 blob 保存;回退只作为 compat 行为存在,不在这里展开做标签治理 +- [ ] 补测试,至少覆盖: + - 每个最小动作都能转成 `MindmapOp` 或 `MindmapCommand` + - 非支持动作不会偷偷走“无差别全量 blob 覆盖” + - compat 回退有显式标记 +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime mindmap_apply_ops` + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-command-client` + +--- + +### Task 4: 建立共享 Entry Contract 与 Renderer Adapter 基础 + +**Files:** +- Modify: `wolai-frontend/src/lib/mindmap/mindmap-projection.ts` +- Create/Modify: `wolai-frontend/src/lib/mindmap/mindmap-entry-contract.ts` +- Create/Modify: `wolai-frontend/src/lib/mindmap/mindmap-renderer-adapter.ts` +- Modify: `wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx` +- Modify: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx` +- Test: `wolai-frontend/src/lib/mindmap/*.test.ts` +- Test: `wolai-frontend/src/components/editor/blocks/*.test.tsx` +- Test: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/*.test.tsx` + +- [ ] 把“系统真相字段”和“画布运行时字段”分成三层: + - projection truth + - renderer input + - chrome / hover UI state +- [ ] 建立 `mindmap-entry-contract`,统一 block 与独立页入口的最小约定: + - 如何拿 projection + - 如何构建 renderer input + - 如何声明 UI 壳层差异 +- [ ] 提取 `mindmap-renderer-adapter`,专门负责: + - projection -> `simple-mind-map` 可渲染数据 + - renderer 事件 -> 规范化编辑意图 +- [ ] 避免继续在 `MindmapBlock.tsx` 或独立页内直接把 `buildMindmapProjection(blob)` 当正式读链 +- [ ] 补测试,至少覆盖: + - adapter 不改写 projection 语义 + - adapter 的兜底只作用于 renderer + - block 与独立页能共用同一 entry contract / renderer adapter +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap-projection mindmap-renderer-adapter src/app/mindmap src/components/editor/blocks` + +--- + +### Task 5: 收口文档内 mindmap block 的主读写真相链 + +**Files:** +- Modify: `wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx` +- Modify: `wolai-frontend/src/lib/mindmap/mindmap-projection.ts` +- Modify: `wolai-frontend/src/lib/mindmap/mindmap-renderer-adapter.ts` +- Modify: `wolai-frontend/src/lib/mindmap/mindmap-command-client.ts` +- Inspect/Modify: `rust/crates/bridge-runtime/src/lib.rs` +- Test: `wolai-frontend/src/components/editor/blocks/*.test.tsx` +- Test: `wolai-frontend/src/lib/mindmap/*.test.ts` +- Test: `rust/crates/bridge-runtime/src/lib.rs` + +- [ ] 让文档内 `mindmap block` 改为消费统一 projection truth,而不是 `buildMindmapProjection(blob)` 私有摘要 +- [ ] 让 block 的最小编辑动作统一走 Task 3 的 command adapter +- [ ] 把节点 hover 操作建立在这条最小写入链上,不再默认走全量 blob 覆盖 +- [ ] 确认 `MindmapBlock.tsx` 不再同时扮演 truth / adapter / chrome 三层 +- [ ] 补测试,至少覆盖: + - block 主读链优先消费 projection truth + - block 最小动作集能转成 `MindmapOp` / command + - 非支持动作不会偷偷回退成无差别整棵覆盖 +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime mindmap` + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- MindmapBlock mindmap-command-client` + +--- + +### Task 6: 把 `/` 插入示例骨架与 Hover Chrome 体验挂到新主链 + +**Files:** +- Modify: `wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx` +- Inspect/Modify: `wolai-frontend/src/store/editor-bridge.ts` +- Inspect/Modify: `wolai-frontend/src/components/editor/*` +- Inspect/Modify: `wolai-frontend/src/app/(app)/documents/[id]/*` +- Test: `wolai-frontend/src/components/editor/blocks/*.test.tsx` + +- [ ] 找到文档页 `/` 命令插入 `mindmap block` 的真实入口,并把它改为直接创建示例骨架 truth +- [ ] 示例骨架固定为: + - 根节点 + - 1 个二级节点 + - 2 个分支主题 +- [ ] `mindmap block` 默认只显示画布与导图本体 +- [ ] 鼠标移入 block 区域后,显示顶部工具栏与右侧面板 +- [ ] 鼠标移入节点后,显示节点级 hover 操作 +- [ ] chrome 显隐只依赖新 truth / adapter 主链,不在旧 blob 路径上额外补逻辑 +- [ ] 补测试,至少覆盖: + - `/` 插入后不是空白壳 + - 默认不常显 chrome + - hover block 后 chrome 出现 + - hover 节点后节点操作出现 + +--- + +### Task 7: 独立导图页同步挂到同一套 Truth + +**Files:** +- Modify: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx` +- Modify: `wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/route.ts` +- Inspect/Modify: `wolai-frontend/src/lib/documents/rust-runtime.ts` +- Inspect/Modify: `rust/crates/bridge-runtime/src/lib.rs` +- Inspect/Modify: `rust/crates/mnote-web/src/routes/mindmap_shell.rs` +- Modify: `wolai-frontend/src/lib/mindmap/mindmap-entry-contract.ts` +- Test: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/*.test.tsx` +- Test: `wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/*.test.ts` + +- [ ] 让独立页 SSR 读链优先请求 Rust `mindmap.projection.get` +- [ ] 让独立页与 block 共用 Task 3/4 产出的 entry contract / renderer adapter / command adapter +- [ ] 如果仍需兼容 blob 返回,必须把它降级为 fallback,并在代码里标出 compat 边界 +- [ ] 保证 route 返回的主体语义是 projection,而不是“顺便附带 data blob 的摘要” +- [ ] 校验 `initialProjection` 命名与真实内容一致,不再出现“其实是本地摘要却叫 projection”的假象 +- [ ] 明确哪些行为允许不同: + - block 以文档内 hover chrome 为主 + - 独立页可保留更完整的工作区 chrome +- [ ] 补测试,至少覆盖: + - projection 正常返回时,页面首屏直接消费 Rust projection + - projection 失败时,compat fallback 行为可见且受控 + - 独立页与 block 读取的是同一 contract,不再分叉 +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- src/app/mindmap src/app/api/mindmap` + +--- + +### Task 8: 标记并隔离仍未切掉的 Compat 区域 + +**Files:** +- Modify: `wolai-frontend/src/app/api/mindmap/[docId]/[mindmapId]/route.ts` +- Modify: `wolai-frontend/src/lib/documents/rust-runtime.ts` +- Modify: `wolai-frontend/src/lib/mindmap/mindmapLocalStore.ts` +- Modify: `wolai-frontend/convex/mindmaps.ts` +- Optional Doc: `design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.md` + +- [ ] 给仍保留 blob 真相的路径打清楚标签: + - `compat_blob_read` + - `compat_blob_write` + - `renderer_only_fallback` +- [ ] 只在 Task 5 / Task 7 主链稳定后,集中补 compat 标记;不和 Task 3 的命令适配职责混写 +- [ ] 避免继续在新代码里把 compat 路径写成正式主路径 +- [ ] 明确 localStorage / 附件广播 / `mindmap-.json` 属于过渡资产,不属于长期真相合同 +- [ ] 给 Convex `mindmaps` 的整棵 blob 存储加一句清晰注释:当前仅是 substrate / compat 持久化,不是长期对象语义 +- [ ] 验证:新执行者一眼能区分哪条是正式路径,哪条只是过渡保底 + +--- + +### Task 9: 补齐最小回归与浏览器验收 + +**Files:** +- Test: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/*.test.tsx` +- Test: `wolai-frontend/src/components/editor/blocks/*.test.tsx` +- Test: `wolai-frontend/src/lib/mindmap/*.test.ts` +- Test: `rust/crates/bridge-runtime/src/lib.rs` +- Optional Script: `scripts/task*-mindmap-smoke.js` + +- [ ] 单测覆盖: + - projection 主读链 + - compat fallback + - renderer adapter + - 最小 command adapter + - block / 独立页共享 truth +- [ ] 补一个浏览器 smoke,至少验证: + - 新建任意页面后,可通过 `/` 命令插入 `mindmap block` + - 插入后立即出现示例骨架,而不是空白壳 + - 默认不常显 chrome + - hover block 后顶部工具栏和右侧面板出现 + - hover 节点后节点级操作出现 + - 至少一个最小编辑动作能成功回显 +- [ ] 独立页 smoke 只作为同链补充验证,不再是本轮产品主验收面 +- [ ] 补一个“禁止回退”断言: + - 当 projection 可用时,不允许默认走 `buildMindmapProjection(blob)` 主路径 +- [ ] 验证命令: + - `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test` + - `cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime` + - 浏览器 smoke 使用仓库现有 `scripts/task*-smoke.js` 风格新增或复用 + + + +## 依赖关系 + +- [ ] Task 1 完成后,才能开始代码实现,避免目标漂移 +- [ ] Task 2 是 Task 3 和 Task 4 的共同前置 +- [ ] Task 3 必须先于 Task 4、Task 5、Task 6、Task 7,否则 entry contract 和 block/page 主链没有稳定命令面 +- [ ] Task 4 必须先于 Task 5 和 Task 7,否则 block / page 没有共享 contract 与 renderer adapter +- [ ] Task 5 是 block 主验收面的第一落点,必须先于 `/` 插入和 hover 体验 +- [ ] Task 6 依赖 Task 5,不能先在旧主路径上做 UI 伪收口 +- [ ] Task 7 依赖 Task 3 和 Task 4;建议在 Task 5 之后执行,确保 page 跟随 block 主链接入 +- [ ] Task 8 不再与 Task 3 重复承担命令适配职责,只负责集中标记和隔离仍残留的 compat 区域 +- [ ] Task 9 只在 Task 5/6/7/8 形成最小闭环后收尾 + +## 退出标准 + +- [ ] 独立导图页主读链已不是 `mindmaps.get + 前端摘要` +- [ ] 文档内 `/` 插入的 `mindmap block` 已成为本轮主验收面,并挂在新 truth / adapter 主链上 +- [ ] `simple-mind-map` 被明确降级为 renderer/editor adapter +- [ ] 至少一组最小编辑动作已走 Rust `MindmapOp` / command,而不是默认全量 blob 覆盖 +- [ ] `/` 插入后默认生成示例骨架,且不是空白壳 +- [ ] 默认隐藏 chrome,hover block / 节点后再显示相应操作 +- [ ] 独立页与内嵌块共享同一套 projection truth 口径 +- [ ] 仍未移除的 blob / localStorage / 附件路径都被清楚标成 compat +- [ ] 测试和 smoke 能证明 Phase 6 已经开始脱离 blob-first,而不是只换了命名 + +## 暂不作为阻塞的尾项 + +- [ ] `Page Aggregate` 写后完整回灌统一 projection +- [ ] page subtree 与正文本地态完全同源 +- [ ] tree realtime 全域单 live cache +- [ ] 导图 blob 存储彻底移除 +- [ ] 全量画布命令 Rust 化 + +## 建议执行顺序 + +- [ ] 第 1 天:Task 1 + Task 2 +- [ ] 第 2 天:Task 3 +- [ ] 第 3 天:Task 4 +- [ ] 第 4 天:Task 5 +- [ ] 第 5 天:Task 6 +- [ ] 第 6 天:Task 7 + Task 8 +- [ ] 第 7 天:Task 9 + 设计稿回填