# Provider architecture The web app communicates with the server via WebSocket using a simple JSON-RPC-style protocol: - **Request/Response**: `{ id, method, params }` → `{ id, result }` or `{ id, error }` - **Push events**: typed envelopes with `channel`, `sequence` (monotonic per connection), and channel-specific `data` Push channels: `server.welcome`, `server.configUpdated`, `terminal.event`, `orchestration.domainEvent`. Payloads are schema-validated at the transport boundary (`wsTransport.ts`). Decode failures produce structured `WsDecodeDiagnostic` with `code`, `reason`, and path info. Methods mirror the `NativeApi` interface defined in `@t3tools/contracts`: - `providers.startSession`, `providers.sendTurn`, `providers.interruptTurn` - `providers.respondToRequest`, `providers.stopSession` - `shell.openInEditor`, `server.getConfig` Codex is the only implemented provider. `claudeCode` is reserved in contracts/UI. ## Client transport `wsTransport.ts` manages connection state: `connecting` → `open` → `reconnecting` → `closed` → `disposed`. Outbound requests are queued while disconnected and flushed on reconnect. Inbound pushes are decoded and validated at the boundary, then cached per channel. Subscribers can opt into `replayLatest` to receive the last push on subscribe. ## Server-side orchestration layers Provider runtime events flow through queue-based workers: 1. **ProviderRuntimeIngestion** — consumes provider runtime streams, emits orchestration commands 2. **ProviderCommandReactor** — reacts to orchestration intent events, dispatches provider calls 3. **CheckpointReactor** — captures git checkpoints on turn start/complete, publishes runtime receipts All three use `DrainableWorker` internally and expose `drain()` for deterministic test synchronization.