# 5-19 [done] Page Aggregate 块投影未优先消费 EditorBlockDocument ## 级别 P1 / 05-editor-mainline 主线迁移缺陷。 ## 现象 `page.body.save` 已在 Rust runtime plan 与 artifact 中保留 `editorDocument`,但 `page.aggregate.get` 构建 `body.blockDocument` 时仍固定从 legacy `documents.content` 投影。 当 `editorDocument` 与旧 `content` 不一致时,AI 块读取、块定位与 Page Aggregate 回读会继续看到旧内容,导致页面域单一真源迁移停留在 legacy content 过渡层。 ## 根因 `rust/crates/bridge-runtime/src/lib.rs` 的 `build_page_aggregate_projection_result` 只读取 `content_result.content`,随后调用 `project_legacy_content_to_block_document`,并把 `projectionSource` 固定为 `documents.content`。 ## 修复 - `page.aggregate.get` 的内容结果识别现在包含 `editorDocument` 与 `blockDocument`。 - Page Aggregate `body.blockDocument` 来源顺序调整为: - `editorDocument`:优先解析 `EditorBlockDocument`,由 Rust runtime 投影为 Page Aggregate 块文档。 - `blockDocument`:已有块投影直接作为次级来源。 - `documents.content`:仅在缺少原生块文档来源时回退。 - `body.projectionSource` 改为真实来源:`editorDocument` / `blockDocument` / `documents.content`。 - 新增回归测试 `page_aggregate_get_prefers_editor_document_over_legacy_content`,覆盖 `editorDocument` 与旧 `content` 冲突时的优先级。 - 新增非法原生块文档防回退保护: - `editorDocument` 存在但不可解析时返回 validation error,不再静默回退到旧 `content`。 - `blockDocument` 存在但不是对象时返回 validation error,不再静默回退到旧 `content`。 - Page Aggregate `body.content` 也同步按原生来源重建: - `editorDocument` 来源下由 `EditorBlockDocument` 生成 legacy content。 - `blockDocument` 来源下由块投影生成 legacy content。 - 避免同一份 Page Aggregate 中 `body.blockDocument` 正确但 `body.content` 仍指向旧正文,导致编辑器/session 下游继续显示或保存旧真相。 ## 验证 - RED:`cargo test --manifest-path rust/Cargo.toml -p bridge-runtime page_aggregate_get_prefers_editor_document_over_legacy_content -- --nocapture` - 旧实现失败,返回 `legacy_1` 而不是 `editor_1`。 - GREEN:`cargo test --manifest-path rust/Cargo.toml -p bridge-runtime page_aggregate -- --nocapture` - 6 passed。 - Rust Web 回归:`cargo test --manifest-path rust/Cargo.toml -p mnote-web page_aggregate -- --nocapture` - 7 passed。 - 格式:`cargo fmt --manifest-path rust/Cargo.toml --all -- --check` - passed。 ## 剩余边界 这次修的是 Page Aggregate 读侧优先级,不是 Convex 原生 `EditorBlockDocument` 落库 schema 的最终切换。`documents:updateContent` 兼容写入仍保留 legacy content substrate;后续主线应继续推进持久层原生块文档字段与命令写入闭环。