Flip the resolve_persist_behavior() fallback from persist-to-config to
session-only. A plain /model <name> (typed or via any picker — CLI,
TUI/Desktop, gateway) now affects only the current session; --global
persists explicitly, and model.persist_switch_by_default: true restores
the old opt-out behavior for users who want switches to stick.
This is the root cause behind the recurring 'session switch applied
globally' bug class (#61458, #63083, #58290, #61190): every surface
funnels its no-flag default through this one function, so per-surface
patches kept missing paths. Fixing the default fixes all surfaces at
once: CLI typed + picker, TUI/Desktop config.set + slash, gateway typed
+ inline picker.
Builds on liuhao1024's #58371 (--provider session scoping, cherry-picked
as the previous commit) and supersedes the per-surface #61488.
Simplify pass on the picker-persist coverage:
- Stub list_picker_providers + resolve_display_context_length so the
tests no longer make real outbound HTTP calls (OpenRouter catalog +
Ollama /api/show) during picker setup and confirmation rendering.
Runtime drops from ~11s to ~0.4s and the tests are now deterministic.
- Collapse the two positive persist cases into one parametrize over the
config seed (nested-dict vs flat-string), asserting the nested-dict
invariant in both.
- Assert the in-memory session override is applied in the --session
case, closing a 'passes for the wrong reason' gap (config untouched
AND the switch still took effect).
- _FakePickerResult -> types.SimpleNamespace.
Mutation re-checked on the final test: both persist cases fail on
pre-fix slash_commands.py; the --session case passes on both.
Add regression coverage for the picker persist fix: drive the real
_handle_model_command with a fake picker-capable adapter that captures
the on_model_selected callback, fire a 'tap', and assert config.yaml is
written (bare /model), left untouched (--session), and that a flat-string
model: is coerced to a nested dict on a tap.
Mutation-checked: the persist and coercion assertions fail on pre-fix
slash_commands.py and pass on the fix.