fix(engine,producer,cli): close review gaps in sub-timeline fail-fast

Address PR #2045 review feedback:
- Share a SubTimelineWaitOutcome type (engine) end-to-end instead of
  widening to string across CapturePerfSummary / RenderPerfSummary /
  telemetry, so the three layers can't drift.
- Dedupe scriptLoadFailures on push — a 4xx response and its trailing
  requestfailed both recorded the same URL, doubling the failed-URL
  list in the fail-fast warning.
- Thread the sub-timeline-wait outcome into render_error (not just
  render_complete): a render that fail-fasts and then fails downstream
  (pollVideosReady, extract, encode) previously dropped this signal on
  the floor. dedupPerfs is now function-scoped so the catch path can
  read it, same treatment as the existing captureAttempts array.
This commit is contained in:
Vance Ingalls
2026-07-08 16:09:47 -07:00
parent 54359f3d6a
commit 8ba3c33915
8 changed files with 79 additions and 31 deletions
+4 -2
View File
@@ -1,8 +1,11 @@
import { redactTelemetryString, type OutputResolutionIssueKind } from "@hyperframes/core";
import type { SubTimelineWaitOutcome } from "@hyperframes/engine";
import { trackEvent } from "./client.js";
import { readConfig } from "./config.js";
export interface RenderObservabilityTelemetryPayload {
/** Worst sub-composition timeline wait outcome across sessions. */
subTimelineWait?: SubTimelineWaitOutcome;
observabilityRenderJobId?: string;
observabilityCompositionHash?: string;
observabilityEventCount?: number;
@@ -47,6 +50,7 @@ export interface RenderObservabilityTelemetryPayload {
function renderObservabilityEventProperties(props: RenderObservabilityTelemetryPayload) {
return {
sub_timeline_wait: props.subTimelineWait,
observability_render_job_id: props.observabilityRenderJobId,
observability_composition_hash: props.observabilityCompositionHash,
observability_event_count: props.observabilityEventCount,
@@ -148,7 +152,6 @@ export function trackRenderComplete(
captureAvgMs?: number;
/** Warmup-robust per-frame capture median (basis for speedup estimates). */
captureP50Ms?: number;
subTimelineWait?: string;
/** <video> element count (speedup segmentation: injection comps read lower). */
videoCount?: number;
capturePeakMs?: number;
@@ -222,7 +225,6 @@ export function trackRenderComplete(
speed_ratio: props.speedRatio,
capture_avg_ms: props.captureAvgMs,
capture_p50_ms: props.captureP50Ms,
sub_timeline_wait: props.subTimelineWait,
video_count: props.videoCount,
capture_peak_ms: props.capturePeakMs,
peak_memory_mb: props.peakMemoryMb,
@@ -58,7 +58,10 @@ export function renderObservabilityTelemetryPayload(
export function renderJobObservabilityTelemetryPayload(
job: RenderJob | undefined,
): RenderObservabilityTelemetryPayload {
return renderObservabilityTelemetryPayload(
job?.errorDetails?.observability ?? job?.perfSummary?.observability,
);
return {
...renderObservabilityTelemetryPayload(
job?.errorDetails?.observability ?? job?.perfSummary?.observability,
),
subTimelineWait: job?.errorDetails?.subTimelineWait ?? job?.perfSummary?.subTimelineWait,
};
}