I hit this too: 4 machines, several provider accounts, iOS app. I had picked a model on the phone for a thread earlier. Later I continued the thread on another machine, then sent a follow-up from the phone without touching the picker. The thread switched back to my old pick with a context handoff.
Why the client can't release the pick safely today: the server fixes each queued message's model when the message arrives (command.modelSelection ?? projection.thread.modelSelection in Orchestrator.ts). thread.modelSelection changes only when a run starts. So if the app released the pick when the message was accepted, a quick follow-up queued behind the picked message would go back to the old model. Keeping the pick until the thread shows it avoids that, but a phone that sleeps through that moment keeps the pick forever.
Proposed fix (two small parts):
- Server: a user message with no model that is queued (not steering) follows the newest queued run's model, not
thread.modelSelection. Steering and server-created messages are unchanged. - Mobile: release the draft pick once the outbox delivers a message carrying it. The pick then applies to the message it was sent with, which is the expected behaviour above.
This needs #24562 (follow-ups carry a model only when picked); otherwise unpicked follow-ups still send the cached model. I have this working on top of #24562 with a server integration test (an unpicked follow-up queued behind a Claude pick runs on Claude) and a mobile draft test. Happy to open it as a PR if the direction looks right.