Skip to content

1.9.1 — an old Codex on the machine no longer hides GPT-6 - #27

Merged
treeleaves30760 merged 2 commits into
mainfrom
fix/codex-catalog-floor
Sep 16, 2026
Merged

treeleaves30760 merged 2 commits into
mainfrom
fix/codex-catalog-floor

Conversation

@treeleaves30760

Copy link
Copy Markdown
Owner

alc --codex claude offered Sol, Terra and Luna and no GPT-6, on a machine where posting gpt-6-astra to chatgpt.com by hand streamed normally. The model worked; only alc's list of it was missing.

The reason

ModelCatalog::refresh shelled out to codex debug models and kept only the TARGET_MODELS entries that came back, then wrote that shorter list over the bundled catalog — which does carry gpt-6-astra.

But codex debug models is not a fact about the account. It is the answer chatgpt.com gives the Codex CLI that asked, and every model carries a minimal_client_version. Probed directly with the reporter's own credentials:

declared client_version gpt-6-astra
0.149.1 (installed) absent
0.154.0 present, minimal_client_version: 0.153.0

The command did not fail. It succeeded with a shorter list, and alc believed it.

alc does not route one byte through the Codex CLI — its bridge posts straight to chatgpt.com — so a Codex that has not heard of a model is evidence about that install and never about the model. Confirmed decisively: POST /backend-api/codex/responses with model: "gpt-6-astra" returned HTTP 200 and streamed, with Codex still at 0.149.1 (a deliberately fake slug is refused by name, so the 200 is a real accept).

bridge_codex_models has said this since 1.5.0, in a comment calling a hard-coded list one release behind Codex "the entire reason this code exists". The refresh path had recreated that bug one layer up, with the installed CLI's version as the gate.

The fix

The catalog alc ships is now a floor. Discovery may enrich a model's metadata and may add models alc has never heard of; it may never remove one. apply_floor runs on every read rather than only on the writing path, so a catalog already pruned onto a user's disk repairs itself on the next command — offline, with no login, and with no Codex upgrade.

And the refresh asks the party that serves the turns. A new src/bridge/models.rs fetches the catalog from chatgpt.com with the credentials the bridge already holds, declaring the newer of alc's own CODEX_CLIENT_VERSION_FLOOR and the version stamped in ~/.codex/models_cache.json. codex debug models is the fallback; both sources share one parser and one filter, and the floor goes back over whichever answered. Membership comes from Codex's own visibility and priority rather than a slug allowlist, so TARGET_MODELS is gone.

Staleness is keyed on the Codex release stamp read out of models_cache.json (a 4 KiB read, no process spawn), so upgrading Codex re-syncs immediately instead of up to a day later.

Three things nobody had reported yet

All the same pruned list:

  • agents::claude::apply_bridge hands the first catalog entry to Claude Code's opus alias. With GPT-6 pruned that was gpt-5.6-sol, so opus silently resolved a tier below what README.md documents.
  • alc config browses the catalog for a Codex profile's model, and the picker re-selected a default when the saved model was absent — so opening the TUI on a profile pinned to gpt-6-astra and confirming overwrote the pin.
  • The picker badged by slug, so it labelled the most capable model [custom] on the day it arrived.

Verification

A/B against a build of the previous release, in one environment: a stub Codex reporting exactly the 0.149.1 list, no login, no network.

alc models picker handed to Claude Code
before sol, terra, luna sol, terra, luna
after gpt-6-astra, sol, terra, luna gpt-6-astra, sol, terra, luna

A cache pruned by the old build recovers GPT-6 on the next command with no codex binary at all. The live account path was exercised against a real codex login. cargo fmt, cargo clippy --all-targets --all-features -- -D warnings and 597 tests are clean.

alc doctor's new "written before the installed Codex release" row was corrected to fire only on a catalog that has actually been synced — the bundled fallback was written before every Codex release and warning about it on a fresh install was a plain falsehood.

Compatibility

A cache written by this build carries three new fields and is refused by 1.9.0 and older, which reject keys they do not know. A downgrade therefore falls back to the bundled catalog, which is complete.

The weekly compatibility job's TARGET_MODELS grep — which would have failed on this commit — is replaced by a two-directional drift check, plus a direct comparison of the declared client version against the Codex it just installed from npm. That last one is the only staleness neither alc nor a list comparison can notice on its own: with no codex login in CI, both sides of the comparison come from the same codex debug models.

🤖 Generated with Claude Code

treeleaves30760 and others added 2 commits September 17, 2026 02:02
`alc --codex claude` offered Sol, Terra and Luna and no GPT-6, on a machine
where posting `gpt-6-astra` to chatgpt.com by hand streamed normally. The
model worked; only alc's list of it was missing.

**alc was asking the wrong party.** `ModelCatalog::refresh` shelled out to
`codex debug models` and kept only the `TARGET_MODELS` entries that came back,
then wrote that shorter list over the bundled catalog - which does carry
`gpt-6-astra`. But `codex debug models` is not a fact about the account; it is
the answer chatgpt.com gives the Codex CLI that asked. Every model carries a
`minimal_client_version`, and `gpt-6-astra`'s is 0.153.0, so a machine on
Codex 0.149.1 is simply not shown it. The command did not fail. It succeeded
with a shorter list, and alc believed it.

alc does not route one byte through the Codex CLI - its bridge posts straight
to chatgpt.com - so a Codex that has not heard of a model is evidence about
that install and never about the model. `bridge_codex_models` has said so
since 1.5.0, in a comment calling a hard-coded list one release behind Codex
"the entire reason this code exists". The refresh path had recreated that bug
one layer up, with the installed CLI's version as the gate.

**The catalog alc ships is now a floor.** Discovery may enrich a model's
metadata and may add models alc has never heard of; it may never remove one.
`apply_floor` runs on every read rather than only on the writing path, so a
catalog already pruned onto a user's disk repairs itself on the next command -
offline, with no login, and with no Codex upgrade.

**And the refresh asks the party that serves the turns.** A new
`src/bridge/models.rs` fetches the catalog from chatgpt.com with the
credentials the bridge already holds, declaring the newer of alc's own
`CODEX_CLIENT_VERSION_FLOOR` and the version stamped in
`~/.codex/models_cache.json`, so the server's gate cannot hide a model behind
an old local Codex. `codex debug models` is the fallback; both sources share
one parser and one filter, and the floor goes back over whichever answered.
Membership now comes from Codex's own `visibility` and `priority` rather than
a slug allowlist, so `TARGET_MODELS` is gone.

Three consequences nobody had reported yet, all of them the same pruned list:

- `agents::claude::apply_bridge` hands the first catalog entry to Claude
  Code's `opus` alias. With GPT-6 pruned that was `gpt-5.6-sol`, so `opus`
  silently resolved a tier below what README.md documents.
- `alc config` browses the catalog for a Codex profile's model, and the picker
  re-selected a default when the saved model was absent - so opening the TUI
  on a profile pinned to `gpt-6-astra` and confirming overwrote the pin.
- The picker badged by slug, so it labelled the most capable model `[custom]`
  on the day it arrived.

Staleness is keyed on the Codex release stamp read out of `models_cache.json`
(a 4 KiB file read, no process spawn), so upgrading Codex re-syncs immediately
instead of up to a day later. `alc models`, `--dry-run` and `alc doctor` now
say which source answered, which entries alc had to supply itself, and why the
account rung did not answer when it did not.

Verified as an A/B against a build of the previous release, in one environment:
a stub Codex reporting exactly the 0.149.1 list, no login, no network. Before,
the picker handed Claude Code three models; after, four, with `gpt-6-astra`
first. A cache pruned by the old build recovers GPT-6 on the next command with
no Codex binary at all.

A cache written by this build carries three new fields and is refused by 1.9.0
and older, which reject keys they do not know. A downgrade therefore falls
back to the bundled catalog, which is complete.

The weekly compatibility job's `TARGET_MODELS` grep - which would have failed
on this commit - is replaced by a two-directional drift check, plus a direct
comparison of the declared client version against the Codex it just installed
from npm. That last one is the only staleness neither alc nor a list
comparison can notice on its own: with no `codex login` in CI, both sides of
the comparison come from the same `codex debug models`.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
One bug, and it was hiding a model you are paying for. On a machine whose
Codex CLI was older than the newest model's `minimal_client_version`, alc
offered `gpt-5.6-sol`, `gpt-5.6-terra` and `gpt-5.6-luna` and no GPT-6 -
while the same `gpt-6-astra` posted to chatgpt.com by hand streamed normally.
alc had been treating `codex debug models` as a fact about the account when
it is an answer scoped to the version of the CLI that asked, and alc routes
nothing through that CLI.

Nothing that exists today changes its behaviour: the same `alc claude`, the
same flags, and a `config.toml` written by 1.9.0 loads unchanged. That is a
patch release.

Two things to know when upgrading.

The model cache gains three fields, and 1.9.0 and older reject keys they do
not know. Downgrading therefore falls back to the catalog bundled in the
binary, which is complete - the list is right either way, it just stops
being fresh. `alc models --refresh` on the older build rewrites it.

`alc models` and `alc doctor` print more than they did: which source
answered, which entries alc had to put back itself, and why the account was
not asked when it was not. A list that is complete only because alc insisted
used to look identical to one the source agreed with, which is what turned a
one-line cause into a long investigation.

You do not have to upgrade Codex for this. The fix works offline, with no
`codex login`, and with no `codex` on PATH at all.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@treeleaves30760
treeleaves30760 merged commit a1d4ba8 into main Sep 16, 2026
7 checks passed
@treeleaves30760
treeleaves30760 deleted the fix/codex-catalog-floor branch September 16, 2026 18:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant