# 7-27 [done][bug] 在线 markdown_edit full_content 会保留旧普通块

> 发现时间：2026-05-18
>
> 状态：`[done]`
>
> 关联主线：`07-ai`
>
> 关联设计：`design/07-ai/process/7-27-online-markdown-writeback-final-content-truth-v2.md`

## 1. 问题定义

`mnote.doc.markdown_edit` 的在线 Convex 文档路径已经切到 final markdown -> block content 直接写回，但 `full_content` 模式下，最终 markdown 通常不包含任何 `<!-- block:... -->` 原始块注释。

当前 `build_page_content()` 会把所有未处理的原始块追加到写回结果尾部，导致全文替换不是“替换全文”，而是：

```text
新全文块...
旧 heading / paragraph / todo 块...
```

## 2. 影响

- AI 执行全文改写、重写大纲、把页面替换为整理后的内容时，会保留旧正文残留。
- Page Aggregate / `mnote.doc.fetch` 回读会看到新旧内容混在一起。
- 7-27 的“最终 markdown 是唯一写回真源”合同被破坏。

## 3. 根因

`parse_final_markdown_to_blocks()` 对无注释的 final markdown 行会生成 `is_new=true` 块，这是正确的。

问题在 `build_page_content()` 的末尾：

```rust
for original in &original_blocks {
    if let Some(id) = block_id_of(original) {
        if !processed_ids.contains(&id) {
            result.push(original.clone());
        }
    }
}
```

该逻辑没有区分：

- 部分 search/replace 丢掉某个块注释：应保守保留缺失旧块，避免误删。
- `full_content` / 全文替换没有任何原始块 ID：应只保留复杂块，普通旧文本块应被替换掉。

## 4. 修复

- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:727) 给 `build_page_content()` 增加策略：
  - 若 parsed 中至少引用了一个原始 block id，则保留未处理原始块，维持安全降级。
  - 若 parsed 中没有任何原始 block id，则视为全文重建，只保留复杂块，不保留普通旧文本块。
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:799) 增加 `is_complex_markdown_original_block()`，用于 full_content 重建时保留 resource / mindmap / table / image / attachment / 非 editable / unsupported / 带 children 的复杂块。
- [doc.rs](/mnt/Data1T/mnote/rust/crates/mnote-web/src/hermes_tools/doc.rs:1059) 增加单元测试：
  - `full_content` 无原始 ID 时不保留旧 heading / paragraph。
  - 原始 resource 复杂块仍保留。
  - 部分块注释丢失时仍保留缺失旧块。

## 5. 验证

```bash
cargo test --manifest-path rust/Cargo.toml -p mnote-web build_page_content -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web hermes_tools_markdown_edit_online_full_content_rejects_unsafe_block_mapping -- --nocapture
cargo test --manifest-path rust/Cargo.toml -p mnote-web hermes_tools_markdown_edit -- --nocapture
cargo fmt --manifest-path rust/Cargo.toml --all -- --check
git diff --check -- rust/crates/mnote-web/src/hermes_tools/doc.rs bugs/07-ai/done/7-27-markdown-edit-full-content-retains-old-blocks-v1.md
```

结果：

- `build_page_content` 相关测试：`2 passed`。
- `hermes_tools_markdown_edit_online_full_content_rejects_unsafe_block_mapping`：`1 passed`。
- `hermes_tools_markdown_edit` 相关测试：`6 passed`。
- Rust workspace format check 通过。
- 相关路径 diff check 通过。
