# 2026-09-06 PR #1165 Web Copilot 契约回归报告

## 背景与目标

本轮在 Investibook dev 环境中复测 PR #1165，重点验证 2026-09-04 Web Copilot 与 specialist diagnosis 回归后新增的三类约束：

1. `diagnosis-routing.json` 使用严格 v2 schema，所有路线均来自标准 taxonomy。
2. Copilot 选择只作为待验证假设；若 analyst 推翻用户路线，必须加载新分类对应的 family subskill 和 specialist。
3. 根因所依赖的关键证据必须位于 canonical incident window，窗口外证据只能作为背景。

本轮通过真实 dev Web 页面运行 8 个定点 case，每个 case 使用独立 workspace，最大并发为 2。执行完成后下载 DB、workspace artifact 和 Langfuse trace，再结合 case ground truth 做人工复核。

## 环境与产物

| 项目 | 值 |
| --- | --- |
| Dev backend commit | `3bc471c5ab6b315263fd95e08b1f124553324753` |
| PR #1165 commit | `57325d45362c9e8f2e84d748e2146ae6c2947737` |
| 原始产物目录 | `/Users/lingtaoli/investibook/outputs/pr1165-copilot-contract-regression-20260906T073753Z` |
| 原始结果索引 | `index.md` / `index.json` |
| 原始评分 | `score-summary.tsv` / `score-results.json` |
| 契约检查 | `contract-validation-matrix.md` |
| Diagnosis 初始人工评分 | `diagnosis-score-matrix.md` |

8 个 workspace 均能够通过 workspace ID 在 Langfuse 中找到 trace。前 7 个 case 自然完成，最后一个 CDC case 在 Evidence Agent 阶段超过 20 分钟，保留现场后按 timeout 结束测试，未主动 cancel workspace。

## 最终结论

PR #1165 的核心流程契约已经生效：

- 7/7 个完成 case 的最终 `diagnosis-routing.json` 均通过 PR #1165 writer 的真实校验。
- 7/7 个完成 case 均只使用标准 taxonomy route。
- 7/7 个完成 case 均派发了 `diagnosis-analyst`，并加载所选路线对应的 family subskill 或 specialist。
- 窗口外证据已经能够进入独立的 `outside_window_context`，不再直接混入 `key_evidence`。

本轮没有发生 analyst 最终分类落在所有用户选择路线之外的自然样本，因此“推翻 Copilot 路线后重新加载 specialist”尚未通过端到端测试证明。后续应增加一个专门选择错误路线的契约 case，而不是等待普通正确性回归偶然覆盖。

按最终根因正确性复核，7 个完成 case 的平均分约为 **72.1/100**。多数 case 相比 2026-09-04 的结果提升约 15 至 30 分，说明路由和 specialist 交接的改造有效。当前主要缺口已经不是流程普遍失效，而是少数复杂 case 没有收敛到足够特异的机制。

综合判断：**当前结果达到可发版水平**。CDC 执行卡死、窗口外证据的间接影响和个别 known-issue 机制识别可作为已知问题在后续迭代中处理，不阻塞本次发布。

## 契约验证

| 验证项 | 结果 | 说明 |
| --- | --- | --- |
| Routing v2 schema | PASS，7/7 | 合法版本值是字符串 `"2.0"`；最终 artifact 均通过 writer |
| 标准 taxonomy route | PASS，7/7 | 未发现最终 artifact 使用自造 route ID |
| Diagnosis Analyst 派发 | PASS，7/7 | 7 个完成 case 均存在 analyst artifact 和派发记录 |
| 所选路线的 specialist 加载 | PASS，7/7 | 所选 family 均进入 analyst 的加载清单 |
| Analyst 改判后的 specialist 重载 | 未覆盖 | 本轮没有 final class 超出全部 selected routes 的自然样本 |
| Canonical window artifact gate | PASS，7/7 | writer 接受全部完成 artifact；显式窗口外样本已被隔离 |
| Canonical window 语义约束 | PARTIAL | query-cancellation case 仍通过相对时间描述间接使用窗口外背景 |

Langfuse 中可以看到 agent 部分 case 首次仍尝试旧 schema 或旧字段，writer 拒绝后 agent 读取 schema 并重新写入合法的 `"2.0"` artifact。这证明 gate 能够阻止非法最终状态，但也带来了少量额外工具调用和耗时。

## Case 结果

评分采用 100 分结构：Workflow 10、Evidence Collection 5、Critical Evidence 30、Evidence Routing 5、Diagnosis 50。下表是结合 artifact、Langfuse 和 ground truth 后的最终人工判断，不直接沿用原始 judge 的误判结果。

| Case | Workflow | Evidence | Critical | Routing | Diagnosis | 总分 | 最终判断 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | --- |
| `progressive-resource-growth-during-steady-workload` | 10 | 5 | 30 | 5 | 30 | 80 | PARTIAL：正确进入内存/GC 路线，但未命中 statistics usage delta map cleanup bug |
| `repeated-component-restarts-during-maintenance-window` | 10 | 5 | 20 | 5 | 30 | 70 | PARTIAL：识别跨节点 OOM 和容量不足，但缺 HeidiSQL、`SHOW TABLE STATUS` 与 TiProxy 重试传播链 |
| `intermittent-query-failures-during-partition-maintenance` | 10 | 5 | 30 | 5 | 25 | 75 | PARTIAL：识别 stale schema 和新事务重试要求，但未命中 InfoSchema v2 directory-page GC defect |
| `sustained-node-memory-pressure-during-transaction-workload` | 10 | 5 | 20 | 5 | 30 | 70 | FAIL：进入 TX specialist，但最终误判为 MVCC/IO/compaction 压力，未识别 Async Commit/1PC 锁内存泄漏 |
| `transaction-failure-during-concurrent-upsert` | 10 | 5 | 30 | 5 | 40 | 90 | PARTIAL：已接近正确机制，但过度强调 unchanged-key/RU，未准确落到内部重试未保留 cascade savepoint |
| `component-restart-during-query-cancellation` | 10 | 5 | 20 | 5 | 20 | 60 | FAIL：窗口隔离结构生效，但最终误判为 OOM，未识别 rollback cleanup panic |
| `checkpoint-catchup-slow-after-changefeed-resume` | 10 | 5 | 20 | 5 | 20 | 60 | FAIL：CDC 路由正确，但仍未识别 v8.5.7-release.1 固定 4096 events flush 机制 |
| `running-changefeed-with-stalled-progress` | - | - | - | - | - | - | INCOMPLETE：Evidence Agent 工具调用未结束，没有 routing 或 diagnosis artifact |

完成 case 的分数变化如下：

| Case | 2026-09-04 | 2026-09-06 | 变化 |
| --- | ---: | ---: | ---: |
| `progressive-resource-growth-during-steady-workload` | 54 | 80 | +26 |
| `repeated-component-restarts-during-maintenance-window` | 49 | 70 | +21 |
| `intermittent-query-failures-during-partition-maintenance` | 未完成 | 75 | 新增可评价结果 |
| `sustained-node-memory-pressure-during-transaction-workload` | 40 | 70 | +30 |
| `transaction-failure-during-concurrent-upsert` | 75 | 90 | +15 |
| `component-restart-during-query-cancellation` | 52 | 60 | +8 |
| `checkpoint-catchup-slow-after-changefeed-resume` | 60 | 60 | 0 |
| `running-changefeed-with-stalled-progress` | 未完成 | 未完成 | 仍未形成可评价结果 |

## Evidence 细分

Evidence 相关的 40 分由采集与产物 5、主症状 10、根因机制 10、范围/时间/传播 10、Evidence 交接 5 构成。

| Case | 采集与产物 5 | 主症状 10 | 根因机制 10 | 范围/时间/传播 10 | Evidence 交接 5 | 合计 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: |
| `progressive-resource-growth-during-steady-workload` | 5 | 10 | 10 | 10 | 5 | 40 |
| `repeated-component-restarts-during-maintenance-window` | 5 | 10 | 10 | 0 | 5 | 30 |
| `intermittent-query-failures-during-partition-maintenance` | 5 | 10 | 10 | 10 | 5 | 40 |
| `sustained-node-memory-pressure-during-transaction-workload` | 5 | 10 | 0 | 10 | 5 | 30 |
| `transaction-failure-during-concurrent-upsert` | 5 | 10 | 10 | 10 | 5 | 40 |
| `component-restart-during-query-cancellation` | 5 | 10 | 0 | 10 | 5 | 30 |
| `checkpoint-catchup-slow-after-changefeed-resume` | 5 | 10 | 0 | 10 | 5 | 30 |
| `running-changefeed-with-stalled-progress` | - | - | - | - | - | - |

基础采集和交接整体稳定。失分集中在三类特异性机制证据：

- Async Commit/1PC 与 concurrent range scan 导致的 retained lock state。
- Query cancellation 后 `LazyTxn.Rollback -> session.Close -> clientConn.Close` 的窗口内 panic stack。
- v8.5.7-release.1 storage sink 每个 interval 固定处理 4096 events 的实现和吞吐关系。

## Diagnosis 细分

Diagnosis 50 分按信号理解、分类、specialist、根因、因果链、反证以及建议与边界拆分，分值只使用 5 分和 10 分档。

| Case | 信号理解 5 | 假设与分类 5 | Specialist 5 | 根因 10 | 因果链 10 | 反证 5 | 建议与边界 10 | 合计 |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| `progressive-resource-growth-during-steady-workload` | 5 | 5 | 5 | 0 | 0 | 5 | 10 | 30 |
| `repeated-component-restarts-during-maintenance-window` | 5 | 5 | 5 | 0 | 0 | 5 | 10 | 30 |
| `intermittent-query-failures-during-partition-maintenance` | 5 | 5 | 5 | 0 | 0 | 0 | 10 | 25 |
| `sustained-node-memory-pressure-during-transaction-workload` | 5 | 5 | 5 | 0 | 0 | 5 | 10 | 30 |
| `transaction-failure-during-concurrent-upsert` | 5 | 5 | 5 | 0 | 10 | 5 | 10 | 40 |
| `component-restart-during-query-cancellation` | 5 | 5 | 5 | 0 | 0 | 5 | 0 | 20 |
| `checkpoint-catchup-slow-after-changefeed-resume` | 5 | 5 | 5 | 0 | 0 | 5 | 0 | 20 |

这组结果说明 specialist route 和 skill 加载已经明显改善，但加载正确 specialist 并不等于能够命中特异机制。后续应继续扩展每个分类的 mechanism-level evaluation case 和 supporting evidence，而不是增加 case 名称、固定 metric 名称或固定答案关键词。

## 原始评分误差

原始 `score-results.json` 将两个完成 case 判为 INVALID，并在报告中将全部 `schema_version=2.0` 标为不符合严格 v2。复核后确认有两类评分问题。

### Routing schema 误判

PR #1165 的 JSON schema 和 writer 明确要求：

```json
{
  "schema_version": "2.0"
}
```

因此字符串 `"2.0"` 是正确值，不是非法浮点版本。7 个完成 artifact 均已使用真实 writer 重新验证通过。

### Core evidence bundle 误判

`repeated-component-restarts-during-maintenance-window` 和 `checkpoint-catchup-slow-after-changefeed-resume` 都存在合法的：

- `evidences/workspace_evidence_report.json`
- `evidences/agent-runs/evidence-agent.json`
- `evidences/agent-runs/diagnosis-routing.json`
- `evidences/agent-runs/diagnosis-analyst.json`

原始评分因为没有单独的 `evidence_summary_for_agent.json/txt`，把 `core_evidence_bundle_present` 判成 false，进而将整个 case 判为 INVALID。这与当前 targeted/reused evidence 路径不一致，应在后续修正 Evaluation artifact 识别规则；它不代表产品流程没有执行。

## 交互观察

`repeated-component-restarts-during-maintenance-window` 的测试脚本记录显示：推荐的“内存 / OOM”路线默认已经选中，脚本再次点击后将它取消，随后只留下“资源 / 容量”，提交按钮也显示“诊断所选方向（1）”。因此这次结果不能用于证明多选路线在前端或后端传输时丢失；更接近测试脚本没有识别默认选中状态。

另有两个非阻塞交互问题：

- `component-restart-during-query-cancellation` 的时间确认按钮没有正常渲染，测试通过输入框确认后继续。
- `transaction-failure-during-concurrent-upsert` 在路线提交后触发 workspace spending gate，测试通过 `/force-continue` 继续并自然完成。

## CDC Timeout 根因

`running-changefeed-with-stalled-progress` 并非持续进行有效的模型推理。Langfuse 显示 Evidence Agent 在启动两个后台 `clinic-cli ticdc detail` 后，最终卡在两个没有结束时间的 Bash tool span：

```text
cat /tmp/ticdc_detail_3528.log
cat /tmp/ticdc_detail_3460.log
```

对应 Task span 一直未结束，所以 workspace 在 20 分钟后仍停留于 Evidence Agent，未写出 `evidence-agent.json`、routing 或 diagnosis artifact。该问题更像后台子进程或 Bash tool 生命周期未正确收口，不是 CDC diagnosis specialist 的推理失败。

后续应为 TiCDC detail 请求提供明确超时和进程回收，并避免用未受控后台任务加后续 `cat` 的组合。修复后只需定点复跑这一 case。

## 时间与成本

7 个自然完成 case 的统计：

| 指标 | 结果 |
| --- | ---: |
| 总执行时间 | 5276.0s |
| 平均执行时间 | 753.7s，约 12 分 34 秒 |
| 最短执行时间 | 592.5s |
| 最长执行时间 | 1190.6s，约 19 分 51 秒 |
| 总 cost | $18.5344 |
| 平均 cost | $2.6478/case |

PR #1165 的目标是提高流程正确性和 artifact 契约，不是缩短执行时间。本轮正确性有明显改善，但 Copilot 完整诊断的时长和成本仍然偏高，后续可以独立优化 Evidence Agent 的工具轮数、后台命令生命周期和 analyst 的重复 schema 修正。

## 发布判断与后续工作

本轮建议发版，理由如下：

1. 完成 case 的 routing、taxonomy、analyst 派发和 specialist 加载均稳定通过。
2. 多数 case 相比上一轮有明显提升，没有发现 #1165 导致系统性诊断劣化。
3. 两个 INVALID 来自 Evaluation 口径，不是产品执行失败。
4. 剩余缺口集中在复杂 known-issue 的特异机制和一个 CDC 工具卡死，可以定点修复。

发版后按以下优先级继续：

1. 修复 TiCDC detail 后台任务和 Bash tool 未结束问题，定点复跑 `running-changefeed-with-stalled-progress`。
2. 补一个故意选择错误 Copilot 路线的契约测试，验证 analyst override 后会重新加载正确 specialist。
3. 加强 canonical window 约束，避免通过“此前约 52 分钟”等相对描述绕过显式时间检查。
4. 修正 Evaluation 对 `schema_version` 和 `core_evidence_bundle_present` 的识别。
5. 后续按分类增加 mechanism-level evidence 和 judge，不采用 case-by-case 的固定答案路由。

## Workspace 与 Trace

| Case | Workspace | Langfuse 主 Trace |
| --- | --- | --- |
| `progressive-resource-growth-during-steady-workload` | [ws-1788680518139-50a9bb01c](https://dev.investibook.com/workspace/ws-1788680518139-50a9bb01c) | [7c507b65b29044ed838d549f2e0a61d8](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/7c507b65b29044ed838d549f2e0a61d8) |
| `repeated-component-restarts-during-maintenance-window` | [ws-1788680649908-78c65331f](https://dev.investibook.com/workspace/ws-1788680649908-78c65331f) | [a49c983613c04bd7a5987f8154e6baea](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/a49c983613c04bd7a5987f8154e6baea) |
| `intermittent-query-failures-during-partition-maintenance` | [ws-1788681492586-481d04f6a](https://dev.investibook.com/workspace/ws-1788681492586-481d04f6a) | [6ebdb84e58ce4dfda774b0bbc3a4ff91](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/6ebdb84e58ce4dfda774b0bbc3a4ff91) |
| `sustained-node-memory-pressure-during-transaction-workload` | [ws-1788681989851-33ef56f88](https://dev.investibook.com/workspace/ws-1788681989851-33ef56f88) | [d2a2a7f7e7fc4a1395d85bcaa2d63f59](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/d2a2a7f7e7fc4a1395d85bcaa2d63f59) |
| `transaction-failure-during-concurrent-upsert` | [ws-1788682188770-5e39ab3b7](https://dev.investibook.com/workspace/ws-1788682188770-5e39ab3b7) | [a23383e736fd465488f23e2824da3a62](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/a23383e736fd465488f23e2824da3a62) |
| `component-restart-during-query-cancellation` | [ws-1788682790055-b473e9d9d](https://dev.investibook.com/workspace/ws-1788682790055-b473e9d9d) | [576dda8ba4cd43f398367c7bb4097234](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/576dda8ba4cd43f398367c7bb4097234) |
| `checkpoint-catchup-slow-after-changefeed-resume` | [ws-1788683071273-60b8cfee3](https://dev.investibook.com/workspace/ws-1788683071273-60b8cfee3) | [781982e8307544ab8e275b3fb004ba11](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/781982e8307544ab8e275b3fb004ba11) |
| `running-changefeed-with-stalled-progress` | [ws-1788683943267-81b612898](https://dev.investibook.com/workspace/ws-1788683943267-81b612898) | [4acaf78c28dc43a6835678bbd96911b0](https://langfuse.dev.investibook.tidbcloud.com/project/investibook-dev/traces/4acaf78c28dc43a6835678bbd96911b0) |
