# Tasks: enterprise-react-iphone **Change ID**: enterprise-react-iphone **Package**: `@suaveplan/react-iphone` **Target path**: `react/ui/react-iphone` **Prerequisite packages on Verdaccio**: `@suaveplan/error`, `@suaveplan/events`, `@suaveplan/logger`, `@suaveplan/react-translate`, `@suaveplan/react-ui` --- ## 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 If any worktrees exist under `.claude/worktrees/`, account for each one: still-active agent, work-pending-merge, or stale-and-prune. Stale worktrees MUST be removed (`git worktree remove`) before opening a new one — code that has been lost twice on main is the failure mode this guards against. - [ ] 0.3 Confirm the package set in `MANIFEST.md` matches `find packages -maxdepth 3 -name package.json` count. Drift here means a prior change archived without regenerating the manifest. ## 1. Scaffold - [ ] Create directory tree per proposal layout. - [ ] Write `package.json` at `0.1.0` with `"sideEffects": false`, exports map. - [ ] Dependencies: `@suaveplan/error workspace:^`, `@suaveplan/events workspace:^`, `@suaveplan/logger workspace:^`, `@suaveplan/react-translate workspace:^`, `@suaveplan/react-ui workspace:^`, `zod catalog:forms`, `@opentelemetry/api catalog:observability`, `tslib catalog:build`. - [ ] Write `tsconfig.json`, `vitest.config.ts`, scripts. --- ## 2. Error codes and types - [ ] Define `CallError` extending `SuaveplanError`; codes: `CALL_SIGNALING_FAILED`, `CALL_WEBRTC_FAILED`, `CALL_MANAGER_NOT_INITIALIZED`. - [ ] Define public types: `CallState`, `CallDirection`, `CallInfo`, `SignalingMessage`, `WebRTCConfig`, `HookExecutionMode`, `ConnectionQuality`, `IceState`, `SignalingState`. --- ## 3. Services ### CallManager - [ ] Basic call state machine: `idle → ringing → active → ended`. `startCall()`, `acceptCall()`, `rejectCall()`, `endCall()`. Emits events via `@suaveplan/events`. OTel spans for each transition. - [ ] Write test + md. ### CallManagerEnhanced - [ ] Extends `CallManager` with `connectionQuality` (derived from ICE stats — not hardcoded), `iceState`, `signalingState` — all real implementations. - [ ] Write test + md. ### CallManagerWebRTC - [ ] Wraps `WebRTCProvider`, wires ICE + SDP negotiation into `CallManager` state machine. - [ ] Write test (mock `RTCPeerConnection` via DI) + md. ### HookManager - [ ] Sync + async hook pipeline (`HookExecutionMode`). `register(hook)`, `execute(event): Promise`. - [ ] Write test + md. ### SignalingClient + SignalingChannelAdapter - [ ] WebSocket-backed signaling; `connect()`, `disconnect()`, `send(message)`, `onMessage(handler)`. - [ ] Throws `CallError(CALL_SIGNALING_FAILED)` on connection failure. - [ ] Write test (real WebSocket via `@suaveplan/testing` mock server or real WS) + md. ### WebRTCProvider - [ ] Manages `RTCPeerConnection`; `createOffer()`, `setRemoteDescription()`, `addIceCandidate()`. - [ ] Throws `CallError(CALL_WEBRTC_FAILED)` on failure. - [ ] Write test (DI-injected `RTCPeerConnection` constructor) + md. ### PhoneStateSerializer + ServerStateManager - [ ] `PhoneStateSerializer` — serializes/deserializes call state for server snapshot sync. - [ ] `ServerStateManager` — manages server-side state deltas. - [ ] Write test + md for each. --- ## 4. Hooks - [ ] `useCallManager` — wraps `CallManager` events via `useSyncExternalStore`, returns call state + actions. - [ ] `useCallTimer` — elapsed-time counter (seconds) while `callState === 'active'`. - [ ] Write tests + stories (playground for each) + md. --- ## 5. Components For each screen (`IncomingCallScreen`, `OutgoingCallScreen`, `ActiveCallScreen`, `EndedCallScreen`): - [ ] Implement with i18n via `useTranslation`. OTel span on mount. - [ ] Write test + stories (default, loading/connecting, error, playground) + md. For video components (`VideoStreamRenderer`, `AudioOnlyContainer`, `CallVideoContainer`): - [ ] Write test + stories + md. For `CallButton` + icons: - [ ] Write test + stories + md. --- ## 6. E2E - [ ] `e2e/call-flow.spec.ts` — Playwright with injected mock `WebRTCProvider` + `SignalingClient`: - Render `IncomingCallScreen`, click accept → `ActiveCallScreen` shown. - Render `ActiveCallScreen`, click end → `EndedCallScreen` shown. - Timer increments during active call. --- ## 7. Verify and publish - [ ] `bunx turbo lint typecheck test --filter=@suaveplan/react-iphone` — green. - [ ] `bunx turbo test:coverage --filter=@suaveplan/react-iphone` — 100%. - [ ] `bun scripts/publish.ts --package @suaveplan/react-iphone`. - [ ] Archive change folder.