Evaluate the ROOT fix for the component-test effect-ordering class: IS_REACT_ACT_ENVIRONMENT = true (a ~30-file act() migration)
Why this exists
Carved out of MOTIR-1737, which shipped option (a) of its three-way decision — the nightly component-effect-audit lane that DETECTS the effect-ordering race — and explicitly deferred option (b), the root fix that REMOVES the class. Logged as its own card rather than left as prose in a merged PR body (the orphaned-deferral rule: a seam owned by "the later story" orphans).
The condition
vitest.config.ts never sets IS_REACT_ACT_ENVIRONMENT, and React Testing Library deliberately turns the act environment OFF for findBy* / waitFor, draining with a bare zero-delay timer. React flushes passive effects on a separate scheduler callback, so an awaited findBy* can resolve with effects still pending: the render landed, the effect did not. Any non-retrying assertion downstream of an effect is then a load-dependent flake. Three instances found so far — MOTIR-1736 (ProjectRoadmapCanvas) plus the two fixed in MOTIR-1737 (OnboardingCanvasRoadmap, TierDocModal).
Setting IS_REACT_ACT_ENVIRONMENT = true in a setup file makes RTL flush effects deterministically, which ends the class outright. It was NOT done in MOTIR-1737 because it is a migration of its own: it surfaces act() warnings across roughly 30 files, each needing its render/interaction wrapped, and bundling that into a one-file race fix would have been an unreviewable diff.
What to do
- Set
IS_REACT_ACT_ENVIRONMENT = truein a happy-dom-scoped setup file and measure the real blast radius (how many files warn, how many fail). - If the blast radius is tractable, migrate the warning files and land it; if it is not, record WHY in this card and close it — the nightly lane remains the standing control either way.
- Whatever the outcome, reconcile the two: with the root fix in place the audit lane becomes redundant and should be retired (
.github/workflows/component-effect-audit.yml,vitest.late-effects.config.ts,tests/helpers/lateEffects.ts, thetest:late-effectsscript, and theCLAUDE.mdsubsection that documents them) rather than left running as dead weight. - Option (c) from MOTIR-1737 — a lint rule banning a bare
expect(<mock>)in a file that also awaitsfindBy*— is NOT part of this card and is not planned: it is a lossy proxy for what (a) already checks exactly.
Acceptance criteria
- The blast radius of
IS_REACT_ACT_ENVIRONMENT = trueis MEASURED and stated (file count, failure count), not estimated. - Either the migration lands with the whole happy-dom suite green, or the card records a concrete reason it was rejected.
- If it lands, the audit lane and its three files are retired in the same PR — no orphaned instrument.
- No production component change; this is test infrastructure only.