Files
hyperframes/packages
JamesandClaude Opus 4.7 ba90b411ed refactor(producer): extract captureStreamingStage (single-machine fusion)
Move the streaming encode fusion path (`useStreamingEncode === true` with
successful encoder spawn) out of `executeRenderJob` into
`services/render/stages/captureStreamingStage.ts`. The stage owns:

- `spawnStreamingEncoder` invocation, including the abort-rethrow vs.
  graceful-fallback handling.
- Parallel + sequential capture-to-stdin loops (Stage 4 absorbs Stage 5
  for streaming renders).
- The streaming encoder's `close()` + result check.
- Defensive cleanup of the streaming encoder in the stage's own
  `try/finally`.

The stage returns either `{ success: true, ... }` (sequencer skips the
disk path AND inline Stage 5) or `{ success: false }` (sequencer falls
back to the disk path). The sequencer's `useStreamingEncode` flag is
no longer flipped imperatively — the result type makes the branch
selection explicit.

Hard constraints preserved verbatim:
- `probeSession` is closed at the same code points (parallel: after
  capture; sequential: in session finally). The local binding nulls
  via the returned result.
- `lastBrowserConsole` is set to the buffer of whichever session was
  active last (probe close path or sequential session finally).
- `job.framesRendered` is updated per-frame; `Streaming frame N/M
  [(K workers)]` `updateJobStatus` payloads fire at the same 30-frame
  and completion checkpoints (parallel) or every frame (sequential),
  with the same percentage math `25 + frameProgress * 55`.
- `Streaming encode failed: <err>` still throws on the encoder's
  `success: false` close result.
- The defensive `try/finally` close-on-throw is preserved, now inside
  the stage instead of the orchestrator.
- `perfStages.captureMs` is still set by the sequencer from
  `stage4Start`; the stage also returns `encodeMs` for the encoder's
  overlapped duration (assigned to `perfStages.encodeMs`).

Removes the orphaned `createFrameReorderBuffer` and
`prepareCaptureSessionForReuse` imports from the orchestrator after
the streaming code moved.

Verified inside `Dockerfile.test`:
- 5/5 fixtures PASS (font-variant-numeric, many-cuts, variables-prod,
  sub-composition-video, gsap-letters-render-compat).
- `gsap-letters-render-compat` (single-worker render, 4s duration)
  exercises the new streaming stage end-to-end —
  `streaming-encode gate enabled=true` confirmed in the log.
- The other 4 fixtures exercise the disk path (workerCount > 1).

Known follow-up: same runtime import cycle situation as captureStage —
the stage imports `updateJobStatus` and types from
`renderOrchestrator.ts`, which imports the stage back. Safe (deferred
to runtime); a future PR will flatten this once all 8 stages are
extracted.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 01:15:03 +00:00
..
2026-05-10 18:34:43 +00:00
2026-05-10 18:34:43 +00:00