From 20242515ec103d4fee912fca534260d98f08d6b6 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 11 May 2026 19:03:02 +0000 Subject: [PATCH] refactor(producer): make sequencer the sole writer of job.duration/totalFrames MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The probe stage previously assigned `job.duration` and `job.totalFrames` inside its body AND the sequencer re-asserted them after the call to restore TS narrowing. Two writers for the same field is a maintenance hazard — a future refactor could drop one and create a silent skew. Move ownership: the stage computes `duration` and `totalFrames` and returns them; the sequencer is the sole writer onto the `RenderJob`. This also aligns with the eventual chunk-worker model where a chunk running in a separate process cannot mutate the orchestrator's `job`. No observable behavior change. `job.duration` / `job.totalFrames` end up with the same values; the zero-duration `throw` still happens inside the stage (now using the local `duration` constant) before any sequencer-side assignment. Verified by: - `bun run --filter @hyperframes/producer typecheck` clean - `bun test packages/producer/src/services/` 175 pass / 1 pre-existing unrelated failure on `main` Review feedback addressed: vanceingalls on #719. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../producer/src/services/render/stages/probeStage.ts | 11 ++++++----- packages/producer/src/services/renderOrchestrator.ts | 6 ++---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/packages/producer/src/services/render/stages/probeStage.ts b/packages/producer/src/services/render/stages/probeStage.ts index e1655db55..f3ba06adc 100644 --- a/packages/producer/src/services/render/stages/probeStage.ts +++ b/packages/producer/src/services/render/stages/probeStage.ts @@ -13,8 +13,11 @@ * plan lists recompile as a sibling phase. * - `composition` (videos/audios/duration) is mutated in place — callers * downstream see the reconciled view through the same object reference. - * - `job.duration` and `job.totalFrames` are assigned at the same code - * points. + * - The stage computes the final composition `duration` and `totalFrames` + * and returns them. Assigning those values onto the `RenderJob` is the + * sequencer's responsibility — a future chunk worker can't mutate the + * orchestrator's `job` object, and keeping the assignment in one place + * prevents the same value living in two writers. * - The "Composition duration is 0" diagnostic builds the same hint * string from the same console-buffer regex and `__timelines` probe. * - The post-probe "failed network requests" warning fires with the same @@ -288,10 +291,8 @@ export async function runProbeStage(input: ProbeStageInput): Promise