Reuse _get_models_cache_path(profile) for profile delete/create instead of a
second path helper, derive the fingerprint home from the auth store path, fold
the three switch test files into one parametrized file, and trim comments/docs.
Behaviour, source axes and switch fast path are unchanged.
A retained per-profile snapshot is now rejected after a switch when the target
profile's .env credential set or model-provider plugins changed, and a
recreated same-name profile no longer inherits the deleted profile's catalog.
- docs/architecture/models-cache-invalidation.md: add 'Invalidation modes'
section describing delete_disk=True/False and why /api/profile/switch
uses the memory-only mode (fingerprint-guarded per-profile disk cache).
- tests: replace the source-text scan of the switch route with two executed
routes.handle_post tests: one captures invalidate_models_cache kwargs and
asserts exactly [((), {'delete_disk': False})]; one runs the real
invalidate_models_cache and asserts the disk file survives while the
in-memory catalog is dropped. Both fail if the route reverts to the
default delete_disk=True.
POST /api/profile/switch called invalidate_models_cache(), whose
test-isolation contract also unlinks models_cache.<profile>.json. On a
switch nothing about the sources changed, so the delete only forced a
full cold rebuild (live provider fetch_models HTTPS calls, ~490k deepcopy
calls) on the very next /api/models — several seconds on every switch.
The disk cache is already keyed per profile and rejected on read when
_models_cache_source_fingerprint() differs, so it is safe to keep. Add a
delete_disk keyword (default True — every existing caller keeps the old
behaviour) and have the switch route pass delete_disk=False.
Regression tests cover: memory-only drop preserves the disk file, default
call still unlinks it, the next get_available_models() serves the disk
snapshot without a live rebuild, and the switch route opts out. Two
existing zero-arg stubs of invalidate_models_cache accept **kwargs now.