Delays (after)
after transitions schedule a timer. The delay is either a number of milliseconds or the name of
a delay registered with MachineLogic::delay(name, ms); delay functions
(Fn(&C, &Event) -> Result<f64>) compute it from context and event.
SyncInterpreter runs timers on a clock you control. Pass a SimulatedClock to with_clock and
move time with interp.advance(&clock, ms) — tests never sleep. RealClock (the default) uses
the wall clock. The tokio interpreter drives after on tokio::time, so tokio::time::pause()
works in tests.
Numeric delays are normalised ("1e3" → 1000 ms), and the timer event, structure hash, snapshots
and diagrams all use the normalised value (xstate.after.1000.<id>). A delay function that fails
or returns NaN/infinity disables that one timer with an error log; an unregistered delay name is
an ImplementationMissing error at start().
Persistence stores the deadlines in the snapshot, and a DueTimerScanner fires matured timers
across process boundaries — see the persistence guide.