Repository navigation
bug(catalog): sync drops operator Ultra Fast declarations despite ultraFastTier opt-in #6817
Description
Client or integration
Codex App
Area
Catalog / models
Summary
With ultraFastTier: true, a manually supplied Ultra Fast declaration on an existing routed catalog row disappears after a successful ocx sync. The row is regenerated with Fast only. This is the retention workflow intended by #3478 / #3429, not a request to synthesize an Ultra Fast tier globally or claim upstream entitlement.
Reproduction
- Configure a provider/model with
modelSupportsServiceTier[model] = true, and enable the existing Ultra Fast setting (ultraFastTier: true). - In the generated catalog, add the following operator-supplied fields to that exact routed row:
{ "slug": "gateway/task-model", "service_tiers": [ {"id":"priority","name":"Fast","description":"provider Fast"}, {"id":"ultrafast","name":"Ultra Fast","description":"operator supplied"} ], "additional_speed_tiers": ["fast", "ultrafast"] } - Read the catalog (or a separately launched app-server's model/list): both declarations are present.
- Run
ocx syncsuccessfully, then read the same catalog again. - Actual: only
priority/fastremains. Expected: retain the exact row's suppliedultrafastalongside fresh Fast metadata while opt-in remains enabled.
The live sync result was reproduced twice on 2.81.0. A build-plus-merge regression on dev commit 71c4ae3 also reproduces the loss with synthetic provider/model data and no upstream inference requests.
Version
2.81.0 installed; source regression also reproduces on dev 71c4ae3 (package version 2.82.0).
Operating system
macOS 26.5.1 (Apple Silicon)
Provider and model
Observed with Krill / gpt-6.1-sol and gpt-6-astra; the source reproduction uses gateway / task-model, so it does not depend on these names.
Logs or error output
sync exit code: 0
before: service_tiers=[priority, ultrafast], additional_speed_tiers=[fast, ultrafast]
after: service_tiers=[priority], additional_speed_tiers=[fast]
source regression before fix: 18 pass, 4 fail
Screenshots and supporting files
Source trace:
- Both retained sync and convergence build fresh rows from the native template.
applyCatalogModelMetadatareplaces tier arrays with Fast-only whensupportsServiceTier === true.mergeCatalogEntriesFromObservedStatedrops the old exact row when a fresh equivalent exists, without carrying its operator-supplied Ultra Fast fields into the replacement.- The existing test named “survives regeneration” only invokes
normalizeRoutedCatalogEntry; it does not exercise fresh build + old-row replacement.
A proposed fix is to preserve only exact persisted routed-row Ultra Fast metadata in the shared final merge, after capability generation and admission filters, using the explicit opt-in from both writers. No new rows, default capability claims, or provider routing changes are needed.
Redacted configuration
{
"ultraFastTier": true,
"providers": {
"gateway": {
"adapter": "openai-responses",
"baseUrl": "https://provider.invalid/v1",
"models": ["task-model"],
"modelSupportsServiceTier": {"task-model": true}
}
}
}Checks
- I searched existing issues and documentation.
- I removed secrets, tokens, account details, request credentials, and personal data.
Activity
fix(catalog): retain operator Ultra Fast declarations across regenera…
lidge-jun commentedon Oct 9, 2026
Fixed by #6819, merged into
devas 730d898.Cause: on regeneration, the routed row is rebuilt from the native template;
applyCatalogModelMetadatareplaces its tiers with Fast only, and the observed-state merge drops the persisted row once a fresh equivalent exists, so the #3478 retention never reached a regenerated row. Codex then rejects a requestedultrafastfor that model because the row no longer lists it.With
ultraFastTieron, sync and convergence now keep the exact persisted row'sultrafastentries alongside the current Fast metadata (first-win on duplicate slugs). The fix ships in the next release; it is not in 2.81.0.