evictStaleProcessing cleared `processing` but left the task in
`coordinatorAdmittedTaskIds`, which is only cleared by specifyTask's
finally — the path a hung promise never reaches. The card stayed
eligible (so the throttle branch never logged or emitted
`task:plan-admission-throttled`) while admitOldest's refresh filtered it
out, leaving it on the "Queued to plan" badge with free slots and no
diagnostic until engine restart. Also drop an untransferred pre-held host
slot, which otherwise waits out the 600s stale-excess valve.
Regression tests assert the invariant on the real production candidate
source: an evicted card is re-offered and its host slot returned, while a
still-live stale task keeps both claims.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>