admin: force a host's worker to reconnect, in band master
The 2026-08-18 incident had no recovery short of a pod restart. Neither existing path could reach a deaf worker: `addHost` dedupes on `workers.contains`, so requestCrawl is a no-op while the dead worker still exists, and `/admin/hosts/block`+`unblock` only writes DB status without tearing a worker down -- it would strand the host as blocked if the second call never landed. `Slurper.forceReconnect` cancels the worker's future and re-queues the host for crawl. Cancellation is the part that matters: a flag cannot wake a fiber parked in netRead, but cancelling readies it and makes the read return error.Canceled. `host_shutdown` is set first so a healthy worker leaves its reconnect loop cleanly rather than racing. `future.cancel` awaits, so runWorker has already released the cursor slot, dropped the map entry and decremented connected_inbound before the respawn is queued -- which is why the respawn does not trip the dedup that made this unrecoverable. Exposed as POST /admin/hosts/reconnect {"hostname": "..."}. It resolves the host without creating it, so reconnecting an unknown host is a 404 rather than a silent insert, and it never changes host status. Verified: zig fmt --check, zig build test, zig build test -Dbackend=zio, zig build -Dbackend=zio, and the production config -Dbackend=zio -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseSafe. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>