diff --git a/scripts/lib/render-smoke.test.mjs b/scripts/lib/render-smoke.test.mjs index a77b5468b..64d4a7a37 100644 --- a/scripts/lib/render-smoke.test.mjs +++ b/scripts/lib/render-smoke.test.mjs @@ -93,10 +93,33 @@ test("a paint landing just under the deadline is not failed by the render timer" `setTimeout(() => { console.log(${JSON.stringify(MARKER)}); ` + `setInterval(() => {}, 1000); }, ${paintAt});`, ), - // Deliberately tight: the render deadline expires while the survival window - // is still open, which is the whole shape of the bug. - timeoutMs: paintAt + 150, - surviveMs: 400, + // The shape being reproduced is an overlap, and only an overlap: + // + // actual paint < timeoutMs < actual paint + surviveMs + // + // i.e. the render deadline expires while the survival window is still + // open. Both margins are deliberately wide, because the two clocks start + // at different moments: `paintAt` is measured from the child's first JS + // tick, while `renderTimer` is armed in the parent at spawn. The left + // margin therefore has to absorb everything in between — child process + // startup, plus whatever scheduling delay the machine is under. + // + // `stub()` spawns `process.execPath` directly, so there is no `script(1)` + // in this path: the PTY wrapper lives in `smoke-tui.mjs`, the caller. Node + // boot alone measured 46-59ms idle here. That fits the old `paintAt + 150` + // budget with room to spare, which is exactly why this read as a flake + // rather than a bug — but under the load of a full `local:gate` run the + // remaining ~90ms of slack is not enough to cover scheduling delay on both + // the child's boot and the parent's timer, and it failed three gate runs + // in a row while passing every time standalone (#2177). The diagnostic it + // failed with, "did not render", is the misreport this test exists to + // catch. + // + // Do not tighten these back up to make the test faster: the overlap is the + // point, not the tightness. 1200ms clears any plausible paint time, and + // still falls inside a survival window that cannot close before ~1750ms. + timeoutMs: 1200, + surviveMs: 1500, }); assert.equal(r.code, 0, `expected pass, got: ${r.message}`); assert.doesNotMatch(r.message, /did not render/);