44 KiB
[recycle] mnote 单仓收口 Rust 内核阶段 Checklist
更新时间:2026-04-14
主工作路径:
/mnt/Data1T/mnote第二工作路径:
/mnt/Data1T/mnote-rust(仅作为历史资产来源,不作为主执行仓)对齐文档:
/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-plan.md目标:把
mnote-rust的必要 Rust 内核逐步回迁到mnote主仓,并始终维持“单仓启动、单仓保存、主前端不分叉”的执行口径。
1. 执行口径与硬边界
- 只保留
/mnt/Data1T/mnote作为唯一主产品仓。 /mnt/Data1T/mnote-rust只保留为历史资产来源、参考实现和待吸收规范,不再承担主线执行入口。wolai-frontend继续承担唯一主产品前端壳,不复制mnote-rust的第二套 Next 前端壳。- Rust 内核统一收口到
/mnt/Data1T/mnote/rust/,不再在主仓根目录散落多个 Rust 源码根。 - 最终保存只认 Convex 主事实层;Rust 的事件、索引、缓存、fixtures 都属于派生层。
- 不通过跨仓软链接、硬链接或路径偷接来假装完成迁移。
- 第一阶段不迁入
design/phases/**、design/execution/**、design/UI/**这类历史叙事文档。 - 第一阶段不迁入
mnote-cli、adapter-onlyoffice、adapter-mindmap、adapter-legacy-mnote。 - Mindmap 继续以
mnote当前实现为主:BlockNote 自定义块为主形态,独立全屏页为辅助形态。 - OnlyOffice 继续保持“正文只嵌文件入口、编辑器在独立页面运行”的产品形态,不回嵌 BlockNote。
wolai-frontend/、wolai-backend/、infra/convex/、src/components/onlyoffice/默认保持不动,除非后续阶段明确接线需要。
2. 当前已确认基线(2026-04-13 已核对)
2.1 已完成事实
/mnt/Data1T/mnote/rust/Cargo.toml与/mnt/Data1T/mnote/rust/Cargo.lock已存在。/mnt/Data1T/mnote/rust/crates/下已落位core-domain、core-protocol、event-log、storage-convex-bridge、index-fts、bridge-runtime、mnote-cli。/mnt/Data1T/mnote/rust/design/INDEX.md与design/core/01~04核心设计文档已落位。- workspace members 仅指向
/mnt/Data1T/mnote/rust/crates/*。 - 已验证
cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1可通过。 - 已验证
cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml可通过。 - 已核对
/mnt/Data1T/mnote/rust/下未发现直接引用/mnt/Data1T/mnote-rust的残留路径。 - 已确认当前主前端链路仍在
mnote:文档页为DocumentShell -> DocumentContent -> BlockNoteEditor,Mindmap 仍复用现有MindmapBlock体系,OnlyOffice 仍为独立页面型编辑器。
2.2 当前仍未开始或未初始化的事实
-
/mnt/Data1T/mnote/rust/bridge/已初始化最小说明目录,crates/bridge-runtime已提供 Phase 1 最小真实执行样板。 -
/mnt/Data1T/mnote/rust/scripts/当前未初始化。 -
/mnt/Data1T/mnote/rust/fixtures/当前未初始化。 -
/mnt/Data1T/mnote/rust/tests/当前未初始化。 -
mnote-cli已并入/mnt/Data1T/mnote/rust/crates/,当前已冻结page/block/search/sidebar/tool的最小命令面与--json输出协议。 -
adapter-onlyoffice、adapter-mindmap、adapter-legacy-mnote尚未并入主仓。 -
/api/documents/content、/api/documents/save、/api/documents/title、/api/documents/stats、/api/sidebar、/api/blocks/patch已接入主仓当前 bridge 包装层并统一返回request_id/trace_id元信息;其中documents/title、documents/stats、documents/options、documents/save已进一步收口到统一的 bridge mutation request 运行时接缝,可先构造与storage-convex-bridge::build_write_request对齐的functionName/payloadJson/args对象再落到 Convex,但整条链仍未直接切到core-protocol -> storage-convex-bridge的真实 Rust crate 执行链。2026-04-15 Phase 1/2 补记:
documents.content.get、documents.title.update、documents.save这 1 读 2 写链现已从主仓 Next route 真实进入crates/bridge-runtime,再由 TS 仅做 Convex transport;同时crates/mnote-cli已在主仓 workspace 落位,并通过page/block/search/sidebar/tool五类最小命令面的--json计划输出冻结当前 CLI 协议。
3. Phase A:Rust workspace 落位(主目标已完成)
完成目标:
/mnt/Data1T/mnote/rust/成为唯一 Rust workspace 根。- P0 crate 与核心规范文档已在主仓内有真实副本。
- 新 workspace 已具备最小自检能力。
Checklist:
- 固定
/mnt/Data1T/mnote/rust/为唯一 Rust workspace 根,后续 Rust 命令统一从这里发起。 - 固定 workspace members 只指向
crates/core-domain、crates/core-protocol、crates/event-log、crates/storage-convex-bridge、crates/index-fts。 - 复制并落位
core-domain、core-protocol、event-log、storage-convex-bridge、index-fts。 - 复制并落位
rust/design/INDEX.md与rust/design/core/01-domain-model-v0.md、02-command-query-tool-protocol-v0.md、03-storage-event-indexing-v0.md、04-onlyoffice-integration-boundary-v0.md。 - 统一 workspace 级别的
edition、license、version、authors约定。 - 跑通
cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1。 - 跑通
cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml。 - 已补跑
cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-domain与cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocol。 - 已在本 checklist 第 1 节固定“第一阶段禁止迁入清单”,明确
mnote-cli、adapter-*、design/phases/**、design/execution/**、第二套 Next 前端壳均不属于本阶段交付。
Phase A 验收:
- Cargo 可在主仓内解析 workspace。
- 主仓内已有 P0 内核与长期规范副本。
- 当前未出现对第二工作路径的直接 Cargo 路径依赖。
- 已完成 crate 单测与文档级禁止迁入清单,Phase A 可视为关闭。
4. Phase B:bridge 入口与 Convex 桥接
完成目标:
- 在
mnote主仓内形成唯一 Rust command/query 入口。 - 首批读写入口从“前端 API 直接调 Convex”切到“前端 API -> Rust bridge -> Convex”。
当前起点(已确认):
/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/content/route.ts当前直接query(api.documents.getContent)。/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/save/route.ts当前已改为构造稳定 envelope 后交给save-command-adapter执行。/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/title/route.ts当前已不再直接拼mutation(api.documents.updateTitle)参数,改为构造稳定 envelope 后交给页面元信息 command adapter 执行。/mnt/Data1T/mnote/wolai-frontend/src/app/api/documents/stats/route.ts当前已不再直接拼mutation(api.documents.updateStats)参数,改为构造稳定 envelope 后交给页面元信息 command adapter 执行。/mnt/Data1T/mnote/wolai-frontend/src/app/api/sidebar/route.ts当前直接聚合多个 Convex query 结果。/mnt/Data1T/mnote/wolai-frontend/src/app/api/blocks/patch/route.ts当前直接读取文档内容、替换 block 树后回写 Convex。
Checklist:
-
已在
wolai-frontend/src/lib/documents/bridge.ts固定当前 bridge 入口,先由主仓 API route 统一走同一层包装。 -
已固定首批 bridge envelope:
request_id、trace_id、workspace_id、actor、source、idempotency_key。 -
约定所有新命令和查询都先进入
core-protocolenvelope,再转给storage-convex-bridge。 -
已把
documents/content与sidebar两条低风险读链接入当前 bridge query 包装层。 -
已把
documents/title、documents/stats、documents/save、blocks/patch接入当前 bridge command 包装层。 -
已为
documents/title、documents/stats收口稳定的页面元信息 command adapter,冻结 route 到 Convex 之间的 payload/target/meta 映射,避免 route 继续直接耦合updateTitle/updateStats的参数细节。 -
已为首批 4 条写链固定当前
bridge -> Convex的函数名、payload 结构和 workspace scope;其中documents.title、documents.stats、documents.options、documents.save已先收口到buildDocumentBridgeMutationRequest这层最小运行时接缝,统一构造与storage-convex-bridge::build_write_request对齐的functionName/payloadJson/args,再由同一执行器落到 Convex;blocks.patch仍未收口到该执行层,且整条链尚未直接切到 Rust crate 内统一执行。 -
已在
wolai-frontend/convex/schema.ts新增command_logs、domain_events两张表,并新增wolai-frontend/convex/bridgeLogs.ts与src/lib/documents/bridge-log.ts承接首批写链日志落账。 -
首批 4 条写链(
documents/title、documents/stats、documents/save、blocks/patch)当前会在成功路径同时写入 command log 与 domain event;失败态、回滚态和统一事务性仍待后续补齐。 -
当前已接入的查询链(
documents/content、sidebar)保持只读,不产生写副作用。 -
已统一
documents/content、documents/save、documents/title、documents/stats、sidebar的首批 bridge 错误返回结构。 -
当前 bridge 仅负责协议校验、请求映射与响应元信息包装,尚未吞并产品 UI 逻辑。
2026-04-14 B 阶段补记:已在
rust/crates/core-protocol中补齐documents.meta.get、documents.content.get、sidebar.dataset.list、documents.save、blocks.patch的最小 query/command 协议对象,并在rust/crates/storage-convex-bridge中补齐对应的 query/command name -> Convex function 映射与单测。当前主仓新增链路已统一先构建稳定 envelope,再由后续真实 Rust bridge 执行链消费;本轮已通过cargo test -p core-protocol -p storage-convex-bridge与cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml验证协议与映射闭环。 2026-04-14 B 阶段第三刀补记:已在wolai-frontend/src/lib/documents/bridge.ts新增buildDocumentBridgeMutationRequest与统一执行器,把documents.title.update、documents.stats.update、documents.options.update、documents.save进一步推进到最小可运行的 Rust bridge 风格接缝。当前这些写链会先生成与storage-convex-bridge::build_write_request对齐的functionName/payloadJson/args运行时对象,再由适配层调用 Convex mutation;配套src/lib/documents/bridge.test.ts已新增 request builder 断言,确认标题更新与正文保存两条链的运行时 request 形状稳定。
Phase B 验收:
- 当前至少已有 2 条查询链(
documents/content、sidebar)和 4 条写链(documents/title、documents/stats、documents/save、blocks/patch)通过当前 bridge 包装层读写 Convex。 - 已补
/api/bridge/trace、/api/bridge/request回查入口,并已切到wolai-frontend/convex/bridgeLogs.ts查询主线;convex/audit.ts当前保留为并行旧实现线,不作为本轮回查入口。 - 当前已接入的请求错误结构已统一到 bridge 错误响应,不再直接抛出临时调试字符串。
- 本批改动只改 API route 与调用 payload,未改页面结构与 UI 外观。
建议验证:
cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml- 已对
/api/documents/content、/api/sidebar做最小读链 smoke:当前主仓实例固定为http://127.0.0.1:3001,/api/sidebar已返回activeWorkspaceId=ws-smoke-temp,新建文档后/api/documents/content可正常返回内容与requestId/traceId。 - 已对
/api/documents/title、/api/documents/stats、/api/documents/save、/api/blocks/patch做最小写链 smoke:真实写入成功,且随后/api/documents/content已读回blocks.patch改写后的正文。 - 已完成真实 Convex 运行前置验证:
infra/convex/docker-compose.yml可启动本地自托管 Convex,pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping已通过。 - 已用真实 Convex CLI 对
bridgeLogs:recordCommandLog、bridgeLogs:recordDomainEvent、bridgeLogs:listByTrace、bridgeLogs:listByRequest做最小 smoke,确认 command log、domain event、trace/request 字段能同时落账并回查。 - 已完成网页/API 级 smoke:从真实
/api/documents/title、/api/documents/stats、/api/documents/save、/api/blocks/patch返回的requestId/traceId,可继续经/api/bridge/trace与/api/bridge/request回查到对应command_logs/domain_events。本轮同时修复src/lib/documents/bridge-log.ts中getAuthedConvexClient()返回值解构错误(此前会导致写链落账时报client.mutation is not a function)。
5. Phase C:页面元信息、Sidebar 与正文保存接入
完成目标:
- 在不更换主前端壳的前提下,把文档元信息、Sidebar 聚合、BlockNote 正文保存逐步切到 Rust 协议层。
- 执行顺序严格按
C1 页面元信息 -> C2 Sidebar 聚合 -> C3 正文保存推进,不跳步。
C1 页面元信息
- 已盘点并锁定文档页元信息读写边界:
src/app/(app)/documents/[id]/page.tsx负责元信息入口,document-content.tsx负责标题/页面选项/统计信息写入,document-shell.tsx仅继续透传既有 UI 壳参数。 - 已锁定并接入当前 C1 最小读链:
src/app/(app)/documents/[id]/page.tsx原先直调api.documents.getMeta,现已改为经GET /api/documents/meta进入现有 bridge query 包装层;新增的服务端 helper 仅负责透传当前请求认证/追踪头并发起同源 bridge route 请求。 - 已把标题更新、页面属性、页面选项、统计信息这批低风险页面元信息操作切到统一的当前协议/适配边界:标题、统计信息、页面选项 3 条写链都已接入当前 bridge command 包装层;其中
documents.title.update、documents.stats.update、documents.options.update已统一收口到wolai-frontend/src/lib/documents/metadata-command-adapter.ts,route 只保留 validation、buildDocumentBridgeContext、buildDocumentCommandEnvelope与稳定错误模型。documents.options本轮不再内联client.mutation(api.documents.updateOptions, ...)。同时已补齐rust/crates/core-protocol的UpdatePageTitle、UpdatePageStats、UpdatePageOptions结构与storage-convex-bridge的 command name -> Convex mutation 映射测试;2026-04-14 又进一步把这 3 条写链切到buildDocumentBridgeMutationRequest,先构造与 RustConvexMutationRequest对齐的最小运行时 request,再交给统一执行器落到 Convex,为后续真实 Rust 执行链留出稳定接缝。 - 当前最小替换已保持现有页面 UI、权限判断、动态导入结构不变:
DocumentShell入参、readOnly/disableDownload/disableCopy计算、notFound()分支与页面结构保持不变,仅将元信息读取入口切到documents.metabridge query。 - 已统一页面元信息链当前口径:
documents.meta读链与documents.title/stats/options写链均复用buildDocumentBridgeContext/ envelope;query payload 与 command payload 已固定documentId/workspaceId,target.pageId 固定文档 business id,回传元信息统一为requestId/traceId/queryName|commandId|commandName,actor/source 也统一来自 bridge context。 - 已为标题更新、页面属性、统计信息补齐当前最小回归验证。
当前最小验证:已对页面选项写链补跑相关文件 eslint / vitest,并完成真实 HTTP smoke,确认在主仓
http://127.0.0.1:3001实例下以ws-smoke-temp工作区调用POST /api/documents/options后,会返回requestId=req_aef4159e-24f2-43a8-b168-864c4b2b2c6c、traceId=trace_3cbc114e-db01-410f-933c-e63d8bd83393、commandId=cmd_2cb6871d-9075-4252-b698-a7c4ea069bfd,且后续/api/bridge/request与/api/bridge/trace已能回查到对应command_logs/domain_events。本轮同时保留documents.meta读链最小验证:真实GET /api/documents/meta?documentId=...&workspaceId=ws-smoke-temp已返回doc + meta.requestId/traceId/queryName=documents.meta.get。另外documents/stats写链的真实 HTTP smoke 也已完成并可回查。2026-04-14 新增一轮真实复测:同一documentId连续执行POST /api/documents/options {showToc:true,layoutDensity:\"compact\"}与POST /api/documents/stats {wordCount:12,characterCount:34,blockCount:2,todoTotal:5,todoDone:3}后,紧跟 5 次GET /api/documents/meta均稳定返回本次写入值,未再复现“同次写入后 meta 读回不稳定”的现象。为避免历史脏数据导致偶发漂移,已把convex/documents.ts的关键by_document_id读写收口到 deterministic canonical record 选择逻辑,并补了重复 business id 的回归测试。 2026-04-14 第二批真实收口:已将仍直接依赖by_document_id.first()的高风险页面/文档关联路径继续切到同一 canonical document helper,当前已覆盖convex/documentShares.ts、convex/documentGroupShares.ts、convex/documentStars.ts、convex/comments.ts、convex/references.ts。这批路径分别影响页面共享权限判定、群组公开、收藏可见性、评论线程读写与反链标题读取;此前若同一 businessdocumentId存在重复物理记录,会继续存在命中漂移风险。本轮已补跑目标文件eslint、src/lib/documents/document-record.test.ts,并用源码扫描确认这批目标文件内已不再残留by_document_id.first();当前未继续扩到mediaAssets.ts、mindmaps.ts等非本批最小闭环路径。 2026-04-14 第三批真实收口:继续只处理剩余 still-high-risk 的documents.by_document_id直接命中点,已新增convex/_utils/documentRecord.ts#getCanonicalParentDocumentId,并把convex/comments.ts、convex/documents.ts中共享/权限祖先链扫描统一改到该 helper,避免同一 businessdocumentId的重复物理记录在父链遍历时再次漂移。同时已把convex/mindmaps.ts的 owner 校验从by_document_id.first()切到requireCanonicalOwnedDocument,并将convex/mediaAssets.ts#createWithStorage的页面归属校验改为getCanonicalDocumentByBusinessId,以覆盖页面内容附件上传这一仍会直接命中旧记录的高风险入口。本批最小验证目标为:补充 canonical helper 单测、对上述目标文件跑eslint,并再次用源码扫描确认comments/documents/mindmaps/mediaAssets内不再残留直接依赖documents.by_document_id的实现。 2026-04-14 第四批真实收口:按本轮 C1 要求只处理convex/documentStars.ts剩余两个父链祖先扫描点,已将resolveSharePermission与resolveGroupSharePermission中手写的documents.by_document_id父级推进统一改为getCanonicalParentDocumentId。同时已补充src/lib/documents/document-record.test.ts的 helper 回归用例,验证重复 businessdocumentId下即使旧记录已删除,父链 helper 仍稳定返回 canonical 父页面 id;并已补跑目标文件eslint与vitest。本轮源码扫描确认wolai-frontend/convex/业务路径中已不再残留直接withIndex(\"by_document_id\")命中点,当前仅剩convex/_utils/documentRecord.ts作为底层 canonical helper 持有该查询。
C1 验收:
-
页面元信息至少已有 3 条低风险链路切入 Rust 层。
-
文档页外观与交互未退化。
-
trace 字段已可回查到页面级写入:
documents.title.update、documents.stats.update、documents.options.update的真实 HTTP 写入均已返回requestId/traceId,且后续/api/bridge/request与/api/bridge/trace已复核可查到对应command_logs/domain_events。2026-04-14 C1 浏览器回归补记:已新增
/mnt/Data1T/mnote/scripts/task019-document-ui-regression.js并在真实本地实例http://127.0.0.1:3001上执行。脚本会创建临时页面,确认 Sidebar 主导航与“私有 / 我的页面”分区可见、文档页标题输入框与 BlockNote 编辑区正常渲染,然后实际修改标题与正文,等待/api/documents/title、/api/documents/save成功返回并出现“已保存”,最后刷新页面确认标题与正文仍保留,再调用/api/documents/purge清理临时页面。实跑结果通过,说明本轮协议层切换后文档页主交互未退化。
C2 Sidebar 聚合
-
盘点 Sidebar 真实数据来源,锁定
sidebar.tsx、private-tree.tsx、file-tree.tsx、use-convex-sidebar-data.ts、sidebar-tree.ts。 -
先把 Sidebar 的查询聚合逻辑抽象成 Rust query 目标,避免继续在前端和 API 中重复拼树。
-
为 Sidebar 建立最小查询契约,至少覆盖页面列表、层级关系、文件树行模型和展开状态所需字段。
-
保留现有 Sidebar UI 和交互,不引入第二套导航壳,也不从
mnote-rust复制sidebar.tsx覆盖现实现。 -
把 Mindmap、表格、媒体等派生资源的聚合边界整理成后续 Rust query 可接入的明确目标。
2026-04-14 盘点补记:当前主入口已确认位于
wolai-frontend/src/components/sidebar/sidebar.tsx,私有树/文件树分别位于components/sidebar/private-tree.tsx与components/sidebar/file-tree.tsx;数据侧同时存在/api/sidebar聚合 route、hooks/use-convex-sidebar-data.ts实时订阅组装,以及lib/sidebar-tree.ts的树/section 构建逻辑,说明 C2 的真实起点是“API 聚合 + 前端二次拼装”的双层结构。 2026-04-14 契约补记:当前最小 Rust query 目标已明确为兼容SidebarInitialData的单查询返回,至少覆盖active_workspace_id、workspaces、documents、trashed_documents、media_assets、trashed_media_assets、mindmap_assets、trashed_mindmap_assets、table_assets、trashed_table_assets、mindmap_docs、mindmap_asset_children,从而先替换聚合来源而不改buildDocumentTree/buildVisibleRows的前端渲染逻辑。 2026-04-14 边界补记:当前已明确必须保持不变的 UI/交互包括starred/public/shared/private/templates分区语义、sort_order -> created_at排序口径、doc/index.md/asset-folder/asset文件树行语义、拖拽/剪贴板协议,以及回收站双 tab 与资源计数行为;Mindmap、表格、媒体三类派生资源的聚合边界已被明确列为 Rust query 后续接入目标。 2026-04-14 C2 第一刀收口补记:已新增wolai-frontend/src/lib/sidebar-data.ts与wolai-frontend/src/lib/server/sidebar-data.ts,把src/app/(app)/layout.tsx、src/app/api/sidebar/route.ts、src/hooks/use-convex-sidebar-data.ts之间重复的SidebarInitialData组装统一收口到共享 helper;同时修复 hook 链路中mindmapAssetChildren长期为空的漂移,补充src/lib/sidebar-data.test.ts,并通过pnpm test src/lib/sidebar-data.test.ts src/lib/file-tree/rows.test.ts与定向eslint验证。基于本轮复核,当前已可确认“多个前端位置不再重复拼装同一棵树”这一验收点达成;但由于 SidebarInitialData 仍未冻结为明确 Rust query contract,C2其余验收项暂不提前勾选。 2026-04-14 C2 第二刀补记:已新增/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/process/sidebar-rust-query-target.md,把sidebar.dataset.list的最小 payload/result、Rust query 与前端投影职责边界、以及“不复制第二套导航壳/不直接输出前端渲染树”的约束固定成文档。当前可确认 Sidebar 查询聚合目标已经从“散落在 route 和 hook 中的实现细节”收口为明确的 Rust query 接入目标。
C2 验收:
-
Sidebar 至少一条主查询已经改由 Rust query 供给。
-
文档树、文件树、回收站等视图语义保持一致。
-
不再需要在多个前端位置重复拼装同一棵树。
2026-04-14 C2 第三刀补记:已新增
wolai-frontend/convex/sidebar.ts,把页面列表、回收站、Mindmap、媒体、表格等数据集收口成单个sidebar.datasetList主查询;src/lib/server/sidebar-data.ts与src/hooks/use-convex-sidebar-data.ts均已切换为消费这条单查询返回,再通过既有SidebarInitialData投影层驱动 UI。配合src/lib/sidebar-data.test.ts的契约冻结、src/lib/file-tree/rows.test.ts的文件树行语义验证,以及定向eslint,当前可确认文档树、文件树、回收站双 tab 依旧沿用原有前端投影逻辑,没有因数据源切换而改变语义。 2026-04-15 C2 第四刀补记:/api/sidebar现已从“先直跑 Convex helper,再额外挂 meta”推进为真实 Rust query transport。当前 route 会先执行buildDocumentQueryEnvelope(name=\"sidebar.dataset.list\") -> resolveRustBridgeQueryPlan -> executeRustBridgeQueryTransport,再把sidebar:datasetList的结果投影回SidebarInitialData;这意味着 Sidebar API 主链已经真正进入 Rust runtime/bridge,而不再只是挂一个 envelope 名字。
C3 BlockNote 正文保存
- 盘点正文保存链路,锁定
blocknote-editor.tsx、schema.ts、文档保存 API 当前入口。 - 先把正文保存切成“前端快照采集”和“Rust command 提交”两个边界。
- 为正文保存定义最小协议对象,至少包含
page_id、workspace_id、revision、actor、source、block 快照、冲突检测字段。 - 先接入低风险保存模式,例如显式保存或节流保存,不先处理复杂协同细节。
- 确保正文链与页面元信息链、Sidebar 链共用同一 identity 口径,不再出现多套 page id 映射。
C3 验收:
-
正文保存至少一条正式链路已经通过 Rust command 回写 Convex。
-
保存失败时可返回稳定错误模型。
-
保存成功时可回查 command log、domain event 与 trace。
2026-04-14 C3 第一刀收口:已为
documents.getContent/documents.save增加独立content_revision与content_conflict_key,避免标题/统计信息更新污染正文 revision;/api/documents/content现会透传revision/conflictDetectionKey,BlockNoteEditor会在自动保存时携带revision、conflictDetectionKey、snapshotCapturedAt、blockCount,并在成功后刷新本地保存元数据。save-command-adapter现把 Convex 冲突归一为409 REJECTEDbridge 错误,编辑器右上角也会展示保存失败信息。当前最小验证已补save-contract/bridge单测,并完成定向 eslint;结果为无 error,仅保留仓库既有 warnings。 2026-04-14 C3 第二刀补记:源码复核确认BlockNoteEditor当前通过useDebouncedCallback(saveContent, 800)以防抖自动保存作为最小低风险保存模式,没有把复杂协同状态直接并入正文写链;同时documents.meta/title/stats/options/save这些 route 都把同一个normalizedDocumentId作为target.pageId,documents.content/savepayload 也统一使用documentId/workspaceId,sidebar.dataset.list则以同一workspace_id作用域返回documents[].id作为页面业务 id,因此当前正文链、页面元信息链与 Sidebar 聚合链已不存在第二套 page id 映射口径。 2026-04-14 C3 第三刀补记:在此前真实/api/documents/save -> /api/bridge/request|tracesmoke 已确认可回查的基础上,本轮又补了src/lib/documents/bridge.test.ts的成功路径断言,明确executeSaveBridgeCommand在 revision/conflictDetectionKey 新协议下仍会调用recordBridgeCommandArtifacts,并把同一requestId/traceId/commandId暴露给回查入口。因此当前“保存成功时可回查 command log、domain event 与 trace”已具备历史 HTTP smoke 与当前单测的双重闭环。 2026-04-14 C3 第四刀补记:save-command-adapter已进一步切到与页面元信息链一致的最小运行时接缝。当前documents.save会先构造functionName=documents:updateContent、payloadJson、args组成的 bridge mutation request,再由统一执行器实际调用 Convex;这让正文保存不再长期停留在“adapter 内直接手写client.mutation(...)”的临时态,同时保留现有冲突归一和落账逻辑不变。 2026-04-15 Phase 5 第一刀补记:search.documents、search.recent已补齐到主仓 Rust query/runtime 主链。当前rust/crates/core-protocol新增SearchDocuments/SearchRecent,storage-convex-bridge与bridge-runtime已支持 query name -> Convex function 映射和运行时分发;rust/crates/index-fts新增evaluate_search_documents,负责标题/正文/思维导图/表格/附件的召回合并、排序、高亮 snippet 与 OCR 待补队列决策。wolai-frontend/src/app/api/search/documents/route.ts现仅保留参数整理、原始数据装载与 HTTP 回传,不再持有 TS 侧的核心 ranking/snippet 逻辑;/api/search/recent继续只承担最近访问写入 side-effect。
6. Phase D:Mindmap 与 OnlyOffice 边界接入
完成目标:
- 保留
mnote当前成熟的 Mindmap 与 OnlyOffice 前端实现。 - 把数据边界、对象边界和回调边界逐步纳入 Rust adapter / protocol 规划,而不是复制第二套对象页壳。
Checklist:
-
锁定 Mindmap 当前主组件和嵌入链路,确认
MindmapBlock.tsx同时服务 BlockNote 内嵌块与独立全屏页。 -
盘点 Mindmap 数据入口,锁定
mindmapLocalStore.ts、mindmapOps.ts、app/api/mindmap/**、app/mindmap/**。 -
把 Mindmap 的前端交互状态与本体数据/ops 边界拆开,后者逐步映射到 Rust 协议层。
-
明确
mnote-rust/app/documents/[id]/mindmap/page.tsx等对象页壳不进入主仓主线。 -
为 Mindmap 设计最小 adapter 目标,至少覆盖节点树、节点引用、节点操作日志和与 page/block 的绑定关系。
-
锁定 OnlyOffice 当前页面和 API 边界,确认
src/app/onlyoffice/、src/app/api/onlyoffice/**、src/components/onlyoffice/的职责分工。 -
保留根目录
src/components/onlyoffice/的静态资源、插件和数据目录,不做误删、不做迁移式替换。 -
把 OnlyOffice 的对象解析、签名、callback、forcesave、代理请求边界整理成 Rust adapter 的明确目标。
-
继续保持“正文只嵌文件入口,OnlyOffice 在独立页面运行”的产品形态。
-
统一 Mindmap 与 OnlyOffice 的页面标识、附件标识、页面归属和追踪字段。
2026-04-14 Phase D 盘点补记:已新增
/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/mindmap-onlyoffice-boundary.md,固定MindmapBlock.tsx与独立全屏页共用同一核心组件、mindmapLocalStore.ts/mindmapOps.ts/app/api/mindmap/**的数据与 ops 边界,以及 OnlyOffice 的page -> client -> sign/proxy/callback/forcesave职责分层。文档同时明确MediaBlock仅作为 Office 附件入口、/onlyoffice继续作为独立编辑页面,且历史仓中的对象页壳与第二套 sidebar 只保留为参考实现。 2026-04-14 Phase D 收口补记:已把 Mindmap API 与组件侧统一到与 OnlyOffice 对齐的业务标识口径。当前 Mindmap 统一使用pageId=documentId、attachmentId=mindmapId、workspaceId作为页面归属,并在/api/mindmap/**返回稳定的requestId/traceId元信息;OnlyOffice 继续使用documentId + assetId作为页面/附件标识,因此两条链后续接 Rust adapter 时不再需要第二套 page/attachment 映射。 2026-04-14 Phase D 浏览器回归补记:已新增/mnt/Data1T/mnote/scripts/task021-mindmap-ui-regression.js并在真实本地实例http://127.0.0.1:3001上执行。脚本使用当前共享的MindmapBlockView全屏入口/mindmap/[docId]/[mindmapId],验证页面data-page-id/data-document-id/data-attachment-id/data-mindmap-id/data-workspace-id元信息、工具栏与“大纲”侧栏渲染、子节点新增与删除后的持久化、以及/api/mindmap/**返回的requestId/traceId会同步回 DOM。考虑到内嵌块与独立页共用同一核心组件,这轮浏览器回归可视为覆盖当前共享交互/保存内核,实跑未见退化。 2026-04-15 Phase D OnlyOffice callback 收口补记:已为OnlyOffice callback新增最小命令media.assets.replace_storage,同步补齐rust/crates/core-protocol的ReplaceMediaAssetStorage、rust/crates/storage-convex-bridge的 command name -> Convex mutation 映射,以及主仓buildDocumentBridgeMutationRequest的运行时接缝。src/app/api/onlyoffice/callback/route.ts现保留下载文件、上传到 Convex Files 获得storageId的现有流程,但最终写回已改为经buildDocumentBridgeContextWithActor -> buildDocumentCommandEnvelope -> executeMediaAssetWritebackBridgeCommand进入统一 bridge 边界,再调用api.mediaAssets.replaceStorageFromUpload。配套src/app/api/onlyoffice/callback/route.test.ts、src/lib/documents/bridge.test.ts、Rust 单测与scripts/task022-onlyoffice-ui-regression.js已通过,确认storage_id在真实浏览器里继续发生变化。
Phase D 验收:
- Mindmap 与 OnlyOffice 的前端界面仍以
mnote当前实现为主,没有引入第二套主壳。 - Mindmap 的节点/操作边界与 OnlyOffice 的签名/callback/forcesave 边界都已进入统一规划。
src/components/onlyoffice/保持可用且未被误删。adapter-onlyoffice、adapter-mindmap仍作为后置实现项,而不是本阶段强行复制进主线。
7. Phase E:历史收口与单仓执行统一
完成目标:
mnote-rust正式退出主产品角色。mnote主仓成为唯一启动、保存、规划和验证入口。
Checklist:
- 统一团队口径:主产品仓只有
/mnt/Data1T/mnote,/mnt/Data1T/mnote-rust只保留为历史参考和资产来源。 - 把所有新的设计、执行清单、架构说明优先写入
/mnt/Data1T/mnote/design/与/mnt/Data1T/mnote/rust/design/。 - 复查仓库脚本和说明文档,去掉“先进
mnote-rust再启动”的旧叙事。 - 统一根目录脚本入口,让仓库级脚本只从
/mnt/Data1T/mnote/scripts/发起,再按需调用cargo --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml ...。 - 对仍需保留的
mnote-rust资料按“核心规范 / 历史阶段 / 参考实现 / 错误方向”分类,避免后续误复制。 - 把已确认不应主线保留的对象页壳、diagnostics 页、smoke 页继续留在历史仓,不进入主仓实现。
- 对主仓内新增的 Rust 目录建立最小维护约定,明确谁负责 workspace、谁负责 bridge、谁负责接入链。
- 重新审查
ARCHITECTURE.md、AGENTS.md、rust-kernel-backport-plan.md与本 checklist,保证四者口径一致。 - 固定“哪些目录默认不动”的硬边界,特别是
wolai-frontend/、wolai-backend/、infra/convex/、src/components/onlyoffice/。
Phase E 验收:
-
后续协作默认只进入
mnote主仓规划和开发。 -
主仓文档和脚本不再把
mnote-rust叙述为主执行入口。 -
历史仓的保留范围、参考价值和禁止误复制范围都已固定下来。
2026-04-14 Phase E 收口补记:已新增
/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-single-repo-maintenance-boundary.md,统一记录主仓执行入口、历史仓资料分类、禁止误复制清单与 workspace/bridge/接入链责任面;同时已复查根package.json与scripts/desktop-hot.js,确认仓库级脚本仍只从/mnt/Data1T/mnote/scripts/发起,且ARCHITECTURE.md已移除把mnote-rust写成未来执行承载面的表述。
8. 发布前总审计(跨阶段)
-
为
/mnt/Data1T/mnote/rust/补基础验证矩阵,至少覆盖cargo metadata、cargo check、必要 crate 单测。 -
为 bridge 入口补集成 smoke,验证最小查询、最小写入、日志生成、事件生成和错误返回。
-
为文档页元信息、Sidebar、BlockNote 保存链补端到端回归,确认 UI 未因为协议层切换而退化。
-
为 Mindmap 补交互回归,重点验证内嵌块、独立页、数据保存、节点操作和工具栏/侧栏行为。
-
为 OnlyOffice 补回归,重点验证签名、代理、callback、forcesave、文档打开和静态资源可用性。
-
检查主仓启动路径,确保开发者只需进入
/mnt/Data1T/mnote就能完成前端、后端、Rust、OnlyOffice 相关联调。 -
检查保存口径,确认页面、块、文档、索引的最终真相仍然落在 Convex,而不是被临时缓存目录劫持。
-
检查
trace_id、request_id、workspace_id、page_id在前端、bridge、Convex、日志中的一致性。 -
对本次回迁引入的所有新目录和新文档做一次清点,确认没有误带入
mnote-rust的历史噪音。 -
为统一观测面补正式 Rust 能力面,至少包含
bridge_request_get、bridge_trace_get、bridge_command_get、event_replay、index_rebuild这组 query/job/tool,并确认 Web 回查入口不再私有直连。2026-04-14 发布前审计补记:已新增
/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-backport-audit-inventory.md,清点主仓rust/已并入的 workspace/crates/设计文档、本轮新增的根design/文档,以及当前仍未并入主线的adapter-*、mnote-cli、bridge/scripts/fixtures/tests目录。文档同时核对了package.json、scripts/desktop-hot.js与AGENTS.md的主仓启动口径,确认开发者只需进入/mnt/Data1T/mnote即可找到前端、后端、Rust 与 OnlyOffice 的联调入口。 -
2026-04-15 task-034 补记:已在
rust/crates/core-protocol增补GetBridgeRequest/GetBridgeTrace/GetBridgeCommand以及bridge_request_get、bridge_trace_get、bridge_command_get、event_replay、index_rebuild五个统一观测/恢复工具;rust/crates/storage-convex-bridge已补 query name -> ConvexbridgeLogs:*映射;rust/crates/bridge-runtime已支持这组 query/job 的 plan/result 输出,并把index-fts::rebuild_from_events暴露为正式index_rebuild恢复入口。前端/api/bridge/request、/api/bridge/trace已切到buildDocumentQueryEnvelope -> resolveRustBridgeQueryPlan -> executeRustBridgeQueryTransport主链,同时支持按commandId过滤与统一排序返回;src/lib/documents/bridge-log.ts也已把命令日志/领域事件状态显式化,为后续失败态、冲突态与补偿落账提供稳定边界。配套验证已通过全量cargo test --manifest-path rust/Cargo.toml与 bridge 定向 eslint。 -
2026-04-15 OnlyOffice 升级与实跑补记:已把
8082文档服务从旧仓mnote-rust/infra/onlyoffice/docker-compose.yml迁回当前主仓/mnt/Data1T/mnote/infra/onlyoffice/docker-compose.yml,并升级到onlyoffice/documentserver:9.3.1。同时修复了/onlyoffice/plugins/*被 middleware 重定向到/auth导致自定义插件桥无法 ready 的问题,为wolai-frontend/public/onlyoffice/plugins/agent-tools/补齐非可视插件配置与plugins.js加载。最终scripts/task022-onlyoffice-ui-regression.js已在真实浏览器中通过,覆盖文档打开、oo_insert_text插件调用、同步保存、callback 写回以及storage_id刷新变化闭环。 -
2026-04-15 OnlyOffice callback bridge 补记:本轮在复跑
scripts/task022-onlyoffice-ui-regression.js前,曾因/auth快速登录触发POST /api/auth -> Could not find public function for 'auth:signIn'导致浏览器脚本卡在登录页;已通过cd /mnt/Data1T/mnote/wolai-frontend && pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping重新注册 Convex functions 后恢复。恢复后同一浏览器脚本再次通过,确认新接入的media.assets.replace_storagebridge 命令没有破坏 OnlyOffice 打开、插件桥、forcesave、callback 与storage_id更新闭环。 -
2026-04-14 浏览器实跑补记:
task-019-document-ui-regression.js已在真实浏览器中覆盖“首页进入文档页 -> Sidebar 可见 -> 修改标题 -> 修改 BlockNote 正文 -> 等待保存成功 -> 刷新后仍保留”的最小闭环。运行前曾因本地 Convex 实例缺少workspaces:ensureDefaultWorkspace导致首页500,本轮已通过pnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping重新注册函数后恢复;最终浏览器脚本通过,且临时页面已清理。 -
对以下禁止事项做最终复查:不双仓并行、不跨仓链接、不复制第二套产品前端壳、不把对象页壳/diagnostics/smoke 页带入主线、不散落多个 Rust 源码根。
-
产出最终 cutover 文档,按能力域列清哪些 route 已仅剩 transport,哪些旧 TS 执行面必须继续迁移或后续删除。
-
以“单仓路径可启动、可保存、可验证、可继续演进”作为发布前收口标准。
2026-04-14 实跑记录:已重新执行
cargo metadata --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml --format-version 1、cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml、cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-domain、cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocol、cargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p storage-convex-bridge,均通过;其中cargo metadata已再次确认 workspace members 固定为core-domain、core-protocol、event-log、storage-convex-bridge、index-fts五个 crate。 2026-04-14 源码审计补记:已新增/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/release-readiness-source-audit.md。该文档基于当前 route、adapter、Convex bridgeLogs 与定向测试,确认 bridge 入口已经覆盖最小查询/写入/日志/事件/错误返回闭环;确认正文、页面元信息、块补丁与 OnlyOffice 附件写回的最终真相仍然落在 Convex mutation;确认trace_id、request_id、workspace_id、page_id在 route、bridge、Convex 日志与回查入口之间使用统一口径;并完成“不双仓并行、不跨仓链接、不复制第二套前端壳、不把 diagnostics/smoke 页带入主线、不散落多个 Rust 源码根”的源码级复查。 2026-04-15 task-035 补记:已新增/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-cutover-v1.md,把主仓当前 TS 执行面按RUST_OWNER / TS_TRANSPORT_KEEP / TS_COMPAT_PENDING / TS_LEGACY_DELETE四类状态完成盘点。文档明确了页面、块、查询聚合、AI、Mindmap、OnlyOffice 的当前归属,也明确了documents/create-child、documents/embed、documents/empty-trash、documents/purge、documents/template、mindmap-trash/empty、mindmap-ai/**与ai-agent非 Rust 核心工具面属于 Phase 8 前必须继续处理的旧面;同时为“何时允许宣布 Rust 成为唯一业务执行平面”补齐了四组 gate。 2026-04-15 task-040/task-042/task-043/task-044 补记:AI 非doc_*核心工具中的search_web、image_read、slash_run已完成第一批 Rust Tool runtime cutover,ai-agent/run不再保留这些工具的 TS 真执行兜底;bridge-log/runtime已补齐统一失败态、冲突态与补偿态的第一批状态闭环,并覆盖页面主写链与 AI/Mindmap 写链;同时已新增/mnt/Data1T/mnote/design/old/08-legacy-rust-kernel/done/rust-kernel-legacy-delete-list.md,把documents/create-child、documents/embed、documents/empty-trash、documents/purge、documents/template、mindmap-trash/empty、builtins/**固定为第一批TS_LEGACY_DELETE。至此 Phase 8 的文档口径已经允许在源码审计层面使用“Rust 已成为 mnote 的唯一业务执行平面;Web route 只保留 transport、auth、session、streaming、proxy 与 callback 壳”这句统一结论。