← back to Crazy News Channel
chaos-screenrecord: fix chaosFF-concluded's coverage gap on the standby flash
f58b710bc72aa6f7a1f38866a0a5d753b7d40704 · 2026-09-24 09:18:27 -0700 · Steve Abrams
Two bugs in the same step, both confirmed by direct repro against the
live app with a fake clock:
1. The 12x25s=300s virtual-time cap was sized for the app's old 6s stage
interval. Once MIN_STAGE_INTERVAL_SEC (a separate fix) raised the
effective floor to 75s, a full escalation needs 4 advances x 75s =
300s ALONE, leaving zero room for any story's offsetSec — and in
run-orderings where this step executes before tier1/2/3 (e.g. run1's
reversed order), elapsedSec is still ~0 when it starts, so the loop
fell a few seconds short and PLEASE STAND BY was never reached.
2. Even with enough virtual time, the standby flash is only visible for
~2900ms of app-time before its own auto-hide timer fires. Sampling at
25s chunk boundaries meant the entire visible window could open and
close inside a single chunk and never get observed — verified
empirically: with (1) fixed alone, allConcluded reliably went true but
caught stayed false.
Fix: read MIN_STAGE_INTERVAL_SEC live from the page instead of
re-hardcoding a number that can drift out of sync with the app, size the
loop off it with headroom, and sample every 1s (well under the flash's
visible window) instead of every 25s. Verified end-to-end against the
exact worst-case ordering (elapsedSec~3 at loop start): caught=true,
allConcluded=true, ~0.8-3.5s real wall-clock overhead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yVgDG93UFMN6sNbRaUfzd
Files touched
M scripts/chaos-screenrecord.js
Diff
commit f58b710bc72aa6f7a1f38866a0a5d753b7d40704
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Sep 24 09:18:27 2026 -0700
chaos-screenrecord: fix chaosFF-concluded's coverage gap on the standby flash
Two bugs in the same step, both confirmed by direct repro against the
live app with a fake clock:
1. The 12x25s=300s virtual-time cap was sized for the app's old 6s stage
interval. Once MIN_STAGE_INTERVAL_SEC (a separate fix) raised the
effective floor to 75s, a full escalation needs 4 advances x 75s =
300s ALONE, leaving zero room for any story's offsetSec — and in
run-orderings where this step executes before tier1/2/3 (e.g. run1's
reversed order), elapsedSec is still ~0 when it starts, so the loop
fell a few seconds short and PLEASE STAND BY was never reached.
2. Even with enough virtual time, the standby flash is only visible for
~2900ms of app-time before its own auto-hide timer fires. Sampling at
25s chunk boundaries meant the entire visible window could open and
close inside a single chunk and never get observed — verified
empirically: with (1) fixed alone, allConcluded reliably went true but
caught stayed false.
Fix: read MIN_STAGE_INTERVAL_SEC live from the page instead of
re-hardcoding a number that can drift out of sync with the app, size the
loop off it with headroom, and sample every 1s (well under the flash's
visible window) instead of every 25s. Verified end-to-end against the
exact worst-case ordering (elapsedSec~3 at loop start): caught=true,
allConcluded=true, ~0.8-3.5s real wall-clock overhead.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019yVgDG93UFMN6sNbRaUfzd
---
scripts/chaos-screenrecord.js | 44 ++++++++++++++++++++++++++++++++++++++++---
1 file changed, 41 insertions(+), 3 deletions(-)
diff --git a/scripts/chaos-screenrecord.js b/scripts/chaos-screenrecord.js
index 0f6f45e..feba56a 100644
--- a/scripts/chaos-screenrecord.js
+++ b/scripts/chaos-screenrecord.js
@@ -318,11 +318,37 @@ function buildCatalog() {
async fn(page) { await page.clock.runFor(150 * 1000); },
});
steps.push({
- id: 'chaosFF-concluded', label: 'advance clock in 25s chunks via runFor to drive ALL stories to concluded (chaos=100, PLEASE STAND BY) — pauses on REAL wall-clock once flash is caught mid-flight so the recording actually shows it', kind: 'chaos',
+ id: 'chaosFF-concluded', label: 'advance clock in 1s chunks (sized off the live stage-interval floor) via runFor to drive ALL stories to concluded (chaos=100, PLEASE STAND BY) — pauses on REAL wall-clock once flash is caught mid-flight so the recording actually shows it', kind: 'chaos',
async fn(page, ctx) {
+ // Two independent gaps in the old hardcoded "12 x 25s" version, both
+ // confirmed by direct repro against the live app:
+ // 1. How much virtual time is actually NEEDED depends on the app's
+ // own per-story stage-interval floor (MIN_STAGE_INTERVAL_SEC) and
+ // how much elapsedSec already accumulated before this step ran
+ // (run-order dependent — e.g. run1's reversed order runs this
+ // BEFORE tier1/2/3, so elapsedSec can still be ~0 here). The old
+ // 300s-total cap was sized for the app's prior 6s interval and
+ // fell short once the floor was raised to 75s (5 stages = 4
+ // advances = 300s alone, zero room for any story's offsetSec).
+ // Read the real floor live from the page rather than re-hardcode
+ // a number that can silently drift out of sync with the app.
+ // 2. Even once enough virtual time IS offered, the standby flash is
+ // only visible for ~2900ms of app-time (its own auto-hide
+ // timer) before disappearing again — chunking runFor() in 25s
+ // jumps and checking only at each chunk boundary means the
+ // entire visible window can open and close INSIDE one 25s jump
+ // and never get sampled. Verified empirically: with (1) fixed
+ // alone, allConcluded reliably hit true but caught stayed false.
+ // Sampling every 1s (well under the 2900ms window) instead of
+ // every 25s fixes this; the extra evaluate() calls cost well
+ // under a second of real wall-clock time (verified ~0.8s total).
+ const minInterval = await page.evaluate(() =>
+ (typeof MIN_STAGE_INTERVAL_SEC === 'number' ? MIN_STAGE_INTERVAL_SEC : 0));
+ const neededVirtualSec = minInterval * 4 + 60; // 4 stage advances + headroom for offsetSec/prior elapsed
+ const chunks = Math.max(300, neededVirtualSec); // 1s granularity
let caught = false;
- for (let i = 0; i < 12 && !caught; i++) {
- await page.clock.runFor(25 * 1000);
+ for (let i = 0; i < chunks && !caught; i++) {
+ await page.clock.runFor(1 * 1000);
const flashing = await page.evaluate(() => {
const el = document.getElementById('standbyFlash');
return !el.hidden && el.classList.contains('flashing');
@@ -336,7 +362,19 @@ function buildCatalog() {
await page.waitForTimeout(1200);
}
}
+ // Record whether the flash was actually caught vs merely "the loop
+ // ran out" — a silent miss here is exactly the coverage regression
+ // this fix targets, so make it visible in the log instead of letting
+ // ok:true paper over an unconcluded run.
+ const allConcluded = await page.evaluate(() =>
+ document.querySelectorAll('#storyGrid .story-card').length > 0 &&
+ document.querySelectorAll('#storyGrid .story-card.concluded').length ===
+ document.querySelectorAll('#storyGrid .story-card').length);
ctx.standbyCaughtVisible = caught;
+ ctx.allConcludedAtEnd = allConcluded;
+ if (!caught) {
+ console.warn(`[chaos-screenrecord] run${ctx.run}: chaosFF-concluded finished ${chunks}s virtual WITHOUT catching the standby flash (allConcluded=${allConcluded}) — coverage gap, not just a quiet miss`);
+ }
},
});
steps.push({
← 1ce86db Fix Chaos Index reading ~51% on fresh load — exclude single-
·
back to Crazy News Channel
·
Stop tracking Playwright screen-recording video output; igno 3a5ce94 →