Files
mnote/design/10-review/process/10-current-mnote-ai-runtime-review-v1.md
T
lix-2026 3311bd0366 chore: document architecture gaps and add dev hot reload
- 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
2026-05-17 23:09:56 +08:00

5.0 KiB
Raw Blame History

10 [process] 当前 mnote 项目 AI / Page Aggregate 定向 Review v1

更新时间:2026-05-17

执行状态:process

范围:当前主线中 Page Aggregate 单一真源、页面 AI 快速编辑、mnote.doc.markdown_edit 与 ACP / Hermes runtime 的源码级定向审查。

1. 本轮结论

本轮没有发现 Page Aggregate 读取主链重新回退到 Next compat builder 的证据;wolai-frontend/src/lib/documents/page-aggregate-loader.ts 仍只走 Rust /api/page-aggregate/:documentId/api/documents/page compat 读链保持 410 退场口径。

新的风险集中在 07-ai 的 markdown 编辑收敛实现:

  • mnote.doc.markdown_edit 已进入实际写入主线,并被 /api/page-ai/block-edit-workflow 调用。
  • 该工具当前先在 markdown 字符串上顺序执行 search/replace,再把原始 operations 重新转换成 mnote.doc.apply_block_ops
  • 转换层仍按“单块文本包含 search”查找目标块,无法忠实表达 markdown 层已经算出的最终结果。

因此,当前 AI 编辑主线不能只看 operationsApplied > 0 或 route 返回 ok=true。需要优先补充 markdown_edit 的中文、多操作、同块、多块、full_content 与失败原子性测试。

2. 发现的问题

R-01 P0:中文归一化匹配使用 byte index 当 char index

关联缺陷:

  • bugs/07-ai/process/7-16-markdown-edit-normalized-search-byte-index-v1.md

证据:

  • rust/crates/mnote-web/src/hermes_tools/doc.rs:920-936

search_replace 的 Level 2 先在 norm_line 上用 find() 得到 UTF-8 byte offset,却把这个 offset 传给 line.char_indices().nth(start) 当作字符序号使用。中文、多字节标点或中英混排时,替换范围会偏移,可能替错片段或生成错误内容。

影响:

  • 页面 AI 对中文正文的“忽略空白 / 全半角差异”替换不可靠。
  • 该问题位于 mnote.doc.markdown_edit 的基础 search/replace 层,会同时影响在线文档和本地 .md 文件。

R-02 P0:同一块内多次 markdown_edit 会被后续 block op 覆盖

关联缺陷:

  • bugs/07-ai/process/7-17-markdown-edit-same-block-multi-op-overwrite-v1.md

证据:

  • rust/crates/mnote-web/src/hermes_tools/doc.rs:779-824
  • rust/crates/mnote-web/src/hermes_tools/doc.rs:854-878
  • rust/crates/mnote-web/src/hermes_tools/doc.rs:976-1008

doc_markdown_edit 已经在 md 变量中顺序应用了所有 search/replace,但 Convex 写入时没有使用这个最终 markdown。它重新读取原始 Page Aggregate blocks,并对每个 operation 用原始 block 文本生成一个 replace block op。

如果两个 operation 命中同一个 block,第二个 block op 的 content 仍从原始文本计算,会覆盖第一个 operation 的结果。也就是说,markdown 层算出的最终结果与实际落库结果可能不一致。

影响:

  • AI 一次请求中常见的“把同一段里的 A 改成 B,同时把 C 改成 D”可能只保留最后一次修改。
  • 前端快路径仍可能显示“已通过页面 markdown 编辑快路径完成写入”,但正文只部分生效。

3. 次级风险

  • doc_markdown_edit 当前允许部分 operation 失败后继续写入已成功的子集,并返回 ok=true。如果这是有意设计,需要在 manifest / UI 中明确“非原子”;如果不是,应改为任一 operation 失败时不写入。
  • changedText 通过 operations.iter().take(applied) 生成摘要;当前如果第一个 operation 失败、第二个成功,摘要会错误地展示第一个失败 operation。
  • /api/page-ai/block-edit-workflow 的系统 prompt 已改成 search/replace,但仍强依赖模型精确复制 pageText;一旦模型输出跨块片段,Convex 写回层不能表达该编辑。

4. 建议下一步

  1. 先给 search_replace 补中文归一化替换单测,再修正 byte / char offset 映射。
  2. doc_markdown_edit 补同一 block 多 operation 的失败用例,明确应以最终 markdown 生成落库内容,或在转换层合并同块操作。
  3. 明确 markdown_edit 的失败原子性:默认建议任一 operation 失败时不写入,除非请求显式允许 partial apply。
  4. /api/page-ai/block-edit-workflow 的验收从“route 成功”提升为“Page Aggregate 回读与预期最终 markdown 一致”。

5. 本轮验证

静态检查范围:

rg -n "markdown_edit|apply_block_ops|block-edit-workflow|local_rule|page_ai_workflow|mnote\\.doc\\.fetch" rust wolai-frontend scripts design/07-ai design/10-review --glob '!rust/target/**' --glob '!node_modules/**'
rg -n "page-aggregate|pageAggregate|PageAggregate|blockDocument|projectionSource|documents/save|documents/options|/api/page-aggregate" rust/crates/mnote-web rust/crates/bridge-runtime wolai-frontend/src scripts --glob '!rust/target/**' --glob '!node_modules/**'

本轮是 review / bug hunt,没有修改 runtime 源码。后续修复应至少补:

cargo test --manifest-path rust/Cargo.toml -p mnote-web markdown_edit
cargo test --manifest-path rust/Cargo.toml -p mnote-web page_ai_workflow