Pure functions, no I/O, no call state. The OpenAI-side WS client (Task 5) and the tap-side WS server (Task 9) call these per event. S4 turn-ownership decision (spec §4.3, load-bearing per ADR-0008) encoded in build_openai_session_update: turn_detection: null. OpenAI's server-side VAD is disabled; the FOB reflex loop (step 4) owns turn-taking; tap playout stays core-authoritative (slice-2 §4.1). S4 test verifies the load-bearing assertion (v['session']['turn_detection'] == Null). Audio is pass-through — OpenAI's PCM base64 (LE i16 24 kHz mono) is indentical to slice-2's tap PCM wire shape (spec §3.5); decode + re-encode as a PcmFrame so the playout ring stays byte-aligned for slice-2's playout-buffer invariants (samples: 480).
48 KiB
48 KiB