Skip to content

webviews test: the minimap preview's delay is read from when the card first shows (base flake) - #23323

Merged
teamleaderleo merged 2 commits into
feat-cmux-nextfrom
scroll-jitter-2/hover-intent-cards
Oct 21, 2026
Merged

teamleaderleo merged 2 commits into
feat-cmux-nextfrom
scroll-jitter-2/hover-intent-cards

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

CI (head a75ef8f): PASS test/hover-intent-cards.test.tsx. The other reds are base: settings/categories.test.ts and agent-pane-scrollbar-full-height (untouched), and the browser-lanes guard on gallery-agent-pane-entries.test.ts (fixed by #23325). The independent review passed.

The flake: in test/hover-intent-cards.test.tsx, "the minimap's turn preview waits its delay, then follows the pointer at once until the rail cools" failed in 2 of the 16 feat-cmux-next runs that ran the webview shards (2026-10-21), at its first check: await wait(200); expect(visible()).toBe(false) received true.

Cause (test, not the rail): the card's delay is 250 ms (CARD_DELAY, threadMinimap/model.ts). It was up only because a loaded runner woke the 200 ms real-timer wait late. Timers only ever fire late, so the check measured the runner, not the delay.

Fix: the case reads when the card first shows, in 10 ms steps. Each step is its own act, so React draws between them; a single long act defers the DOM update to its end. It asserts that this is at least 200 ms after the pointer came, and that the card shows by 850 ms (the old 200 + 650). A step can only end late, so a slow runner can't fail it.

It still catches the bug (mutation check, local):

CARD_DELAY result
0 ms fails (seen at 17 ms)
110 ms (the old delay) fails (seen at 126 ms)
180 ms fails (seen at 190 ms)
250 ms (shipped) passes, 5 of 5 runs

The warm and cool checks between the two delayed shows are unchanged. #23092's owner confirmed this file is mine to fix and that #23092 doesn't touch it.

Agent session: cmux16

🤖 Generated with Claude Code

…d first shows

"the minimap's turn preview waits its delay ..." failed in 2 of 16 base runs at its first
check: still hidden after wait(200). The card's delay is 250 ms (CARD_DELAY), so the card
was up only because a loaded runner woke the 200 ms wait late. The case now reads, in
10 ms steps (each its own act, so React draws between them), when the card first shows,
and asserts that is at least 200 ms after the pointer came. A step only ends late, so a
slow runner never fails it; with CARD_DELAY at 0, 110 or 180 ms it fails (seen at 17,
126 and 190 ms), and passes at 250 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15d18-f5e3-77e3-a3e6-159012f35d5f&host=cmux16
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by scroll-jitter-2 on cmux16 · session

@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Review 034956c: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr23323 -f ref=scroll-jitter-2/hover-intent-cards -f platform=macos -f backend_mode=local

Unclear: web / react-apps-check failed: no known signature; failed step: Check webview test shards. This PR merged before its CI finished: fix forward on main.

CI failed on 034956c4a7 (run 39591353047 attempt 1): 3 code, 1 unknown.

Job Verdict Why
web / react-apps-check (2) code a web test failed
web / react-apps-check (1) code a web test failed
web / react-apps-check (3) code a web test failed
web / react-apps-check unknown no known signature; failed step: Check webview test shards

Failures:

  • seen on other PRs chiefsCard.test.tsx Chiefs lists every Chief: picture, name, role, backend and lock: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row names the backend the way Home and the Chief editor do, never by its raw id: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row shows a chosen model even when no harness is named: failed (job)
  • seen on other PRs chiefsCard.test.tsx a row opens the same editor as Home, and Save goes through the host's relay: failed (job)
  • seen on other PRs chiefsCard.test.tsx New Chief opens the editor empty; Back returns to the list: failed (job)
  • seen on other PRs agent-pane-scrollbar-full-height.test.ts a composer that grows and shrinks leaves the rows a reader reads where they were on every frame: failed (job)
  • seen on other PRs agent-pane-scrollbar-full-height.test.ts a composer that grows and shrinks keeps a followed view at its end on every frame: failed (job)
  • seen on other PRs chiefPetCard.test.tsx the page shows None and every character, None chosen while the pet is off: failed (job)
  • seen on other PRs chiefPetCard.test.tsx picking a character shows the pet with it; None hides it: failed (job)
  • seen on other PRs chiefPetCard.test.tsx Show Pet and Hide Pet turn the pet on and off with its character kept: failed (job)
  • ... 3 more in the job logs
Matched log lines
web / react-apps-check (2): (fail) Chiefs lists every Chief: picture, name, role, backend and lock [380.85ms]
web / react-apps-check (1): (fail) the page shows None and every character, None chosen while the pet is off [512.47ms]
web / react-apps-check (3): (fail) the categories are the approved ones, in order [0.40ms]

Not re-run automatically: web / react-apps-check (2), web / react-apps-check (1), web / react-apps-check (3), web / react-apps-check are not machine failures.

Written by scripts/ci/classify_failures.py (ci-failure-attribution.yml); signatures are its SIGNATURES table. A machine verdict is the runner's fault, not this PR's; yours means the failing file is one this PR changes, also red on main that main's latest full suite fails the same way, seen on other PRs that it failed on another pull request's run lately.

red: web / Web status; NEW: green on the base b7afd18; do not merge until green; see lane-rules
red: web / react-apps-check; no finished base run on b7afd18 to compare; do not merge until green; see lane-rules
red: web / react-apps-check (1); no finished base run on b7afd18 to compare; do not merge until green; see lane-rules
red: web / react-apps-check (2); no finished base run on b7afd18 to compare; do not merge until green; see lane-rules
red: web / react-apps-check (3); no finished base run on b7afd18 to compare; do not merge until green; see lane-rules

CI fast guards failed on a75ef8fd41 (https://github.com/manaflow-ai/cmux/actions/runs/39589797849). It does not block the merge; a red guard merged into main breaks it for every open PR.
The log named no failed step; see the run.

Agents: python3 scripts/ci/guard_attribution.py fix applies the mechanical fixes locally.

Tour of 034956c4a7 (run): no media. The tour did not run: only webview code changed (1 path(s)), which the gallery advisory run checks in Linux Chromium on the pull request (its artifact holds any captures); add the media-tour-mac label to tour it on a Mac.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-gfd7e created for this PR by the cmux coordinator.

@blacksmith-sh

blacksmith-sh Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Found 8 test failures on Blacksmith runners:

Failures

Test View Logs
src/pages/settings/categories.test.ts/categories.test View Logs
src/pages/settings/categories.test.ts/categories.test View Logs
src/pages/settings/chiefPetCard.test.tsx/chiefPetCard.test.tsx View Logs
src/pages/settings/chiefPetCard.test.tsx/chiefPetCard.test.tsx View Logs
src/pages/settings/chiefsCard.test.tsx/chiefsCard.test.tsx View Logs
src/pages/settings/chiefsCard.test.tsx/chiefsCard.test.tsx View Logs
test/agent-pane-scrollbar-full-height.test.ts/agent-pane-scrollbar-full-height.test View Logs
test/agent-pane-scrollbar-full-height.test.ts/agent-pane-scrollbar-full-height.test View Logs

Fix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

@teamleaderleo
teamleaderleo merged commit 4c5ed9a into feat-cmux-next Oct 21, 2026
@teamleaderleo
teamleaderleo deleted the scroll-jitter-2/hover-intent-cards branch October 21, 2026 11:21
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
* test(webviews): a fixed-wait check names fixed waits and honors a reasoned marker

Fails until scripts/check-fixed-waits.ts exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: a ratchet refuses new fixed-time waits in tests

check:fixed-waits (in `bun run check`) names each test wait for a fixed number
of ms: page.waitForTimeout, Bun.sleep, a setTimeout that resolves a promise
after a non-zero delay, and calls to a local helper built on one. A fixed wait
passes on an idle machine and fails on a loaded runner that wakes it late, or
hides the bug it waits out (#23323). A test waits for a condition instead, uses
fake timers when the timing is the behavior, or keeps the wait with a
`// fixed-wait: <reason>` comment.

The 398 waits from before the rule have per-file counts in
scripts/fixed-waits-baseline.tsv. A file fails with more unmarked waits than
its row, and with fewer until the row is lowered (--update-baseline), so the
count only moves down; the sweep PRs lower it. pageSwitch's 16 ms
no-requestAnimationFrame fallback keeps its wait with a reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): the fixed-wait check counts helper uses, block-body timers and exported helpers

Fails on the first detector: a helper with no delay parameter counted only at
its definition, a helper passed as a value (act(settle)) not at all, a timer
callback with a block body was missed, and so was an exported helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: the fixed-wait check counts every use of a sleep helper

From review. A wait inside a named function makes it a helper, and each use
counts instead of the definition: a call, or the helper passed or returned as a
value (act(settle), return { open }), applied outward through helpers built on
helpers. So another `await settle()` in a file raises its count. A helper whose
delay parameter defaults to 0 waits only when a use passes a delay. An exported
helper also counts at its definition, since its callers are in other files.

Also caught: timer callbacks with a block body that resolve the promise,
window/globalThis.setTimeout and Bun.sleepSync. A marker counts anywhere in the
wait's statement, or on a comment-only line above it, so a trailing marker no
longer covers the next line. The scan covers every source under test/
(harnesses, latency helpers), not just *.test files, and skips fixtures. A
malformed baseline row now fails instead of passing as NaN.

The baseline is regenerated: 819 waits in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): a new wait inside an existing helper must raise the fixed-wait count

Review of #23365 found that a second wait or helper call added inside a
function that already waits was not counted. These cases fail on the
current detector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* fix(webviews): count every fixed wait and every helper use, inside helpers too

A wait counted only through the outer uses of its enclosing helper, so a new
wait or helper call inside a helper that already waited changed nothing. Now
each unmarked wait site counts, and each use of a helper outside its own
body, so any new wait raises the count. Waits in exported helpers count at
the site, which replaces the export rule. Export lists, typeof and member
declaration names are no longer uses. The baseline is regenerated: 989 waits
in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* ci(web): run the fixed-wait ratchet in the feat-cmux-next warn branch

Under CMUX_NEXT_STYLE_GUARDS=warn the webviews-check step runs bun run check as
separate commands, so check:fixed-waits never ran there. It fails the step,
like check:browser-lanes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…23415)

* test(webviews): a fixed-wait check names fixed waits and honors a reasoned marker

Fails until scripts/check-fixed-waits.ts exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: a ratchet refuses new fixed-time waits in tests

check:fixed-waits (in `bun run check`) names each test wait for a fixed number
of ms: page.waitForTimeout, Bun.sleep, a setTimeout that resolves a promise
after a non-zero delay, and calls to a local helper built on one. A fixed wait
passes on an idle machine and fails on a loaded runner that wakes it late, or
hides the bug it waits out (#23323). A test waits for a condition instead, uses
fake timers when the timing is the behavior, or keeps the wait with a
`// fixed-wait: <reason>` comment.

The 398 waits from before the rule have per-file counts in
scripts/fixed-waits-baseline.tsv. A file fails with more unmarked waits than
its row, and with fewer until the row is lowered (--update-baseline), so the
count only moves down; the sweep PRs lower it. pageSwitch's 16 ms
no-requestAnimationFrame fallback keeps its wait with a reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): the fixed-wait check counts helper uses, block-body timers and exported helpers

Fails on the first detector: a helper with no delay parameter counted only at
its definition, a helper passed as a value (act(settle)) not at all, a timer
callback with a block body was missed, and so was an exported helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: the fixed-wait check counts every use of a sleep helper

From review. A wait inside a named function makes it a helper, and each use
counts instead of the definition: a call, or the helper passed or returned as a
value (act(settle), return { open }), applied outward through helpers built on
helpers. So another `await settle()` in a file raises its count. A helper whose
delay parameter defaults to 0 waits only when a use passes a delay. An exported
helper also counts at its definition, since its callers are in other files.

Also caught: timer callbacks with a block body that resolve the promise,
window/globalThis.setTimeout and Bun.sleepSync. A marker counts anywhere in the
wait's statement, or on a comment-only line above it, so a trailing marker no
longer covers the next line. The scan covers every source under test/
(harnesses, latency helpers), not just *.test files, and skips fixtures. A
malformed baseline row now fails instead of passing as NaN.

The baseline is regenerated: 819 waits in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): a new wait inside an existing helper must raise the fixed-wait count

Review of #23365 found that a second wait or helper call added inside a
function that already waits was not counted. These cases fail on the
current detector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* fix(webviews): count every fixed wait and every helper use, inside helpers too

A wait counted only through the outer uses of its enclosing helper, so a new
wait or helper call inside a helper that already waited changed nothing. Now
each unmarked wait site counts, and each use of a helper outside its own
body, so any new wait raises the count. Waits in exported helpers count at
the site, which replaces the export rule. Export lists, typeof and member
declaration names are no longer uses. The baseline is regenerated: 989 waits
in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): U2 waits for conditions, not fixed times

The 19 U2 unit-test files had 142 fixed waits under the stricter
detector; none are left and their baseline rows are gone.

- Timing under test runs on bun's fake timers: the new tab's picked-name
  fade, the summary card's running-time tick, the kept-attachments rest
  timer, the transcript's anchor settle, the tooltip's scroll quiet time
  (now also checked inside the quiet window) and the link bubble's
  no-hover-card check.
- Polls that already waited on a condition (render card, dropped chips,
  KaTeX, prompt accepted) yield a macrotask per try instead of sleeping.
- The image viewer's actions wait for the host request (or the refusal
  label); the changelog pages wait for their release to draw.
- Menu and composer settle() helpers and PreviewCard's teardown yield
  one macrotask: act() flushes the rest, and the 20 ms were slack.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): yield a task before the no-bubble and one-request asserts

The hover test now lets promises and a later task run before it asserts
no bubble, and the image viewer waits one more task so a duplicate
request would show.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): mark the two 3 s frame-watch windows as fixed waits

#23374 merged after the fixed-wait ratchet (#23365) ran CI, and it added a
3 s waitForTimeout in two tests, which puts feat-cmux-next over its baseline.
Both waits are observation windows: the test records every painted frame for
3 s after the chat opens and asserts none jumped, so the time is the test.
They carry a fixed-wait marker instead of a raised baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): lower the fixed-wait baseline after the base merge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…23416)

* test(webviews): a fixed-wait check names fixed waits and honors a reasoned marker

Fails until scripts/check-fixed-waits.ts exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: a ratchet refuses new fixed-time waits in tests

check:fixed-waits (in `bun run check`) names each test wait for a fixed number
of ms: page.waitForTimeout, Bun.sleep, a setTimeout that resolves a promise
after a non-zero delay, and calls to a local helper built on one. A fixed wait
passes on an idle machine and fails on a loaded runner that wakes it late, or
hides the bug it waits out (#23323). A test waits for a condition instead, uses
fake timers when the timing is the behavior, or keeps the wait with a
`// fixed-wait: <reason>` comment.

The 398 waits from before the rule have per-file counts in
scripts/fixed-waits-baseline.tsv. A file fails with more unmarked waits than
its row, and with fewer until the row is lowered (--update-baseline), so the
count only moves down; the sweep PRs lower it. pageSwitch's 16 ms
no-requestAnimationFrame fallback keeps its wait with a reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): the fixed-wait check counts helper uses, block-body timers and exported helpers

Fails on the first detector: a helper with no delay parameter counted only at
its definition, a helper passed as a value (act(settle)) not at all, a timer
callback with a block body was missed, and so was an exported helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: the fixed-wait check counts every use of a sleep helper

From review. A wait inside a named function makes it a helper, and each use
counts instead of the definition: a call, or the helper passed or returned as a
value (act(settle), return { open }), applied outward through helpers built on
helpers. So another `await settle()` in a file raises its count. A helper whose
delay parameter defaults to 0 waits only when a use passes a delay. An exported
helper also counts at its definition, since its callers are in other files.

Also caught: timer callbacks with a block body that resolve the promise,
window/globalThis.setTimeout and Bun.sleepSync. A marker counts anywhere in the
wait's statement, or on a comment-only line above it, so a trailing marker no
longer covers the next line. The scan covers every source under test/
(harnesses, latency helpers), not just *.test files, and skips fixtures. A
malformed baseline row now fails instead of passing as NaN.

The baseline is regenerated: 819 waits in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): a new wait inside an existing helper must raise the fixed-wait count

Review of #23365 found that a second wait or helper call added inside a
function that already waits was not counted. These cases fail on the
current detector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* fix(webviews): count every fixed wait and every helper use, inside helpers too

A wait counted only through the outer uses of its enclosing helper, so a new
wait or helper call inside a helper that already waited changed nothing. Now
each unmarked wait site counts, and each use of a helper outside its own
body, so any new wait raises the count. Waits in exported helpers count at
the site, which replaces the export rule. Export lists, typeof and member
declaration names are no longer uses. The baseline is regenerated: 989 waits
in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): U1 waits for conditions, not fixed times

Removes the fixed sleeps from the U1 batch's 20 unit-test files.

- Hover and dwell delays (session hover card, sidebar preview, minimap turn
  preview, URL chip grace, settings backdrop and theme dwell, scroll anchor
  settle, warm New Tab post, prompt delivery deadlines) run on bun:test's fake
  timers: each test checks the behavior is absent one tick before its delay and
  present at it, so a slow runner cannot change the result.
- Async results (shell reads, sign-in polls, client reconnects and resyncs,
  pasted image chips, KaTeX and diagram rendering, the code-card handoff,
  changelog and settings host calls, menu picks) are awaited with bounded
  `until` loops that yield with setTimeout 0 and fail naming what they waited for.
- The settings claim-paint test counts calls and stream events in flight and
  waits until all are delivered, rather than waiting 300 ms.
- The reveal frame helper in transcript-switch-back is left for the shared
  post-paint frame helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): mark the two 3 s frame-watch windows as fixed waits

#23374 merged after the fixed-wait ratchet (#23365) ran CI, and it added a
3 s waitForTimeout in two tests, which puts feat-cmux-next over its baseline.
Both waits are observation windows: the test records every painted frame for
3 s after the chat opens and asserts none jumped, so the time is the test.
They carry a fixed-wait marker instead of a raised baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): lower the fixed-wait baseline after the base merge

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
teamleaderleo added a commit that referenced this pull request Oct 21, 2026
…23462)

* test(webviews): a fixed-wait check names fixed waits and honors a reasoned marker

Fails until scripts/check-fixed-waits.ts exists.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: a ratchet refuses new fixed-time waits in tests

check:fixed-waits (in `bun run check`) names each test wait for a fixed number
of ms: page.waitForTimeout, Bun.sleep, a setTimeout that resolves a promise
after a non-zero delay, and calls to a local helper built on one. A fixed wait
passes on an idle machine and fails on a loaded runner that wakes it late, or
hides the bug it waits out (#23323). A test waits for a condition instead, uses
fake timers when the timing is the behavior, or keeps the wait with a
`// fixed-wait: <reason>` comment.

The 398 waits from before the rule have per-file counts in
scripts/fixed-waits-baseline.tsv. A file fails with more unmarked waits than
its row, and with fewer until the row is lowered (--update-baseline), so the
count only moves down; the sweep PRs lower it. pageSwitch's 16 ms
no-requestAnimationFrame fallback keeps its wait with a reason.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): the fixed-wait check counts helper uses, block-body timers and exported helpers

Fails on the first detector: a helper with no delay parameter counted only at
its definition, a helper passed as a value (act(settle)) not at all, a timer
callback with a block body was missed, and so was an exported helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* webviews: the fixed-wait check counts every use of a sleep helper

From review. A wait inside a named function makes it a helper, and each use
counts instead of the definition: a call, or the helper passed or returned as a
value (act(settle), return { open }), applied outward through helpers built on
helpers. So another `await settle()` in a file raises its count. A helper whose
delay parameter defaults to 0 waits only when a use passes a delay. An exported
helper also counts at its definition, since its callers are in other files.

Also caught: timer callbacks with a block body that resolve the promise,
window/globalThis.setTimeout and Bun.sleepSync. A marker counts anywhere in the
wait's statement, or on a comment-only line above it, so a trailing marker no
longer covers the next line. The scan covers every source under test/
(harnesses, latency helpers), not just *.test files, and skips fixtures. A
malformed baseline row now fails instead of passing as NaN.

The baseline is regenerated: 819 waits in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): a new wait inside an existing helper must raise the fixed-wait count

Review of #23365 found that a second wait or helper call added inside a
function that already waits was not counted. These cases fail on the
current detector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* fix(webviews): count every fixed wait and every helper use, inside helpers too

A wait counted only through the outer uses of its enclosing helper, so a new
wait or helper call inside a helper that already waited changed nothing. Now
each unmarked wait site counts, and each use of a helper outside its own
body, so any new wait raises the count. Waits in exported helpers count at
the site, which replaces the export rule. Export lists, typeof and member
declaration names are no longer uses. The baseline is regenerated: 989 waits
in 132 files.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* ci(web): run the fixed-wait ratchet in the feat-cmux-next warn branch

Under CMUX_NEXT_STYLE_GUARDS=warn the webviews-check step runs bun run check as
separate commands, so check:fixed-waits never ran there. It fails the step,
like check:browser-lanes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): mark the two 3 s frame-watch windows as fixed waits

#23374 merged after the fixed-wait ratchet (#23365) ran CI, and it added a
3 s waitForTimeout in two tests, which puts feat-cmux-next over its baseline.
Both waits are observation windows: the test records every painted frame for
3 s after the chat opens and asserts none jumped, so the time is the test.
They carry a fixed-wait marker instead of a raised baseline.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): B1 waits for conditions, not fixed times

Browser tests in batch B1 wait for the state they then assert instead of
sleeping: waitForFunction on focus, results, visibility and editor text
(ui-a11y, editor-csp, wheel pass-through, subagent groups), the daemon's
own signals (a background request heard or answered, a call heard, the
first prompt, the trust check) instead of sleep-polling, the chat list's
websocket frame and the stand-in host's pending answers (New Tab first
frame and composer), the parked page's claim hook and the dev server's
listen line (settings open frames), finished finite animations before
measuring an open menu, and the img error event after the inline
handler would have run (locale). "Nothing happens" checks get a positive
signal first: a console marker after the key for Ctrl-B, the pane's own
Escape listener for the question card. The hover check in ui-a11y runs
the page's clock past the delay instead of the wall clock. Waits whose
delay is the scenario (late daemon and host answers, the moving layout
in chat-find) and the no-hint check carry fixed-wait markers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

* test(webviews): B1 frame waits on the shared painted-frame helper

The question card's arrival wait and New Tab list motion's "first rows
settle" wait now use window.cmuxPaintFrame (test/support/paintedFrames),
the latter followed by the rows' finite animations finishing. The inline
double requestAnimationFrame waits added in the first commit move to the
same helper. Baseline regenerated on the merged base.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a15c78-27ca-7140-a6c7-95f0db83b18c&host=huge-blue

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant