# Batch J Worker C：ACP 稳定性与 benchmark checklist 草案

> 创建时间：2026-05-21
>
> 只读审查，不修改代码。

## 1. 读取过的关键文件

| 文件 | 行数 | 内容 |
|------|------|------|
| `design/07-ai/process/7-15-page-ai-acp-agent-runtime-unified-layer-v1.md` | 1029 | ACP 统一层设计：架构、协议、session lifecycle |
| `design/07-ai/process/7-34-acp-runtime-cleanup-availability-stability-tail-v1.md`| 300+ | 本任务上游：P0/P1/P2 checklist |
| `design/07-ai/done/7-25-acp-session-runtime-enhancement-plan-v1.md` | 371 | Session 持久化与管理增强规划 |
| `design/07-ai/done/7-30-acp-session-load-resume-checklist-v1.md` | ~80 | `session/load` 闭环已归档 |
| `design/07-ai/done/7-31-acp-permission-decision-loop-checklist-v1.md` | ~80 | Permission 决策闭环已归档 |
| `design/07-ai/done/7-32-acp-tool-location-and-open-action-checklist-v1.md` | ~80 | Tool locations + open action 已归档 |
| `design/07-ai/done/7-33-acp-session-info-plan-ui-checklist-v1.md` | ~80 | Session info + plan UI 已归档 |
| `rust/crates/mnote-web/src/acp_runtime.rs` | 500+ | Runtime lifecycle manager |
| `rust/crates/mnote-web/src/acp_session_manager.rs` | 700+ | Session lifecycle + event dispatch |
| `rust/crates/mnote-web/src/acp_bridge.rs` | 400+ | ACP ↔ SSE bridge |
| `rust/crates/mnote-web/src/acp_client.rs` | 746 | JSON-RPC 2.0 client |
| `rust/crates/mnote-web/src/acp_types.rs` | 800 | ACP 协议类型定义 |

## 2. ACP 多会话稳定性 smoke 最小脚本方案

### 2.1 测试目标

验证 ACP runtime 在处理 3+ 并发 session 时的稳定性：session 创建、prompt 流式、cancel、子进程异常恢复、事件去重。

### 2.2 测试设计

**方案类型**：Playwright 独立脚本 + Rust 端到端测试

**输入**：
1. 3 个参数化的 ACP run profile（reasonix + hermes × 2 不同 profile）
2. 每个 session 的 prompt 文本（简单固定 prompt："请用中文说'你好'，不要做其他操作"）
3. 超时配置（每个 run 最长 15s）

**操作步骤**：

```
Step 1: 创建 3 个 ACP session（POST /api/hermes/client/sessions）
  ├─ session_1: profile=reasonix
  ├─ session_2: profile=hermes (profile=mnoteai)
  └─ session_3: profile=hermes (profile=default)

Step 2: 在 3 个 session 上启动 run（POST /api/hermes/client/sessions/{id}/runs）
  并发发起，每个 session 间隔 ≤500ms

Step 3: 通过 SSE 流式读取事件（GET /api/hermes/client/events/{run_id}）
  对每个 run 读取到 run.completed 或超时 15s
  记录：message.delta 事件数量、tool.started、tool.completed

Step 4: cancel 验证
  Step 2 后立即 cancel session_2（POST /api/hermes/client/runs/{run_id}/abort）
  验证收到 run.failed / abort.completed

Step 5: 验证事件去重
  对 session_1 的 SSE 流，检查 textDelta 的 deduplication 逻辑
  （accumulated text 不重复增长）

Step 6: 清理
  删除 3 个 session（DELETE /api/hermes/client/sessions/{session_id}）
```

**断言**：

| # | 断言 | 优先级 |
|---|------|--------|
| 1 | 3 个 session 均创建成功（返回 200 + sessionId） | P0 |
| 2 | 3 个 run 均收到 `run.completed`（无超时） | P0 |
| 3 | session_2 的 cancel 在 3s 内生效（收到 `run.failed` 或 `abort.completed`） | P0 |
| 4 | 所有 SSE 流在 `run.completed` 后 500ms 内自动关闭（无泄漏） | P1 |
| 5 | session_1 的 message.delta 累计 length 不小于 4（中文"你好"） | P1 |
| 6 | 事件去重正常：textDelta 无重复或突然截断 | P1 |
| 7 | 3 个 session 互相不干扰（事件不交叉） | P1 |
| 8 | ACP 子进程数 = session 数（无 zombie） | P2（度量） |

**证据文件**：
- `artifacts/acp-stability/events-session-1.jsonl`
- `artifacts/acp-stability/events-session-2.jsonl`
- `artifacts/acp-stability/events-session-3.jsonl`
- `artifacts/acp-stability/runtime-metrics.json`
- `artifacts/acp-stability/process-list.txt`（`ps aux | grep -E 'hermes|acp'`）

### 2.3 浏览器可见验证点

1. **session 列表** — 打开页面 AI drawer → session list 应显示 3 个活跃 session
2. **run 状态** — 每个 session 的 run 状态从 `sending` → `running` → `completed`
3. **cancel 反馈** — 被 cancel 的 session 显示 "已请求停止" + 后续不再有 tool call
4. **无 UI 异常** — 无 502/500 错误，无工具 manifest 加载失败

建议截图：
- 3 session 同时运行的页面 AI drawer 快照
- cancel 后的 UI 状态
- 清理后 session 列表为空

## 3. Reasonix cache benchmark 最小脚本方案

### 3.1 测试目标

对比 Hermes / Reasonix 在相同 prompt 下的首次运行、二次运行（cache 命中）的耗时差异。

### 3.2 测试设计

**输入**：

| 维度 | 值 |
|------|-----|
| Prompt | "读取当前页面，列出前三段的主题"（约 20 token） |
| 样本数 | 每 runtime × 2（cold + cached）= 4 次 |
| Runtime | Hermes (mnoteai profile)、Reasonix |
| 页面 | 已知内容的本地 Markdown 文档（>50 行） |

**操作步骤**：

```
Step 1: 预热
  创建一个 ACP session（profile=reasonix），发送 prompt，等待完成，删除 session

Step 2: 冷启动测试（Reasonix）
  新 session（profile=reasonix）→ prompt → 计时 → 记录 total_ms

Step 3: Cache 命中测试（Reasonix）
  同一 session re-prompt → 计时 → 记录 total_ms
  注意：确保 prompt 内容一致，观察 response 中是否有 cache hit 提示

Step 4: 冷启动测试（Hermes）
  新 session（profile=hermes/mnoteai）→ prompt → 计时 → 记录 total_ms

Step 5: Cache 命中测试（Hermes）
  同一 session re-prompt → 计时 → 记录 total_ms

Step 6: 重复 Step 2-5 共 1 轮（共 8 次测量）
```

**输出格式**（JSON）：

```json
{
  "schema": "mnote.acp_cache_benchmark.v1",
  "timestamp": "2026-05-21T12:00:00Z",
  "runs": [
    {
      "runtime": "reasonix",
      "phase": "cold",
      "trial": 1,
      "totalMs": 4230,
      "firstTokenMs": 1200,
      "completionMs": 3030,
      "toolCalls": 1,
      "messageCharCount": 85,
      "cacheHit": false
    },
    {
      "runtime": "reasonix",
      "phase": "cached",
      "trial": 1,
      "totalMs": 890,
      "firstTokenMs": 210,
      "completionMs": 680,
      "toolCalls": 1,
      "messageCharCount": 85,
      "cacheHit": true
    }
  ],
  "summary": {
    "reasonixColdAvgMs": 4440,
    "reasonixCachedAvgMs": 920,
    "hermesColdAvgMs": 5100,
    "hermesCachedAvgMs": 3100,
    "speedupRatio": 4.8
  }
}
```

### 3.3 浏览器验证点

1. **页面 AI drawer 运行时选择器** — 切换 hermes/reasonix 时的 UI 响应
2. **首次对话速度** — 冷启动时 UI 从 "thinking" 到首次 token 的延迟
3. **cache 提示** — Reasonix cached run 的 tool.call/complete 速度应更快
4. **内存观察** — 浏览器 devtools → Performance → JS heap 无异常增长

### 3.4 建议测试脚本存放位置

```
scripts/task-acp-stability-smoke.js          ← 多会话稳定性
scripts/task-acp-cache-benchmark.js           ← cache benchmark
```

参考已有：`scripts/task-page-block-ai-tools-smoke.js`、`scripts/task-hermes-page-ai-baseline-smoke.js`。

## 4. P0 vs P2 归类

| 测试项 | 级别 | 理由 |
|--------|------|------|
| 3 个 session 创建 + 正常完成 | **P0** | 并发是基本稳定性要求 |
| Cancel 在合理时间内生效 | **P0** | UX 基础：用户停止必须工作 |
| SSE 流在 run 完成后关闭 | **P1** | 防止资源泄漏 |
| 事件去重正确 | **P1** | 文本重复或截断影响 UX |
| Session 间事件不交叉 | **P1** | 数据隔离是基本正确性 |
| Cold vs cached 耗时对比 | **P2** | 度量性质，不影响正确性 |
| 子进程数量 | **P2** | 度量性质 |
| 具体第一 token 时间 | **P2** | 度量性质 |

## 5. 建议的现有 targeted test

```bash
# 现有 ACP 单元测试（可复用）
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web acp_session_manager -- --test-threads=1
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web acp_bridge -- --test-threads=1
cd /mnt/Data1T/mnote/rust && cargo test -p mnote-web acp -- --test-threads=1

# 现有 smoke 测试（参考模式）
node scripts/task-page-block-ai-tools-smoke.js
node scripts/task-hermes-page-ai-baseline-smoke.js
```
