Files
suaveplan/openspec/archive/2026-05-23-enterprise-react-audio-stream-transport-share/proposal.md
2026-05-27 23:29:53 +01:00

3.4 KiB

@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 — <SharedTransportIndicator> 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/.