test(scripts): anchor the render-smoke overlap paint to the parent's clock - #2181
Merged
cliffhall merged 1 commit intoAug 28, 2026
Conversation
There was a problem hiding this comment.
Pull request overview
Stabilizes the render-smoke overlap regression test by aligning child paint timing with the parent clock.
Changes:
- Uses an absolute paint target to absorb child startup delay.
- Explicitly verifies the deadline falls within the survival window.
- Reduces test runtime while preserving mutation coverage.
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
3 tasks
…clock The case reproduces an overlap — the render deadline expiring while the survival window is still open — and it had to buy that overlap with a startup allowance. `paintAt` is measured from the child's first JS tick while `renderTimer` is armed in the parent at spawn, so a plain `setTimeout(paint, N)` lands at `N + startup` and the deadline has to cover whatever startup turns out to be. #2177 widened that allowance (150ms to 950ms), which moves the threshold rather than removing it: the case still fails, as "did not render", on any machine loaded enough to blow the new number. The child is now told the wall-clock instant to paint at and sleeps for whatever is left of it on arrival, so startup is absorbed by the sleep instead of added to it and the paint lands at ~300ms from spawn however slow the boot was. `timeoutMs: 600` / `surviveMs: 900` then satisfies the right-hand side of the overlap for ANY paint time including 0, so a boot slow enough to swallow the anchor entirely still reproduces the shape rather than degrading into a different case. The one startup assumption left is that boot completes before the deadline at all, an order of magnitude over the 46-59ms measured idle here. Passing is no longer taken as evidence on its own: the verdict's first-paint time is read back and the overlap asserted, so a paint landing early enough to put the deadline outside the survival window fails loudly instead of passing while testing nothing. Verified by mutation — removing the `clearTimeout(renderTimer)` this case guards fails it at 607ms, i.e. the timer still fires inside the survival window. Verified under load — 8/8 with 16 busy loops pinning all 8 cores. Runtime drops from ~1.75s to ~1.2s. Closes #2180 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev Signed-off-by: cliffhall <cliff@futurescale.com>
cliffhall
force-pushed
the
v2/fix/2180-render-smoke-startup-independent
branch
from
August 28, 2026 03:51
b912308 to
2e4e76a
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #2180
scripts/lib/render-smoke.test.mjs→ "a paint landing just under the deadline is not failed by the render timer" buys the overlap it tests with a startup allowance, and that is what makes it flake.Why widening didn't settle it
paintAtis measured from the child's first JS tick;renderTimeris armed in the parent, at spawn. So a plainsetTimeout(paint, N)lands atN + startup, andtimeoutMshas to cover whatever startup turns out to be:#2178 widened that allowance from 150ms to 950ms. That moves the threshold rather than removing it — the case still fails, as
did not render, on any machine loaded enough to blow the new number. Which is precisely the misdiagnosis this test exists to catch, and precisely what #2180 asked to stop depending on.The fix
Anchor the paint to the parent's clock. The child is told the wall-clock instant to paint at and sleeps for whatever is left of it when it gets there:
Startup is now absorbed by the sleep instead of added to it, so the paint lands at ~300ms measured from spawn however slow the boot was.
The constants then close the remaining gap. The shape under test is an overlap, and only an overlap:
timeoutMs: 600/surviveMs: 900satisfies the right-hand side for any paint time, including 0 — so a boot slow enough to swallow the anchor entirely still reproduces the overlap rather than degrading into some other case. The one startup assumption left is that boot completes before the deadline at all, an order of magnitude over the 46-59ms measured idle here.It can no longer pass vacuously
A widened timing test can go green while testing nothing, so passing is not taken as evidence on its own. The first-paint time is read back out of the verdict and the overlap asserted:
A paint landing early enough to put the deadline outside the survival window now fails loudly instead of passing.
Verification
Mutation. Removing the
clearTimeout(renderTimer)on first paint (render-smoke.mjs:267) — the line this case guards:It fails at 607ms, i.e. the render timer still fires inside the survival window. Restored, 15/15 pass.
Under load. 8 consecutive runs with 16 busy loops pinning all 8 cores: 8/8 pass. (The old fixture is what failed three gate runs in a row on a far lighter machine.)
Gate.
npm run local:gategreen end to end.Cost. Runtime drops, ~1.75s → ~1.2s.
Acceptance criteria
forbidOutput, the exit-before-paint case, the survival assertions) — untouched, 15/15🤖 Generated with Claude Code
https://claude.ai/code/session_013hzwzS8UvBsr4yZm7o7sev