- add npm dev:hot wrapper using cargo-watch and page reload polling - add mnote-web dev hot reload endpoint and coverage - record current architecture review and tracked bug findings across realtime, tree, editor, and AI runtimes Verification: - node scripts/task-dev-hot-plan-test.js - node --check scripts/dev-hot.js - cargo test -p mnote-web dev_hot -- --nocapture
2.8 KiB
2.8 KiB
7-17 [process][bug] mnote.doc.markdown_edit 同块多操作写回会覆盖前序修改 v1
发现时间:2026-05-17
状态:
[process]关联主线:
07-ai关联代码:
rust/crates/mnote-web/src/hermes_tools/doc.rs:779-824— markdown 字符串层顺序执行 operationsrust/crates/mnote-web/src/hermes_tools/doc.rs:854-878— Convex 写回重新转换成 block opsrust/crates/mnote-web/src/hermes_tools/doc.rs:976-1008—build_block_ops_from_markdown_edit
1. 问题定义
doc_markdown_edit 会先把所有 search/replace 顺序应用到 md:
match search_replace(&md, &search, &replace) {
Ok(new_md) => {
md = new_md;
applied += 1;
}
...
}
但在线 Convex 文档写回时没有使用这个最终 md。当前实现重新读取 Page Aggregate blocks,然后对每条 operation 基于原始 block 文本生成一个 replace block op:
let block_text = block.get("text").and_then(Value::as_str).unwrap_or("");
let new_text = block_text.replacen(search, replace, 1);
如果两条 operation 命中同一个 block,第二条 operation 的 new_text 仍从原始 block_text 计算,会覆盖第一条 operation 的结果。
2. 影响
用户在页面 AI 中一次提出多个同段修改时,可能只保留最后一个修改。例如:
[
{ "search": "A", "replace": "B" },
{ "search": "C", "replace": "D" }
]
若 A 和 C 都在同一个 block 中,markdown 层预期最终是 B ... D,但写回层可能生成两个 replace block op:
op1 content = 原始文本中 A -> B
op2 content = 原始文本中 C -> D
最终第二次 replace 会把 block 写成只包含 C -> D 的版本,前一次 A -> B 被丢失。
3. 根因
doc_markdown_edit 有两套编辑结果:
md:顺序应用 operations 后的真实 markdown 结果。block_ops:从原始 blocks 和原始 operations 重新推导出来的写回操作。
Convex 写回使用的是 block_ops,而不是 md。这让“markdown 编辑主路径”在在线文档里退化成了不完整的 block ops 转换层。
4. 建议修复
- 最小修复:
build_block_ops_from_markdown_edit先按 block 聚合 operations,并基于当前已更新文本连续计算同块最终 content。 - 更稳妥修复:以最终
md作为单一结果,走 markdown -> EditorBlockDocument / page.body.save 的正式转换链,不从原始 operations 二次推导写回结果。 - 增加同一 block 多 operation 的单测和真实 Page Aggregate 回读 smoke。
- 明确部分失败是否允许写入;默认建议任一 operation 失败时不写入,除非调用方显式允许 partial apply。
5. 状态
已确认源码层缺陷,尚未修复。进入 process 等待实现和验证。