# R2.2.4 所有分组客户错误与 CLI 渐进披露报告

## 交付范围

- `runtime errors --all-groups`：按稳定 group ID 游标分页，默认返回所有分组概要。
- `runtime errors --group <name-or-id>`：下钻单个分组的原生 Ops 指标、账号根因、策略效果和 request ID 索引。
- `--platform <name>`：可选平台过滤。
- `--page-token <group-id>`：固定分页游标，不使用手工 `limit` 规避输出问题。
- `runtime list|get|errors|apply|delete`：默认统一为 Kubernetes 风格紧凑表格。
- `--json`、`--full`、`--raw`：仅在显式请求时返回机器结构或完整披露。

## 运行面证据

- 目标：PK01 host-Docker。
- 实际镜像：`docker.1panel.live/weishaw/sub2api:0.1.153`，容器 healthy。
- 数据源：Sub2API 原生 dashboard overview、account availability、concurrency、upstream-errors、requests 和 system-logs。
- 原生 system-log 没有保留全部策略事件时，CLI 显式回退到 runtime 日志。
- system-log sink 的 queue、drop 和 write failure 均为 0。

## 所有分组概要

同一 60 分钟查询页共 3 个分组：

- 全局：757 次请求，8 次客户错误，客户错误率 1.06%，34 次上游错误，上游错误率 4.49%。
- `unidesk-codex-pool`，group 2：277 次请求，6 次客户错误，错误率 2.17%；21 次上游错误，上游错误率 7.58%。
- `自用`，group 3：480 次请求，2 次客户错误，错误率 0.42%；13 次上游错误，上游错误率 2.71%。
- `grok`，group 5：窗口内无请求和错误。
- group 2 承担 36.6% 请求，却产生 75% 客户错误，是当前主要客户错误来源。

查询时两个活跃分组均为 3/218 并发、队列 0。降低全局或分组并发不能解释当前错误，不应作为主修复。

## 账号和共享证据边界

- group 2、3 共享大部分 OpenAI 账号。
- 原生 dashboard 请求量和客户错误率按 group 精确统计，可以跨组汇总。
- upstream-errors 是账号级数据；共享账号的根因记录会出现在多个 group 下钻中，禁止跨组相加。
- 缺少 `group_id` 的临时摘号事件只能按账号 membership 和 request ID 关联，CLI 已标注为共享证据。
- 原生聚合显示每个活跃组 9 个账号、6 个可用、3 个错误账号。
- 错误账号为 29、30 的余额不足 403，以及 31 的 API Key 所属分组已删除 403。

账号共享窗口内的 34 条上游根因记录为：

- overload：18。
- status-only-upstream-failure：9。
- generic-upstream-failure：7。

## 客户可见错误链

### 长耗时失败后 context 已取消

- `cf6b6257-9640-414f-918d-c55180fb6a8d`：`gpt-5.6-luna`，账号 27 返回 502，约 41.6 秒后进入 failover，下一次选号立即报 `context canceled`，最终 502。
- `4ee54daa-f41c-4f50-bd72-11080c38e299`：`gpt-5.6-sol` 流式请求，账号 27 返回 502，约 730.8 秒后进入 failover，下一次选号立即报 `context canceled`，最终 502。
- 两条请求均已触发切号；失败点是第一个上游耗尽了客户请求时间预算，不是 `max_account_switches` 太小，也不是池容量不足。

### HTTP 200 后流式失败

- `46c1374a-c7f1-49f8-877d-d7ffb216976c`：账号 28 返回 503 后切到账号 33，网关最终 access status 为 200。
- 随后出现 `openai.forward_failed`，原文指向 `input[2].encrypted_content` 的 ObjectParam/required-parameter 错误。
- CLI 现判定 `outcome=degraded`、`reason=forward-failed-http-success`，不再把 HTTP 200 误报为完整成功。
- 流式语义已经提交后不能安全拼接另一个上游响应，透明换号只适用于提交语义响应之前。

## 临时不可调度和 failover 效果

- group 3 下钻观察到 20 次临时不可调度事件、13 个 failover 请求。
- 其中 2 个明确成功、1 个明确失败、10 个结果在有限日志索引中缺失。
- 另有 1 个 `forward_failed + HTTP 200` degraded 请求。
- 规则能减少立即重复命中坏账号，但无法恢复已经耗尽 context 的请求，也无法恢复已经提交语义流后的协议错误。

## 官方仓库与版本判断

- 官方 v0.1.153 发布说明只涉及调度缓存异常时间、WebSocket 生命周期等修复，没有声明改变当前 HTTP Responses 的 failover 时间预算或流式提交后切号规则。
- 官方 issue #2067 与合并 PR #2068 证明旧版曾存在 Responses 多轮 reasoning item 回放导致 404/502 的协议转换缺陷；修复已在 2026-04-29 合入主线。
- 当前 `encrypted_content` 原文与该 issue 相近但不完全相同，不能直接判定为同一个缺陷。
- 现有证据不支持从 v0.1.153 回退；回退可能重新引入已修复的 Responses 协议问题。
- 官方来源：
  - https://github.com/Wei-Shaw/sub2api/releases/tag/v0.1.153
  - https://github.com/Wei-Shaw/sub2api/issues/2067
  - https://github.com/Wei-Shaw/sub2api/pull/2068

## 调优建议

- P0：保持 v0.1.153，不回退，不提高 `max_account_switches`，不降低全池并发。
- P0：确认实际 OpenAI 响应头/首 token 超时，把单个慢上游的允许时间收紧到能为至少一次 failover 留出预算；先做有界对照，不直接照抄固定值。
- P1：继续使用最多 3 分钟的保守临时不可调度；当前一分钟冷却已经频繁命中，不扩大到无关键词的所有 5xx。
- P1：针对账号 28 的 overload 和账号 27 的 502 保持即时冷却，观察完整 60 分钟窗口的客户错误率和 failover 成功率。
- P1：对账号 33 的 `gpt-5.6-sol` continuation/`encrypted_content` 错误积累更多 request 证据；重复出现时再做账号与模型级调度隔离，不能凭单个样本做全账号摘除。
- P1：修复账号 29、30 的余额和账号 31 的失效 API Key 后，通过真实请求验证再恢复；禁止仅改 `schedulable`。
- P2：继续增强原生 system-log 对策略事件和最终 outcome 的索引，减少 runtime fallback 与 outcome missing。

## 验证

- `bun --check`：`runtime.ts`、`remote-python-sync.ts`、`output.ts` 通过。
- `git diff --check` 通过。
- `bun test scripts/src/output.test.ts`：2 pass，0 fail。
- 默认 `runtime errors --all-groups`：紧凑表格，无 JSON envelope，无 `outputTruncated`。
- 默认 `runtime errors --group 3`：紧凑详情、共享证据提示和 request 索引可见。
- 默认 `runtime list`：Kubernetes 风格账号列表。
- 显式 `--json`：返回机器可读结构。
- degraded trace 与两条 failover-no-candidate trace 均通过真实 PK01 原生 API 回归。

## 后续

- 父任务 R2.2 保持进行中，继续按完整窗口观察调优效果。
- 未创建外部 GitHub issue；相关未决项继续由本 MDTODO 问题域跟踪，避免未经授权写入外部系统。
