# 09 页面 AI 快速块编辑 Runtime Review

> 状态：`done`
>
> 日期：2026-05-16
>
> 关联主线：
> - `design/old/07-ai/process/7-10-page-block-ai-tooling-execution-checklist-v1.md`
> - `design/07-ai/reference/7-12-page-ai-hermes-tool-routing-and-review-surface-v1.md`
> - `design/07-ai/done/7-9-page-block-ai-tooling-roadmap-v1.md`
> - `design/05-editor-mainline/done/5-13-page-block-identity-and-command-contract-v1.md`

---

## 0. 归档说明

本文件是 2026-05-16 的页面 AI fast block edit 历史审查快照。其记录的 `local_rule` / `doc_apply_block_ops` 快路径已被后续 `mnote.doc.markdown_edit` 主路径替代，不再作为当前 runtime 口径。

当前有效口径见：

- [10-current-mnote-ai-runtime-review-v1](./10-current-mnote-ai-runtime-review-v1.md)
- [11-current-full-architecture-review-v1](./11-current-full-architecture-review-v1.md)
- [7-18 AI markdown_edit 阶段状态合同漂移](../../../bugs/07-ai/done/7-18-ai-markdown-edit-phase-state-contract-drift-v1.md)
- [7-20 page_ai_workflow 绕过 Hermes tool executor / audit / toggle](../../../bugs/07-ai/done/7-20-page-ai-workflow-bypasses-hermes-tool-executor-v1.md)

归档后的结论：`page-ai/block-edit-workflow` 仍是简单编辑 fast-path 入口，但当前实现应通过模型生成 markdown search/replace / full_content 后调用 `mnote.doc.markdown_edit`，并复用统一 mnote tool executor；`mnote.doc.apply_block_ops` / `mnote.block.*` 只作为结构性块操作辅助。

## 1. 本轮结论

页面 AI 块写入的慢点不在 Rust 块工具本身，也不在 Convex 持久化本身。

本轮真实浏览器 smoke 显示：

- 旧路径：页面 AI 先调用 `/api/page-ai/block-edit-workflow`，快路径模型阶段耗时约 `7695ms`，随后因模型输出的块定位未命中 projection，`doc_apply_block_ops` 返回 `mnote_block_not_found`，前端继续 fallback 到 `/api/hermes/client/runs`，最终由 Hermes agent 调 `mnote.doc.apply_block_ops` 写入，总可见耗时约 `13246ms`。
- 新路径：同一类简单中文块操作先由 mnote 本地 planner 解析为 `replace/insert_after/delete` operations，再直接调用 Rust `doc_apply_block_ops`。浏览器 smoke 回读可见耗时 `788ms`；后端日志显示 `operation_source=local_rule`、`model_ms=0`、`apply_ms=42`、`total_ms=42`，且未进入 `/api/hermes/client/runs`。

因此，当前要继续做的是 Hermes 工具路由、上下文冻结、dry-run/review 与 Rust 写入校验基建，而不是继续让 Hermes agent 反复执行同一个端到端动作，也不是在 mnote 内新建第二套 AI runtime。

---

## 2. 慢的直接原因

### 2.1 通用 agent 编排链路太长

旧页面 AI 编辑链路实际包含：

```text
浏览器输入
  -> Hermes session/profile/tools 初始化
  -> 模型理解页面任务
  -> 模型选择工具
  -> 工具调用
  -> 回读或继续推理
  -> 最终回复
```

这适合复杂任务，但不适合“把 A 替换为 B / 在 A 后插入 C / 删除 D”这类明确块操作。

### 2.2 模型直接产 operations 不够可靠

本轮快路径第一版已经绕开 Hermes agent，但仍让 DeepSeek 直接根据 `page_xml/page_text` 生成 operations。失败点是：

```text
model_ms ~= 7695
operations = 3
apply -> mnote_block_not_found
fallback -> Hermes agent
```

说明模型输出了看似正确的操作数，但 block 定位信息没有命中当前 Page Aggregate projection。这个问题不能靠增加 smoke 次数解决，必须让 mnote runtime 在模型前后都掌握定位与校验。

### 2.3 失败后 fallback 放大了耗时

第一版前端逻辑在快路径失败时继续进入 `/api/hermes/client/runs`。这导致一次用户请求可能经历：

```text
快路径模型失败成本 + Hermes agent 成功成本
```

本轮已改为：只有后端明确返回 `page_ai_workflow_not_block_edit` 才允许 fallback；其他快路径错误直接在本轮 run 中失败展示，避免重复写入和重复等待。

---

## 3. 已完成的修正

### 3.1 页面 AI 快速块编辑 route

已新增并接入：

- `POST /api/page-ai/block-edit-workflow`
- 文件：`rust/crates/mnote-web/src/routes/page_ai_workflow.rs`

该 route 负责：

- 接收当前页面冻结后的 `mnote.page_ai_context.v1`。
- 为明确中文编辑语句先走本地 operation planner。
- 无法本地解析时才调用小模型生成 operations。
- 最终统一走 `mnote.doc.apply_block_ops`，由 Rust 生成 canonical content 并保存。

### 3.2 简单块操作本地 planner

已支持这类明确表达：

```text
把「A」替换为「B」；
在「C」后插入「D」；
删除「E」。
```

输出直接是：

```json
[
  {"op":"replace","matchText":"A","content":"B"},
  {"op":"insert_after","matchText":"C","content":"D"},
  {"op":"delete","matchText":"E"}
]
```

该层的目的不是做通用自然语言理解，而是把高频、低歧义、可确定的块编辑从模型路径剥离出来。

### 3.3 快路径可观测性

后端日志已记录：

- workflow started/completed
- operation source：`local_rule` 或 `model`
- operations 数量
- model 耗时
- apply 耗时
- total 耗时

smoke 也已在失败时写出 evidence JSON，并记录 `/api/page-ai/*` 与 `/api/hermes/client/*` 请求/响应。

---

## 4. 验证证据

命令：

```bash
cargo test -p mnote-web page_ai_workflow -- --nocapture
cargo test -p mnote-web hermes_tools -- --nocapture
MNOTE_PAGE_AI_FAST_TIMEOUT_MS=60000 node scripts/task-page-ai-block-edit-workflow-smoke.js
```

结果：

- `page_ai_workflow`：2 passed。
- `hermes_tools`：22 passed。
- 浏览器 smoke：通过。

最新浏览器 evidence：

```text
/mnt/Data1T/mnote/tmp/page-ai-block-edit-workflow-smoke/mp86uciu.json
```

关键值：

```json
{
  "timingsMs": {
    "pageAiWriteVisible": 788
  },
  "usedFastWorkflow": true,
  "usedHermesRun": false,
  "finalTexts": [
    "第一段 mp86uciu",
    "插入段 mp86uciu",
    "第二段已修改 mp86uciu"
  ]
}
```

后端关键日志：

```text
operation_source="local_rule"
model_ms=0
apply_ms=42
total_ms=42
```

---

## 5. 剩余问题

### 5.1 不能把本地 planner 当成完整 AI runtime

当前本地 planner 只覆盖低歧义中文引号表达。它证明了正确的 runtime 方向，但不是最终答案。

需要继续建设：

- PageAIContextBuilder：冻结 selection/page context，减少模型输入。
- PageAIIntentParser：先判定是明确块操作、结构化改写、摘要问答、还是复杂编辑。
- PageAIOperationPlanner：把明确操作转成 `mnote.doc.apply_block_ops`，复杂操作才调用小模型。
- PageAIOperationValidator：模型输出后必须用 projection 校验 blockId/matchText/allowedTargetBlockIds。
- PageAIApplyController：统一处理 yolo 写入、失败展示、回读验证、审计日志。

### 5.2 模型输出 operations 仍需修

当请求不能被本地 planner 解析时，仍会调用模型。该路径必须补：

- 输出 schema 更严格，禁止模型臆造 blockId。
- 优先 `matchText` 或由服务端根据 text resolve block，而不是信任模型 blockId。
- 模型输出后做 dry-run validate，不命中时不要 fallback Hermes agent 重新跑。
- 把 validation error 反馈给用户或进入后续 clarify/retry，而不是隐式整页写。

### 5.3 Hermes agent 不应承担短路径编辑

Hermes 仍适合：

- 多步骤页面理解。
- 跨页面检索。
- 工具不可直接表达的复杂任务。
- 外部 skill/plugin 编排。

但对当前页面小段落块增删改，mnote 自己的 runtime 应该在浏览器/Rust route 内完成 `intent -> operations -> apply -> readback`。

---

## 6. 下一步建议

优先级应从“继续 smoke”切到“补 AI runtime 基建”：

1. `PageAIIntentParser`
   - 输入：用户 prompt、scope、selection、page context。
   - 输出：`direct_block_ops | model_block_ops | question | unsupported`。
   - 目标：不让每条简单编辑都进入 Hermes agent。

2. `PageAIOperationPlanner`
   - 扩展当前本地 planner。
   - 支持常见中文/英文明确表达。
   - 支持选区内“改成/润色/拆成列表”等可控操作。

3. `PageAIOperationValidator`
   - 所有 operations apply 前先 resolve projection。
   - 对 blockId、matchText、allowedTargetBlockIds、editable、children、revisionRef 做统一校验。
   - 失败返回结构化错误，不 fallback 通用 agent。

4. `PageAIApplyController`
   - 统一 yolo 模式下的写入、回读、状态展示和失败提示。
   - 后续再接 preview/review session，而不是现在把 review 作为默认阻塞。

5. 模型路径瘦身
   - 对必须调用小模型的任务，发送 `page_xml/text + allowed operations schema`。
   - 模型只负责生成候选 operations；最终定位、校验和写入仍由 Rust runtime 负责。

---

## 7. 当前判断

小段落编辑低于 10s 已经被证明可达，且当前 smoke 为 `788ms`。

下一阶段的关键不是再证明“能写”，而是把这条快路径产品化：

```text
用户意图
  -> mnote intent/parser
  -> operation planner
  -> projection validator
  -> Rust apply
  -> readback
  -> UI 状态/审计
```

Hermes agent 应从默认编辑执行器退回到复杂任务编排器。
