Files
mnote/design/old/08-legacy-rust-kernel/process/rust-kernel-backport-phase-checklist.md
T

44 KiB
Raw Blame History

[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-cliadapter-onlyofficeadapter-mindmapadapter-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-domaincore-protocolevent-logstorage-convex-bridgeindex-ftsbridge-runtimemnote-cli
  • /mnt/Data1T/mnote/rust/design/INDEX.mddesign/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 -> BlockNoteEditorMindmap 仍复用现有 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-onlyofficeadapter-mindmapadapter-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/titledocuments/statsdocuments/optionsdocuments/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.getdocuments.title.updatedocuments.save 这 1 读 2 写链现已从主仓 Next route 真实进入 crates/bridge-runtime,再由 TS 仅做 Convex transport;同时 crates/mnote-cli 已在主仓 workspace 落位,并通过 page/block/search/sidebar/tool 五类最小命令面的 --json 计划输出冻结当前 CLI 协议。

3. Phase ARust workspace 落位(主目标已完成)

完成目标:

  • /mnt/Data1T/mnote/rust/ 成为唯一 Rust workspace 根。
  • P0 crate 与核心规范文档已在主仓内有真实副本。
  • 新 workspace 已具备最小自检能力。

Checklist

  • 固定 /mnt/Data1T/mnote/rust/ 为唯一 Rust workspace 根,后续 Rust 命令统一从这里发起。
  • 固定 workspace members 只指向 crates/core-domaincrates/core-protocolcrates/event-logcrates/storage-convex-bridgecrates/index-fts
  • 复制并落位 core-domaincore-protocolevent-logstorage-convex-bridgeindex-fts
  • 复制并落位 rust/design/INDEX.mdrust/design/core/01-domain-model-v0.md02-command-query-tool-protocol-v0.md03-storage-event-indexing-v0.md04-onlyoffice-integration-boundary-v0.md
  • 统一 workspace 级别的 editionlicenseversionauthors 约定。
  • 跑通 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-domaincargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocol
  • 已在本 checklist 第 1 节固定“第一阶段禁止迁入清单”,明确 mnote-cliadapter-*design/phases/**design/execution/**、第二套 Next 前端壳均不属于本阶段交付。

Phase A 验收:

  • Cargo 可在主仓内解析 workspace。
  • 主仓内已有 P0 内核与长期规范副本。
  • 当前未出现对第二工作路径的直接 Cargo 路径依赖。
  • 已完成 crate 单测与文档级禁止迁入清单,Phase A 可视为关闭。

4. Phase Bbridge 入口与 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 enveloperequest_idtrace_idworkspace_idactorsourceidempotency_key

  • 约定所有新命令和查询都先进入 core-protocol envelope,再转给 storage-convex-bridge

  • 已把 documents/contentsidebar 两条低风险读链接入当前 bridge query 包装层。

  • 已把 documents/titledocuments/statsdocuments/saveblocks/patch 接入当前 bridge command 包装层。

  • 已为 documents/titledocuments/stats 收口稳定的页面元信息 command adapter,冻结 route 到 Convex 之间的 payload/target/meta 映射,避免 route 继续直接耦合 updateTitle/updateStats 的参数细节。

  • 已为首批 4 条写链固定当前 bridge -> Convex 的函数名、payload 结构和 workspace scope;其中 documents.titledocuments.statsdocuments.optionsdocuments.save 已先收口到 buildDocumentBridgeMutationRequest 这层最小运行时接缝,统一构造与 storage-convex-bridge::build_write_request 对齐的 functionName/payloadJson/args,再由同一执行器落到 Convexblocks.patch 仍未收口到该执行层,且整条链尚未直接切到 Rust crate 内统一执行。

  • 已在 wolai-frontend/convex/schema.ts 新增 command_logsdomain_events 两张表,并新增 wolai-frontend/convex/bridgeLogs.tssrc/lib/documents/bridge-log.ts 承接首批写链日志落账。

  • 首批 4 条写链(documents/titledocuments/statsdocuments/saveblocks/patch)当前会在成功路径同时写入 command log 与 domain event;失败态、回滚态和统一事务性仍待后续补齐。

  • 当前已接入的查询链(documents/contentsidebar)保持只读,不产生写副作用。

  • 已统一 documents/contentdocuments/savedocuments/titledocuments/statssidebar 的首批 bridge 错误返回结构。

  • 当前 bridge 仅负责协议校验、请求映射与响应元信息包装,尚未吞并产品 UI 逻辑。

    2026-04-14 B 阶段补记:已在 rust/crates/core-protocol 中补齐 documents.meta.getdocuments.content.getsidebar.dataset.listdocuments.saveblocks.patch 的最小 query/command 协议对象,并在 rust/crates/storage-convex-bridge 中补齐对应的 query/command name -> Convex function 映射与单测。当前主仓新增链路已统一先构建稳定 envelope,再由后续真实 Rust bridge 执行链消费;本轮已通过 cargo test -p core-protocol -p storage-convex-bridgecargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml 验证协议与映射闭环。 2026-04-14 B 阶段第三刀补记:已在 wolai-frontend/src/lib/documents/bridge.ts 新增 buildDocumentBridgeMutationRequest 与统一执行器,把 documents.title.updatedocuments.stats.updatedocuments.options.updatedocuments.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/contentsidebar)和 4 条写链(documents/titledocuments/statsdocuments/saveblocks/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 可启动本地自托管 Convexpnpm exec convex dev --once --tail-logs disable --env-file ../.env.all --run ping:ping 已通过。
  • 已用真实 Convex CLI 对 bridgeLogs:recordCommandLogbridgeLogs:recordDomainEventbridgeLogs:listByTracebridgeLogs: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.tsgetAuthedConvexClient() 返回值解构错误(此前会导致写链落账时报 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.updatedocuments.stats.updatedocuments.options.update 已统一收口到 wolai-frontend/src/lib/documents/metadata-command-adapter.tsroute 只保留 validation、buildDocumentBridgeContextbuildDocumentCommandEnvelope 与稳定错误模型。documents.options 本轮不再内联 client.mutation(api.documents.updateOptions, ...)。同时已补齐 rust/crates/core-protocolUpdatePageTitleUpdatePageStatsUpdatePageOptions 结构与 storage-convex-bridge 的 command name -> Convex mutation 映射测试;2026-04-14 又进一步把这 3 条写链切到 buildDocumentBridgeMutationRequest,先构造与 Rust ConvexMutationRequest 对齐的最小运行时 request,再交给统一执行器落到 Convex,为后续真实 Rust 执行链留出稳定接缝。
  • 当前最小替换已保持现有页面 UI、权限判断、动态导入结构不变:DocumentShell 入参、readOnly/disableDownload/disableCopy 计算、notFound() 分支与页面结构保持不变,仅将元信息读取入口切到 documents.meta bridge query。
  • 已统一页面元信息链当前口径:documents.meta 读链与 documents.title/stats/options 写链均复用 buildDocumentBridgeContext / envelopequery payload 与 command payload 已固定 documentId/workspaceIdtarget.pageId 固定文档 business id,回传元信息统一为 requestId/traceId/queryName|commandId|commandNameactor/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-864c4b2b2c6ctraceId=trace_3cbc114e-db01-410f-933c-e63d8bd83393commandId=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.tsconvex/documentGroupShares.tsconvex/documentStars.tsconvex/comments.tsconvex/references.ts。这批路径分别影响页面共享权限判定、群组公开、收藏可见性、评论线程读写与反链标题读取;此前若同一 business documentId 存在重复物理记录,会继续存在命中漂移风险。本轮已补跑目标文件 eslintsrc/lib/documents/document-record.test.ts,并用源码扫描确认这批目标文件内已不再残留 by_document_id.first();当前未继续扩到 mediaAssets.tsmindmaps.ts 等非本批最小闭环路径。 2026-04-14 第三批真实收口:继续只处理剩余 still-high-risk 的 documents.by_document_id 直接命中点,已新增 convex/_utils/documentRecord.ts#getCanonicalParentDocumentId,并把 convex/comments.tsconvex/documents.ts 中共享/权限祖先链扫描统一改到该 helper,避免同一 business documentId 的重复物理记录在父链遍历时再次漂移。同时已把 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 剩余两个父链祖先扫描点,已将 resolveSharePermissionresolveGroupSharePermission 中手写的 documents.by_document_id 父级推进统一改为 getCanonicalParentDocumentId。同时已补充 src/lib/documents/document-record.test.ts 的 helper 回归用例,验证重复 business documentId 下即使旧记录已删除,父链 helper 仍稳定返回 canonical 父页面 id;并已补跑目标文件 eslintvitest。本轮源码扫描确认 wolai-frontend/convex/ 业务路径中已不再残留直接 withIndex(\"by_document_id\") 命中点,当前仅剩 convex/_utils/documentRecord.ts 作为底层 canonical helper 持有该查询。

C1 验收:

  • 页面元信息至少已有 3 条低风险链路切入 Rust 层。

  • 文档页外观与交互未退化。

  • trace 字段已可回查到页面级写入:documents.title.updatedocuments.stats.updatedocuments.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.tsxprivate-tree.tsxfile-tree.tsxuse-convex-sidebar-data.tssidebar-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.tsxcomponents/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_idworkspacesdocumentstrashed_documentsmedia_assetstrashed_media_assetsmindmap_assetstrashed_mindmap_assetstable_assetstrashed_table_assetsmindmap_docsmindmap_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.tswolai-frontend/src/lib/server/sidebar-data.ts,把 src/app/(app)/layout.tsxsrc/app/api/sidebar/route.tssrc/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 contractC2 其余验收项暂不提前勾选。 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.tssrc/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.tsxschema.ts、文档保存 API 当前入口。
  • 先把正文保存切成“前端快照采集”和“Rust command 提交”两个边界。
  • 为正文保存定义最小协议对象,至少包含 page_idworkspace_idrevisionactorsource、block 快照、冲突检测字段。
  • 先接入低风险保存模式,例如显式保存或节流保存,不先处理复杂协同细节。
  • 确保正文链与页面元信息链、Sidebar 链共用同一 identity 口径,不再出现多套 page id 映射。

C3 验收:

  • 正文保存至少一条正式链路已经通过 Rust command 回写 Convex。

  • 保存失败时可返回稳定错误模型。

  • 保存成功时可回查 command log、domain event 与 trace。

    2026-04-14 C3 第一刀收口:已为 documents.getContent / documents.save 增加独立 content_revisioncontent_conflict_key,避免标题/统计信息更新污染正文 revision;/api/documents/content 现会透传 revision/conflictDetectionKeyBlockNoteEditor 会在自动保存时携带 revisionconflictDetectionKeysnapshotCapturedAtblockCount,并在成功后刷新本地保存元数据。save-command-adapter 现把 Convex 冲突归一为 409 REJECTED bridge 错误,编辑器右上角也会展示保存失败信息。当前最小验证已补 save-contract/bridge 单测,并完成定向 eslint;结果为无 error,仅保留仓库既有 warnings。 2026-04-14 C3 第二刀补记:源码复核确认 BlockNoteEditor 当前通过 useDebouncedCallback(saveContent, 800) 以防抖自动保存作为最小低风险保存模式,没有把复杂协同状态直接并入正文写链;同时 documents.meta/title/stats/options/save 这些 route 都把同一个 normalizedDocumentId 作为 target.pageIddocuments.content/save payload 也统一使用 documentId/workspaceIdsidebar.dataset.list 则以同一 workspace_id 作用域返回 documents[].id 作为页面业务 id,因此当前正文链、页面元信息链与 Sidebar 聚合链已不存在第二套 page id 映射口径。 2026-04-14 C3 第三刀补记:在此前真实 /api/documents/save -> /api/bridge/request|trace smoke 已确认可回查的基础上,本轮又补了 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:updateContentpayloadJsonargs 组成的 bridge mutation request,再由统一执行器实际调用 Convex;这让正文保存不再长期停留在“adapter 内直接手写 client.mutation(...)”的临时态,同时保留现有冲突归一和落账逻辑不变。 2026-04-15 Phase 5 第一刀补记:search.documentssearch.recent 已补齐到主仓 Rust query/runtime 主链。当前 rust/crates/core-protocol 新增 SearchDocuments/SearchRecentstorage-convex-bridgebridge-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 DMindmap 与 OnlyOffice 边界接入

完成目标:

  • 保留 mnote 当前成熟的 Mindmap 与 OnlyOffice 前端实现。
  • 把数据边界、对象边界和回调边界逐步纳入 Rust adapter / protocol 规划,而不是复制第二套对象页壳。

Checklist

  • 锁定 Mindmap 当前主组件和嵌入链路,确认 MindmapBlock.tsx 同时服务 BlockNote 内嵌块与独立全屏页。

  • 盘点 Mindmap 数据入口,锁定 mindmapLocalStore.tsmindmapOps.tsapp/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=documentIdattachmentId=mindmapIdworkspaceId 作为页面归属,并在 /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-protocolReplaceMediaAssetStoragerust/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.tssrc/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-onlyofficeadapter-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.mdAGENTS.mdrust-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.jsonscripts/desktop-hot.js,确认仓库级脚本仍只从 /mnt/Data1T/mnote/scripts/ 发起,且 ARCHITECTURE.md 已移除把 mnote-rust 写成未来执行承载面的表述。

8. 发布前总审计(跨阶段)

  • /mnt/Data1T/mnote/rust/ 补基础验证矩阵,至少覆盖 cargo metadatacargo check、必要 crate 单测。

  • 为 bridge 入口补集成 smoke,验证最小查询、最小写入、日志生成、事件生成和错误返回。

  • 为文档页元信息、Sidebar、BlockNote 保存链补端到端回归,确认 UI 未因为协议层切换而退化。

  • 为 Mindmap 补交互回归,重点验证内嵌块、独立页、数据保存、节点操作和工具栏/侧栏行为。

  • 为 OnlyOffice 补回归,重点验证签名、代理、callback、forcesave、文档打开和静态资源可用性。

  • 检查主仓启动路径,确保开发者只需进入 /mnt/Data1T/mnote 就能完成前端、后端、Rust、OnlyOffice 相关联调。

  • 检查保存口径,确认页面、块、文档、索引的最终真相仍然落在 Convex,而不是被临时缓存目录劫持。

  • 检查 trace_idrequest_idworkspace_idpage_id 在前端、bridge、Convex、日志中的一致性。

  • 对本次回迁引入的所有新目录和新文档做一次清点,确认没有误带入 mnote-rust 的历史噪音。

  • 为统一观测面补正式 Rust 能力面,至少包含 bridge_request_getbridge_trace_getbridge_command_getevent_replayindex_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-clibridge/scripts/fixtures/tests 目录。文档同时核对了 package.jsonscripts/desktop-hot.jsAGENTS.md 的主仓启动口径,确认开发者只需进入 /mnt/Data1T/mnote 即可找到前端、后端、Rust 与 OnlyOffice 的联调入口。

  • 2026-04-15 task-034 补记:已在 rust/crates/core-protocol 增补 GetBridgeRequest/GetBridgeTrace/GetBridgeCommand 以及 bridge_request_getbridge_trace_getbridge_command_getevent_replayindex_rebuild 五个统一观测/恢复工具;rust/crates/storage-convex-bridge 已补 query name -> Convex bridgeLogs:* 映射;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_storage bridge 命令没有破坏 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 1cargo check --manifest-path /mnt/Data1T/mnote/rust/Cargo.tomlcargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-domaincargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p core-protocolcargo test --manifest-path /mnt/Data1T/mnote/rust/Cargo.toml -p storage-convex-bridge,均通过;其中 cargo metadata 已再次确认 workspace members 固定为 core-domaincore-protocolevent-logstorage-convex-bridgeindex-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_idrequest_idworkspace_idpage_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-childdocuments/embeddocuments/empty-trashdocuments/purgedocuments/templatemindmap-trash/emptymindmap-ai/**ai-agent 非 Rust 核心工具面属于 Phase 8 前必须继续处理的旧面;同时为“何时允许宣布 Rust 成为唯一业务执行平面”补齐了四组 gate。 2026-04-15 task-040/task-042/task-043/task-044 补记:AI 非 doc_* 核心工具中的 search_webimage_readslash_run 已完成第一批 Rust Tool runtime cutoverai-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-childdocuments/embeddocuments/empty-trashdocuments/purgedocuments/templatemindmap-trash/emptybuiltins/** 固定为第一批 TS_LEGACY_DELETE。至此 Phase 8 的文档口径已经允许在源码审计层面使用“Rust 已成为 mnote 的唯一业务执行平面;Web route 只保留 transport、auth、session、streaming、proxy 与 callback 壳”这句统一结论。