Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
# @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/`.

View File

@@ -0,0 +1,66 @@
# Tasks — enterprise-react-audio-stream-transport-share (chunk D, final)
## 0. Pre-flight (non-negotiable)
- [ ] 0.1 Confirm clean working tree (`git status` reports nothing) and no in-flight worktrees with uncommitted work (`git worktree list` then `git status` in each)
- [ ] 0.2 Account for every `.claude/worktrees/*` entry; prune stale ones via `bun scripts/worktree-prune.ts --remove`.
- [ ] 0.3 Confirm `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json | wc -l`.
## 1. Transport-share control channel
- [ ] 1.1 `src/transport-share/control-channel.ts` — wire protocol envelopes (`play`/`pause`/`seek`/`setTempo`), per-session coordinator
- [ ] 1.2 `.types.ts`, `.test.ts`, `.md`, `index.ts`
## 2. Share state machine
- [ ] 2.1 `src/transport-share/share-state.ts` — `local | driving | receiving` transitions
- [ ] 2.2 `.types.ts`, `.test.ts`, `.md`, `index.ts`
## 3. useTransportShare hook
- [ ] 3.1 `src/hooks/use-transport-share/use-transport-share.ts`
- [ ] 3.2 `.types.ts`, `.test.tsx`, `.md`, `index.ts`
- [ ] 3.3 Tests cover: play-on-driver-advances-receivers, driver-disconnect-returns-share-to-local, receiver-controls-no-op
## 4. SharedTransportIndicator component
- [ ] 4.1 `src/components/shared-transport-indicator/shared-transport-indicator.tsx`
- [ ] 4.2 `.types.ts`, `.test.tsx`, `.stories.tsx`, `.md`, `index.ts`
## 5. Auto-reconnect
- [ ] 5.1 `src/session/reconnect.ts` — `@suaveplan/retry` integration, only on `network`/`signalling` classes
- [ ] 5.2 `.test.ts`, `.md`
- [ ] 5.3 Wire `'reconnect-attempt'` and `'reconnect-failed'` events into `StreamSession`
- [ ] 5.4 Increment counters registered in chunk A
## 6. Subpath exports
- [ ] 6.1 Add `./transport-share`, `./hooks/use-transport-share`, `./components/shared-transport-indicator` to `package.json` exports
## 7. Playwright E2E
- [ ] 7.1 `tests/e2e/transport-share.spec.ts` — two browsers, local signalling fixture
- [ ] 7.2 Marked `.spec.ts` (Playwright); runs under e2e turbo pipeline only
## 8. Full-package gate
- [ ] 8.1 `bunx turbo lint typecheck test --filter=@suaveplan/react-audio-stream` — green across ALL chunks (A+B+C+D merged)
- [ ] 8.2 `bunx turbo test:coverage --filter=@suaveplan/react-audio-stream` — 100/100/100/100 on every file
- [ ] 8.3 `bunx turbo build --filter=@suaveplan/react-audio-stream` — green; purity test asserts no audio-context references in `dist/`
- [ ] 8.4 `docs:check` — every implementation `.ts`/`.tsx` has a sibling `.md` with the 6 sections
## 9. Spec fold + archive
- [ ] 9.1 Fold the canonical spec into `openspec/specs/react-audio-stream/spec.md` (single document with all 9 Requirements from the original)
- [ ] 9.2 Move `openspec/changes/enterprise-react-audio-stream/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream/`
- [ ] 9.3 Move `openspec/changes/enterprise-react-audio-stream-session-core/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream-session-core/`
- [ ] 9.4 Move `openspec/changes/enterprise-react-audio-stream-transports/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream-transports/`
- [ ] 9.5 Move `openspec/changes/enterprise-react-audio-stream-hooks-components/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream-hooks-components/`
- [ ] 9.6 Move `openspec/changes/enterprise-react-audio-stream-transport-share/` → `openspec/archive/2026-05-23-enterprise-react-audio-stream-transport-share/`
- [ ] 9.7 `bun scripts/folder-reorg/generate-manifest.ts` to refresh `MANIFEST.md`
- [ ] 9.8 Prune the worktree (`bun scripts/worktree-prune.ts --remove`)
## 10. Hand-off
- [ ] 10.1 Commit on `feat/react-audio-stream-transport-share`. No push.