Persist PageTree expand state via control-plane view-state and align chevron/DOM with restored expansion; keep Sidex-style shallow page-tree scan and drop the unused recursive scanner that only added cargo noise. Add password vault workbench routes/runtime/skill/CLI, split page_ai_pi into a module package, and retire Hermes/ACP/OpenHub recycle + root harness evidence from the index while gitignoring recycle and local diag dumps. Archive superseded design/bugs docs under old/, point architecture at ARCHITECTURE.md, and refresh smokes for Pi S1–S7, vault, and editor regressions so the working tree can stay clean.
447 lines
41 KiB
Markdown
447 lines
41 KiB
Markdown
# [recycle] 10-review 顺序执行清单与验收标准
|
||
|
||
> 执行状态:已完成并归档到 `design/10-review/done/`。本文是本轮 10-review 的最终验收依据与防回归口径,根目录 `design/10-review/README.md` 仅保留索引。
|
||
|
||
> 更新时间:2026-05-14
|
||
>
|
||
> 上游依据:
|
||
> - `/mnt/Data1T/mnote/design/10-review/README.md`
|
||
> - `/mnt/Data1T/mnote/design/10-review/done/01-rust-kernel-web-review.md`
|
||
> - `/mnt/Data1T/mnote/design/10-review/done/02-frontend-editor-tree-review.md`
|
||
> - `/mnt/Data1T/mnote/design/10-review/done/03-convex-realtime-storage-review.md`
|
||
> - `/mnt/Data1T/mnote/design/10-review/done/04-secondary-domains-and-design-governance-review.md`
|
||
> - `/mnt/Data1T/mnote/design/10-review/done/05-tree.md`
|
||
> - `/mnt/Data1T/mnote/design/04-tree-domain/done/4-24-resource-tree-filetree-pagetree-source-contract-checklist-v1.md`
|
||
> - `/mnt/Data1T/mnote/design/05-editor-mainline/done/5-12-main-editor-object-tab-resource-alignment-checklist-v1.md`
|
||
|
||
## 0. 执行前提
|
||
|
||
`05-tree.md` 中关于 Resource Tree / File Tree / Page Tree、ObjectIdentity、mindmap 与 `index.md` 隔离的核心事项已经由 `4-24` 与 `5-12` 承接到 `done/`。后续执行不要重复重做该主线,只需要保留防回归验证。
|
||
|
||
本清单按依赖顺序执行。原则是先修会影响主链一致性和数据可信度的 P0,再处理 realtime / projection / compat 收口,最后做次级域和文档治理。
|
||
|
||
## 1. P0:修正 Rust page write artifact 一致性
|
||
|
||
状态:已完成第 1 项代码侧与 Rust 3000 验证。Rust `/api/documents/title` 与 `/api/documents/options` 已切到 artifact 记录路径;`page.layout.updateOptions` 已补 tree domain event / conservative resync artifact;Rust 3000 下已直接验证标题更新后 `bridge.workspace.overview` 可读到 `page.head.updateTitle` command log 与 `tree.node.renamed` domain event,`/api/tree/events` 也能输出包含新标题的 stream 事件。完整 File Tree 标题同步仍归入第 6 项继续处理。
|
||
|
||
目标:让 3000 主入口下的页面标题、页面设置、正文保存拥有一致 side effect,确保 tree stream 能看到相关变更。
|
||
|
||
建议修改范围:
|
||
|
||
- `rust/crates/mnote-web/src/routes/documents.rs`
|
||
- `rust/crates/mnote-web/src/routes/command_support.rs`
|
||
- `rust/crates/mnote-web/src/transport/convex.rs`
|
||
- 必要时补充 `wolai-frontend/convex/bridgeLogs.ts` 查询侧验证
|
||
|
||
执行项:
|
||
|
||
- [x] 将 Rust `/api/documents/title` 的命令执行切到 artifact 记录路径,或统一复用正式 page/tree command route。
|
||
- [x] 将 Rust `/api/documents/options` 的命令执行切到 artifact 记录路径,或统一复用正式 page/tree command route。
|
||
- [x] 明确 artifact 写失败策略:主 mutation 成功但 artifact 失败时至少要有可观测错误,并触发保守 resync 或明确降级。
|
||
- [x] 补回归测试:标题更新后,`bridgeLogs:listWorkspaceOverview` 能看到对应 command/domain event。
|
||
|
||
验收标准:
|
||
|
||
- [x] `cargo test -p mnote-web documents_title -- --nocapture` 或等价标题 route 测试通过。
|
||
- [x] `cargo test -p mnote-web documents_options -- --nocapture` 或等价页面设置 route 测试通过。
|
||
- [x] 手动或脚本验证:更新标题后 `/api/tree/events` 输出 delta 或 resync,不需要刷新整页才能看到 sidebar/breadcrumb 变化。
|
||
- [x] Rust route 与 Next legacy adapter 对同一 page write 的 canonical command / artifacts 语义一致。
|
||
|
||
证据:
|
||
|
||
- `rust/crates/mnote-web/src/routes/documents.rs`:`title` / `options` 使用 `execute_runtime_command_via_convex_with_artifacts`,响应 `meta.artifacts` / `meta.artifactError`。
|
||
- `rust/crates/bridge-runtime/src/lib.rs`:`page.layout.updateOptions` 产生 `page.layout.options_updated` domain event 与 `resync_required` stream delta。
|
||
- `rust/crates/mnote-web/src/transport/convex.rs`:发送给 legacy `documents:updateOptions` 时剥离 artifact-only 字段。
|
||
- 已通过:Rust 3000 目标脚本创建临时页面后调用 `/api/documents/title`,再查 `/api/bridge/workspace?targetPageId=<documentId>&aggregateType=page&aggregateId=<documentId>`,确认返回 `command_name=page.head.updateTitle` 与 `event_type=tree.node.renamed`。
|
||
- 已通过:Rust 3000 目标脚本创建临时页面后调用 `/api/documents/title`,再查 `/api/tree/events?workspaceId=<workspaceId>&maxPolls=1&pollMs=250`,确认 stream 文本包含新标题且包含 `snapshot` / `delta` / `resync` 事件。
|
||
- 已通过:`node scripts/task123-rust-web-tree-live-stream-consumer-smoke.js`。
|
||
- 部分通过:`node scripts/task110-page-title-single-truth-smoke.js` 在 Rust 3000 下已通过页头、breadcrumb、sidebar、page tree 标题一致性检查;当前失败点为 File Tree 标题行,继续归入第 6 项处理。
|
||
- 已通过:`pnpm test -- src/app/api/documents/route-adapters.test.ts src/lib/documents/page-write-command-adapter.test.ts`(Vitest 实际执行 112 个测试文件、457 个测试),Next `documents/title` route 与 page write adapter 继续生成 `page.head.updateTitle` canonical command 并进入 Rust artifact writer。
|
||
- 已通过:`cargo test -p mnote-web documents_ -- --nocapture`。
|
||
- 已通过:`cargo test -p bridge-runtime page_head_update_title_command_plan_uses_canonical_page_command -- --nocapture`。
|
||
- 已通过:`cargo test -p bridge-runtime page_layout_update_options_command_plan_uses_canonical_page_command -- --nocapture`。
|
||
- 已通过:`cargo test -p bridge-runtime document_options_command_plan_maps_to_documents_update_options -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web convex_command_args_strips_page_options_artifacts_for_legacy_mutation -- --nocapture`。
|
||
|
||
## 2. P0:移除或显式隔离假 fallback 数据
|
||
|
||
状态:已完成代码侧收口与负向单测。Search 默认不再返回内置固定业务结果;workspace shell projection 默认进入 degraded empty;Sidebar/File Tree dev fallback 仅在 `allow_dev_fixtures` 开启时可用,并带隐藏 debug/dev 标识。
|
||
|
||
目标:失败、超时、Convex 不可用时,不再返回看起来像真实业务数据的 fixture / fallback。
|
||
|
||
建议修改范围:
|
||
|
||
- `rust/crates/mnote-web/src/routes/search.rs`
|
||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||
- `rust/crates/mnote-web/src/routes/snapshot_support.rs`
|
||
|
||
执行项:
|
||
|
||
- [x] 优先移除或强门禁 Search 的 `fallback_search_dataset`。
|
||
- [x] 对 workspace shell projection 加载失败的最小合成数据做决策:返回明确 degraded/empty/error,不能伪装成真实 workspace projection。
|
||
- [x] 对 `allow_dev_fixtures` 相关 sidebar/filetree fallback 增加明确 debug/dev 标识,并确认 3000 默认启动链不会误开。
|
||
- [x] 增加负向 smoke:Convex/query 不可用时,Search、Sidebar、File Tree 不返回固定假业务数据。
|
||
|
||
验收标准:
|
||
|
||
- [x] 关闭或破坏 Convex query 后,Search 不返回内置固定结果。
|
||
- [x] 关闭或破坏 projection 加载后,workspace/sidebar/filetree 响应带明确错误、空状态或 degraded 标记。
|
||
- [x] 3000 默认入口不会出现 fixture workspace、fixture document、fixture filetree row。
|
||
- [x] 相关负向测试或 smoke 在失败场景下能稳定断言“不返回假数据”。
|
||
|
||
证据:
|
||
|
||
- `rust/crates/mnote-web/src/routes/search.rs`:Convex/search query 失败时,默认返回空结果与 `meta.degraded=true`;仅 `allow_dev_fixtures` 开启时使用 `fallback_search_dataset`。
|
||
- `rust/crates/mnote-web/src/routes/web_shell.rs`:workspace shell projection 失败时,默认返回 degraded empty dataset;Sidebar/File Tree dev fallback HTML 增加 `data-mnote-dev-fixture` 标识。
|
||
- `rust/crates/mnote-web/src/workspace_shell.rs`:workspace shell projection/render 支持 `degraded` / `devFixture` 标识。
|
||
- 已通过:`cargo test -p mnote-web search_ -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web sidebar_and_filetree_do_not_return_dev_fixtures_by_default -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web workspace_shell_sidebar_html_marks_degraded_and_dev_fixture_states -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web document_shell_returns_page_aggregate_snapshot -- --nocapture`。
|
||
|
||
## 3. P1:补齐 OnlyOffice Rust callback / forcesave 写回链
|
||
|
||
状态:已完成代码侧与真实 Rust 3000 smoke。Rust `/api/onlyoffice/callback` 与 `/api/onlyoffice/forcesave` 已改为显式代理 legacy Next 写回链;未配置 legacy Next 时返回明确失败/unsupported,不再静默 no-op 成功;`task174` 已验证 OnlyOffice 附件打开链路与 docKey。
|
||
|
||
目标:Rust Web 主入口下 OnlyOffice 保存不能出现“返回成功但未写回”的情况。
|
||
|
||
建议修改范围:
|
||
|
||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`
|
||
- `rust/crates/adapter-onlyoffice/`
|
||
- `wolai-frontend/src/app/api/onlyoffice/callback/route.ts` 作为 legacy 写回参考
|
||
- `scripts/task174-rust-onlyoffice-attachment-open-smoke.js`
|
||
|
||
执行项:
|
||
|
||
- [x] 决定 Rust route 直接写回,还是显式代理到 legacy Next 写回链。
|
||
- [x] 如果直接写回,接入 media asset / storage 写回与 callback 状态处理。(本轮选择显式代理 legacy Next 写回链,直接写回不适用。)
|
||
- [x] forcesave 不再返回纯 `mnote-web-rust-noop` 成功语义;若仍未支持,必须返回明确 unsupported/degraded。
|
||
- [x] 补真实浏览器 smoke:打开 OnlyOffice 附件、触发保存、重新打开后内容或版本可验证。
|
||
|
||
验收标准:
|
||
|
||
- [x] `/api/onlyoffice/callback` 在需要写回的 status 下会产生真实持久化写入或明确失败。
|
||
- [x] `/api/onlyoffice/forcesave` 不再静默 no-op 成功。
|
||
- [x] `node scripts/task174-rust-onlyoffice-attachment-open-smoke.js` 或等价 smoke 通过。
|
||
- [x] 3000 主链不会 shadow 掉 legacy Next 的真实写回能力。
|
||
|
||
证据:
|
||
|
||
- `rust/crates/mnote-web/src/routes/onlyoffice.rs`:callback / forcesave 代理到 `legacy_next_base_url` 的 Next `/api/onlyoffice/*` 写回链;缺少 legacy 写回链时返回明确失败。
|
||
- 已通过:`cargo test -p mnote-web onlyoffice_ -- --nocapture`。
|
||
- 已通过:`node scripts/task174-rust-onlyoffice-attachment-open-smoke.js`,输出 `ok=true`,创建临时 docx attachment,打开 `/onlyoffice` 编辑 URL,并返回稳定 `docKey`。
|
||
|
||
## 4. P1:收口 Page Aggregate provenance
|
||
|
||
状态:已完成代码侧与文档侧收口。`/api/page-aggregate/:id` 继续保持 Rust `mnote.page_aggregate.v1` 主读链,但当底层由 `documents:getMeta + documents:getContent` substrate 构建时,response `source` 与 owner header 已明确标为 `CompatMetaContentJoin` / `compat-join`,不再误写成完整 `KernelProjection`。
|
||
|
||
目标:Page Aggregate 读链保持 Rust-first,但来源标识必须反映真实构建路径,避免把 `meta/content join` 写成完整 kernel-native projection。
|
||
|
||
建议修改范围:
|
||
|
||
- `rust/crates/core-protocol/src/page_aggregate.rs`
|
||
- `rust/crates/bridge-runtime/src/lib.rs`
|
||
- `rust/crates/mnote-web/src/routes/web_shell.rs`
|
||
- `wolai-frontend/src/lib/documents/page-aggregate-loader.ts`
|
||
- `design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`
|
||
- `design/05-editor-mainline/done/5-6-page-aggregate-alignment-checklist-v1.md`
|
||
|
||
执行项:
|
||
|
||
- [x] 明确 `PageAggregateSource::KernelProjection` 与 `CompatMetaContentJoin` 的边界。
|
||
- [x] 如果 route 仍由 `getMeta + getContent` 构建,返回 source 或 response header 应反映真实来源。
|
||
- [x] 文档更新为“Rust route 主读链已成立,底层仍是 Rust runtime adapter 消费 meta/content substrate”。
|
||
- [x] 保留或删除 `PageAggregateSource::Fixture` 前,先确认测试和本地 fixture 依赖。(本轮保留,仅用于测试或显式 dev fixture 语义。)
|
||
|
||
验收标准:
|
||
|
||
- [x] `/api/page-aggregate/:id` 返回的 source/provenance 与实际构建路径一致。
|
||
- [x] 文档中不再出现“Page Aggregate 已完全 kernel-native projection 闭环”的过满表述。
|
||
- [x] 前端 loader 仍只消费 `mnote.page_aggregate.v1`,不恢复 TS runtime builder 主链。
|
||
- [x] Page Aggregate provenance 变更有 Rust 单测或 loader 单测覆盖。
|
||
|
||
证据:
|
||
|
||
- `rust/crates/bridge-runtime/src/lib.rs`:`page.aggregate.get` 根据 query data 是否包含 `meta + content` 选择 `CompatMetaContentJoin`,否则保留 `KernelProjection`。
|
||
- `rust/crates/mnote-web/src/routes/web_shell.rs`:`/api/page-aggregate/:id` 测试断言 `x-mnote-page-aggregate-owner=compat-join` 且 `result.source=CompatMetaContentJoin`。
|
||
- `design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`:补充 Rust route 主读链与完整 kernel-native projection 的边界。
|
||
- `design/05-editor-mainline/done/5-6-page-aggregate-alignment-checklist-v1.md`:补充 `CompatMetaContentJoin` / `KernelProjection` 验收口径。
|
||
- `design/05-editor-mainline/done/5-5-1-page-aggregate-contract-v1.md`:新增 `source` / provenance 契约说明。
|
||
- 已通过:`cargo test -p bridge-runtime page_aggregate_get_query_executes_into_core_projection -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web page_aggregate_endpoint_returns_snapshot_contract -- --nocapture`。
|
||
|
||
## 5. P1:优化 tree stream 的 Convex 查询模型
|
||
|
||
状态:已完成代码侧与基础 Rust 3000 smoke。`bridgeLogs:listWorkspaceOverview` 已从全量 workspace collect 后内存分页,改为基于 `workspace_id + created_at + id` 及常用过滤组合索引的有界窗口查询;Rust `/api/tree/events` 的 snapshot/delta/resync 协议未改,polling-backed SSE 仍按“最新窗口 + Rust cursor 比较”工作,当前定位为过渡实现。`task123` 和标题更新目标脚本已证明 Rust 3000 stream 可输出 snapshot / title event;完整浏览器 tree integration smoke 仍因 sidebar row 可见性失败,归入第 6 项继续处理。
|
||
|
||
目标:让 `/api/tree/events` 可以长期承载主链,避免 SSE 轮询叠加全量日志扫描。
|
||
|
||
建议修改范围:
|
||
|
||
- `wolai-frontend/convex/bridgeLogs.ts`
|
||
- `wolai-frontend/convex/schema.ts`
|
||
- `rust/crates/mnote-web/src/routes/sse.rs`
|
||
- `rust/crates/mnote-web/src/routes/stream_support.rs`
|
||
- `wolai-frontend/src/lib/tree-stream/`
|
||
|
||
执行项:
|
||
|
||
- [x] 为 `command_logs` 增加按 `workspace_id + created_at/id` 的查询路径。
|
||
- [x] 为 `domain_events` 增加按 `workspace_id + created_at/id` 或 command cursor 的查询路径。
|
||
- [x] `listWorkspaceOverview` 不再每轮 collect 全量 workspace 日志后内存分页。
|
||
- [x] 明确 polling-backed SSE 是过渡实现还是长期实现;若长期使用,补连接数、日志量、延迟边界测试。(本轮明确为过渡实现,live 轮询仍查最新窗口并由 Rust 做 cursor 比较。)
|
||
|
||
验收标准:
|
||
|
||
- [x] 大量历史日志存在时,overview 查询仍按 cursor / limit 返回,不全量 collect。
|
||
- [x] `/api/tree/events` 的 snapshot/delta/resync 协议不破坏现有前端消费。
|
||
- [x] `pnpm --dir wolai-frontend test -- tree-stream` 或等价 tree-stream 测试通过。
|
||
- [x] 至少一条 smoke 覆盖标题/树变更后 SSE 能正常输出增量或保守 resync。
|
||
|
||
证据:
|
||
|
||
- `wolai-frontend/convex/schema.ts`:`command_logs` 增加 `by_workspace_created_at`、`by_workspace_status_created_at`、`by_workspace_target_page_created_at`、`by_workspace_target_block_created_at`;`domain_events` 增加 `by_workspace_created_at`、`by_workspace_status_created_at`、`by_workspace_aggregate_created_at`。
|
||
- `wolai-frontend/convex/bridgeLogs.ts`:`listWorkspaceOverview` 改为 `fetchCommandLogWindow` / `fetchDomainEventWindow`,通过索引 `order("desc").take(scanLimit)` 和 cursor 上界查询,移除对 workspace 全量日志的 `.collect()`。
|
||
- `rust/crates/mnote-web/src/routes/sse.rs`:live poll 语义保持不变,仍清空 bridge pagination cursor 后查最新窗口,再由 Rust 比较当前 stream cursor。
|
||
- 已通过:`pnpm test -- src/lib/tree-stream`(Vitest 实际执行 111 个测试文件、452 个测试)。
|
||
- 已通过:`cargo test -p mnote-web stream_ -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web tree_realtime_route_returns_rust_web_owned_snapshot_event -- --nocapture`。
|
||
- 已通过:`pnpm exec eslint convex/bridgeLogs.ts convex/schema.ts` 无错误;保留既有 `any` 风格警告。
|
||
- 已通过:`node scripts/task123-rust-web-tree-live-stream-consumer-smoke.js`。
|
||
- 已通过:Rust 3000 目标脚本验证 `/api/documents/title` 后 `/api/tree/events?maxPolls=1&pollMs=250` 输出包含新标题的 stream 事件。
|
||
- 未通过:`node scripts/task120-rust-web-tree-integration-smoke.js` 在等待 child sidebar row 可见时超时,完整浏览器 tree integration 继续归入第 6 项处理。
|
||
- 受既有问题阻塞:`pnpm exec tsc --noEmit --pretty false` 仍被 `.next` 旧生成文件、Convex documents 类型和 mindmap/OnlyOffice 等无关类型错误阻塞;本轮新增 `bridgeLogs.ts` / `schema.ts` 未出现在错误列表中。
|
||
|
||
## 6. P1:统一 Sidebar / File Tree live cache 与主文档壳 no-refresh 验收
|
||
|
||
状态:代码侧完成,真实浏览器 create / rename / move / archive / purge 主链已通过。`usePreferredSidebarSnapshot` 已从“sync key 与 initial 对比”的特殊规则,改为基于 `getSidebarDataFreshness()` 的 version 仲裁,并保留 tree stream cursor 作为 live 元信息;`AppLayoutShell`、Sidebar、Breadcrumb、SearchPalette 继续消费同一份 preferred snapshot。Rust 3000 下已修复 `tree:delta` 的 title-only patch 被误当成空 projection 渲染的问题,`task110` 已通过页头、breadcrumb、sidebar、page tree、File Tree 标题一致性检查;`task120` 已通过 child sidebar row 可见性、rename live delta、reload 与 purge 后消失检查;`task177` 已覆盖 move / archive live DOM reducer,确认页面树与 File Tree 行局部更新后文档页头仍稳定。2026-05-14 追加验收口径:File Tree / Page Tree 的“无刷新可见”必须在 `http://127.0.0.1:3000/documents/<id>` 主文档壳验证,覆盖页面 `tree.node.create`、页面 delete/purge、页面内 mindmap create 三条链路;`/tree` debug route 与 3001/Next 路径只能作为补充排查,不能替代 3000 主入口验收。
|
||
|
||
目标:减少 `initial / query / tree_stream` 三源 freshness 选择,把 Sidebar、Breadcrumb、文档页头收口到统一 live cache / projection version 仲裁。
|
||
|
||
建议修改范围:
|
||
|
||
- `wolai-frontend/src/components/app-layout-shell.tsx`
|
||
- `wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.ts`
|
||
- `wolai-frontend/src/components/sidebar/sidebar.tsx`
|
||
- `wolai-frontend/src/lib/tree-stream/`
|
||
|
||
执行项:
|
||
|
||
- [x] 定义 live snapshot 的 version/cursor 仲裁字段。
|
||
- [x] `usePreferredSidebarSnapshot` 从 sync key 比较推进到 cursor/version 比较。
|
||
- [x] Sidebar、Breadcrumb、文档页头统一消费同一 preferred/live snapshot。
|
||
- [x] 保留 initial snapshot 只作为首屏启动输入,不能长期压过更新后的 stream/query。
|
||
- [x] Rust 3000 主文档壳监听 `tree:local-command`,在 `tree.node.create` / delete 成功后即时更新 Page Tree 与 File Tree DOM。
|
||
- [x] Rust 3000 主文档壳监听同页 mindmap 资产写入:slash 插入触发 `/api/mindmap/<doc>/<mindmap>` POST 成功后,File Tree 即时出现 `mindmap-<id>.json` asset row。
|
||
|
||
验收标准:
|
||
|
||
- [x] 新建、重命名、移动、归档页面后,Sidebar、Breadcrumb、文档页头无互相打架或回退闪烁。
|
||
- [x] `usePreferredSidebarSnapshot` 有单测覆盖 query、initial、tree_stream 三者的新旧仲裁。
|
||
- [x] 真实浏览器 smoke 覆盖至少一个 tree command 后 Sidebar 与文档页头一致。
|
||
- [x] 真实浏览器 smoke 必须覆盖 `3000 /documents/<id>` 主文档壳中页面新建后 Page Tree / File Tree 立即出现,且 `navigationEvents.length=0`。
|
||
- [x] 真实浏览器 smoke 必须覆盖同一主文档壳中页面删除或 purge 后 Page Tree / File Tree 立即移除,且不依赖浏览器刷新。
|
||
- [x] 真实浏览器 smoke 必须覆盖同一主文档壳中页面内新建 mindmap 后 File Tree 立即出现对应 asset row;该链路是 `/api/mindmap/<doc>/<mindmap>` 资产写入,不等同于页面 `tree.node.create`。
|
||
|
||
证据:
|
||
|
||
- `wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.ts`:输出 `version` 与 `cursor`,以 `getSidebarDataFreshness()` 比较 initial/query/tree_stream;stream fallback 时不参与仲裁,同版本时优先 live stream。
|
||
- `wolai-frontend/src/components/app-layout-shell.tsx`:向 preferred snapshot 仲裁传入 `treeStream.cursor`,Sidebar、Breadcrumb、SearchPalette 仍消费同一 preferred data。
|
||
- `wolai-frontend/src/components/sidebar/sidebar.tsx`:Sidebar 内部 fallback 路径也传入 `treeStream.cursor`。
|
||
- `wolai-frontend/src/components/sidebar/use-preferred-sidebar-snapshot.test.tsx`:新增 query 比旧 stream 更新时优先 query、stream 与 query 同版本时优先 stream 并暴露 cursor 的回归用例。
|
||
- 已通过:`pnpm test -- src/components/sidebar/use-preferred-sidebar-snapshot.test.tsx src/components/app-layout-shell.test.tsx src/components/sidebar/sidebar-sync.test.tsx`(Vitest 实际执行 111 个测试文件、454 个测试)。
|
||
- 已通过:`pnpm exec eslint src/components/sidebar/use-preferred-sidebar-snapshot.ts src/components/sidebar/use-preferred-sidebar-snapshot.test.tsx src/components/app-layout-shell.tsx src/components/sidebar/sidebar.tsx` 无错误;`sidebar.tsx` 保留既有 warning。
|
||
- 已通过:`cargo test -p mnote-web tree_realtime_route_returns_rust_web_owned_snapshot_event -- --nocapture`。
|
||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`:`renderSidebarSnapshot` 只在 payload 明确带 projection items 时重渲染 Sidebar;单文档 `upsert_document` title patch 改为只调用 `updateTitleEverywhere()`,避免 rename delta 把 Sidebar 渲染成空树。
|
||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`:新增 `move_document` / `remove_document` 的小型 DOM reducer,移动时更新页面树与 File Tree 行的父节点,归档时局部移除对应行。
|
||
- `rust/crates/mnote-web/src/transport/convex.rs`:tree create / rename / archive / restore / move 及 compat documents mutation 发送给 legacy Convex mutation 前剥离 artifact-only 字段,避免 validator 因 `streamDeltaHint` / `domainEventPlan` 返回 502。
|
||
- 已通过:`cargo test -p mnote-web sidebar_tree_runtime -- --nocapture`。
|
||
- 已通过:`cargo test -p mnote-web convex_command_args_strips -- --nocapture`。
|
||
- 已通过:`node scripts/task110-page-title-single-truth-smoke.js` 在 Rust 3000 下通过页头、breadcrumb、sidebar、page tree、File Tree 标题一致性检查。
|
||
- 已通过:`node scripts/task120-rust-web-tree-integration-smoke.js` 在 Rust 3000 下通过 root/child row、active 切换、rename live delta、reload 与 purge 检查。
|
||
- 已通过:`node scripts/task112-tree-rust-family-regression-smoke.js`,但当前页面选项壳缺少 move/embed 入口导致 picker 部分 skipped:`move_embed_entry_missing_in_current_page_options_shell`。
|
||
- 已通过:`node scripts/task177-tree-move-archive-live-smoke.js`,覆盖 `move_document` live event 后页面树 / File Tree 行 `data-parent-id` 更新,以及 `remove_document` live event 后两棵树局部移除归档行;文档页头和标题输入保持根页面标题稳定。
|
||
- 已通过:`node scripts/task179-tree-create-delete-no-reload-smoke.js`,覆盖 Rust `/tree` `convex_workspace` 下 File Tree create/delete 与 Page Tree create;该脚本只作为 debug route 补充证据,不再代表最终主链验收。
|
||
- 已通过:`MNOTE_UI_BASE_URL=http://127.0.0.1:3000 node scripts/task426-mnote-web-main-no-reload-smoke.js`,覆盖 `3000 /documents/<id>` 主文档壳:页面 create/delete 无刷新即时更新 Page Tree / File Tree,页面内 mindmap create 经 `/api/mindmap/<doc>/<mindmap>` POST 后即时插入 `asset:<mindmapId>` File Tree row,`afterMindmapCreate.localApplied=true`。
|
||
|
||
## 7. P1:明确 `pageSubtree` 与本地正文编辑关系
|
||
|
||
状态:已完成。策略已固定为:server `pageSubtree` 仍是正式 projection 来源;当本地标题草稿或正文快照与 server snapshot 不一致时,前端允许用当前本地 content 生成临时 `pageSubtree`,并通过 `pageSubtreeSource=local` 暴露给 AI context,避免继续复用旧 server subtree 或让 AI 长期失去结构上下文。React `DocumentAiAgentPanel` 侧已有 client state / runtime 单测覆盖;Rust 3000 当前文档页使用全局浮动页面 AI,本轮已补同等 local `pageSubtree` context 构造与真实浏览器 smoke。
|
||
|
||
目标:用户正常编辑正文后,AI 面板、阅读视图、结构视图不能因为本地 content 与 server snapshot 不同而长期失去结构上下文。
|
||
|
||
建议修改范围:
|
||
|
||
- `wolai-frontend/src/components/editor/page-aggregate-client-state.ts`
|
||
- `wolai-frontend/src/components/editor/document-content.tsx`
|
||
- `wolai-frontend/src/lib/documents/page-subtree.ts`
|
||
- `rust/crates/core-protocol/src/page_aggregate.rs`
|
||
|
||
执行项:
|
||
|
||
- [x] 决定 `pageSubtree` 是 server-only projection,还是允许本地临时 projection。
|
||
- [x] 标记本地临时 projection 与 server projection 的来源差异,避免把本地临时结构误认为 kernel projection。
|
||
- [x] AI 面板读取最新 page aggregate snapshot 时,能拿到本地编辑后的结构上下文。
|
||
- [x] 真实编辑器 smoke 验证本地正文编辑后阅读态结构 / AI context 不丢失。
|
||
|
||
验收标准:
|
||
|
||
- [x] 本地正文或标题草稿变化后,不再继续复用旧 server `pageSubtree`。
|
||
- [x] 本地正文或标题草稿变化后,可生成临时 `pageSubtree` 供阅读态 / AI context 使用。
|
||
- [x] AI context 明确带 `pageSubtreeSource`,可区分 `server` / `local` / `none`。
|
||
- [x] 浏览器实测:编辑正文标题或 heading 后,结构面板 / AI context 能看到本地最新结构。
|
||
|
||
证据:
|
||
|
||
- `wolai-frontend/src/components/editor/page-aggregate-client-state.ts`:新增 `PageAggregateClientPageSubtreeSource`,server 快照未变时返回 `source=server`;本地 content/title 草稿变化时用 `buildPageSubtreeProjection` 生成 `source=local`。
|
||
- `wolai-frontend/src/components/editor/DocumentAiAgentPanel.tsx`:`PageAggregateAiSnapshot` 增加 `pageSubtreeSource`。
|
||
- `wolai-frontend/src/components/editor/DocumentAiAgentPanel.runtime.tsx`:AI request context 增加 `pageSubtreeSource`。
|
||
- `wolai-frontend/src/components/editor/page-aggregate-client-state.test.ts`:覆盖本地正文/标题变化后生成临时 `pageSubtree`,以及 server snapshot 下 `pageSubtreeSource=server`。
|
||
- `rust/crates/mnote-web/src/ssr/pages/layout.rs`:历史 Rust 3000 全局浮动页面 AI 曾在发送旧 `/api/ai-agent/run` 前读取当前 Leptos/Tiptap 编辑器 DOM;当本地内容与 server aggregate 正文不同,生成 `source=local` 的临时 subtree / outline / evidence,并在 context 中发送 `pageSubtreeSource=local`。2026-05-14 起这只保留为历史上下文证据;当前页面 AI 主链已改为 Hermes client proxy,页面上下文进入 Hermes run/session context,最新页面事实由 Hermes 通过 mnote plugin tool 回读。
|
||
- 已通过:`pnpm test -- src/components/editor/page-aggregate-client-state.test.ts src/components/editor/DocumentAiAgentPanel.runtime.test.tsx src/components/editor/document-content.test.ts`(Vitest 实际执行 111 个测试文件、454 个测试)。
|
||
- 已通过:`node scripts/task178-page-ai-local-subtree-context-smoke.js`,Rust 3000 下打开真实文档页,把编辑器内容改成本地 heading 后打开页面 AI,并拦截旧 `/api/ai-agent/run` 请求确认 `context.pageSubtreeSource=local`、`documentBlocks` / `outline` / `subtree.stats.headingCount` 均包含本地最新 heading。该 smoke 已在 2026-05-14 默认退役为 historical smoke,脚本现本机归档于 gitignored `recycle/scripts/retired-ai-agent-run-smokes/`;当前页面 AI 长期验收以 `scripts/task-hermes-page-ai-*.js` 和 `scripts/task-page-block-ai-tools-smoke.js` 矩阵为准。
|
||
- 已通过:`pnpm exec eslint src/components/editor/page-aggregate-client-state.ts src/components/editor/page-aggregate-client-state.test.ts src/components/editor/DocumentAiAgentPanel.tsx src/components/editor/DocumentAiAgentPanel.runtime.tsx` 无错误;`DocumentAiAgentPanel.runtime.tsx` 保留既有 `any` warning。
|
||
|
||
## 8. P2:清理或标注 stale mapping / legacy compat
|
||
|
||
状态:已完成。`/api/documents/page` 与 `/api/mnote-web/stream` 已经明确退场为 410 compat 边界;`storage-convex-bridge` 不再把 `page.aggregate.get` 映射到不存在的 Convex `documents:getPageAggregate`,而是显式落到 `queries:unknown` 边界。Rust `/api/page-aggregate/:id` 当前先读取 `documents.meta.get` / `documents.content.get`,再交给 `bridge-runtime` 的 `page.aggregate.get` 组装 core projection,不走缺失 Convex function。
|
||
|
||
目标:保留的 compat 都必须是显式迁移/调试边界;不再让后续实现误把 stale mapping 当主链。
|
||
|
||
建议修改范围:
|
||
|
||
- `rust/crates/storage-convex-bridge/src/mapping.rs`
|
||
- `rust/crates/mnote-web/src/app.rs`
|
||
- `rust/crates/mnote-web/src/routes/gateway.rs`
|
||
- `rust/crates/mnote-web/src/routes/documents.rs`
|
||
- `wolai-frontend/src/lib/documents/page-aggregate-builder.ts`
|
||
- `wolai-frontend/src/app/api/documents/page/route.ts`
|
||
- `wolai-frontend/src/app/api/mnote-web/stream/route.ts`
|
||
|
||
执行项:
|
||
|
||
- [x] 处理 `page.aggregate.get -> documents:getPageAggregate`:实现、移除或标注为 future/stale。
|
||
- [x] legacy Next proxy 保留时,命名与注释统一为 explicit migration/debug boundary。
|
||
- [x] TS `page-aggregate-builder` 保留为测试/adapter/reference,不得重新接回 runtime 主链。
|
||
- [x] 410 compat route 保持退场语义,并补负向测试防止重新启用。
|
||
|
||
验收标准:
|
||
|
||
- [x] 全仓没有生产路径调用不存在的 `documents:getPageAggregate`。
|
||
- [x] 默认 3000 主链不走 legacy Next proxy。
|
||
- [x] `/api/documents/page` 与 `/api/mnote-web/stream` 继续保持明确退场响应。
|
||
- [x] 文档和代码注释不会把 compat/fallback 描述成当前主路径。
|
||
|
||
证据:
|
||
|
||
- `rust/crates/storage-convex-bridge/src/mapping.rs`:`page.aggregate.get` 显式标注为 stale/future compat placeholder。
|
||
- `wolai-frontend/src/app/api/documents/page/route.ts`:返回 410,提示直接使用 `/api/page-aggregate/:documentId`。
|
||
- `wolai-frontend/src/app/api/mnote-web/stream/route.ts`:返回 410,提示直接使用 `/api/tree/events`。
|
||
- `design/10-review/done/03-convex-realtime-storage-review.md`:已明确指出 `documents:getPageAggregate` 目前缺少 Convex 实现,属于方向滞后或 future/stale 口径。
|
||
- `rust/crates/storage-convex-bridge/src/mapping.rs`:`page.aggregate.get` 改为 `queries:unknown`,并注释说明 page aggregate 主读链由 Rust route + `bridge-runtime` 组装,避免误触发不存在的 `documents:getPageAggregate`。
|
||
- 已通过:`rg -n "documents:getPageAggregate|getPageAggregate" rust wolai-frontend src -g '!node_modules' -g '!target'`,仅剩 mapping 注释说明,无生产调用。
|
||
- 已通过:`cargo test -p storage-convex-bridge -- --nocapture`。
|
||
- 已通过:`cargo test -p bridge-runtime page_aggregate_get_query_executes_into_core_projection -- --nocapture`。
|
||
|
||
## 9. P2:处理 Mindmap 次级未闭合项
|
||
|
||
状态:已完成。Mindmap `export` 不再映射到未受控的 `EXPORT` runtime command,UI state 继续禁用该入口;旧 `/api/mindmap-ai/expand-node` Next route 已显式退役为 410,并指向 AI Agent 内置 `mindmap_expand_node` 工具;legacy MindmapSidebar 中调用旧 route 的补完入口已从渲染层关闭。mindmap 内容保存主链仍保持 `mindmap.command.apply`,没有回退到 Page Aggregate body 保存链;真实 3000 `task169` 已通过,证明 mindmap 与 `index.md` 隔离未回归。
|
||
|
||
目标:`05-tree.md` 的 mindmap 污染 `index.md` 已完成;剩余处理能力入口与实现不一致的问题。
|
||
|
||
建议修改范围:
|
||
|
||
- `wolai-frontend/src/lib/mindmap/mindmap-action-map.ts`
|
||
- `wolai-frontend/src/lib/mindmap/simple-mind-map-bridge.ts`
|
||
- `wolai-frontend/src/app/api/mindmap-ai/expand-node/route.ts`
|
||
- `rust/crates/core-protocol/src/tool.rs`
|
||
- `rust/crates/bridge-runtime/src/lib.rs`
|
||
|
||
执行项:
|
||
|
||
- [x] 处理 Mindmap `EXPORT`:加入安全命令并补 smoke,或在 UI state 中禁用并标注延期。
|
||
- [x] 处理 Mindmap AI expand route:按 Hermes plugin / Rust bridge 重接,或显式退役该 route。
|
||
- [x] 保持 mindmap 内容保存继续走 `mindmap.command.apply`,不得回退到 Page Aggregate body 保存链。
|
||
|
||
验收标准:
|
||
|
||
- [x] UI 不展示无法执行的 Mindmap export 能力,或 export 能真实执行并有测试覆盖。
|
||
- [x] `/api/mindmap-ai/expand-node` 不再表现为“产品入口存在但稳定 501”而无说明。
|
||
- [x] `node scripts/task169-mindmap-realtime-smoke.js` 继续通过,证明 mindmap 与 `index.md` 隔离未回归。
|
||
|
||
证据:
|
||
|
||
- `wolai-frontend/src/lib/mindmap/mindmap-action-map.ts`:`export` 改为 `localView`,不再下发 `runtimeCommand: "EXPORT"`。
|
||
- `wolai-frontend/src/lib/mindmap/mindmap-ui-state.ts`:`unsupportedActionIds` 继续包含 `export`,UI state 中该入口保持禁用。
|
||
- `wolai-frontend/src/app/api/mindmap-ai/expand-node/route.ts`:旧 Next route 返回 410,`x-mnote-compat-boundary=mindmap-expand-node-route-retired`。该退役说明不再指向旧 `/api/ai-agent/run` 作为长期承接面;后续若恢复 Mindmap AI,应按 Mindmap domain 另拆 Hermes plugin / Rust bridge 迁移。
|
||
- `wolai-frontend/src/components/editor/blocks/MindmapSidebar.tsx`:legacy 侧栏中调用 `/api/mindmap-ai/expand-node` 的补完入口通过 `MINDMAP_LEGACY_EXPAND_NODE_ENTRY_ENABLED=false` 从渲染层关闭。
|
||
- 已通过:`pnpm test -- src/lib/mindmap/mindmap-action-map.test.ts src/lib/mindmap/mindmap-ui-state.test.ts src/lib/mindmap/simple-mind-map-bridge.test.ts src/app/api/mindmap-ai/expand-node/route.test.ts`(Vitest 实际执行 112 个测试文件、457 个测试)。
|
||
- 已通过:`pnpm exec eslint src/lib/mindmap/mindmap-action-map.ts src/lib/mindmap/mindmap-action-map.test.ts src/lib/mindmap/mindmap-ui-state.test.ts src/app/api/mindmap-ai/expand-node/route.ts src/app/api/mindmap-ai/expand-node/route.test.ts src/components/editor/blocks/MindmapSidebar.tsx` 无错误;保留 `MindmapSidebar.tsx` 既有 `AiPanel` 未使用 warning。
|
||
- 已通过:`cargo test -p bridge-runtime mindmap_command_apply_plan_uses_kernel_command_facade -- --nocapture`,确认 mindmap 内容保存仍走 `mindmap.command.apply` / `mindmaps:applyCommand` facade。
|
||
- 已通过:`node scripts/task169-mindmap-realtime-smoke.js`(Rust 3000 已启动,脚本退出码 0)。最终结果 `ok=true`、`failures=[]`,同一页面最终 File Tree mindmap row 数量为 1,`mindmapId=mindmap_1778695090474`,object identity 仍为同一 `objectKind:"mindmap"`。
|
||
- 已通过:`cargo test -p bridge-runtime mindmap -- --nocapture`,17 个 mindmap 相关测试通过;普通 `mindmap.command.apply` 改为 `mindmap.content.updated + noop`,`mindmaps.put createOnly=false` 也不再默认 tree resync。
|
||
- 已通过:`cargo test -p mnote-web mindmap -- --nocapture`,6 个 mindmap 相关测试通过,覆盖 Rust `/api/mindmap/:docId/:mindmapId` 的 object artifact 响应。
|
||
- 已通过:`node scripts/task169-mindmap-realtime-smoke.js` 最新结果 `ok=true`、`failures=[]`;6 条可解析普通 `mindmap.command.apply` 响应均为 `eventType=mindmap.content.updated`、`streamOp=noop`,另有 1 条 Playwright response body 读取失败被记录为 `skippedReadFailures=1`;同一页面最终仍只有 1 条 mindmap asset row,`mindmapId=mindmap_1778698542703`。
|
||
|
||
## 10. P3:文档治理与回填
|
||
|
||
状态:已完成文档侧收口。`10-review/README.md` 已指向本执行清单;`05-tree.md` 已标明 Resource Tree / ObjectIdentity / mindmap 与 `index.md` 隔离主线由 `4-24` / `5-12` 承接完成;`5-5-1` 已修正 `showHeadingNumbers` / `embedDefaultBlockId` 的 runtime payload 口径;`90-reference` 的对话式尾巴已清理,`design/README.md` 已补充参考目录不能覆盖主线设计的引用边界。
|
||
|
||
目标:让设计目录继续反映真实主线,不把参考资料或过时清单误当成当前架构。
|
||
|
||
建议修改范围:
|
||
|
||
- `design/10-review/README.md`
|
||
- `design/10-review/done/05-tree.md`
|
||
- `design/05-editor-mainline/done/5-5-1-page-aggregate-contract-v1.md`
|
||
- `design/90-reference/`
|
||
|
||
执行项:
|
||
|
||
- [x] 在 `05-tree.md` 中补充最终采用的 object editor / object tab 方案摘要,并说明核心执行已由 `4-24` / `5-12` 完成。
|
||
- [x] 修正 `5-5-1` 中 `showHeadingNumbers` / `embedDefaultBlockId` 已接入 runtime payload 的滞后描述。
|
||
- [x] 清理 `design/90-reference` 问答式残留,保留为中性参考笔记。
|
||
- [x] 在引用规范中再次强调 `90-reference` 不参与 process/done 状态判断,不是上位架构来源。
|
||
|
||
验收标准:
|
||
|
||
- [x] `design/10-review/README.md` 能指向本执行清单。
|
||
- [x] `05-tree.md` 不再让后续 worker 误以为 Resource Tree / ObjectIdentity / mindmap 止血仍未执行。
|
||
- [x] `design/90-reference` 的内容不再保留“需要我给你...”这类对话尾巴。
|
||
- [x] 主线文档对 Page Aggregate、tree realtime、ObjectIdentity 的描述与当前代码事实一致。
|
||
|
||
证据:
|
||
|
||
- `design/10-review/README.md`:补充执行入口,指向 `done/06-execution-checklist-and-acceptance.md`,并说明 `done/05-tree.md` 核心主线已由 `4-24` / `5-12` 承接。
|
||
- `design/10-review/done/05-tree.md`:开头增加执行状态,明确本文不再作为待办清单直接执行。
|
||
- `design/05-editor-mainline/done/5-5-1-page-aggregate-contract-v1.md`:`showHeadingNumbers` / `embedDefaultBlockId` 改为“runtime payload 已贯通,但深语义未完成”的口径。
|
||
- `design/90-reference/90-1-filetree.md`、`design/90-reference/90-2-yemianshu.md`:删除“需要我给你...”对话尾巴。
|
||
- `design/README.md`:补充 `90-reference/` 只能作为生态资料或背景材料,不能覆盖主线设计稿。
|
||
- `design/03-rust-web/done/3-15-runtime-fallback-retirement-checklist-v1.md`:从 `process/` 迁入 `done/`,文件自身 checkbox 已全部完成,且与第 2 / 第 8 项 fallback、compat 退场证据一致。
|
||
- `design/06-mindmap/done/6-mindmap-phase6-kmind-parity-detail-checklist-v1.md`:从 `process/` 迁入 `done/`,文件自身 checkbox 已全部完成,并已有 `task167-mindmap-kmind-parity-smoke.js` 等 Phase 6 KMind parity 证据。
|
||
- 已验证:`rg -n "需要我给你|我可以|你要不要|是否需要|请告诉我|如果你愿意|要我|我来" design/90-reference` 无匹配。
|
||
- 已完成只读状态审计:`design/03-rust-web/process/3-3-rust-web-tree-realtime-event-stream-v1.md`、`design/05-editor-mainline/process/5-5-page-aggregate-single-truth-alignment-v1.md`、`design/05-editor-mainline/done/5-6-page-aggregate-alignment-checklist-v1.md`、`design/06-mindmap/reference/6-mindmap-kernel-phase6-projection-editor-v1.md`、`design/06-mindmap/done/6-mindmap-phase6-leptos-ui-shell-reuse-checklist-v1.md` 仍有未完成项或长期主线尾项,继续保留在 `process/`;`design/07-ai/done/7-3-page-ai-hermes-panel-and-mnote-plugin-v1.md`、`design/07-ai/done/7-4-page-ai-hermes-panel-execution-checklist-v1.md`、`design/07-ai/done/7-5-hermes-client-proxy-contract-v1.md`、`design/07-ai/done/7-6-mnote-hermes-plugin-tool-contract-v1.md` 已迁入 `done/`,后续活跃 AI 体验面由 `design/07-ai/process/7-7-page-ai-mini-hermes-control-surface-v1.md` 承接;`design/old/**` 不纳入活跃 process/done 迁移判断。
|
||
|
||
## 11. 全局 Done Gate
|
||
|
||
全部清单完成前,不应把 10-review 状态描述为“单一真源已完全闭环”。可以描述为:
|
||
|
||
> Rust 已经持有主语义主导权,Page Aggregate、tree command、tree realtime、Resource/ObjectIdentity 主线已经切入;剩余工作集中在 artifact 一致性、fallback 退场、realtime 查询模型、provenance 口径和 compat 边界收口。
|
||
|
||
全部完成的最低验收:
|
||
|
||
- [x] P0 两项全部完成,且有自动化测试或真实 smoke 证据。
|
||
- [x] `05-tree.md` 已执行事项通过 `task169` 或等价 smoke 防回归。
|
||
- [x] `/api/page-aggregate/:id` provenance 与真实来源一致。
|
||
- [x] `/api/tree/events` 不依赖全量日志扫描作为长期查询模型。
|
||
- [x] 3000 默认主链不返回假业务数据、不走 legacy proxy、不静默 no-op 保存。
|
||
- [x] 设计文档中的 `process/`、`done/` 状态与真实代码和验收证据一致。
|
||
|
||
## 12. 关联缺陷验收状态
|
||
|
||
本执行清单本身已完成;与本轮用户反馈直接相关的两个 bug 文档状态如下:
|
||
|
||
- `bugs/04-tree-domain/done/4-25-tree-command-create-delete-reload-latency-v1.md`:Rust `/tree` debug shell 的 create / delete 强刷新子项已关闭,`task179` 已通过无 reload 与耗时验收;React Sidebar 直接 create/delete 已改为本地更新,不再同步等待 `refreshTree()`;Rust-family React shell 的 create / rename / move host mutation 回调也已改为本地 apply,不再默认整树 refetch。文档已迁入 `done/`。
|
||
- `bugs/05-editor-mainline/done/5-11-mindmap-ghost-assets-and-tree-command-latency-v1.md`:ghost mindmap asset 增长的 NodeView document id 误归属链路已止血,`task169` 已通过同一页面单 mindmap row 与 object identity 稳定验收;普通 mindmap 节点编辑 artifact 语义已收窄为 `mindmap.content.updated + noop`;已新增 `task180` 只读候选审计脚本用于清理前取证,并支持 `/api/tree/projections/file` 的只读投影输入以审计 File Tree duplicate row。真实 File Tree projection 审计已确认当前 workspace 下 `fileTreeMindmapRows=10`、`duplicateFileTreeMindmapRows=0`、`candidateCount=0`。历史清理候选为 0,因此本轮不执行数据删除;文档已迁入 `done/`。
|