The notified() method had a TOCTOU race: if fire() was called between
the is_set() check and the .notified().await call, notify_waiters()
would drop the notification (no waiters registered yet), causing the
caller to hang indefinitely.
Fix: create the Notified future before the flag check. This registers
as a waiter immediately, so any concurrent fire() / notify_waiters()
call will wake it correctly.
Race scenarios (all now handled):
- fire() before notified() call: flag is set, fast path returns
- fire() between is_set() and .await: future is registered, woken
- fire() after .await: future is woken normally
This is the root cause of the intermittent selfdev reload hang.
Also adds:
- 6 unit tests for InterruptSignal (src/agent.rs)
- scripts/test_reload.py: 18-test suite for the full reload path