Out-of-scope finding surfaced while fixing MOTIR-1736 (the ProjectRoadmapCanvas auto-reset flake). Logged per notes.html mistake #27 rather than absorbed into that PR, whose scope was one file.
vitest.config.ts never sets IS_REACT_ACT_ENVIRONMENT, and RTL's async wrapper deliberately turns the act environment OFF for findBy* / waitFor, draining with a bare setTimeout(0). React flushes passive effects on a separate scheduler callback (setImmediate under Node). So in EVERY component test, an awaited findBy* can resolve with pending passive effects — the render landed, the effect did not. Any non-retrying assertion that depends on an effect is then a load-dependent flake. MOTIR-1736 was one instance; nothing structurally confines it to that file.
Flipping the scheduler ordering makes the latent race deterministic, with no added delay (so it does not create false "too slow" failures):
// tests/helpers/__auditLateEffects.ts (setupFiles, via a throwaway config)
const real = globalThis.setImmediate;
globalThis.setImmediate = (fn, ...args) => real(() => setTimeout(() => fn(...args), 0));
Run over all 150 component test files (1270 tests), this reproduced MOTIR-1736's exact CI failure pre-fix, passed it post-fix, and flagged two other genuine failures:
tests/components/OnboardingCanvasRoadmap.test.tsx — "shows a 'Your plan' preview at the top level and drills into the epic roots"tests/components/TierDocModal.test.tsx — "fetches the pre-plan and renders the tier doc (DirectionDocView) for the clicked tier" (fails as Unable to find an element with the text: /building an internal tool for a small team/i — the effect-driven fetch/render never lands within the query budget)Excluded as instrument artifacts, do not chase: appearance-sync.test.tsx (5 tests) uses vi.useFakeTimers(), so the shim's real setTimeout never fires — artifact, not a race. An earlier 8 ms-delay variant of the shim also flagged sprint-points-refetch.test.tsx and delete-work-item-dialog.test.tsx; both pass at zero delay, so they were "slowed past the 1 s findBy budget", not ordering races. The zero-delay form is the trustworthy instrument — start from it.
waitFor, and flush with await act(async () => {}) before any negative assertion. Confirm each fails pre-fix and passes post-fix under the zero-delay shim.IS_REACT_ACT_ENVIRONMENT = true in a setup file so RTL flushes effects deterministically — the root fix, but it surfaces act() warnings across ~30 files and is its own migration; (c) a lint rule banning a bare expect(<mock>) assertion in a test file that also awaits findBy*. Recommend (a) now, and evaluate (b) as a follow-up — (b) removes the whole class rather than detecting it.motir-core/CLAUDE.md § E2E tests wait on the AUTHORITATIVE signal gained a component-test bullet in the MOTIR-1736 PR.