NeuroReach: aligned LSL ingestion and channel layout

one pull for EEG + IMU, not two consumers fighting over the inlet! Check channel order/counters too. later: tiny timeline viewer for markers + sample gaps?

code pointers: signal-engine/acquisition/, MockUnicornOutlet, and signal-engine/run_ws_server.py for the mock-to-score development path.

acquisition rule: EEGInlet.get_chunk() performs one aligned pull_chunk for EEG and IMU. The spec warns that two consumers pulling separately from the same inlet can consume one another's samples and gap the EEG stream.

recorded stream layout: 17 channels at 250 Hz; positions 0–7 map to [Fz, C3, Cz, C4, Pz, PO7, Oz, PO8]; 8–13 are accelerometer/gyro values; 14–16 are battery, counter and validation. The observed bridge stream type was Data, not EEG, and lacked channel-label XML, so the inlet has a fixed-layout fallback. This is a recorded bridge configuration, not a guarantee about every device/version.

timing: maintain a roughly six-second ring buffer; update the processing loop around 20–50 Hz. Marker stream NeuroReach-Markers, type Markers, uses string payloads label|{json} for cue onset, imagery-window boundaries, feedback and score events. time_correction() is part of the intended synchronization procedure.

review questions: how are counter discontinuities, invalid samples, rate changes and timestamps handled? Verify the actual stream's channel metadata before applying the fallback. Synchronization targets in the specification need measurement; naming everything LSL does not establish measured timing accuracy.

Sample report: electrode montage and processing rates.
Sample report: electrode montage and processing rates.

Eight-channel EEG display with electrode labels and auto-gain.
Eight-channel EEG display with electrode labels and auto-gain.