Windows timers fire in ~15 ms steps, so the fixed tick(30) in the joinPresence
stream test ended before the three stub events (tick(2) each) were applied, and
the failed assertion skipped handle.stop(). The live handle's heartbeat interval
and endless stub stream then kept the test process alive, which CI saw as ten
silent minutes. Tests now poll for the state they assert and stop every handle
in finally. run-tests.mjs gives each test a 2 minute deadline and kills a run
that outlives 8 minutes with a message.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>