Phase A — EditorRuntimeActor 内存缓存层 - 新增 editor_actor.rs: EditorBlockDocument 内存态 + apply_command + load_or_init - block.rs 四个写工具(replace/insert/delete/move)接入 actor 路径 - editor_actor feature flag(MNOTE_WEB_ENABLE_EDITOR_ACTOR=true 默认开启) - bridge-runtime 三个核心函数公开化 - rust-toolchain: 1.89 → stable(修复 spike WASM 编译阻塞) Phase B — 编辑器增量 delta channel - BlockDelta/DeltaOperation 类型 + actor.build_block_delta() - leptos-tiptap spike: mnote:editor:block-delta CustomEvent 监听 + JSON patch - DocumentAiAgentPanel: 拦截 blockDelta → window dispatchEvent - 工具响应含 blockDelta 字段供前端消费 Phase C — 事件 stream delta - broadcast channel 在 AppState/actor/SSE 三层贯通 - tree_events SSE 端点发 block.delta 事件 - 旧客户端降级兼容 环境修复 - rustc recursion_limit = 1024(修复 Leptos SSR 类型深度溢出) - run-convex-deploy.js(封装 Convex function 部署到本地后端 3210) ref: design/07-ai/process/7-13-page-block-editor-runtime-actor-v1.md
12 KiB
4-35 [done] Convex File Tree 标题即 Markdown 文件名体系切换 v1
更新时间:2026-05-15
背景:
- 用户反馈本地文件夹中新建页面会先显示
/mnt/Data1T/mnote/tmp/image copy 98.png,再转回新页面.md。- 用户判断这是在线文件夹与本地文件夹的冲突,后续希望“统一而不是继续局部修改”。
- 目标倾向:不再采用 Convex
page -> index.md体系,而是采用直接新页面.md体系,文件名与标题相同;在线文件夹尽量向本地文件夹靠拢。
1. 决策问题
当前 convex_workspace 的 File Tree 长期以复合资源树表达页面:
page/document
index.md
mindmap asset
attachment asset
local_folder 则天然以真实文件系统表达:
新页面.md
图片.png
子目录/
这两种形态同时存在时,UI、active row、rename、新建、外部 watcher、projection refresh 容易出现不一致。用户观察到的“先显示 tmp 图片路径,再转回新页面.md”就是这类冲突的症状之一:同一套 File Tree UI 里混入了本地路径资源、Convex 页面容器、index.md 伪文件和异步投影校准。
本设计稿用于冻结新的方向:后续 Convex File Tree 应逐步向本地文件夹模型靠拢,把页面在文件树中的默认表现改为直接的 Markdown 文件行,例如 新页面.md,而不是页面容器下的 index.md。
2. 建议结论
建议新建一个设计文档,而不是只建 bug 修补。
原因:
- 这会改变
file_treeprojection 合同,不只是修一个显示名称。 - 这会影响
ObjectIdentity、active row、rename/title sync、resource parent、trash、restore、search、open intent 和 smoke 期望。 - 现有
4-24/5-12已把index.md作为 Page Aggregate body 的 object identity 收口到 done;如果要废弃或弱化该 UI 体系,必须有新的迁移设计覆盖旧口径,不能在代码里零散改。 - Convex 存储层仍然是 document record,不等于必须在 File Tree UI 中展示
index.md伪文件。可以先改 projection / UI 语义,再决定是否迁移底层存储。
3. 范围
本设计只讨论 convex_workspace 在 File Tree 中的页面呈现与命令语义,不改变 local_folder 已有真实文件系统规则。
纳入范围:
- Convex 页面在 File Tree 中显示为
{title}.md。 - 新建页面时直接出现
新页面.md,不先出现page/index.md或临时资源路径。 - 重命名页面时,标题与文件名同源:
新标题对应新标题.md。 - 点击
{title}.md打开 Page Aggregate body。 - mindmap、附件、OnlyOffice、代码附件继续作为同一页面下的资源对象,但不能再依赖可见的
index.md子行作为锚点。 - Active / reveal 以
{title}.mdrow 或明确 asset row 为准。
暂不纳入范围:
- 立即迁移 Convex 底层 documents 表结构。
- 自动双向同步 local folder 与 Convex。
- Markdown 文件名与标题的所有非法字符、大小写、重名冲突最终规则;本稿先冻结方向,具体规则后续 checklist 补齐。
4. 新旧模型对比
旧模型:
新页面
index.md
mindmap-mindmap_xxx.json
image.png
新目标模型:
新页面.md
mindmap-mindmap_xxx.json
image.png
解释:
新页面.md是页面正文对象的 File Tree row。- 该 row 的 object identity 可继续内部映射到 Page Aggregate body,但 UI 不再展示
index.md。 - 资源行仍然挂在页面正文对象下面,表达“属于该页面/正文 block 关联资源”。
- Page Tree 仍可显示
新页面,不带.md,作为页面导航 projection。
5. 关键合同变更
5.1 File Tree row
Convex 页面正文 row:
rowKind=markdown_page或沿用index但对 UI 隐藏index.md语义,需要后续冻结。title="{pageTitle}.md"。objectIdentity="page:markdown:{documentId}"或兼容映射到既有page:index:{documentId},但对外不再暴露为index.md。documentId仍是 Convex document id。resourceMeta.sourceKind="convex_workspace"。
本地 .md row:
- 保持真实文件名。
objectIdentity与本地 page identity 绑定,不以裸路径作为长期唯一 id。
5.2 Rename / title sync
Convex workspace 中:
- 文件树重命名
新标题.md应写入页面标题新标题。 - 页面标题编辑应能同步更新 File Tree 行显示为
新标题.md。 .md扩展名是 projection/UI 层文件语义,不应直接写进页面标题。- 重名冲突必须返回结构化 preflight,不允许静默覆盖或临时跳成其它资源路径。
Local folder 中:
- 继续以真实文件名为主,标题优先级仍按现有本地 Markdown 规则处理。
5.3 Create
Convex workspace 新建页面:
- 命令结果中应直接携带最终 File Tree row identity 与
title="新页面.md"。 - UI 乐观插入时不得先显示本地 tmp 路径、上传文件名或
index.mdfallback。 - 如果后端 title 去重为
新页面 2,前端最终只校准成新页面 2.md,中间不出现无关资源名。
5.4 Resource parent
mindmap / attachment 等资源仍挂在页面正文对象下,但 parent row 从旧 index:{documentId} 或 page container 迁移到新的 markdown page row。
需要特别验证:
- 点击 mindmap asset 后 active row 不跳回
{title}.md,除非确实打开的是页面正文。 - 删除
{title}.md进入页面垃圾箱;删除资源进入资源垃圾箱。 - purge 页面时 Convex document 与其资源关系按正式命令同步清理或标记孤儿处理。
6. 与既有设计的覆盖关系
本稿不否定 4-24 / 5-12 的单一真源目标,只调整 File Tree 的可见模型:
- 仍然保留 Page Aggregate body 是页面正文真源。
- 仍然保留 mindmap / attachment / OnlyOffice 是独立 resource object。
- 仍然要求 object identity 隔离,避免 mindmap 污染页面正文。
- 变化是:Convex File Tree 不再必须通过可见
index.md行表达页面正文对象。
后续如执行本设计,必须同步更新以下旧口径:
design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md中“页面节点下固定派生 index.md row”的可见 UI 表达。design/05-editor-mainline/done/5-12-main-editor-object-tab-resource-alignment-checklist-v1.md中index.md tab的命名口径,可迁移为markdown page tab或{title}.md tab。design/10-review/done/05-tree.md作为历史记录不直接改写,但 README 或新设计需说明其index.md口径已被本稿覆盖。
7. 建议实施阶段
P0:只改 Convex File Tree projection 的页面正文显示
- 新建页面后 File Tree 直接出现
{title}.md。 - 点击
{title}.md打开 Page Aggregate body。 - Page Tree 仍显示无扩展名标题。
- 保持底层 object identity 兼容,减少一次性改动。
P1:Active / reveal / object identity 迁移
- active page body 映射到
{title}.mdrow。 - mindmap asset 打开后保持 asset active,不降级为页面正文 row。
- 长列表 reveal 稳定。
P2:Rename / create / conflict preflight
- 文件树 rename
{title}.md与页面标题同步。 - 新建同名页面明确生成
新页面 2.md或返回冲突选择。 - 不再出现临时 tmp 路径或资源文件名作为页面 row title。
P3:旧 index.md UI 退场
- 默认 Convex File Tree 不显示
index.md。 - 如仍需 debug,可通过显式 debug/projection inspector 展示旧 identity。
- 更新 smoke 和设计口径,避免后续继续围绕
index.md修补 UI。
8. 验收标准
- 在 Convex workspace 新建页面后,File Tree 首次可见 row 就是
新页面.md或去重后的{title}.md,不得短暂显示/tmp/...、图片文件名、index.md或其它 fallback。 - 点击
{title}.md打开页面正文;点击 mindmap asset 打开 mindmap object editor,二者 active row 不互相覆盖。 - 页面标题编辑与 File Tree rename 最终保持一致:标题
ABC对应 File TreeABC.md。 - 同名冲突、非法字符、扩展名输入等情况有结构化 preflight 和可预测结果。
- Local folder 与 Convex workspace 共用同一 File Tree UI 组件、selection/focus/reveal/context menu/keyboard 行为;差异只来自 source capability 与 executor。
- 真实浏览器 smoke 覆盖:新建页面、重命名、点击页面正文、点击 mindmap、滚动下半部分点击、删除进垃圾箱、restore 后 reveal。
9. 当前状态
当前状态:done
本文已从 process/ 迁入 done/。Convex File Tree 默认可见页面正文行当前以 doc:<documentId> + {title}.md 为准;旧设计稿中的可见 index.md 仅作为历史 object identity / 兼容语义理解,不再作为默认 UI 模型继续派生新任务。
2026-05-15 已完成 P0/P1/P2 的最小切片:
bridge-runtime的 Convexfile_treeprojection 不再为页面正文派生可见index.mdrow。- Convex 页面正文 row 继续使用
rowKind=document/rowId=doc:<documentId>,但标题改为{pageTitle}.md。 - mindmap / attachment / table 等资源继续挂在
doc:<documentId>下。 - 3000 主文档壳本地 create apply 同步改为只插入
doc:<documentId>,标题显示为{title}.md,不再插入index:<documentId>。 - File Tree 当前页面 selected / focused 默认改为
doc:<documentId>。 task169的“回到页面正文”验证从点击index:<documentId>改为点击doc:<documentId>,object identity 仍为page。- File Tree inline rename 对页面正文 row 输入
{title}.md时,提交给tree.node.rename前会剥离.md,页面标题保持{title},File Tree 显示保持{title}.md。 - File Tree inline rename 已加入主壳内校验:空名、非法文件名字符、同级同名页面会停留在输入框内并显示结构化提示,不提交 rename command。
已通过验证:
cargo test --manifest-path rust/Cargo.toml -p bridge-runtime file_tree_projection -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web file_tree_projection -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_filetree_runtime_uses_markdown_page_row_without_local_index_child -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_shell_filetree_renderer_outputs_initial_nested_html_contract -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web sidebar_tree_runtime -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_shell -- --nocapture
MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task426-mnote-web-main-no-reload-smoke.js
MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task438-filetree-title-md-active-reveal-smoke.js
MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task439-filetree-title-md-rename-smoke.js
MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task440-page-title-filetree-md-sync-smoke.js
MNOTE_UI_BASE_URL=http://127.0.0.1:3428 node scripts/task169-mindmap-realtime-smoke.js
真实浏览器结果文件:
tmp/task426-mnote-web-main-no-reload-smoke/result.jsontmp/task438-filetree-title-md-active-reveal-smoke/result.jsontmp/task439-filetree-title-md-rename-smoke/result.jsontmp/task440-page-title-filetree-md-sync-smoke/result.jsontmp/task169-mindmap-realtime-smoke/result.json
本轮 P3 收口:
- 页面标题编辑反向同步到 File Tree
{title}.md已由真实浏览器 smokescripts/task440-page-title-filetree-md-sync-smoke.js覆盖:标题栏输入{title}后,File Tree 显示{title}.md,Page Tree 与标题输入框保持{title},且不出现index:<documentId>行。 tree_shell/filetree_renderer.rs的默认 nested fixture 已从可见index.md子行改为页面 markdown row 下挂 mindmap asset;rowKind=index仍只作为历史 projection / 命令兼容解析保留,不再作为默认 Convex File Tree UI 口径。- 旧设计中的“可见
index.md”表述由本稿覆盖:后续 UI / smoke / review 应以doc:<documentId>+{title}.md作为 Convex 页面正文 row;如果文档讨论历史index.md,必须明确它是兼容身份或历史记录,不是默认可见行。
仍保留的后续增强:
- 删除进垃圾箱、restore 后 reveal、双浏览器 resync、搜索过滤下 reveal 等更宽场景继续由
4-28、4-34与后续 tree domain checklist 覆盖。