The drain thread could take a signal off the queue and still be writing
it when stop() flushed (an empty queue) and returned; the interrupt could
also land mid-write. A resolve submitted just before shutdown could be
lost. That is what failed SinkAndScheduleTest on the release/0.1 build.
stop() now ends the drain loop with a flag, joins the thread (up to 10 s,
interrupting only if it does not finish), then flushes what is left. The
drain poll is 200 ms so stop() returns promptly. New regression test fails
on the old code (3 of 4 runs) and passes on the fix.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>