# @suaveplan/react-audio-stream — transport-share + auto-reconnect (chunk D) - **Target path**: `packages/ui/react/react-audio-stream/` - **Tier**: browser/react - **Date**: 2026-05-23 - **Status**: PROPOSED — chunk D of the 4-chunk `enterprise-react-audio-stream` split. Final chunk; archives the parent change folder. ## Why Transport-share (the "watch the DJ play" scenario) and auto-reconnect both compose the session-core, transports, and hooks-components chunks. They land last because they need every earlier piece in place. This chunk also performs the spec fold and archive of the parent `enterprise-react-audio-stream` folder. ## What changes 1. **Transport-share control channel** — `src/transport-share/control-channel.ts` defines the wire protocol (`'play'`, `'pause'`, `'seek'`, `'setTempo'` envelopes) and the per-session `TransportShareCoordinator` that listens to the granting peer's local `Transport` and forwards events to receivers. 2. **Share state machine** — `src/transport-share/share-state.ts` tracks `'local' | 'driving' | 'receiving'`; transitions via `requestTransportShare(peerId)` / `grantTransportShare()` / driver-disconnect signal. 3. **`useTransportShare()`** — `src/hooks/use-transport-share/use-transport-share.ts` exposes the state + grant/request methods to React. 4. **Shared-transport indicator** — `` component renders "Shared transport active" when in receiving mode; controls dispatched while receiving no-op without throwing. 5. **Auto-reconnect** — `src/session/reconnect.ts` wires `@suaveplan/retry`-driven exponential back-off (base 1 s, multiplier 2, jitter ±20%, max 30 s, capped at `maxReconnectAttempts` default 8) into the `StreamSession` lifecycle. Only `network` and `signalling` interruption classes trigger reconnect; `media-permission`, `peer`, and explicit `disconnect()` skip. 6. **Reconnect events** — `'reconnect-attempt'` (with attempt number), `'reconnect-failed'` (after exhaustion). Counters `react_audio_stream_reconnect_attempt_total` / `react_audio_stream_reconnect_failed_total` increment per event (instruments registered in chunk A). 7. **Playwright E2E** — `tests/e2e/transport-share.spec.ts` runs two real browser instances against a local signalling-channel fixture and asserts share-mode propagation. Marked browser-tier; runs only under the e2e turbo pipeline. 8. **Spec fold + archive** — final task in this chunk: - Fold `openspec/changes/enterprise-react-audio-stream/specs/react-audio-stream/spec.md` into `openspec/specs/react-audio-stream/spec.md` (the canonical version). - Move `openspec/changes/enterprise-react-audio-stream/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream/`. - Also move the four split change folders (`enterprise-react-audio-stream-{session-core,transports,hooks-components,transport-share}/`) to the archive alongside it. - Regenerate `MANIFEST.md`. ## Requirements landed by this chunk From the original spec: - Auto-reconnect with exponential back-off (full) - Transport-share mode (full) ## Impact - ~15 files (control channel + share state + 1 hook + 1 component + reconnect + E2E). - Imports `StreamSession`, `InterruptionClassifier`, `ReactAudioStreamError` from chunk A; `useStreamSession` from chunk C. - Final chunk — runs full package gate (`lint typecheck test:coverage` at 100/100/100/100), folds canonical spec, archives all 5 change folders (parent + 4 splits) into `openspec/archive/`.