Part of #448
Problem
test_routing.py (30,372 lines) exercises CodexProxyHandler through private methods (_write_sse_event, _relay_official_passthrough_sse_response, ...). This pins the handler's internal shape: no decomposition of codex_proxy.py can proceed while a third of the test corpus depends on implementation details. Before any migration, the Gateway needs a behavior floor at its true interface: HTTP in, HTTP/SSE out.
Outcome
An in-process (or loopback) harness that drives the production Gateway as a black box:
- Start the Gateway with a test-scoped settings/providers fixture; issue real
POST /v1/responses, POST /v1/chat/completions, GET /v1/models, GET /health requests; capture full response bodies and ordered SSE event streams.
- Upstreams are stub HTTP servers speaking Responses / Chat Completions (reuse existing fixtures where possible) — no live providers.
- Deterministic assertion helpers for SSE lifecycles (ordered events, exactly-one terminal event) reusable by later migrated tests.
- A starter characterization suite covering the highest-traffic behaviors: route selection official/external, streaming + non-streaming happy path, one protocol-translation path (Responses client → Chat upstream), normalized error classes, cancellation.
Non-goals
- Migrating
test_routing.py content (Stage 2A).
- Changing any production code paths.
Acceptance criteria
Verification class
Standard (test infrastructure; no production contract change). Python core suite once at candidate.
Part of #448
Problem
test_routing.py(30,372 lines) exercisesCodexProxyHandlerthrough private methods (_write_sse_event,_relay_official_passthrough_sse_response, ...). This pins the handler's internal shape: no decomposition ofcodex_proxy.pycan proceed while a third of the test corpus depends on implementation details. Before any migration, the Gateway needs a behavior floor at its true interface: HTTP in, HTTP/SSE out.Outcome
An in-process (or loopback) harness that drives the production Gateway as a black box:
POST /v1/responses,POST /v1/chat/completions,GET /v1/models,GET /healthrequests; capture full response bodies and ordered SSE event streams.Non-goals
test_routing.pycontent (Stage 2A).Acceptance criteria
mainwith zero production diffs.CodexProxyHandler/codex_proxyinternals (Stage 1D, same PR or linked PR).Verification class
Standard (test infrastructure; no production contract change). Python core suite once at candidate.