## ADDED Requirements ### Requirement: Channel-based streaming reducer The streaming layer SHALL dispatch WS frames into typed channels (`text`, `tool_call`, `tool_result`, `status`, `error`) instead of a flat `applyFrame` pattern match. Each channel SHALL produce deltas independently but merge into a single `StreamState` via a deterministic ordering function. #### Scenario: Text delta dispatched to text channel - **WHEN** a `delta` frame with `content` arrives - **THEN** the text channel accumulates the chunk and the merged state appends it to the target message's content #### Scenario: Tool call dispatched to tool_call channel - **WHEN** a `tool_call` frame with a `tool_call` object arrives - **THEN** the tool_call channel pushes it to `message.tool_calls` on the target message id ### Requirement: Mid-stream reconnection without snapshot The hook SHALL support mid-stream reconnection by replaying missed deltas per-channel, using a monotonic `seq` counter on each frame. If the server cannot replay, a full `snapshot` frame SHALL be used as fallback. #### Scenario: Reconnection with missed deltas - **WHEN** the WebSocket reconnects during an active stream - **THEN** the client sends the last processed `seq` per-channel and the server replays missed deltas - **AND** if replay is unavailable, the server sends a `snapshot` frame and the reducer resets to that state ### Requirement: Out-of-order frame buffering The reducer SHALL buffer out-of-order frames per-channel and flush them only when the sequence number is contiguous from the last known value. #### Scenario: Frame arrives out of order - **WHEN** a frame with `seq=5` arrives before `seq=4` for the same channel - **THEN** the reducer holds `seq=5` in a per-channel buffer - **AND** when `seq=4` arrives, both frames SHALL be applied in order ### Requirement: Channel frame schema in ws-frames The `@boocode/contracts` ws-frames schema SHALL define typed channel delta frames with a `seq` field, a `channel` discriminator, and channel-specific payloads. #### Scenario: Channel frame validates correctly - **WHEN** a channel delta frame matches the schema - **THEN** `WsFrameSchema.safeParse` returns success