feat: EditorRuntimeActor - 三层缓存/delta/事件架构
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
This commit is contained in:
+1
-1
@@ -3,7 +3,7 @@
|
||||
> 更新时间:2026-05-13
|
||||
>
|
||||
> 2026-05-15 口径更新:
|
||||
> - 本文件完成时的 `index.md` 可见 UI 模型已被 `/mnt/Data1T/mnote/design/04-tree-domain/process/4-35-convex-filetree-title-md-source-alignment-v1.md` 覆盖。
|
||||
> - 本文件完成时的 `index.md` 可见 UI 模型已被 `/mnt/Data1T/mnote/design/04-tree-domain/done/4-35-convex-filetree-title-md-source-alignment-v1.md` 覆盖。
|
||||
> - 后续 Convex File Tree 默认页面正文行显示为 `{title}.md`,rowId 为 `doc:<documentId>`;本文中的 `index.md` 仅表示历史正文 object identity / 兼容语义,不再作为默认可见子行继续扩展。
|
||||
>
|
||||
> 上游依据:
|
||||
|
||||
@@ -0,0 +1,237 @@
|
||||
# 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 长期以复合资源树表达页面:
|
||||
|
||||
```text
|
||||
page/document
|
||||
index.md
|
||||
mindmap asset
|
||||
attachment asset
|
||||
```
|
||||
|
||||
`local_folder` 则天然以真实文件系统表达:
|
||||
|
||||
```text
|
||||
新页面.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 修补。
|
||||
|
||||
原因:
|
||||
|
||||
1. 这会改变 `file_tree` projection 合同,不只是修一个显示名称。
|
||||
2. 这会影响 `ObjectIdentity`、active row、rename/title sync、resource parent、trash、restore、search、open intent 和 smoke 期望。
|
||||
3. 现有 `4-24` / `5-12` 已把 `index.md` 作为 Page Aggregate body 的 object identity 收口到 done;如果要废弃或弱化该 UI 体系,必须有新的迁移设计覆盖旧口径,不能在代码里零散改。
|
||||
4. 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}.md` row 或明确 asset row 为准。
|
||||
|
||||
暂不纳入范围:
|
||||
|
||||
- 立即迁移 Convex 底层 documents 表结构。
|
||||
- 自动双向同步 local folder 与 Convex。
|
||||
- Markdown 文件名与标题的所有非法字符、大小写、重名冲突最终规则;本稿先冻结方向,具体规则后续 checklist 补齐。
|
||||
|
||||
## 4. 新旧模型对比
|
||||
|
||||
旧模型:
|
||||
|
||||
```text
|
||||
新页面
|
||||
index.md
|
||||
mindmap-mindmap_xxx.json
|
||||
image.png
|
||||
```
|
||||
|
||||
新目标模型:
|
||||
|
||||
```text
|
||||
新页面.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.md` fallback。
|
||||
- 如果后端 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}.md` row。
|
||||
- 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 Tree `ABC.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` 的 Convex `file_tree` projection 不再为页面正文派生可见 `index.md` row。
|
||||
- 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。
|
||||
|
||||
已通过验证:
|
||||
|
||||
```bash
|
||||
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.json`
|
||||
- `tmp/task438-filetree-title-md-active-reveal-smoke/result.json`
|
||||
- `tmp/task439-filetree-title-md-rename-smoke/result.json`
|
||||
- `tmp/task440-page-title-filetree-md-sync-smoke/result.json`
|
||||
- `tmp/task169-mindmap-realtime-smoke/result.json`
|
||||
|
||||
本轮 P3 收口:
|
||||
|
||||
- 页面标题编辑反向同步到 File Tree `{title}.md` 已由真实浏览器 smoke `scripts/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 覆盖。
|
||||
@@ -1,6 +1,6 @@
|
||||
# 4-6 [done] Tree Command Protocol Cutover Stage 2 v1
|
||||
|
||||
> 更新时间:2026-04-18
|
||||
> 更新时间:2026-05-16
|
||||
>
|
||||
> 目的:冻结树域 command protocol 的长期命名面,并明确 `documents.*` 到 `tree.*` 的兼容迁移口径。
|
||||
|
||||
@@ -100,3 +100,29 @@
|
||||
- Rust / 前端都接受 `tree.*`
|
||||
- 主调用路径默认走 `tree.*`
|
||||
- `documents.create` 等兼容命名不再是新增主语义入口
|
||||
|
||||
## 8. 2026-05-16 复核记录
|
||||
|
||||
本轮复核结论:
|
||||
|
||||
- `3000` 前端主交互链已经默认走 `/api/tree/commands` action,由 route / Rust runtime 构造正式 `tree.*` command envelope。
|
||||
- `documents.*` 仍作为兼容 alias 和 Convex legacy mutation 函数名存在,但不再作为页面生命周期主链新增语义入口。
|
||||
- `bridge-runtime` 已给 `documents.create/title.update/move/delete/restore/purge/copy_tree` 兼容 alias 的 execution plan 增加 `commandProtocol` 元数据:
|
||||
- `owner=rust-runtime-kernel`
|
||||
- `preferredCommandName=tree.*`
|
||||
- `compatCommandName=documents.*`
|
||||
- `deprecatedAlias=true/false`
|
||||
- `mnote-web` transport 在调用 Convex legacy mutation 前剥离 `commandProtocol`,该字段只作为 Rust plan / artifact 审计边界,不进入旧 validator。
|
||||
|
||||
已验证命令:
|
||||
|
||||
```bash
|
||||
cargo test --manifest-path rust/Cargo.toml -p bridge-runtime tree_ -- --nocapture
|
||||
cargo test --manifest-path rust/Cargo.toml -p mnote-web tree_command -- --nocapture
|
||||
cargo test --manifest-path rust/Cargo.toml -p mnote-web convex_command_args_strips_tree_archive_artifacts_for_legacy_mutation -- --nocapture
|
||||
```
|
||||
|
||||
后续仍需单独收口:
|
||||
|
||||
- `/api/documents/create-child` 仍是 compat-only 子页面创建入口,后续应迁到 `/api/tree/commands` 或明确退役。
|
||||
- `mnote-cli` 中页面生命周期命令仍构造旧 `documents.*`,后续若 CLI 继续保留为正式入口,应迁到 `tree.*`。
|
||||
|
||||
Reference in New Issue
Block a user