* fix(whispercpp): reuse an on-disk same-size weight at startup
The Settings picker already lets a downloaded same-size model stand in
when the language-derived sibling is absent, but the startup path never
applied it: a headless config with language=en-us and model_size=medium
demanded ggml-medium.en.bin while ggml-medium.bin sat in the models
directory and loads fine.
Move the stand-in into whispercpp_model_info.on_disk_stand_in so both
paths share it, and give resolve_whispercpp_variant a prefer_on_disk
flag that only language-derived results use: pinned variants and stored
specializations still load exactly what they name, the .en preference
still wins when that file is present, and checksum verification is
untouched. get_model_size_for_engine opts in so startup and headless
launches match the Settings semantics.
Fixes#916
* fix(whispercpp): keep is_model_downloaded free of makedirs
get_model_path creates the model directory for callers that are about to
write a file, but is_model_downloaded is a read-only probe: on a fresh
profile its makedirs ran inside tests that stub os.makedirs for the
config directory, breaking them, and a bare existence check should not
mutate the filesystem anyway. Resolve the file path without creating
directories in the probe; get_model_path keeps creating for writers.
Refs #916
* test(whispercpp): annotate the stand-in fixture's return type
AGENTS.md requires type hints on every signature; _downloaded returns the
context manager from patch.object.
Refs #916
---------
Co-authored-by: Jatin K Malik <jatinkrmalik@gmail.com>