Files
mnote/docs/superpowers/plans/2026-05-10-mindmap-phase6-projection-editor-checklist.md
T

313 lines
20 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.
# Mindmap Phase 6 leptos-mindmap Projection Editor v1 Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` where independent code slices exist, or `superpowers:executing-plans` when running this checklist task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
>
> 旧 Rust-native 计划已归档:
> `/mnt/Data1T/mnote/recycle/design/superpowers-plans/2026-05-10-mindmap-phase6-projection-editor-checklist.rust-native.md`
**Goal:** 交付 `leptos-mindmap`:以 Rust kernel 作为导图事实源与命令面,以 `simple-mind-map` / KMind-like runtime 作为 `leptos-tiptap` NodeView 中的显示与交互 adapter。
**Architecture:** `kernel truth -> mindmap.kernel_projection.v1 -> mindmap.simple_mind_map_scene.v1 -> leptos-mindmap island -> simple-mind-map runtime -> adapter diff / command bridge -> kernel command`
**Tech Stack:** Rust `core-protocol`、Rust `bridge-runtime`、Rust `mnote-web``leptos-tiptap` island、`simple-mind-map`、KMind/lx-doc reference code、Playwright smoke、Convex compat substrate。
---
## 口径修正状态
- [x] 已确认旧 `Rust / Leptos 原生 Projection Editor` 口径过时。
- [x] 已将旧设计稿归档到 `recycle/design/06-mindmap/process/`
- [x] 已将旧 checklist 归档到 `recycle/design/superpowers-plans/`
- [x] 已把当前执行口径修正为 `leptos-mindmap`
- [x] 后续每完成一个实现节点,必须在本 checklist 中勾选对应项。
- [x] 2026-05-10 现实复核:当前已勾选的 Task 6/7/8/退出标准只代表“projection / command 最小闭环 + 手写伪画布 smoke”通过,不代表真实 `simple-mind-map` runtime 已接入。最终 UI/runtime 完成判定以后续 `Phase 6.1` 为准。
## 范围冻结
### 本计划明确要做
- [ ] 定义 kernel projection 与 `simple-mind-map` adapter projection 的边界。
- [ ]`leptos-tiptap` NodeView 中挂载 `leptos-mindmap`
- [ ] 使用 `simple-mind-map` runtime 渲染真实导图画布。
- [ ] 参考 `lx-doc/mind-map` 和 KMind 插件复刻第一阶段 toolbar/sidebar/bottom bar。
- [ ] 通过 adapter command bridge 把用户编辑写回 Rust kernel。
- [ ]`data_change` 这类粗粒度事件建立 diff 到 kernel command 的转换。
- [ ] 保留 `compat_payload` 承接暂未语义化的高级字段。
- [ ] 更新 smoke,验证真实节点、连线、编辑、reload 和截图证据。
### 本计划明确不做
- [ ] 不把 `simple-mind-map` runtime data 作为 canonical truth。
- [ ] 不直接嵌入完整 Vue2 `lx-doc/mind-map` 应用并保存 blob。
- [ ] 不恢复旧 React `MindmapBlock.tsx` 作为 3000 文档页默认主链。
- [ ] 不要求本轮完成 Rust-native renderer。
- [ ] 不在本轮完整复刻 KMind 多根、MOC、镜像块、思源块预览、PDF 标注跳转。
- [ ] 不立即移除 Convex `mindmaps` blob;它只作为 compat substrate / import-export / fallback snapshot。
## 文件职责图
- `design/06-mindmap/process/6-mindmap-kernel-phase6-projection-editor-v1.md`
- 当前 `leptos-mindmap` 设计口径。
- `rust/crates/core-protocol/src/mindmap.rs`
- kernel projection、adapter projection、command DTO。
- `rust/crates/bridge-runtime/src/lib.rs`
- projection builder、adapter scene builder、command apply。
- `rust/crates/mnote-web/`
- projection / command route 与 3000 文档页运行时分发。
- `rust/spikes/leptos-tiptap-spike/src/lib.rs`
- mindmap NodeView 与 island 挂载。
- `wolai-frontend/src/lib/mindmap/*`
- adapter、diff、simple-mind-map bridge、legacy compat。
- `wolai-frontend/src/components/editor/blocks/MindmapBlock.tsx`
- legacy React/simple-mind-map 参考实现,不作为默认主链。
- `design/05-editor-mainline/reference-code/lx-doc/mind-map`
- UI、命令、插件和主题参考。
- `design/05-editor-mainline/reference-code/kmind-plugin`
- KMind 打包实现和视觉行为参考。
- `scripts/task166-mindmap-phase6-block-smoke.js`
- Phase 6 浏览器 smoke。
---
### Task 1: 冻结 leptos-mindmap Contract
**Files:**
- Modify: `rust/crates/core-protocol/src/mindmap.rs`
- Modify: `rust/crates/core-protocol/src/lib.rs`
- Test: `rust/crates/core-protocol/src/lib.rs`
- [x] 定义 `MindmapKernelProjection`,包含 `schema``documentId``mindmapId``rootNodeId``revision``nodes``edges``summaries``associativeLines``layout``theme``view``capabilities``source`
- [x] 定义 `MindmapAdapterProjection`,包含 `schema``runtime="simple-mind-map"``root``layout``theme``themeConfig``view``config``compatPayload``kernelRevision`
- [x] 定义最小 command DTO`updateText``insertChild``insertSiblingAfter``deleteNode``moveNode``patchView``setLayout``setTheme`
- [x] 标记 `MindmapTreeNode` / `MindmapOp` 为 compat DTO。
- [x] 补 Rust 单测:kernel projection 与 adapter projection 都能序列化为 camelCase JSON。
- [x] 验证命令:`cd /mnt/Data1T/mnote/rust && cargo test -p core-protocol mindmap`
### Task 2: 建立 Adapter Projection Builder
**Files:**
- Modify: `rust/crates/bridge-runtime/src/lib.rs`
- Test: `rust/crates/bridge-runtime/src/lib.rs`
- [x] 增加 `mindmap.kernel_projection.get` 查询。
- [x] 增加 `mindmap.simple_mind_map_scene.get` 查询。
- [x] 从 kernel truth 或 compat substrate 构建 `simple-mind-map` 可消费的 `root/layout/theme/view/config`
- [x] projection 返回明确 `source`,如 `kernel``compat-blob``adapter-cache`
- [x] 默认骨架包含 `KMIND``二级节点`、两个 `分支主题``概要`
- [x] 补 Rust 单测:同一 mindmapId 能输出 kernel projection 和 adapter projection,节点数量一致。
- [x] 验证命令:`cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime mindmap_projection`
### Task 3: 审计 lx-doc / KMind Runtime 能力
**Files:**
- Inspect: `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/Edit.vue`
- Inspect: `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/ToolbarNodeBtnList.vue`
- Inspect: `design/05-editor-mainline/reference-code/lx-doc/mind-map/src/pages/Edit/components/SidebarTrigger.vue`
- Inspect: `design/05-editor-mainline/reference-code/kmind-plugin/app/app.js`
- Output Optional: `design/06-mindmap/process/6-mindmap-leptos-adapter-reference-notes-v1.md`
- [x] 列出本轮需要注册的 `simple-mind-map` 插件。
- [x] 列出 toolbar 命令到 kernel command 的映射。
- [x] 列出右侧栏第一阶段保留项:节点样式、导图样式、主题、结构、大纲。
- [x] 列出底部工具第一阶段保留项:统计、搜索、缩放、回根节点、全屏或只读。
- [x] 列出必须进入 `compat_payload` 的字段。
- [x] 明确哪些 KMind 专有能力延期。
### Task 4: 实现 simple-mind-map Bridge
**Files:**
- Create/Modify: `wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts`
- Create/Modify: `wolai-frontend/src/lib/mindmap/leptos-mindmap-adapter.ts`
- Create/Modify: `wolai-frontend/src/lib/mindmap/mindmap-command-diff.ts`
- [x] 动态加载 `simple-mind-map`,避免 SSR 阶段访问 `window/document`
- [x] 注册本轮必需插件:Drag、KeyboardNavigation、Export、Select、RichText、AssociativeLine、Search、Scrollbar、OuterFrame 等按审计结果取舍。
- [x] 支持从 `MindmapAdapterProjection` 初始化 runtime。
- [x] 监听 `data_change``view_data_change``node_active``back_forward``scale``translate`
- [x] 暴露 `execCommand` 安全包装,不让 UI 任意写 blob。
- [x] 销毁时清理 runtime、事件监听和定时器。
### Task 5: 建立 Command Bridge 与 Diff
**Files:**
- Modify: `wolai-frontend/src/lib/mindmap/mindmap-command-diff.ts`
- Modify: `rust/crates/bridge-runtime/src/lib.rs`
- Test: relevant Rust and TS tests
- [x] 直接命令优先:toolbar 明确动作直接发 kernel command。
- [x] `data_change` diff 能识别文本更新、插入子节点、插入同级节点、删除节点、移动节点。
- [x] `view_data_change` 转成 `mindmap.view.patch`
- [x] 主题与结构变化转成 `mindmap.theme.set` / `mindmap.layout.set`
- [x] 暂不可识别字段进入 `compat_payload.patch`,并记录字段路径。
- [x] command 成功后刷新 projection revision。
- [x] command 失败时 UI 显示可定位错误,不伪装保存成功。
### Task 6: 嵌入 Leptos Tiptap Mindmap NodeView
**Files:**
- Modify: `rust/spikes/leptos-tiptap-spike/src/lib.rs`
- Modify: relevant generated island runtime
- Inspect/Modify: `design/05-editor-mainline/reference-code/leptos-tiptap/tiptap/src/extensions/tiptap_paragraph.ts`
- [x] `/` 命令插入 mindmap block 时,Tiptap 节点只保存 `mnoteBlockType="mindmap"``mindmapId``rootNodeId``projectionVersion`
- [x] NodeView 创建 `data-testid="mnote-mindmap-editor-root"`
- [x] NodeView 挂载 `leptos-mindmap` island。
- [x] island 初始化时请求 `mindmap.simple_mind_map_scene.get`
- [x] adapter 初始化失败时显示 `adapter_init_failed`
- [x] projection 获取失败时显示 `projection_load_failed`
- [x] 不创建 `.mnote-mindmap-react-mount` 作为主链合同。
### Task 7: 复刻第一阶段 KMind-like UI
**Files:**
- Create/Modify: relevant leptos-mindmap UI files
- Reference: `lx-doc/mind-map/src/pages/Edit/components/Toolbar.vue`
- Reference: `lx-doc/mind-map/src/pages/Edit/components/SidebarTrigger.vue`
- Reference: `lx-doc/mind-map/src/pages/Edit/components/NavigatorToolbar.vue`
- [x] 顶部工具栏包含撤销、重做、编辑节点、同级节点、子节点、删除节点、标签、超链接、备注、图片、图标、概要、关联线、公式、格式刷、导入、导出。
- [x] 工具栏按钮禁用状态跟随 active node。
- [x] 右侧栏包含节点样式、导图样式、主题、结构、大纲。
- [x] 底部栏包含字数/节点数、回根节点、搜索、缩放百分比、全屏或只读入口。
- [x] 默认主题对齐 KMind 截图:根节点红色、二级节点蓝色、分支蓝色文本、概要括号线。
- [x] 移动端或窄宽度下工具栏能折叠为更多菜单。
### Task 8: 更新 Browser Smoke
**Files:**
- Modify: `scripts/task166-mindmap-phase6-block-smoke.js`
- Reference: `scripts/TESTING_REFERENCE.md`
- Output: `tmp/task166-mindmap-phase6-block-smoke/*.png`
- Output: `tmp/task166-mindmap-phase6-block-smoke/result.json`
- [x] smoke 启动前检查 3000 / 8000 端口占用,并输出 PID、进程名、命令行。
- [x] 使用真实测试账号登录。
- [x] 新建或打开临时文档,通过 `/` 命令插入 mindmap block。
- [x] 断言 `data-testid="mnote-mindmap-editor-root"` 存在。
- [x] 断言 `simple-mind-map` runtime 画布存在且 bounding box 非零。
- [x] 断言至少 4 个可见节点和 3 条可见连线。
- [x] 截图保存插入后、编辑后、reload 后三张图。
- [x] 编辑一个节点文本,等待 kernel command 成功,再 reload,断言新文本仍存在。
- [x] 结构化输出 JSON,包含 `ok``task``baseUrl``documentId``mindmapId``nodeCount``edgeCount``kernelRevision``adapterSource``screenshots``resultPath`
- [x] 失败时错误信息必须指出阶段,例如 `projection_load_failed``adapter_init_failed``runtime_render_failed``command_failed``reload_mismatch`
### Task 9: 调整 Legacy React / Blob 边界
**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`(当前文件已不存在,边界由 `leptos-mindmap-adapter.ts` / `simple-mind-map-bridge.ts` 与静态断言覆盖)
- [x] 给旧 React mindmap 文件增加注释:仅为 legacy/compat/reference,不是 3000 文档页默认主链。
- [x] 禁止新增代码把 `.mnote-mindmap-react-mount` 作为 Phase 6 主验收合同。
- [x] 禁止新增代码把 `window.__mindmapInstance` 作为 smoke 成功条件。
- [x] 保留旧 blob 导入能力,但明确它是 import/compat,不是 canonical edit path。
- [x] 补静态断言或 smoke:默认文档页 host 为 `leptos_tiptap_island` 时不加载旧 React mindmap 主链。
### Task 10: 独立导图页接同一 Adapter Contract
**Files:**
- Modify: `rust/crates/mnote-web/src/routes/mindmap_shell.rs`
- Modify: `rust/crates/mnote-web/src/ssr/pages/mindmap.rs`
- Modify: `wolai-frontend/src/app/mindmap/[docId]/[mindmapId]/page.tsx`
- [x] 独立导图页读取同一 `mindmap.simple_mind_map_scene.get`
- [x] 独立页和文档 block 共用 command bridge。
- [x] 独立页可以有更完整 chrome,但 projection、command、revision contract 必须一致。
- [x] compat fallback 必须带 `source="compat-blob"`UI 或日志可见。
- [x] 补 smoke 或 route 单测:同一个 `mindmapId` 在 block 和独立页返回相同 root、node count、revision。
### Task 11: 验证与复核
**Files:**
- Test: Rust protocol/runtime tests
- Test: leptos-tiptap island build
- Test: `scripts/task166-mindmap-phase6-block-smoke.js`
- [x] 运行 `cd /mnt/Data1T/mnote/rust && cargo test -p core-protocol mindmap`
- [x] 运行 `cd /mnt/Data1T/mnote/rust && cargo test -p bridge-runtime mindmap`
- [x] 重新构建 leptos-tiptap island。
- [x] 启动本地服务,确认 3000 主链来自 `mnote-web` 文档页。
- [x] 运行 `node scripts/task166-mindmap-phase6-block-smoke.js`
- [x] 人工查看 smoke 输出截图,确认不是标题占位、不是空容器、不是旧 React mount。
- [x] 每完成一个 checklist 项,必须基于代码或验证结果再勾选。
### Task 12: Phase 6.1 现实复核与真实 Runtime Cutover
**Files:**
- Modify: `design/05-editor-mainline/reference-code/leptos-tiptap/tiptap/src/extensions/tiptap_paragraph.ts`
- Modify: `rust/spikes/leptos-tiptap-spike/src/lib.rs`
- Modify: `rust/spikes/leptos-tiptap-spike/generated/island/snippets/leptos-tiptap-c355e6ec24c3df4c/src/js/generated/tiptap_paragraph.js`
- Reuse/Modify: `wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts`
- Reuse/Modify: `wolai-frontend/src/lib/mindmap/leptos-mindmap-adapter.ts`
- Reuse/Modify: `wolai-frontend/src/lib/mindmap/mindmap-command-diff.ts`
- Modify: `scripts/task166-mindmap-phase6-block-smoke.js`
- Output: `tmp/task166-mindmap-phase6-block-smoke/*.png`
- Output: `tmp/task166-mindmap-phase6-block-smoke/result.json`
- [x] 确认当前 `tiptap_paragraph.ts` 的 NodeView 是手写 DOM/SVG`renderScene()` 拼接 toolbar、`<button data-testid="mindmap-node">``<path data-testid="mindmap-edge">`
- [x] 确认当前截图 `/mnt/Data1T/mnote/tmp/task166-mindmap-phase6-block-smoke/03-after-reload.png``image copy 70.png``image copy 60.png` 的真实工作台形态差距明显。
- [x] 确认当前 `wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts` 已有真实 `new MindMap(...)` bridge,但没有接入 leptos-tiptap NodeView 主链。
- [x]`tiptap_paragraph.ts` 中的 `renderScene()` 手写节点/连线逻辑改为只创建 runtime mount element、状态层和错误层。
- [x] 建立 leptos-tiptap 可加载的 browser-side adapter 入口,复用 `createLeptosMindmapAdapter()`,避免在 generated bridge 中复制第二套 simple-mind-map 初始化逻辑。
- [x] adapter 初始化时请求 `mindmap.simple_mind_map_scene.get`,把 projection 的 `root/layout/theme/themeConfig/view/config` 传给真实 `simple-mind-map`
- [x] adapter 内部真实调用 `new MindMap({ el, data, layout, theme, themeConfig, viewData, config })`
- [x] NodeView 销毁时调用 bridge `destroy()`,清理 runtime、监听器和 DOM。
- [ ] `data_change` / `view_data_change` 通过 `mindmap-command-diff.ts` 转换为 kernel command 或 `compatPayload.patch`,再调用 `mindmap.command.apply`
- [x] command 成功后刷新 adapter projection 或同步 runtime revision;失败时显示 `command_failed`,不得伪装保存成功。
- [ ] toolbar 的“子节点 / 同级节点 / 删除 / 回根 / 缩放”优先调用 runtime command,再经 command bridge 回写 kernel。
- [x] 右侧栏和底部栏只保留第一阶段 chrome,不再占据画布主要宽度;视觉对齐 `image copy 60.png` 的内嵌 KMind 工作台。
- [x] 删除或降级旧 `.mnote-mindmap-node`、手写 `mindmap-edge`、固定 `svg viewBox` 成为 fallback/debug,不作为默认主链。
- [x] 更新 smoke:禁止以手写 `.mnote-mindmap-node``path[data-testid="mindmap-edge"]` 作为成功条件。
- [x] 更新 smoke:断言真实 runtime mount 内存在 simple-mind-map 生成的 SVG/HTML 层、节点布局非零、连线来自 runtime 渲染层。
- [x] 更新 smoke:保存插入后、编辑后、reload 后截图,并人工对比 `image copy 60.png` / `image copy 70.png` 的工作台结构。
- [x] 运行 `cd /mnt/Data1T/mnote/wolai-frontend && pnpm test -- mindmap` 或等效 TS 单测,验证 adapter/diff 合同。
- [x] 重新构建 leptos-tiptap island。
- [x] 运行 `node scripts/task166-mindmap-phase6-block-smoke.js`
- [x] 只有 smoke 结果 JSON、截图和代码检查都证明真实 `simple-mind-map` runtime 已接入后,才允许勾选本 Task 完成。
备注:2026-05-10 首轮真实 runtime cutover 已通过;仍未勾选的 `view_data_change` 持久化与 toolbar 缩放绑定属于后续交互完善项,不能反向否定真实 runtime 已接入。
### Task 13: UI Shell Reuse 后续收口
**Current Checklist:**
- `design/06-mindmap/process/6-mindmap-phase6-leptos-ui-shell-reuse-checklist-v1.md`
- [x] 2026-05-11 已将后续 UI 可用度收口迁入独立 checklist,目标是 `leptos-mindmap + simple-mind-map runtime + Leptos/Rust floating overlay UI shell`
- [x] 新 checklist 已完成 Task 5A/5B/6/7/8/9/10/11/12/13 的核心验收:floating overlay、Leptos/Rust shell、toolbar/sidebar/navigator/context menu、command bridge、smoke 截图与旧 React 边界。
- [x] 后续 KMind/lx-doc 视觉细化、图标体系、主题细节和高级面板内容按新 checklist 继续,不再把本旧计划的手写伪画布阶段作为 UI 完成判定。
## 退出标准
> 2026-05-10 现实复核后,本段退出标准重新打开。旧勾选只代表伪画布阶段的最小闭环,不能作为最终完成依据。
- [x] 文档页 `/` 插入 mindmap block 后,默认主链是 `leptos-tiptap` NodeView + 真实 `leptos-mindmap` adapter。
- [x] 插入后截图可见 KMind-like 真实根节点、分支节点、概要和连线,且节点/连线由 `simple-mind-map` runtime 渲染。
- [x] `simple-mind-map` runtime 只作为 editor adapter,不是 canonical truth。
- [x] 最小节点编辑动作通过 Rust kernel command 回写,reload 后仍存在。
- [x] smoke 输出结构化 JSON 和截图证据,失败信息能定位到 projection、adapter、runtime、command 或 reload 阶段。
- [x] 旧 React/simple-mind-map block 不在 Phase 6 默认文档页主链内。
- [x] 默认 smoke 不再把手写 `.mnote-mindmap-node` / `path[data-testid="mindmap-edge"]` 当作完成条件。
## 暂不作为阻塞的尾项
- [ ] Rust-native mindmap renderer。
- [ ] 完整复杂布局算法 Rust 化。
- [ ] KMind 多根节点。
- [ ] MOC / 文档树导图。
- [ ] 思源块悬浮预览与镜像块。
- [ ] PDF 标注跳转。
- [ ] 导图 blob 存储彻底移除。
- [ ] Page Aggregate 写后完整回灌统一 projection。
- [ ] tree realtime 全域单 live cache。
## 建议执行顺序
- [x] 第 1 天:Task 1 + Task 2,冻结 projection 和 adapter scene contract。
- [x] 第 2 天:Task 3 + Task 4,审计参考实现并建立 simple-mind-map bridge。
- [x] 第 3 天:Task 5,打通 command bridge 和 adapter diff。
- [x] 第 4 天:Task 6 + Task 7 + Task 8,完成的是手写伪画布最小闭环,不是最终真实 runtime。
- [x] 下一步:Task 12,真实 `simple-mind-map` runtime cutover,替换手写 DOM/SVG 画布。
- [x] Task 12 通过后:复核 Task 9 + Task 10 + Task 11,确认 legacy、独立页和验证口径没有回到伪画布。
- 2026-05-11 复核:新 UI shell checklist 已完成旧 React 边界注释、`editor-host-config` 静态断言和 `task166` smoke;默认成功条件为 `mnote-mindmap-editor-root``simple-mind-map-runtime``mindmap-rust-shell`