Code-review findings from the slice-2 final whole-branch review:
- tap_client.rs: close arm sends session_end (not bye) per §5.2, awaits
brain bye with bounded 500ms timeout, then ws.close(). Promotes the
Task-7-documented Minor to Important's required spec compliance.
- session_map.rs: AppState::close() now clears channel.tap = None before
Closing->Closed, sends close signal, bounded-awaits engine task for the
teardown handshake (500ms cap), aborts as fallback. Per §5.1 step 5.
- pcm.rs + tap_audio_pipe.rs: AudioPipe trait gains clear_playout_ring()
(default no-op for EchoAudioPipe); TapAudioPipe clears the VecDeque.
RtcSession::clear_playout_ring delegates. Per §5.3 step 4 playout-on-
disconnect-flush contract.
- tap_engine.rs: spawn_tap_engine creates + shares a flush_tx mpsc
channel; run_engine_loop signals flush after each failed pump loop
(before backoff); TapConn.flush_rx is drained by drive_all_sessions
to call RtcSession::clear_playout_ring.
- tests/tap_integration.rs: new reconnect-path test asserts Channel
stays Connected, metrics.reconnect_attempts increments, playout
returns None during outage, playout resumes after EchoServer
restart with fresh frames (no stale bleed-through). Per §8.4.
- static/index.html: one static line acknowledging external-brain
routing per §7.2 (defer real-time tap status to step-3 GUI).
Spec ref: 2026-06-28-slice-2-agent-tap-design.md §5.1 step 5, §5.2, §5.3 step 4, §7.2, §8.4.