-
Notifications
You must be signed in to change notification settings - Fork 1.1k
fix(codex): retire gpt-5.4 and gpt-5.4-mini from the Codex login surface #4327
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a8b26e1
5d664b1
fa1fe32
fe01c0f
32bd541
2c26549
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,108 @@ | ||||||||||||||||||||||||||||
| # gpt-5.4 / gpt-5.4-mini retirement on the Codex login surface | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Objective | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| OpenAI retired `gpt-5.4` and `gpt-5.4-mini`. Remove them from the Codex (ChatGPT | ||||||||||||||||||||||||||||
| OAuth) login surface of this proxy: the native catalog, everything that projects it | ||||||||||||||||||||||||||||
| (`/v1/models`, the dashboard picker, the desktop projection, Claude discovery), and | ||||||||||||||||||||||||||||
| every opencodex-owned default that still dispatches one of the two slugs. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| The replacement floor is `gpt-5.6-luna` — it is now the cheapest native model on the | ||||||||||||||||||||||||||||
| ChatGPT login lane, so every helper/sidecar/warmup default lands there. The login | ||||||||||||||||||||||||||||
| provider's own `defaultModel` moves there too: `gpt-5.6-sol` was considered because it | ||||||||||||||||||||||||||||
| is priority 1 in the pinned snapshot and `gpt-5.4` held a general-purpose role, but the | ||||||||||||||||||||||||||||
| owner chose luna so a default that nobody asked for stays the cheapest live model | ||||||||||||||||||||||||||||
| (owner decision, 2026-09-12). | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Constraints and scope boundary | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| In scope: `src/codex/**`, `src/oauth/**`, `src/vision/**`, the Codex-login parts of | ||||||||||||||||||||||||||||
| `src/server/**`, `src/cli/**`, `src/types/**`, `src/lib/shadow-call.ts`, `gui/`, | ||||||||||||||||||||||||||||
| `docs/` (the maintainer-facing pages, not only `docs-site/`), `docs-site/` (all locales), | ||||||||||||||||||||||||||||
| `structure/`, `scripts/release-notes.ts`, and `tests/`. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Out of scope, deliberately: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - Third-party vendor rosters that publish their own snapshots — `github-copilot` | ||||||||||||||||||||||||||||
| (`src/providers/registry.ts`), `cursor` (`src/adapters/cursor/*`), `codebuddy`, | ||||||||||||||||||||||||||||
| `opencode`, `command-code`, and `scripts/model-metadata.source.json`. This follows | ||||||||||||||||||||||||||||
| the `deepseek-v4-pro` precedent (`e86ab5bd8d`): a first-party retirement notice does | ||||||||||||||||||||||||||||
| not end a vendor's deployment, and deleting their row would strip a live route's | ||||||||||||||||||||||||||||
| context window and effort ladder while the model keeps arriving from `/models`. | ||||||||||||||||||||||||||||
| - Historical pricing in `src/usage/expected-prices.ts` and its tests. Past usage rows | ||||||||||||||||||||||||||||
| still have to cost correctly after the model stops being routable. | ||||||||||||||||||||||||||||
| - Slugs that only look related: `gpt-5.4-nano`, `gpt-5.4-pro`, `gpt-5.4-high`, | ||||||||||||||||||||||||||||
| `openai/gpt-5.4-mini` (OpenRouter metadata). None are part of this retirement. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| No push, PR, merge, release, or deploy. Local commits only. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Evidence gathered at P | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Three read-only `xai/grok-4.6` verifier subagents swept the tree in parallel. Their | ||||||||||||||||||||||||||||
| combined inventory: 146 files, 592 `gpt-5.4*` hits, of which the Codex-login-owned | ||||||||||||||||||||||||||||
| set is the one this unit changes. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| Structural findings that shape the phase order: | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| 1. `NATIVE_OPENAI_MODELS` (`src/codex/catalog/native-models.ts:156`) is the single | ||||||||||||||||||||||||||||
| membership list. `SUPPORTED_NATIVE_OPENAI_SLUGS`, `nativeModelRows`, | ||||||||||||||||||||||||||||
| `nativeOpenAiSlugs`, `accountBoundNativeOpenAiSlugsBySelector`, | ||||||||||||||||||||||||||||
| `filterSupportedNativeSlugs`, `model-routes.ts` `supportedNative`, and | ||||||||||||||||||||||||||||
| `CANONICAL_NATIVE_CATALOG_CONTENT_POLICY.nativeBackfillSlugs` all derive from it. | ||||||||||||||||||||||||||||
| Removing the two slugs there propagates to every projection without further edits. | ||||||||||||||||||||||||||||
| 2. Persisted BARE rows clean themselves up. Once the slugs leave the list, | ||||||||||||||||||||||||||||
| `isUnsupportedOpenAiNativeSlug` returns true for `gpt-5.4` and `gpt-5.4-mini` and the | ||||||||||||||||||||||||||||
| canonical merge runs `unsupportedNativeEntries: "drop"` (`sync.ts:847`, filter at | ||||||||||||||||||||||||||||
| `1068-1070`), so a user's on-disk catalog loses them on the next sync. | ||||||||||||||||||||||||||||
| Account-namespaced rows are a different path: that predicate returns false for any slug | ||||||||||||||||||||||||||||
| containing `/` (`metadata.ts:113`), so `team/gpt-5.4` is not dropped by it. Those rows | ||||||||||||||||||||||||||||
| stop being *generated* because `accountBoundNativeOpenAiSlugsBySelector` and | ||||||||||||||||||||||||||||
| `availableAccountNativeSlugs` both seed from `NATIVE_OPENAI_MODELS`. wp2 must prove what | ||||||||||||||||||||||||||||
| happens to an already-persisted `selector/gpt-5.4` row with a focused test rather than | ||||||||||||||||||||||||||||
| assuming it disappears. | ||||||||||||||||||||||||||||
| 3. `UPSTREAM_NATIVE_ENTRIES` never contained either slug — `upstreamNativeEntryForSlug` | ||||||||||||||||||||||||||||
| admits only `gpt-5.6-*` and self-described natives — so deleting the two pinned rows | ||||||||||||||||||||||||||||
| in `src/codex/data/upstream-models.json` changes capability fallbacks only, not the | ||||||||||||||||||||||||||||
| sync-replacement authority. `gpt-5.2` and `codex-auto-review` stay pinned, which is | ||||||||||||||||||||||||||||
| why `SELF_DESCRIBED_NATIVE_OPENAI_MODELS` must remain an explicit allowlist. | ||||||||||||||||||||||||||||
| 4. The defaults are independent of the catalog list and fail separately. Warmup | ||||||||||||||||||||||||||||
| (`src/codex/warmup.ts:30`), the token guardian (`src/oauth/token-guardian.ts:55`), | ||||||||||||||||||||||||||||
| and the vision describer (`src/vision/plan.ts:14`) all still dispatch | ||||||||||||||||||||||||||||
| `gpt-5.4-mini` and would 404 after retirement regardless of catalog membership. | ||||||||||||||||||||||||||||
| 5. The startup sidecar migration (`src/server/index.ts:686`) rewrites a *stored* | ||||||||||||||||||||||||||||
| `gpt-5.4-mini` to `gpt-5.6-luna`, but an unset vision model never equals that | ||||||||||||||||||||||||||||
| string, so it falls through to `DEFAULT_VISION_MODEL` and still calls the retired | ||||||||||||||||||||||||||||
| model. That gap is the reason wp3 exists as its own cycle. | ||||||||||||||||||||||||||||
| 6. `DEFAULT_SHADOW_SOURCE_MODELS` is already `["gpt-5.6-luna"]`. `gpt-5.4-mini` there | ||||||||||||||||||||||||||||
| is an *inbound* prefix for Codex 0.144.x helper calls, not a dispatch target, so it | ||||||||||||||||||||||||||||
| stays documented as a restore option and is not treated as a retired default. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Work-phase map | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| | Phase | Unit doc | Outcome | Depends on | | ||||||||||||||||||||||||||||
| |---|---|---|---| | ||||||||||||||||||||||||||||
| | wp1 | this document | Roadmap locked, scope boundary recorded | — | | ||||||||||||||||||||||||||||
| | wp2 | `010_catalog_removal.md` | The two slugs leave the native catalog and its pinned metadata | wp1 | | ||||||||||||||||||||||||||||
| | wp3 | `020_defaults_repoint.md` | Every opencodex-owned default moves to a live slug | wp1 | | ||||||||||||||||||||||||||||
| | wp4 | `030_surfaces_and_gate.md` | GUI, docs locales, structure docs, full gate, closing record | wp2, wp3 | | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| wp2 and wp3 touch disjoint files and could run in either order; wp2 runs first because | ||||||||||||||||||||||||||||
| its membership decision is what the wp3 tests assert against. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Risks | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| - **Over-removal.** Deleting a vendor roster row would break a live Copilot or Cursor | ||||||||||||||||||||||||||||
| route. Mitigation: the scope boundary above, plus a final `rg` sweep that expects | ||||||||||||||||||||||||||||
| vendor hits to remain. | ||||||||||||||||||||||||||||
| - **Under-removal.** A default left on `gpt-5.4-mini` turns into a silent 404 on every | ||||||||||||||||||||||||||||
| warmup or image description. Mitigation: wp3 enumerates each default site explicitly. | ||||||||||||||||||||||||||||
| - **Test churn masking a real break.** ~278 test hits are in scope. Mitigation: each | ||||||||||||||||||||||||||||
| test edit is classified as membership (must change), floor (must repoint), or | ||||||||||||||||||||||||||||
| historical (must not change), and the full suite is the closing gate. | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| ## Acceptance | ||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||
| DONE requires: no retired slug in a Codex-login-owned surface, every default on a live | ||||||||||||||||||||||||||||
| slug, `bun run typecheck` clean, the focused domain suites green, the full | ||||||||||||||||||||||||||||
| `bun run test` green, `bun run structure:check` green, and this unit carrying a closing | ||||||||||||||||||||||||||||
| record with quoted evidence. | ||||||||||||||||||||||||||||
|
Comment on lines
+103
to
+108
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win Narrow the acceptance criterion to exclude the intentional shadow-intercept exception.
Limit the criterion to native membership, generated projections, and dispatch defaults: Proposed wording-DONE requires: no retired slug in a Codex-login-owned surface, every default on a live
-slug, `bun run typecheck` clean, the focused domain suites green, the full
-`bun run test` green, `bun run structure:check` green, and this unit carrying a closing
-record with quoted evidence.
+DONE requires: no retired slug in native membership, generated projections, or dispatch
+defaults; every default on a live slug; `bun run typecheck` clean; the focused domain
+suites green; the full `bun run test` green; `bun run structure:check` green; and this
+unit carrying a closing record with quoted evidence. The shadow-intercept restore value
+is an intentional compatibility exception.📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,125 @@ | ||
| # wp2 — Remove the retired slugs from the Codex-login native catalog | ||
|
|
||
| Membership only. No default moves here; that is wp3. | ||
|
|
||
| ## MODIFY src/codex/catalog/native-models.ts | ||
|
|
||
| `NATIVE_OPENAI_MODELS` line 156. Before: | ||
|
|
||
| ```ts | ||
| "gpt-5.5", "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex-spark", | ||
| ``` | ||
|
|
||
| After: | ||
|
|
||
| ```ts | ||
| "gpt-5.5", "gpt-5.3-codex-spark", | ||
| ``` | ||
|
|
||
| Two comments name the removed slugs as examples and must stop doing so, because after | ||
| this change they would describe a list that no longer holds them: | ||
|
|
||
| - line 75, in the `SELF_DESCRIBED_NATIVE_OPENAI_MODELS` doc comment: the sentence "the | ||
| pin also holds `gpt-5.5`, `gpt-5.4` and `gpt-5.4-mini`" stays true of the snapshot, but | ||
| the retired slugs are no longer admission candidates at all. Rewrite it around the pins | ||
| that remain reachable — `gpt-5.5`, `gpt-5.2`, `codex-auto-review` — so the reason the | ||
| allowlist is explicit rather than structural survives the retirement. | ||
| - line 175, in `NATIVE_MAIN_DRAIN_SENTINEL_MODELS`: drop `gpt-5.4` and | ||
| `gpt-5.4-mini` from the "would have widened the sentinel to" enumeration, leaving | ||
| `gpt-5.5` and `gpt-5.3-codex-spark`. The set itself is unchanged — neither slug | ||
| was ever a member. | ||
|
|
||
| ## MODIFY src/codex/catalog/metadata.ts | ||
|
|
||
| Line 165, `NATIVE_OPENAI_CONTEXT_OVERRIDES`: DELETE | ||
| `"gpt-5.4": { contextWindow: 1_000_000, maxContextWindow: 1_000_000 },`. This was the | ||
| only 1M native; `gpt-5.4-mini` has no entry and took its window from the pin. | ||
|
|
||
| Line 123, the operating-cap comment: the sentence "and gpt-5.4 runs 272,000 against | ||
| 1,000,000" describes a row that is going away. Rewrite it to cite only the GPT-5.6 | ||
| slugs it already discusses. | ||
|
|
||
| Line 540, the `upstreamNativeEntryForSlug` allowlist comment: "would also admit | ||
| gpt-5.5/gpt-5.4/gpt-5.4-mini" becomes "would also admit gpt-5.5/gpt-5.2/codex-auto-review". | ||
| The behaviour is unchanged; the example set follows the pins that can still be reached. | ||
|
|
||
| ## KEEP src/codex/data/upstream-models.json (audit reversal) | ||
|
|
||
| The plan originally called for deleting the two pinned objects (`"slug": "gpt-5.4"` at | ||
| line 460, `"slug": "gpt-5.4-mini"` at line 565). The A phase reversed that. | ||
|
|
||
| This file is a snapshot of upstream's bundled catalog, and `metadata.ts:580` states the | ||
| contract: "The pinned JSON is left byte-identical to upstream; only the projection fills | ||
| in." The snapshot already carries `gpt-5.2` and `codex-auto-review`, neither of which is | ||
| in `NATIVE_OPENAI_MODELS`, so a pinned row has never been an exposure decision. | ||
|
|
||
| Nothing re-exposes a retired slug from the snapshot alone. `PINNED_NATIVE_CAPABILITY_ENTRIES` | ||
| and `UPSTREAM_NATIVE_ENTRIES` are both built by iterating `NATIVE_OPENAI_MODELS`, so once | ||
| the slugs leave that list their pinned rows are never looked up. The one consumer that | ||
| reads raw snapshot rows, `GATED_MODEL_CLIENT_VERSION_FLOOR` in | ||
| `src/codex/model-entitlements.ts:135`, filters on `ACCOUNT_GATED_NATIVE_OPENAI_MODELS` | ||
| (Daybreak only) and never sees them. | ||
|
|
||
| Deleting ~205 lines of upstream-owned JSON would change no behaviour while breaking the | ||
| file's fidelity to its source and churning `reserve-catalog-lifecycle.test.ts` and | ||
| `codex-model-entitlements.test.ts`, which read it directly. Membership is the lever. | ||
|
|
||
| ## MODIFY src/codex/catalog/parsing.ts, src/codex/catalog/effort.ts, src/codex/catalog/sync.ts | ||
|
|
||
| Comment-only. Each names `gpt-5.4` or `gpt-5.4-mini` as the illustrative "older native" | ||
| (`parsing.ts:521` preserved-row cap, `effort.ts:62` xhigh clamp, `sync.ts:263` mock | ||
| max/ultra). Replace the examples with `gpt-5.5` / `gpt-5.3-codex-spark`. No predicate | ||
| changes: the clamp keys on "is not a gpt-5.6 native", so a request that still names a | ||
| retired slug is still clamped correctly. | ||
|
|
||
| ## Tests | ||
|
|
||
| Membership assertions that must drop the slugs: | ||
|
|
||
| - `tests/codex-integration/codex-catalog.test.ts` — `filterSupportedNativeSlugs` | ||
| expectation at 6954 and the visibility inputs at 6943-6944; delete the "native gpt-5.4 | ||
| uses its 1M context window override" test at 3459-3466 with the override itself. | ||
| The "preserved gpt-5.4-mini rows get the openai cap" test at 3640-3678 cannot simply be | ||
| kept: it feeds a preserved row through `mergeCatalogEntriesForSync`, and after membership | ||
| removal that row is a droppable unsupported native. Run it first — if it drops, repoint | ||
| the fixture onto a surviving non-overridden native so the #1430 cap regression keeps its | ||
| coverage. Line 3686 (`nativeOpenAiContextWindow("gpt-5.4", 272_000)`) names a retired | ||
| slug in a test about the generic cap, so repoint it too. | ||
| KEEP 3817 (negative: the slugs must not leak into `UPSTREAM_NATIVE_ENTRIES` — still true | ||
| and now trivially so), KEEP the Nova1 routed alias fixtures at 1175-1205 and the cursor | ||
| rows at 4340-4893. | ||
| - `codex-catalog-sync-hardening.test.ts` 118-140, 275-281, 373-376 — repoint the native | ||
| fixtures onto `gpt-5.5` / `gpt-5.6-luna`; 729-765 likewise. | ||
| - `codex-catalog-golden.test.ts` 41 and the `"gpt-5.4@9"` golden projection at 76. | ||
| - `codex-catalog-model-picker-order.test.ts` 153-167. | ||
| - `codex-catalog-restore.test.ts` — the hide/priority/window fixtures listed in the | ||
| audit; the 1M expectation at 398 goes with the override. | ||
| - `native-model-toggle.test.ts` 71-72 and 299. KEEP 79 (`cursor/gpt-5.4` proves vendor | ||
| slugs are ignored by native visibility) and 234-243 (preserved compact-limit map). | ||
| - `model-visibility-management-api.test.ts` 376-436 — a removed slug is no longer a | ||
| valid native visibility target, so these move to a surviving native. | ||
| - `codex-convergence-account-selectors.test.ts`, `codex-auth-context.test.ts`, | ||
| `codex-metadata-integrity.test.ts`, `codex-v2-gate.test.ts`, `effort-policy.test.ts` | ||
| 281-315 — these use the slug as a live native request id; repoint to `gpt-5.5`. | ||
| `effort-policy.test.ts` 435-439 keeps testing the clamp, on a surviving old native. | ||
| - `tests/claude-integration/` — `claude-models-discovery.test.ts` expected roster, | ||
| `claude-model-info.test.ts` (its "only authoritative 1M native" claim dies with the | ||
| override), `claude-context-windows.test.ts` 24-29, `claude-inbound.test.ts`. | ||
| - `tests/clients/desktop-3p.test.ts` 215-221 — same 1M native subject. | ||
|
|
||
| Do not touch: `tests/usage/**`, `tests/providers/**` vendor suites, | ||
| `tests/fixtures/commandcode-models.json`, `tests/responses/responses-shadow-intercept.test.ts`, | ||
| `tests/routing/subagent-*` (operator rosters and a negative sentinel assertion). | ||
|
|
||
| Four more in-scope files the first sweep left unclassified: | ||
| `tests/codex-integration/codex-app-server-processes.test.ts:491-500` KEEP (the | ||
| `codex --config model=...` fixture exercises a command-line detector; any token works), | ||
| `tests/codex-integration/slug-codec.test.ts:106` KEEP (codec round-trip pair, not | ||
| membership), `tests/responses/empty-completion-guard.test.ts:467` KEEP (string formatting), | ||
| `tests/vision/vision-eligibility.test.ts:225` REPOINT to `gpt-5.6-luna` — unlike the | ||
| OpenRouter rows at 22-26 this one is the native eligibility subject and belongs to wp3. | ||
|
|
||
| ## Proof for this phase | ||
|
|
||
| `bun test tests/codex-integration tests/claude-integration tests/clients` green, plus | ||
| `bun run typecheck`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| # wp3 — Move every opencodex-owned default off the retired slugs | ||
|
|
||
| Every lane goes to `gpt-5.6-luna`, including the login provider default (owner | ||
| decision, 2026-09-12). Each site below dispatches a real request today and would 404 | ||
| after retirement. | ||
|
|
||
| ## MODIFY src/oauth/index.ts | ||
|
|
||
| Line 331, the `chatgpt` OAuth definition: `defaultModel: "gpt-5.4"` becomes | ||
| `defaultModel: "gpt-5.6-luna"`. | ||
|
|
||
| Be accurate about what this constant does, because the first draft of this plan was not: | ||
| `upsertOAuthProvider` returns at `src/oauth/index.ts:1476` for `chatgpt`, so the value is | ||
| never persisted onto a provider row, and `src/cli/models.ts:139`, `src/cli/provider.ts` | ||
| and `src/server/fast-row.ts:133` all read `config.providers[*].defaultModel` rather than | ||
| this constant. It is the ChatGPT login definition's declared default, not a live 404 | ||
| dispatch path. It still moves: leaving a retired slug as the login surface's stated | ||
| default is wrong on its own terms, and any future consumer would inherit it. | ||
|
|
||
| ## MODIFY src/oauth/token-guardian.ts | ||
|
|
||
| Line 55, `DEFAULTS.codexWarmupModel`: `"gpt-5.4-mini"` becomes `"gpt-5.6-luna"`. | ||
| Line 87 reads a stored override first, so a user who explicitly set | ||
| `tokenGuardian.codexWarmupModel: "gpt-5.4-mini"` keeps calling the retired model. | ||
| Extend the existing startup migration (below) to rewrite that stored value too. | ||
|
|
||
| ## MODIFY src/codex/warmup.ts | ||
|
|
||
| Line 30: `const DEFAULT_MODEL = "gpt-5.4-mini"` becomes `"gpt-5.6-luna"`. | ||
| Line 31: `FALLBACK_MODELS = ["gpt-5.5", "gpt-5.6-luna"]` becomes `["gpt-5.5"]` — luna | ||
| is now the primary, and the loop already skips a fallback equal to the primary, so | ||
| leaving it would be dead weight that reads as a second chance. | ||
|
|
||
| ## MODIFY src/vision/plan.ts | ||
|
|
||
| Line 14: `const DEFAULT_VISION_MODEL = "gpt-5.4-mini"` becomes `"gpt-5.6-luna"`. | ||
| Lines 71 and 87 consume it and need no edit. This is the one that the startup sidecar | ||
| migration cannot reach: an unset `visionSidecar.model` never equals the old string, so | ||
| today an untouched install still describes images with a retired model. | ||
|
|
||
| After this, `src/vision/eligibility.ts:51` and `src/vision/backends.ts:51` — both | ||
| already `gpt-5.6-luna` — agree with the runtime instead of contradicting it. | ||
|
|
||
| ## MODIFY src/server/management/config-routes.ts | ||
|
|
||
| Lines 823-824, the vision effort-table normalization: both `"gpt-5.4-mini"` literals | ||
| become `"gpt-5.6-luna"`. Lines 724 and 963 are already luna and stay. | ||
|
|
||
| ## MODIFY src/cli/config-command.ts | ||
|
|
||
| Line 148: `const model = vision.model || "gpt-5.4-mini"` becomes `"gpt-5.6-luna"`, and | ||
| the line 147 comment that names the old bounded default follows it. | ||
|
|
||
| ## MODIFY src/server/index.ts | ||
|
|
||
| KEEP the sidecar migration block at 686-701 — it is the only thing that rewrites a | ||
| stored `gpt-5.4-mini` for existing users, and its destination is already luna. Two | ||
| changes: | ||
|
|
||
| 1. Extend it to `config.tokenGuardian?.codexWarmupModel === "gpt-5.4-mini"`, which is | ||
| currently not migrated and is a live dispatch path. | ||
| 2. Correct the comment: it claims "explicit user choices are preserved", but the check | ||
| is exact equality, so an explicitly chosen `gpt-5.4-mini` is rewritten too. After | ||
| retirement that is the right behaviour; the comment should say so rather than | ||
| describe a guarantee the code does not make. | ||
|
|
||
| The `SIDECAR_MIGRATION_CUTOFF` date gate stays as-is. | ||
|
|
||
| ## MODIFY src/types/config.ts, src/types/tools.ts, src/types/request.ts | ||
|
|
||
| Doc comments only, but they are the published contract: | ||
|
|
||
| - `config.ts:1125` — "Default gpt-5.4-mini" for `codexWarmupModel` becomes luna. | ||
| - `config.ts:604` and `:614` — the shadow-intercept comments claim both slugs are | ||
| defaults while the code ships luna only. Correct them to state the default is | ||
| `gpt-5.6-luna` and `gpt-5.4-mini` is an opt-in `sourceModels` value for 0.144.x | ||
| clients. | ||
| - `tools.ts:16` and `request.ts:103` — the synthetic web_search comments still name a | ||
| "gpt-5.4-mini sidecar"; `src/web-search/index.ts:23` has been luna for a while. | ||
|
|
||
| ## KEEP src/lib/shadow-call.ts | ||
|
|
||
| `DEFAULT_SHADOW_SOURCE_MODELS` stays `["gpt-5.6-luna"]` and the 0.144.x note stays. | ||
| This list is what the proxy *intercepts*, not what it sends: a 0.144.x client emitting | ||
| `gpt-5.4-mini` helper calls is exactly who benefits from an intercept, and an operator | ||
| can restore the prefix through `sourceModels`. Adding it back to the default would | ||
| change intercept behaviour for every install, which is a separate decision from | ||
| retiring the model. | ||
|
|
||
| ## Tests | ||
|
|
||
| - `tests/codex-integration/warmup.test.ts` 97-141, `codex-warmup.test.ts` 38/55, | ||
| `token-guardian.test.ts` 253, `codex-quota-auto-refresh-main-admission.test.ts` 290 — | ||
| the warmup chain becomes `gpt-5.6-luna` then `gpt-5.5`. | ||
| - `tests/vision/**` — `sidecar-abort.test.ts` (21 fixtures), `vision-reasoning-contract.test.ts` | ||
| (14, retune to luna's ladder), `sidecar-settings-vision-filter.test.ts` 137/189, | ||
| `sidecar-settings-vision-controls.test.ts` 89, `vision-anthropic.test.ts` 419. | ||
| KEEP `vision-eligibility.test.ts` 22-26 (OpenRouter `openai/gpt-5.4-mini` metadata). | ||
| - `tests/web-search/web-search.test.ts` — 26 settings fixtures move to luna. | ||
| - `tests/server/server-combo-failover-e2e.test.ts` — 10 live-forward model ids. | ||
| - A new regression for the widened migration: a stored | ||
| `tokenGuardian.codexWarmupModel: "gpt-5.4-mini"` is rewritten to luna at startup. | ||
| - `tests/vision/vision-eligibility.test.ts:225` — the native eligibility subject moves to | ||
| luna; 22-26 stay (OpenRouter `openai/gpt-5.4-mini` metadata). | ||
| - KEEP `tests/server/config.test.ts` 98 and `server-startup-reconcile-resilience.test.ts` 57 | ||
| (legacy roster inputs), `tests/server/api-debug.test.ts` (log-parser fixture), | ||
| `tests/responses/**` (shadow restore hatch), `tests/usage/**` (historical pricing). | ||
|
|
||
| ## Proof for this phase | ||
|
|
||
| `bun test tests/vision tests/web-search tests/server tests/codex-integration` green, | ||
| plus `bun run typecheck`. |
Uh oh!
There was an error while loading. Please reload this page.