SIGN IN SIGN UP

fix(mllm-cache): media turns can capture companions again, and every companion store now uses the key its reader asks with

Multimodal chats never reused cache. Four separate defects, all in the
hybrid SSM companion lane:

1. _ssm_capture_boundaries_for returned [] for EVERY media turn. The
   discard path records the boundary it needed via
   _ssm_required_checkpoint_tokens and this function is its only
   consumer, so the requirement was re-recorded and re-ignored every
   turn -- a media conversation could never heal, and an identical
   repeat turn still reported cached=0. Media turns now capture, but
   only inside the pure-text prefix that precedes the first media
   placeholder, block-aligned so the KV chain can actually pair.

2. _derive_hybrid_companion_delta would advance recurrent state across a
   gap containing media placeholders with a TEXT-ONLY forward. Those
   positions get re-fed without their pixel values: coherent output,
   wrong content, no error anywhere. The fetch side now declines the
   same pairing the store side already refuses.

3. _store_companion_from_clean_pass stored with no cache_extra_keys at
   all, on the premise that media prompts never route through it. That
   premise is false -- the vmlx#91 delta derive routes through
   _prefill_for_clean_ssm. So a media companion landed under the bare
   token key, where the media-lane reader (which asks with the media
   salt) can never find it, and a reader asking WITHOUT the salt would
   find it for a DIFFERENT image: two turns can carry byte-identical
   placeholder token ids and completely different pictures. The salt is
   now threaded through the whole chain, and an unsalted media store is
   declined rather than guessed at. A media probe that FAILS is not a
   positive reading and never blocks a store.

4. run_idle_rederive popped the salt off the queue entry, probed
   has_complete WITH it, then ran the clean prefill WITHOUT it. The
   probe below therefore always missed, so every media re-derive paid
   the 50-200MB deep clone plus disk write TWICE -- and the first copy
   was the unsalted media companion from defect 3.

Tests: 10 new, covering the non-block-aligned media boundary (372
tokens, media at 300 -- deliberately not a multiple of 64 or 256),
media-at-position-0, text-lane invariance, store/fetch key symmetry,
the unsalted-media decline, the failed-probe-must-not-block invariant,
and the idle re-derive double-store.

Full A/B against a stashed tree: same 3 pre-existing failures before and
after (bundled-python drift gate plus two cross-file pollution cases in
test_engine_audit), 1449 -> 1459 passing.
J
Jinho Jang committed
dc56278151bb9ebe202aef0576b7d8698b3876f6
Parent: e89006f