Operator asked for maximum raw signal off the sensors so a future
trained pose / fine-motion model has everything it needs, instead of
only the amplitude scalar we surfaced before. Adds four fields to
NodeInfo:
phases: Vec<f64> per-subcarrier atan2(Q,I), radians
n_antennas: u8 RX antenna count from WiFi driver
noise_floor_dbm: i8 noise floor reported by ESP-IDF
timestamp_us: u64 per-frame µs timestamp from the sensor
Each is `skip_serializing_if = zero-or-empty` so feature_state ticks
(which carry no raw CSI) stay slim in the WS payload — only real raw
CSI frames populate them.
NodeState gains: latest_phases / latest_noise_floor /
latest_n_antennas / latest_timestamp_us (per-node stash, replaces
having to keep a parallel phase_history). The raw-CSI ingest path
populates these on every frame.
Verified live: WS now emits 185 messages over 4 s (~46 fps) with
both amplitude[56] and phases[56] populated; noise_floor reports -91
dBm; n_antennas reports 1 (ESP32-S3 single antenna).