From 474d44c4db534f0133a7189745d100b2b10e352c Mon Sep 17 00:00:00 2001 From: Said Turksever Date: Mon, 19 Oct 2026 16:57:06 +0100 Subject: [PATCH] fix(qa-cctv-v2): report a stalled renderer apart from a missed sibling pick When the sibling-owner pick misses after fewer than 3 rendered frames, the cause is a stalled renderer, not a pick regression. Record it as a failure on the headful sign-off path and as inconclusive under headless GL, with "renderer stalled: N/3 frames" in the detail. A missed pick after 3 frames still fails in both modes. Also corrects the catalog-size comment (~3,700). Co-Authored-By: Claude Opus 5.5 --- scripts/qa-cctv-v2.mjs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/scripts/qa-cctv-v2.mjs b/scripts/qa-cctv-v2.mjs index 9234093be..b291c54f4 100644 --- a/scripts/qa-cctv-v2.mjs +++ b/scripts/qa-cctv-v2.mjs @@ -141,7 +141,7 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); // Every page.waitForFunction / page.evaluate is a single CDP call that // puppeteer aborts after `protocolTimeout` (default 180s). The headful drain -// budget is uncapped and reaches ~50 minutes on the full ~3,900-camera +// budget is uncapped and reaches ~50 minutes on the full ~3,700-camera // catalog, so long waits are polled in slices of at most WAIT_SLICE_MS and // protocolTimeout is set with headroom above the largest slice. const WAIT_SLICE_MS = 120000; @@ -1432,20 +1432,28 @@ async function main() { ), }; }, emptyClickPoint); + const siblingOwnsPick = + siblingTarget?.pickedId === 'qa-cctv-sibling-owner' && + siblingTarget.ownsExactObject; + // A missed pick after fewer than 3 frames means the renderer stalled, not + // that picking regressed: fail it on the real-GPU sign-off path, leave it + // inconclusive under headless GL. + const siblingRendererStalled = + siblingTarget && !siblingOwnsPick && siblingTarget.framesRendered < 3; record( 'sibling test object owns its canvas pick', + !siblingTarget + ? null + : siblingRendererStalled + ? HEADFUL + ? false + : null + : siblingOwnsPick, siblingTarget - ? siblingTarget.pickedId === 'qa-cctv-sibling-owner' && - siblingTarget.ownsExactObject - : null, - siblingTarget - ? `picked=${siblingTarget.pickedId} exactOwner=${siblingTarget.ownsExactObject} projectionΔ=${siblingTarget.projectionDelta} frames=${siblingTarget.framesRendered}/3` + ? `${siblingRendererStalled ? `renderer stalled: ${siblingTarget.framesRendered}/3 frames in 10s; ` : ''}picked=${siblingTarget.pickedId} exactOwner=${siblingTarget.ownsExactObject} projectionΔ=${siblingTarget.projectionDelta} frames=${siblingTarget.framesRendered}/3` : 'no previously verified empty canvas ray was available', ); - if ( - siblingTarget?.pickedId === 'qa-cctv-sibling-owner' && - siblingTarget.ownsExactObject - ) { + if (siblingOwnsPick) { await page.mouse.click(siblingTarget.x, siblingTarget.y); await sleep(250); } @@ -1470,8 +1478,7 @@ async function main() { }); record( 'sibling canvas click passes through without CCTV selection or deselection', - siblingTarget?.pickedId === 'qa-cctv-sibling-owner' && - siblingTarget.ownsExactObject + siblingOwnsPick ? siblingClick.activeId === clickEvidenceSetup.activeId && siblingClick.transitions === siblingClick.baselineTransitions && siblingClick.focusEvents === 0 &&