Repository navigation
fix: stop three CI flakes from treating clocks as readiness - #861
Merged
Merged
Conversation
The workflow sandbox armed its one-second sync watchdog before the child was listening, so a slow spawn reported a trivial script as timed out. Sidebar drag-click suppression expired after 250ms, so a slow post-drop render let the trailing click toggle the workspace. The composer source-picking test polled for a menu the flushed render had already produced and hit Vitest's suite timeout. Refs #829 Co-authored-by: tt-a1i <tt-a1i@users.noreply.github.com>
tt-a1i
marked this pull request as ready for review
October 16, 2026 06:43
This was referenced Oct 16, 2026
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.
Problem
Required CI on PR #857 failed three times in a row, each time on a different test that the PR does not touch, while recent
mainruns were green. The same class of failure is already tracked in #829.native extension graphs cycle management strips through the composed editor—Script execution timed outafter the workflow tool reported failure in 1s. Runtime Node (Windows parallel 2/2), run 38848560632, job 116804466501. The script wasexport const meta = { name: "navigation workflow" }; return 1;.tests/web/composer-context-navigation.spec.ts— VitestTest timed out in 5000mson the first test. UI ubuntu-latest Node 22.19.0, run 38850034958, job 116809000734. The same run passed on Node 24, Node 26, and Windows.tests/web/session-sidebar.spec.ts— during a project drag,toggleWorkspacewas called once with["/project-1"]. UI windows-latest Node 22.19.0, run 38850838416, job 116811465931. The same file's 43 tests passed on Ubuntu. This is the empty pin-drop flake already noted on Flaky CI tests: session-history E2E anchor, Windows git-info refresh, Windows setup-config lock timeout #829.The same Windows Node job as (1) also failed
a reused PID does not impersonate the dead lock owner(setup-config.test.ts). That case stays on #829; this PR does not change it.Value
These three checks are required for merge. Each failure asks for a rerun of an unrelated PR. The protections stay: a non-yielding workflow script is still killed at 1s, a drag's trailing click still does not toggle a workspace, and a mismatched session path still does not open file reference or replace the draft.
Approach
The three failures share a cause class — a fixed clock used as a readiness signal — but not one implementation. A shared wait helper or a shard-concurrency change would not fix them. No retries, skips, or widened deadlines.
Workflow sandbox (product bug).
SANDBOX_SYNC_TIMEOUT_MS(1s) is the contractual deadline for non-yielding script (while (true) {}). The parent armed that watchdog beforechild.send(init), so process startup was charged against it. On a busy Windows runner, spawningnode --permissionexceeded 1s and a trivial script was reported asScript execution timed out. The child now registers its IPC handler and sends{ kind: "listening" }first. The parent arms the 1s watchdog only then, and only then sendsinit. Exit and spawn errors still finish the run. A child that never listens and never exits waits until the caller aborts, which matches the existing rule that a workflow has no wall-clock deadline. Tests passstartDelayMson that one call (not a process-global hook, becausenode:testcan run tests in a file concurrently). The 1s constant is unchanged.Sidebar trailing click (product bug). Suppression was
Date.now() + 250after drop, andNumber.POSITIVE_INFINITYduring the drag. The contract is: the drag's trailing click (detail !== 0, no new pointerdown) must not toggle; a keyboard click (detail === 0) must; a later pointerdown starts a new gesture and that click must toggle. Under load the post-drop render plus the test'swaitForexceeded 250ms, so the synthetic trailing click was no longer inside the window. Suppression is now a flag set by the drag, consumed by that one click, or cleared by a pointerdown while no drag is active. The 250ms window is removed, not widened. The regression waits 300ms after drop before thedetail: 1click, so the old window fails deterministically.Composer source picking (unstable test). The first test awaited
findByRolefor a file-reference menuitem that the flushedupdate()render already produces. CI spent about 5.5s on that test and died on Vitest's 5s timeout at theit()line, not on Testing Library's ~1sasyncUtilTimeout(TestingLibraryElementError). Later tests in the same file were only about 2× local. A cross-filevi.useFakeTimers()leak did not reproduce with Vitestisolateor--no-isolate. The assertion is nowgetByRoleafterupdate(). A missing menu fails immediately.testTimeoutis unchanged.Validation
Before the product fixes, on this machine:
return 1reject withScript execution timed outat 1005ms (Timeout.<anonymous>insandbox.ts).fireEvent.clickwithdetail: 1, failed withtoggleWorkspacecalled once with["/project-1"](same assertion as job 116811465931).After the fixes:
node --test --experimental-strip-types tests/extensions/workflows/sandbox.test.ts— 36 passed.return 1withstartDelayMs: 1500resolved in 1561ms.while (true) {}with the same delay and an 8s test abort rejected/Script execution timed out/in 2549ms (startup plus the 1s deadline, notWorkflow was aborted). The existing undelayedwhile (true) {}tests still failed the script at about 1030ms.session-sidebar.spec.tsandcomposer-context-navigation.spec.ts— 57 passed. The pin-drop test, including the 300ms gap, passed in 628ms.bun run checkpassed (config, docs, discipline, web build, format, lint, typecheck).bun run test— Node 2642 tests, 2633 passed, 0 failed, 9 skipped; UI 98 files, 1520 passed. This VM's global git config setscore.fsmonitorandcore.untrackedCache. With those on,tests/web/session-worktree.test.ts("forks source HEAD detached…") fails in isolation at the source-index byte compare, becausegit worktree addrewrites the index with FSMN/UNTR extensions. That assertion passes when those two settings are off, which is how the full run above was executed. The test is not part of this change. The composer 5s stall was not reproduced locally (findByRolereturned in about 21ms here).CI on
20a7b98completed with no failed checks. Required workflow run 38861005953: every job succeeded, including the three jobs that failed on #857 (Windows parallel 2/2, UI ubuntu Node 22.19.0, UI windows Node 22.19.0). Not merged.Other flakes, not changed here
From #829 and
mainreruns since the #831 flake fix (10 completed, non-cancelledmainCI runs through 38847154103):setup-configreused-PID lock timeout (same job as failure 1 above; diagnosed, not fixed).tests/web/workbar-session-position.spec.ts— missingREADME.mdbutton. UI windows-latest, run 38764433340 (failed three attempts, then green).tests/web/openpi-web.e2e.ts—Response has been disposed. Web E2E shard 1/2, run 38774705615.tests/extensions/ai-providers/antigravity.test.ts— first SSE event vs lifetime timers. Windows parallel 1/2, run 38776735793 attempt 1.In that 10-run window, 4 runs were not green on the first attempt (3 later succeeded after rerun, 1 stayed red: 38736671833, UI windows). Across the last 100
mainCI runs, 76 were not cancelled; 7 of those went green only after a rerun (~9%), and 6 stayed red. Primary failures were Windows UI, Windows Node, and one Web E2E shard. The "Require all test jobs" / "Background terminals (Windows)" failures in those runs are gate steps that fail because a dependency failed. Finalmainsuccess hides those reruns. This sample is small and mixed with real failures, so it is an estimate of the gate, not a rate to target.A shared wait helper is not warranted: the clocks live in Node IPC, pointer events, and a React assertion. Lowering shard concurrency would not correct a watchdog that starts too early or a click window that is the wrong signal.
Impact
startDelayMsis a test option onrunWorkflowSandbox, not a model tool.listeningand never exits is no longer misreported as a script timeout at 1s; cancellation and process exit still end the run.web/dist/app.jsmatches the sidebar change. The 1s script deadline and the drag/keyboard/new-gesture click contract are covered by regression tests.