89 lines
5.0 KiB
Markdown
89 lines
5.0 KiB
Markdown
# 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. 本轮验证
|
|||
|
|
|
|||
|
|
静态检查范围:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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 源码。后续修复应至少补:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
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
|
|||
|
|
```
|