Note
Grok responding on behalf of Julius.
Triage
Thanks @sonhyrd for the clear report and the pointer into resolveAppModelSelectionForInstance. Reading current main, this looks like a real composer/send mismatch, not only a label glitch.
What I found
- The stored selection is what the server runs.
cursorSdkModelSelectionforwardsmodelSelection.modeland its options unchanged (apps/server/src/provider/cursorSdkModel.ts). - The composer resolves a different one.
deriveEffectiveComposerModelStateresolves the thread model throughresolveAppModelSelectionForInstance, and for Cursor an unmatched slug becomesoptions.find(isDefault)?.slug ?? options[0]?.slug(apps/web/src/modelSelection.ts). Cursor's discovered models never setisDefault(buildCursorDiscoveredModelsFromSdk), so that is the first catalog row. Auto / Balance is that row when it isauto-smart: the trait picker reads the resolved model's descriptors, so the storedeffort: mediumis dropped andoptimize_forshows its default. Only OpenCode and Antigravity keep an unknown slug as unavailable. That split is intentional inappendUnavailableDynamicModelSelectionand covered bymodelSelection.test.ts("does not add unavailable options for other providers"). - Sending uses the resolved selection.
ChatComposerbuildsselectedModelSelectionfrom it, andstartThreadTurnputs that onmessage.dispatch. If it differs from the thread, the orchestrator emitsthread.model-selection-updatedand the next run uses it (Orchestrator.ts, themodelSelectionsEqualcheck in dispatch). A reply from that composer would switch this thread to Auto. - Why the catalog might not contain the stored slug.
orchestrator_capabilitieslistingclaude-opus-5-5does not by itself prove the composer's option list contains it. That tool returnsprovider.modelswith no preference filter. The composer then hides slugs insettings.providerModelPreferences, and a per-thread composer draft (modelSelectionByProviderfor that instance) replaces the thread selection even when the stored slug would resolve. That draft is on the desktop client, not in either server's settings. A client snapshot that is stale or for a different instance fails the same way and lands on the first row. - Related. No open duplicate of this Cursor fallback. Nearby reports (Claude permission Auto, Codex effort, hidden-default settings) are different mechanisms.
Likely fix area
apps/web/src/modelSelection.ts / composer model resolution. Some options:
- Treat an unmatched Cursor slug as unavailable the way OpenCode and Antigravity do, instead of falling back to the first catalog row.
- Keep the stored selection for send when the composer only failed to match it for display.
Workaround: don't send from that composer. t3_thread_send / another turn started from the stored selection keeps claude-opus-5-5.
A maintainer will decide on the fix direction.