fix(hybrid,dflash2): post-turn clean-prefill memory waves + resume cache math
Two shipping-reachable defects found during the 1.6.34 release gate, both
proven live on Qwen3.8-27B-JANG_4D:
1) Post-turn background clean prefill: every completed hybrid thinking text
turn ran up to two full-prompt background forwards (store-time clean
store, then idle SSM re-derive) whose chunk loop retained each chunk's
Metal transients for the whole pass. On an 11k-token conversation the
waves reached 81GB RSS and aborted the serve process about two minutes
after the turn (uncatchable command-buffer OOM in a background thread,
no traceback) -- and twice escalated to a machine-level watchdog panic
with the wired limit raised. The loop now returns each chunk's
transients to the allocator (mx.clear_cache per chunk), and the
store-time pass stores the SSM companion it just computed
(is_complete=True, positional-latent exemption applied) so
run_idle_rederive's has_complete probe skips the second full-prompt
pass entirely.
2) DFlash2 resume: the session-store resume path builds a fresh drafter
RotatingKVCache and force-sets its offset to the absolute conversation
position; upstream sizes physical buffer growth from that logical
offset, so a resume past the drafter window computed a negative
mx.zeros dimension ("[full] Negative dimensions not allowed") on the
first 1-token update after an accepted==0 verify cycle. A resume-math
patch keys growth on the write index, sizes it from the physical fill,
and slices the returned view to the written region while the buffer is
under its window -- a no-op for every upstream flow, where offset
equals fill.
Tests: rotating-cache resume math (6, real mlx_lm class, including the
exact crash state), clean-pass allocator discipline + companion store +
positional-latent exemption (4). Panel suite 3191 passed. J
Jinho Jang committed
e8b2b60872d8d62f9366a7a3c08e52b6b86f5dc5
Parent: eac732f