# R2.2.10 任务报告

## 结论

- 最近 30 分钟复取时，账号 `lyon9801`（ID 15）共 37 次尝试、37 次成功、0 次失败，TTFT P95 为 9040 ms；“自用”分组唯一客户错误来自账号 27 的流式 504。因此 `lyon9801` 的 503 是更早的孤立事件，不是当前持续不稳定。
- `lyon9801` 不是 Sub2API 直连账号。它绑定 proxy 3：`platform-infra-sub2api-pk01-local-egress-proxy`，HTTP endpoint 为 `127.0.0.1:10809`。实际路径是 PK01 `sub2api-app` → PK01 本地 Hysteria 客户端 → NC01 Hysteria 服务端 → OpenAI。
- 代表请求 `da415526-b124-4e23-a4a7-ea48154c851e` 在请求开始约 1556485 ms 后收到上游 HTTP 503。Sub2API 随即进入 failover，但 1 ms 后选号因 `context canceled` 失败，最终返回 502。客户影响的主要放大器是错误发现过晚，切号时已无可执行上下文，而不是 failover 未实现。
- 另一请求 `4bba7f9b-15e3-4891-b063-bd65fb6e3704` 在 HTTP 200 后出现上游 `response.failed`，现由 trace 正确标记为 `degraded / forward-failed-http-success`。这是响应已提交后的流内失败，不能安全切号，也不等同于 proxy 连接失败。
- 当前证据更支持 OpenAI/Codex 上游返回 HTTP 503 或应用层流失败，不支持 PK01 DNS、proxy connect、TCP reset、容器重启、OOM 或 NC01 Hysteria 重启为主因。历史瞬时丢包仍不能凭当前快照绝对排除。

## 基础设施证据

- PK01 `sub2api-app`：running，restart 0，OOM false，host network。
- 账号 proxy 3：active，`127.0.0.1:10809`；当前有 4 条 established 本地 TCP socket。
- PK01 proxy owner：`hysteria`，`host-proxy-hysteria.service` active/running，restart 0；最近两小时 journal 未命中 reconnect、disconnect、timeout 或 error。
- PK01 DNS 为 `127.0.0.53`，默认路由经 `eth0 / 10.0.8.1`；可见接口 RX/TX error/drop 均为 0。
- NC01 服务端容器：`vpn-hysteria2`，镜像 `tobyxdd/hysteria:v2.9.3`，running，restart 0，OOM false，host network；运行文件实际位于 `/root/vpn-server`。故障时刻附近没有对应 tunnel disconnect/reconnect 日志。
- 账号 15 的近期 Sub2API 网络错误索引没有 DNS failure、proxy connect failure、connection reset、unexpected EOF、broken pipe、connection refused、network unreachable 或 transport timeout。

## Sub2API v0.1.153 源码归因

- 账号存在 `ProxyID` 时，OpenAI forward 把账号 proxy URL 传给 HTTP upstream；HTTP proxy 通过 `http.Transport.Proxy` 生效。因此容器没有 `HTTP_PROXY` 环境变量不能证明账号直连。
- HTTP 503 属于已收到 HTTP response 的路径；所有 5xx 会构造 `UpstreamFailoverError` 并触发账号切换。
- proxy、DNS、TCP 或 TLS 在 HTTP round trip 前失败时走 transport-error 路径，Ops status 为 0，最终 failover error 为 502。账号 15 的代表证据是 upstream status 503，不符合该传输故障路径。
- OpenAI response-header timeout 在 v0.1.153 默认是 0；PK01 运行实例也显示 disabled。它允许请求长时间等待，但现有 Ops 只有端到端耗时，不能把 1556485 ms 全部断言为等待响应头。
- 客户 context 已取消时，源码明确不再 failover；这解释了 503 后 1 ms 即 `account_select_failed: context canceled`。

## CLI 增强

新增只读入口：

```bash
bun scripts/cli.ts platform-infra sub2api codex-pool runtime infrastructure \
  --target PK01 --group 3 --account lyon9801 --since 30m
```

默认 Kubernetes 风格文本输出账号名称、proxy 绑定、容器状态、代理环境摘要、DNS、默认路由、接口计数器、socket、监听进程、服务状态和近期网络错误分类。该命令不发上游请求或网络探针，不修改账号、proxy、runtime、调度或 YAML；机器读取仍需显式 `--json`。

## 建议

- 暂不因这次孤立 503 降权或摘除 `lyon9801`；最近 30 分钟为 37/37 成功。
- 下一步源头优化优先研究 OpenAI response-header timeout 与客户 deadline/failover 预算的配合，使 5xx 在客户上下文取消前暴露；这属于配置候选，当前未实验、未下发。
- 对 HTTP 200 后 `response.failed`，应继续作为 degraded 客户可见错误单列；响应已提交后不能依靠换号掩盖。
- 若再次发生，直接用 request ID 同时抓 trace 与 infrastructure，并保留故障时刻的 Hysteria per-session 指标；不要用故障后的 socket 快照替代历史证据。

## 验证

- `bun --check scripts/src/platform-infra-sub2api-codex/runtime.ts`
- `bun --check scripts/src/platform-infra-sub2api-codex/remote-python-sync.ts`
- `bun --check scripts/src/output.ts`
- `bun test scripts/src/output.test.ts`：2 pass，0 fail。
- `git diff --check`
- `runtime.ts`：2970 行，低于 3000 行硬上限。
