Skip to content

Fast-capture: fallback-ratio guard for #3423 x #3429 seam (100%-fallback renders pass artifact validation) #3482

Description

@miga-heygen

Context

PR #3480 (branch fix/draw-element-canvas-fallback, closes #3423) added a
per-frame screenshot fallback for the drawElement fast-capture path: when
drawElementImage throws a recoverable error (canvas not initialized, or
the native "No cached paint record" InvalidStateError), the affected frame
falls back to Page.captureScreenshot instead of hard-failing the render.

Review feedback on #3480 (from tai) flagged a seam with PR #3429's artifact
validation (ArtifactTransaction.validate() /
packages/producer/src/services/render/artifactTransaction.ts):

If a composition is 100% broken and every frame falls back to screenshot
capture, the render passes #3429's artifact validation (correct frame
count, correct duration) but ships N wrong-pixel frames as "complete."

To be precise about the actual risk: the screenshot fallback itself produces
correct pixels (it's the platform's normal, well-tested capture path) —
the real risk is a silent, total loss of the fast-capture speedup (and by
extension a masked persistent bug, e.g. a canvas-injection regression)
going completely unnoticed because the render still "succeeds" with the
right frame count/duration. Today nothing distinguishes "recovered a
handful of edge-case frames" from "drawElement never engaged for the whole
render" in either telemetry or artifact validation.

What #3480 does today

getCapturePerfSummary() in packages/engine/src/services/frameCapture.ts
now emits a console.warn when deNcprFallbacks / frames exceeds 50%, so
the condition is at least visible in render logs / telemetry ingestion.
This is a diagnostic only — it does not fail or flag the render artifact.

Follow-up needed (pick one, or combine)

  1. Fallback-ratio circuit breaker (engine or producer-side): if the
    realized deNcprFallbacks / frames ratio exceeds some threshold (e.g.
    50%), fail the render explicitly instead of shipping it as "complete" —
    forcing a re-render with forceScreenshot (which the orchestrator already
    knows how to do for DrawElementVerificationError) rather than silently
    accepting a render that never got the fast-capture speedup.
  2. deNcprFallbacks/frames guard on the fix(producer): assert render artifact duration and frame count before commit #3429 side: thread the ratio
    (already available via CapturePerfSummary.deNcprFallbacks /
    RenderPerfSummary) into ArtifactTransaction.validate() or the
    orchestrator's post-render checks, so artifact validation can distinguish
    "correct frame count via drawElement" from "correct frame count via
    total fallback."
  3. At minimum: promote the current warn-only diagnostic into a structured
    CaptureWarning / render-telemetry field so it's queryable across the
    fleet, not just visible in ad hoc log scraping.

Pointers

  • packages/engine/src/services/frameCapture.ts: getCapturePerfSummary
    (ratio warning), captureFrameCore / captureFrameToBufferPipelined /
    captureFramesBatchPipelined (the three per-frame/batch fallback sites),
    CaptureSession.deNcprFallbacks.
  • packages/engine/src/services/drawElementService.ts:
    DE_CANVAS_NOT_INITIALIZED_CODE, produceDrawElementFrameBatch.
  • packages/producer/src/services/render/artifactTransaction.ts:
    ArtifactTransaction.validate() (current frame-count/duration-blind
    validation).

Filed from PR #3480 review discussion (reviewer: tai).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions