SIGN IN SIGN UP

fix(cache): make the SSD budget real end-to-end and stop v17 corrupting migration fingerprints

The 10% disk default shipped inert and the new SSD-only default could not
start DSV4 at all. Both were found by running the thing rather than reading it.

Engine

- normalize_block_disk_cache_budget() collapses the GB/percent flags to one
  number at the single parse_args point, and both scheduler config builders
  call it. The GB flag defaults to None so a percent can size the cache, but
  the resolver only ran inside the paged-default helper; every other path read
  the raw attribute and got None. BlockDiskStore then raises on
  "'>' not supported between NoneType and float", the generic path swallows it
  ("Continuing without disk cache"), and the disk-ONLY path -- the new shipping
  default -- refuses to start. Observed live on DeepSeek-V4-Flash-0731:
  startup printed max=NoneGB and the engine exited during lifespan startup.
  Note getattr(args, 'x', 10.0) did not save it: the default does not fire when
  the attribute exists and is None.
- percent 0 now means unlimited, matching --block-disk-cache-max-gb 0 and the
  Session Settings slider. It previously returned a flat 10GB, inventing a cap
  for a user who explicitly asked for none.
- The fatal disk-only error now carries the cause it used to hide 40 lines
  above it in a swallowed except Exception.

Panel

- buildArgs emits --block-disk-cache-max-percent, and fresh configs seed 0 GB
  instead of 10. The engine resolves explicit-GB-wins, so seeding the flat GB
  meant the percent could never take effect and the slider was decorative.
- The v17 SSD-first default is now a POST-pass. Every legacy cache migration is
  an exact-tuple fingerprint that includes usePagedCache, so flipping it first
  rewrote near-miss tuples into exact matches and re-fired migrations users had
  deliberately escaped. It also skips any pass where the version stamp declined
  because the bundle is unreachable -- otherwise it rewrites the fingerprint
  the retry depends on and the retry never fires.
- ZAYA CCA and openPangu v2 are exempt: both carry runtime policies that
  contradict SSD-only, and a persisted value the launcher overrules would show
  the checkbox Off while the engine ran the RAM tier.
- Per-session "Clear SSD cache" button in Session Settings, reporting which
  tiers were cleared and which were skipped. paged_prefix:blocks_in_use means
  nothing was freed there, so a flat "Cleared." would be a lie.
- One definition of the percent default in src/shared/cacheDefaults.ts.
- The percent tooltip carries the semantics the GB tooltip used to: one
  aggregate root shared across namespaces and typed companions, with the
  smallest finite limit enforced across live sessions. All five locales.

Verified live on the box, SSD-only, TQ off (stored quantization=none):
DSV4-Flash-0731, Gemma-4-26B (rotating SWA) and Qwen3.8-27B-4D (SSM companion)
answer correctly across changed prefixes, reasoning-effort changes, tools
toggled per turn, JSON and XML tool dialects, malformed and truncated tool
calls, and reasoning blocks in history. RAM tracks model size: gemma4 16.2GB
after load with a 2.9GB on-disk block cache.
J
Jinho Jang committed
9200e6ef34f382cf36c229b040d06fcafd69031b
Parent: ae47fcf