If the C/Python eval was stuck in code without a poll site (sync XHR
inside bend!-call, a builtin that doesn't pass through leval), the
SAB pause flag would set, waitForPending would time out after 5s,
and then portal-snapshot would queue behind the still-busy worker
and never resolve. autoPauseTab hung on that await and never
reached its terminate loop — leaving the worker running while the
user sat on a new tab watching the old loop keep streaming.
Now:
* SAB pause wait drops from 5s to 2s.
* If the eval is still in flight after the pause wait, skip the
snapshot attempt entirely — the worker isn't yielding and the
snapshot would just hang the UI.
* Snapshot eval + portal-save bridge are wrapped in withTimeout
(2s + 1.5s) so even if pause partially worked but snapshot
stalled, we fall through to the unconditional worker.terminate
at the bottom of autoPauseTab.
* The hard-cancel branch and the SAB-timeout-fallback now share the
same pending-rejection loop instead of duplicating; the
unconditional terminate loop at the end kills the worker.
pauseAndSnapshot (manual ⏸ button) also surfaces the timeout case
with an alert pointing at cancel + reboot instead of locking the UI.