Six review findings, three of them evict-then-fail orderings:
- The chat load reclaimed the GPU without telling the arbiter it existed. A
chat load holds no llama-server process until its GGUF has downloaded,
which is minutes, so a competing Images/Video acquire in that window
found nothing to cancel, took the GPU, and the chat load then spawned
onto the same device. It now registers an in-flight marker through
acquire_for's register hook (under the arbiter lock, as the image and
video loads do), the evictor cancels a marked load, and the route undoes
itself if ownership moved while it loaded.
- The Hub-download conflict check ran after that handoff, so a GGUF the
download manager already owns destroyed the resident Images/Video
pipeline and then 409'd, having loaded nothing. It moves above the
handoff, together with the marker it handshakes with.
- The image load released the engine router's transition lock before
registering the load, so a second load choosing the other engine could
unload the still-idle engine this one captured; the load then landed on a
deactivated engine, where generate, status, unload and the arbiter's
evictor can no longer reach it. Registration now happens under that lock
and refuses if the engine changed.
- Training a DiT family on a host with no GPU was accepted: nf4 is not a
CPU fallback, its 4-bit load goes through bitsandbytes, which requires
CUDA, XPU or MPS. The start unloaded the working Images pipeline, pulled
the text encoders, and only then died in the child. Rejected before the
teardown now, and /info stops advertising a precision that always 400s.
SDXL keeps its documented fp32-on-CPU path.
- Both diffusion pages kept the routed-pick marker forever, so re-picking
the same checkpoint (after chat evicted it) neither loaded nor cleared
the query string. The marker is released once the query is gone. The
Images key also carried a stray NUL byte, which made the file read as
binary to grep and other tooling.
- diffusers dropped Python 3.9 in 0.38, so the unconditional >=0.39.0 pin
left pip no candidate at all on 3.9 and made every install that composes
the huggingface extras unresolvable there. The floor is conditional now.
Also fixes tests that were already red on the branch: two hand-built
request fakes had gone stale against fields this branch added, and the
handoff-ordering test only failed on a host with fewer than two GPUs.