Files
PaperClipAI/packages
DottaandClaude Opus 5 b73524ec2a feat(runner): stream live Codex turns end to end
The clean-room chat revealed a finished reply instead of writing one: the
live session accumulated agent deltas in its turn waiter, the package
session server awaited the whole turn and answered with one JSON body, and
the browser waited on `response.json()`. Nothing between the provider and
the page could show work in progress, so the board saw the answer appear
all at once.

A turn now streams:

- `Phase7LiveSession` publishes bounded, ordered live turn events and
  mirrors the waiter's assembled text into the transcript entry the reply
  will finally occupy, so one rendered card grows and the settled text is
  still assembled in exactly one place.
- `src/phase7/turn-stream.ts` defines the NDJSON frame codec and reader.
  The decoder refuses a replayed, reordered, oversized, late, or truncated
  frame rather than applying a stale view.
- `POST /api/phase7/ui/message` flushes headers, then writes one frame per
  event-loop tick of provider activity. Admission checks still answer with
  a JSON body and their own status code, because they are decided before
  the first frame. Client disconnect interrupts the provider turn.
- The browser client consumes frames and renders each projection in place;
  the settled payload is applied last and remains the authority. Stop,
  reset, and `New chat` abandon the stream, and frames from an abandoned
  turn generation are dropped.

Measured against real Codex through real runnerd: headers at 265 ms, 62
growing assistant states from the first character to a 301-character reply
at 3.1 s, the last interim state identical to the settled one, and a single
assistant card in the settled thread.

The scenario explorer and every fixture, preset, and replay route are
unchanged and stay deterministic.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 18:29:28 +00:00
..