# R2.2.6 任务报告

## 结果

- 完成纯分析 CLI 增强，未修改 Sub2API 配置、账号 runtime、YAML 或运行面。
- `runtime errors --all-groups` 默认使用 Kubernetes 风格概要表，支持所有分组概览和 `--group <name-or-id>` 精确下钻。
- 指定分组详情新增原生 `openai-token-stats` 模型时延表，以及原生 `request-errors` 的模型、账号、状态、同步/流式、阶段、入口和精确路径分布。
- 客户错误画像由 CLI 自动读取原生分页并完成统计，只对 request ID 样本做有界渐进披露，不要求用户手工调整 limit。
- `trace` 继续以原生 requests 和 system-logs 为主；requests 缺记录时只在同一 `--since` 窗口查询原生 request-errors，runtime 日志仅补原生索引缺失的事件。

## 最近 60 分钟全分组证据

- 三个分组合计约 468 个请求、11 个客户可见错误，客户错误率约 2.35%，上游错误率约 4.70%。
- `unidesk-codex-pool`：约 61 至 67 个请求、7 个客户错误，窗口滚动错误率约 10.45% 至 11.48%。
- `自用`：407 个请求、4 个客户错误，错误率 0.98%。
- `grok`：窗口内无流量、无错误。
- 查询时并发约 8/218、队列为 0；当前快照不能代表错误瞬间，但没有证据支持把全局并发不足作为近期主因。

## 分组根因

- `unidesk-codex-pool` 的 7 个客户错误全部是：
  - 模型 `gpt-5.6-luna`；
  - 账号 27；
  - 同步 `/v1/responses`；
  - 上游阶段；
  - 5 个 502、2 个 503。
- `自用` 的 4 个客户错误全部是：
  - 模型 `gpt-5.6-sol`；
  - 流式 `/responses`；
  - 账号 15 占 3 个 504，账号 27 占 1 个 502。
- 近期失败不是所有模型、账号和路径均匀恶化，而是两个窄错误簇。

## request trace 证据

- `c76b05df-ad84-4055-bb5a-d363a77e94a1`：约 197.056 秒后账号 27 返回 503，首次 failover、下一次选号失败和最终 502 发生在同一毫秒，选号错误为 `context canceled`。
- `2c1211b5-1f9f-441a-9ef8-1f80795097cd`：约 50.863 秒后账号 27 返回 502，failover 与 `context canceled` 同时发生。
- `d66d7ea7-4e78-475c-8f93-b315435b79f7`：约 1772.971 秒后账号 15 返回上游 504，随后立即 `context canceled` 并包装成最终 502。
- `4ee54daa-f41c-4f50-bd72-11080c38e299`：约 730.835 秒后账号 27 返回 502，约 1 毫秒后 `context canceled`。
- 四个近期代表请求都已进入 failover；临时不可调度规则也有真实命中。直接传播点是 failover 开始时原请求上下文已经取消，不是缺少规则或没有触发切号。

## v0.1.153 官方源码判断

- OpenAI Responses handler 的转发和下一次账号选择都复用 `c.Request.Context()`。
- 收到 `UpstreamFailoverError` 后 handler 记录失败账号并直接继续选号；若客户请求上下文已经取消，下一次选择会立即返回 `context canceled`。
- `gateway.openai_response_header_timeout` 是 v0.1.153 已有配置，作用范围是等待 OpenAI 上游 HTTP 响应头，不影响响应头之后的流式传输。
- v0.1.153 发布说明没有修复上述 failover 上下文生命周期问题，因此没有证据支持回退版本。

## 候选方案

1. 配置级有界缓解，不涉及 Sub2API 源码变更：
   - 设置 OpenAI 专用 response-header timeout，可让真正卡在响应头前的 730 秒或 1773 秒请求更早转成 failover，从而保留切号窗口。
   - 它不能解决 50 至 197 秒内已经返回的 502/503，也不能解决流式内容已经提交后的失败。
   - 近期 TTFT P99 在分组 2 约 231 至 245 秒、分组 3 约 101 秒；TTFT 不是响应头时延，因此 255/270 秒只能作为排除过低值的观测下限，不能直接视为安全配置。
2. 精确源码方案，涉及 Sub2API 源码变更：
   - 增加响应头实际等待时长与首个语义流事件时长，区分响应头前等待和响应头后无事件。
   - 在下游尚未提交且客户 deadline 仍有预算时，为单次上游尝试使用更短的 attempt context；超时后在原客户 context 内切号。
   - 明确禁止在客户已经断开后继续后台重试，避免无效上游消耗。
3. 窄路由治理：
   - 分组 2 优先治理账号 27 的 `gpt-5.6-luna` 能力和错误分类；分组 3 优先治理账号 15/27 的 `gpt-5.6-sol` 长流式等待。
   - 不建议用降低全池并发、账号 pinning、扩大临时不可调度时长或版本回退替代根因治理。

## 验证

- `bun --check` 通过：`runtime.ts`、`remote-python-sync.ts`、`output.ts`。
- `bun test scripts/src/output.test.ts`：2 通过、0 失败。
- `git diff --check` 通过。
- 原入口读取验证通过：全分组概要、分组 2/3 详情、四个近期 request trace。
- 超过 3000 行的既有 `remote-python-sync.ts` 拆分已登记为 R2.2.7，本任务未混入大范围机械重构。
