diff --git a/packages/producer/src/services/renderOrchestrator.ts b/packages/producer/src/services/renderOrchestrator.ts index ff9869e3a4..5ec06074e2 100644 --- a/packages/producer/src/services/renderOrchestrator.ts +++ b/packages/producer/src/services/renderOrchestrator.ts @@ -3264,6 +3264,15 @@ async function executeRenderPipeline(input: { usePageSideCompositing: capturePlan.usePageSideCompositing, hasHdrContent: capturePlan.hasHdrContent, forceScreenshot: capturePlan.forceScreenshot, + // Re-recorded here because `syncCapturePlan` above is where routing is + // actually decided — including "reverted", which the earlier update + // could not know. Without this, capture observability keeps whatever + // was true before the plan resolved, so a render that failed while + // routed reports no routing state at all: `de_parallel_router` was + // present on 95% of render_complete events and 0.8% of render_error. + // The failure path is the one the rollout is watching. + deWorkerInversion, + deParallelRouter, }); observability.checkpoint("capture_strategy", "resolved", { plan: capturePlan.kind, diff --git a/packages/producer/src/utils/ffprobeArgvContract.test.ts b/packages/producer/src/utils/ffprobeArgvContract.test.ts index 66d7a4e4e2..a4817f9168 100644 --- a/packages/producer/src/utils/ffprobeArgvContract.test.ts +++ b/packages/producer/src/utils/ffprobeArgvContract.test.ts @@ -173,8 +173,18 @@ function discoverCallers(): { found: string[]; unclassified: string[]; shell: st for (const entry of readdirSync(dir)) { if (SKIP_DIRS.has(entry) || entry.startsWith(".")) continue; const abs = join(dir, entry); - if (statSync(abs).isDirectory()) walk(abs); - else if (isSourceFile(entry)) classify(abs); + // Per-entry, because a single unreadable one used to abort the whole + // traversal: a dangling symlink under packages/studio/data/projects + // threw ENOENT on stat, so every package sorting after `studio` — + // including both studio-server callers — silently stopped being + // checked. Skipping the entry keeps the sweep complete; the manifest + // assertion is what caught the truncation. + try { + if (statSync(abs).isDirectory()) walk(abs); + else if (isSourceFile(entry)) classify(abs); + } catch { + /* unreadable entry (dangling symlink, permissions) — not a caller */ + } } }; for (const root of SWEEP_ROOTS) {