Repository navigation
[Bug]: v1 to base leaves newer native models pinned to v1 when the pristine catalog predates them #5636
Description
Client or integration
Codex App
Area
Catalog / models
Summary
Returning from forced v1 to base can leave native models pinned to v1 indefinitely when those models were added after the immutable pristine catalog backup.
On a 2.63.0 installation, base was selected, but both gpt-6-astra and gpt-6-luna remained multi_agent_version: "v1" in the active catalog and models cache. The shipped native metadata pins both to v2. The older pristine backup did not contain either model.
This is on-disk state, not just a stale Desktop app-server cache. The independently repaired WSL executable-discovery problem is tracked in #5635. Existing issues about global-v2 precedence (#2184, #2409) and stale picker state (#1046) describe different mechanisms.
Reproduction
A deterministic source-level reproduction avoids toggling any live environment:
- Start with a native baseline map that predates a model, for example one containing only an older native model.
- Add a current native row such as
{ slug: "gpt-6-luna", multi_agent_version: "v2" }. - Apply
applyMultiAgentMode(entries, "v1"), then serialize/reload the rows as a retained catalog would. - Apply
applyMultiAgentMode(entries, "default", false, { nativeDefaults: oldBaseline }). - Actual on the release source: the row stays v1. Expected: a mode round-trip should preserve enough provenance to restore the pre-override value without guessing.
Root cause in src/codex/catalog/parsing.ts: forced modes overwrite the value without retaining its origin. Default mode intentionally preserves a live native pin when a supplied baseline has no entry for it. That preservation is valid for genuinely new native metadata, but it cannot distinguish a prior forced v1 value after provenance is lost.
A local fix records the original native value (including an unpinned/null state) before the first forced override and consumes it on return to base only when native authority genuinely lacks the model. It preserves these precedence rules:
- pristine baseline entries, including explicit null, win;
- authoritative upstream/native alias pins win;
- routed-row normalization is not bypassed;
- repeated v1/v2 changes do not replace the original value;
- historical unmarked rows are not automatically reinterpreted.
Legacy polluted rows require a separate explicit migration. On the affected host, only the Astra/Luna pins in catalog and cache were recovered from known shipped metadata, with before-images, hash guards and the existing serialized atomic catalog writers. Historical pristine backups were not edited or deleted.
Version
@bitkyc08/opencodex 2.63.0, release baseline 96b1406; Codex 0.155.0-alpha.16.
Operating system
Observed with Windows Codex Desktop + Ubuntu 24.04.1 LTS / WSL2. The catalog round-trip mechanism is not WSL-specific.
Provider and model
Native ChatGPT: gpt-6-astra, gpt-6-luna. No fallback to another model was used.
Logs or error output
Before explicit legacy recovery:
effective mode: default/base
active catalog: gpt-6-astra=v1, gpt-6-luna=v1
models cache: gpt-6-astra=v1, gpt-6-luna=v1
shipped pins: gpt-6-astra=v2, gpt-6-luna=v2
pristine backup: neither model present
After local fix + bounded recovery:
base retained; both files show the two native v2 pins
fresh GPT-6 Luna parent -> GPT-6 Luna child: initial task and follow-up succeeded
Screenshots and supporting files
Regression tests exercise serialized retained merges, repeated forcing, v1 -> v2 -> base, native-v1 preservation, original unpinned state, authoritative baseline string/null values, routed normalization and the no-baseline path. An independent local review identified a precedence defect in the first candidate; it was reproduced and fixed before installation.
Combined relevant validation: 689 tests across 12 files, zero failures; TypeScript no-emit, structure consistency, privacy scan and file-size guards passed. The full upstream suite was not run; this is not a PR readiness or exhaustive runtime claim.
Separate compatibility observation, not part of this bug fix: after explicit user opt-in to the already-existing plaintextV2AgentMessages setting and proxy restart, a fresh Luna v2 parent successfully sent an initial task and same-child follow-up to openrouter/~z-ai-glm-flash-latest. Proxy records confirm both GLM calls used OpenRouter at max effort with HTTP 200. This was not automatic v1 fallback, and encrypted-task recovery remained disabled.
Redacted configuration
{
"multiAgentMode": "default"
}This denotes effective base mode; the persisted mode key may be absent. The source fix does not enable global v2 or experimental message compatibility settings.
Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
Ingwannu commentedon Sep 23, 2026
Confirmed on current
dev. In default mode,applyMultiAgentMode()intentionally preserves a string pin for a native row absent fromnativeDefaults; after a forced v1/v2 pass overwrites that same field, the code has no provenance left to distinguish the forced stamp from a legitimate live pin. The fix therefore needs explicit original-value provenance (including an original absent/null value), must not overwrite that provenance on repeated forced toggles, and must continue honoring authoritative baseline/native pins and routed-row normalization. Historical unmarked rows should not be guessed or silently migrated. This is a real catalog-state bug; the stated regression matrix is the right acceptance boundary.fix(catalog): restore a native row's multi-agent pin after a forced m…
fix(catalog): restore a native row's multi-agent pin after a forced m…
fix(codex): bundle lane D — Codex home and WSL runtime discovery, int…
lidge-jun commentedon Sep 23, 2026
Fixed on
devby #5680 (squash-merged as aa2406b). A forced v1/v2 pass now records each row's originalmulti_agent_versiononce, and returning to base restores it for native rows the pristine catalog predates. Baseline and native pins still win.