Two silent wire mistakes on the Responses transport and its auxiliary
adapter shared one root cause: the transport had no notion of what a
model can be told about reasoning, so it always projected the default
`medium` and always omitted a disable.
- `reasoning_effort: none` was dropped from the request. On a reasoning
model that defaults to medium (gpt-5.6) the model kept thinking: 76
reasoning tokens against 0 with an explicit `reasoning.effort: none`.
The disable now goes on the wire as `{"effort": "none"}` wherever the
route's vocabulary has `none`; an unset effort is the only state that
omits the field. A route that rejects `none` already trips the
reasoning-mandatory recovery (warn, drop the disable, retry).
- Chat-era OpenAI models on api.openai.com (gpt-4o, gpt-4.1, -mini,
fine-tunes) 400 on any `reasoning` key, so every `openai-api` request
to them failed. `_codex_efforts_for_route` now returns `()` for them
(new `model_metadata.openai_model_rejects_reasoning`, a denylist so an
unknown future model keeps its dial) and both the main transport and
`_CodexCompletionsAdapter` send no reasoning field. Only the exact
OpenAI origin is judged: a relay serving those ids may translate.
Fixes#75227Fixes#76255