Skip to content

bug(catalog): clamp in b7ce5aad strips max/ultra from all models regardless of Codex binary version #297

Description

@Wibias

Bug

Commit b7ce5aad ("fix(codex): clamp catalog reasoning efforts to installed binary's ladder") introduced clampCatalogModelsToCodexSupport, which runs as the last step of syncCatalogModels and strips any effort rung not found in the installed Codex binary's bundled catalog.

The problem: even on a current Codex binary, codexSupportedReasoningEfforts reads the binary's bundled native model entries (gpt-5.5, gpt-5.4, etc.), and those entries only list low/medium/high/xhigh. So max and ultra are never present in the derived supported set — and the clamp removes them from every model in the catalog, including routed models and the gpt-5.6 family.

Reproduction

  1. Run opencodex sync with any current Codex binary.
  2. Check opencodex-catalog.json — every model's supported_reasoning_levels tops out at xhigh. max and ultra are gone.
  3. The Codex UI model picker caps effort selection at xhigh for all models, including gpt-5.6-sol, anthropic/claude-sonnet-5, and all other routed providers.

Root cause

codexSupportedReasoningEfforts (src/codex/catalog.ts) scans only bare native slugs (no /) in the bundled catalog for known effort strings. Those slugs ship with supported_reasoning_levels that stop at xhigh in the binary's own bundled catalog — because the binary predates the max/ultra additions to its native ladder. So the derived supported set is {low, medium, high, xhigh}.

The ensureGpt56ReasoningLevels / ensureUltraReasoningLevel calls earlier in the sync correctly add max and ultra, but the clamp at line 2205 undoes all of it before the file is written.

Suggested fixes

Option A — seed the supported set from CODEX_REASONING_LEVELS (simplest)
Treat max and ultra as always-valid in codexSupportedReasoningEfforts regardless of what the bundled native entries happen to declare. They are defined in CODEX_REASONING_LEVELS and the request pipeline already handles wire-clamping to the model's real top rung via nativeEffortClamp/adapters — so letting them through the catalog clamp is safe.

// in codexSupportedReasoningEfforts, seed with the full ladder first
const efforts = new Set(CODEX_REASONING_LEVELS.map(l => l.effort));
// then union in whatever the binary confirms

Option B — version-gate the clamp
Only apply the clamp when the Codex binary is old enough to actually crash on unknown rungs. The commit message cites 0.133.0 as the problematic version. Read the binary version and skip the clamp for binaries >= the first version that accepts max/ultra.

Option C — run ensure-functions after the clamp
ensureGpt56ReasoningLevels / ensureUltraReasoningLevel are explicitly designed to restore max/ultra. Moving them to run after clampCatalogModelsToCodexSupport instead of before would let their intent survive.

Context

  • Regression introduced: b7ce5aad (landed 2026-07-22)
  • Affects: every model in the synced catalog — anthropic/claude-sonnet-5, gpt-5.6-sol, all routed providers, etc.
  • CODEX_REASONING_LEVELS in src/reasoning-effort.ts correctly defines all six rungs (lowultra); the issue is purely in the clamp's source-set derivation from native binary entries that predate max/ultra.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions