feat(streams): add WebSocket writer lifecycle (#3833)
## Summary & Motivation Implements the client half of `workflow-stream-ws/v1` behind the existing default-off `WORKFLOW_STREAMS_TRANSPORT=ws` gate, populating the `createWriteSession` seam only when opted in. - Writes and closes are serialized over one socket per writer lifetime; groups above the v1 per-request chunk cap are split without resetting writer-local sequence. - Any failure before the upgrade is accepted (declined upgrade, proxy, load error, a dispatch that beats the handshake) falls back to HTTP for the rest of the writer's life. - Once a write is on the socket, a missing or uncorrelatable reply poisons the session rather than replaying over HTTP, since a duplicate append cannot be ruled out. - Idle clean closes reconnect with the same writer id, capped at three attempts so a draining server can't hot-loop. - The handshake gets a `workflow.stream.ws.connect` span and each frame a synthesized `http POST` span, so per-event tracing survives the non-`fetch` transport. ## Test Plan New unit tests cover the lifecycle, fallback, and poisoning paths; 598 `@workflow/world-vercel` tests plus package build/typecheck and workspace lint/format pass. Root build/typecheck couldn't run locally (missing Rust toolchain for the unrelated `@workflow/swc-plugin`).
A
Alex Langenfeld committed
d4817ce548216a48b155548be5b123483394f37a
Parent: f5aeaa8
Committed by GitHub <noreply@github.com>
on 9/10/2026, 2:21:51 PM