Found while running npm run local:gate repeatedly on #2264 (PR #2322), a branch touching zero files under clients/.
What happens
Two files in the web unit project fail intermittently, always with Error: Test timed out in 5000ms. — never with a failed assertion:
clients/web/src/components/screens/SkillsScreen/SkillsScreen.test.tsx
clients/web/src/test/core/mcp/skillsVerification.test.ts
Both are #2248 surfaces. Observed across five gate runs on the same branch:
| Run |
Result |
| 1 |
green |
| 2 |
red — 1 timeout (SkillsScreen > "offers Up only below the skill root, and returns to it") |
| 3 |
green |
| 4 |
red — 5 timeouts (2 in SkillsScreen, 3 in skillsVerification) |
| 5 |
green |
Why it is load, not the branch
- The branch changes five markdown/tooling files and nothing under
clients/ — git diff origin/v2/main...HEAD --name-only on v2/chore/2264-testing-handoff.
- Re-running both files in isolation passes 156/156.
- In the red run,
SkillsScreen.test.tsx took 91382ms for 111 tests; alone it takes ~48s. The suite was starved, and a 5s per-test cap is what turned that into a failure.
Why it is worth fixing rather than re-running
This is the same class as the Storybook-project-had-no-testTimeout finding: a per-test cap inherited from vitest's 5000ms default, on tests whose work is real enough to exceed it when the machine is busy. It is green on an idle machine and red on a loaded one, which means it fails in CI as a function of runner contention rather than of the code — and it trains people to re-run a red gate instead of reading it, which is exactly what the gate exists to prevent.
Suggested direction
Not asserted as the fix — whoever takes this should measure first:
- Find out what actually takes the time. If a single
waitFor in these files is doing real polling work, the honest fix may be a longer testTimeout for the unit project, or a per-test timeout on the specific cases.
- If instead the tests are waiting on something that should be deterministic (an accordion panel, a listing read), the fix is to remove the wait rather than extend the budget.
WARNING: Do not close this by raising a waitFor timeout alone — a waitFor is capped by the project testTimeout, so raising only the inner wait changes nothing.
Acceptance
- The cause is identified as one of the two above, and said explicitly in the fix.
- Twenty consecutive
unit project runs of both files, with the machine deliberately loaded, are green.
🤖 Generated with Claude Code
https://claude.ai/code/session_018zwYWanPhvgu6wiKoeGg4N
Found while running
npm run local:gaterepeatedly on #2264 (PR #2322), a branch touching zero files underclients/.What happens
Two files in the web
unitproject fail intermittently, always withError: Test timed out in 5000ms.— never with a failed assertion:clients/web/src/components/screens/SkillsScreen/SkillsScreen.test.tsxclients/web/src/test/core/mcp/skillsVerification.test.tsBoth are #2248 surfaces. Observed across five gate runs on the same branch:
SkillsScreen> "offers Up only below the skill root, and returns to it")SkillsScreen, 3 inskillsVerification)Why it is load, not the branch
clients/—git diff origin/v2/main...HEAD --name-onlyonv2/chore/2264-testing-handoff.SkillsScreen.test.tsxtook 91382ms for 111 tests; alone it takes ~48s. The suite was starved, and a 5s per-test cap is what turned that into a failure.Why it is worth fixing rather than re-running
This is the same class as the Storybook-project-had-no-testTimeout finding: a per-test cap inherited from vitest's 5000ms default, on tests whose work is real enough to exceed it when the machine is busy. It is green on an idle machine and red on a loaded one, which means it fails in CI as a function of runner contention rather than of the code — and it trains people to re-run a red gate instead of reading it, which is exactly what the gate exists to prevent.
Suggested direction
Not asserted as the fix — whoever takes this should measure first:
waitForin these files is doing real polling work, the honest fix may be a longertestTimeoutfor theunitproject, or a per-test timeout on the specific cases.WARNING: Do not close this by raising a
waitFortimeout alone — awaitForis capped by the projecttestTimeout, so raising only the inner wait changes nothing.Acceptance
unitproject runs of both files, with the machine deliberately loaded, are green.🤖 Generated with Claude Code
https://claude.ai/code/session_018zwYWanPhvgu6wiKoeGg4N