Iter 32 — completes the helper-extraction discipline started in iter 30.
The iter 15 inline `ns.latest_sync = Some(sync); ns.latest_sync_at = ...`
was the LAST untested receive-side mutation; now it's a named method
with 2 tests covering its full state-transition surface.
Refactor:
Add `NodeState::apply_sync_packet(pkt, now)` taking an Instant so
the test can pass deterministic timing.
udp_receiver_task now calls the method instead of touching the
fields inline — one less place to break the staleness gate.
Tests (2 new — sync_snapshot_helper_tests module now at 5 tests):
apply_sync_packet_populates_a_fresh_node
Mirrors udp_receiver_task's first-packet-from-unknown-node path:
asserts latest_sync goes from None → Some, latest_sync_at matches
the passed Instant exactly (no clock skew from real Instant::now()),
and sync_snapshot() now returns Some (REST 200 OK path lit up).
apply_sync_packet_overwrites_older_data
Subsequent packets must replace, not accumulate. Asserts sequence,
local_us advance, and the staleness clock resets. This is what
keeps the §A0.10-smoothed offset tracking the latest beacon rather
than drifting with stale state.
cargo test sync_snapshot_helper → 5/5 green.
Branch-coord clean — no Cargo.toml / cli.rs touched.
Co-Authored-By: claude-flow <ruv@ruv.net>