Skip to content

fix(rule): preserve lifecycle synchronization semantics - #1579

Merged
aidenybai merged 6 commits into
mainfrom
codex/fix-react-bench-pr-488-false-positives
Aug 5, 2026
Merged

fix(rule): preserve lifecycle synchronization semantics#1579
aidenybai merged 6 commits into
mainfrom
codex/fix-react-bench-pr-488-false-positives

Conversation

@aidenybai

@aidenybai aidenybai commented Aug 5, 2026

Copy link
Copy Markdown
Member

Why

React Bench PR #488 excluded six React Doctor rules after 193 of 198 adjudicated occurrences proved to be false positives. The remaining detector gaps still reported valid controlled-state fallbacks, owned-resource transitions, and prop-originated lifecycle synchronization; five genuine reset-state findings must remain reportable.

Before, 54 confirmed false-positive occurrences still reported. After, all 193 confirmed false positives are silent and the five named true positives still report at their exact locations.

What changed

  • prove synchronous owned-resource release and identity invalidation before suppressing reset-state diagnostics
  • recognize bounded controlled-state dependency selections whose fresh fallback is unreachable
  • preserve prop provenance through immutable memoizers, transparent transforms, refs, and global JSON round trips without accepting child-owned state
  • require equivalent local state writes for state-driven lifecycle callback synchronization
  • retain state ownership for memoizer-named custom hooks that create React state
  • add focused rule regressions, deterministic multi-rule fuzz verdicts, corpus fixtures, and a patch changeset

Eval results

The self-contained React Bench PR #488 runner processed 166 full-source examples and 198 diagnostic occurrences with zero parse failures. It matched all intended outcomes: 193 confirmed false positives are silent and only the five required true-positive suffixes report.

Exact-SHA parity compared da0647e with 1b8c62b across all 2,000 pinned projects: 2,000 compared, zero skipped, +0 additions, -24 removals, and 10,364 unchanged diagnostics. The removals are 19 no-pass-data-to-parent, four no-prop-callback-in-effect, and one no-reset-all-state-on-prop-change finding; all 24 identities match the source-audited false-positive set.

Paired sequential performance found zero project regressions. Candidate aggregate time was 539,632.191 ms versus 541,731.395 ms for base (0.996x); median project ratio was 0.994 and p95 was 1.113.

The exact-head full-rule shadow completed 2,000/2,000 with zero failures. Projecting its reports onto the five-rule impact scope matched the scoped candidate exactly: +0/-0 with all 10,364 diagnostics unchanged and zero skipped projects.

Local RDE could not start because the sibling eval environment is missing AXIOM_DATASET and AXIOM_TOKEN; the complete Daytona evidence above used the copied DAYTONA_API_KEY.

Test plan

  • bun tmp/audit-react-bench-pr-488.ts --summary — 198/198 intended outcomes, zero parse failures
  • nr test — passed all 15 tasks
  • nr lint — exit 0; only existing fuzz-corpus warnings
  • nr typecheck — passed all 16 tasks
  • nr format:check — passed all 6,180 files
  • nr smoke:json-report — schema v3 report passed
  • strict 500-mutation fuzz runs for all six affected rules plus the final exhaustive-deps review fixes — passed
  • fuzz corpus verdict smoke — all declared pass/fail seeds preserved
  • nlx react-doctor@latest --verbose --scope changed — no issues
  • full GitHub CI matrix — passed, including Node 20 rerun
  • git diff --check — passed

Note

Medium Risk
Broad changes to static-analysis heuristics across six related rules could miss edge-case violations or over-suppress, though extensive regression and fuzz corpus coverage mitigates that.

Overview
React Doctor / ESLint plugin: several state-and-effects rules get smarter provenance and lifecycle analysis so React Bench–style patterns stop false-alarming without weakening real findings.

exhaustive-deps now treats classic controlled/uncontrolled ?? [] selections as stable when the uncontrolled branch is provably non-nullish and the controlled prop type excludes null (including global Array / ReadonlyArray), while still reporting reachable fresh fallbacks and imported types that shadow Array.

no-reset-all-state-on-prop-change skips “reset all state on prop change” when the same effect synchronously invalidates or releases owned resources (abort, ref epoch bumps, collection clears, memoized cleanup helpers, etc.) via new hasSynchronousResourceLifecycleTransition.

Parent-sync rules (no-pass-data-to-parent, no-pass-live-state-to-parent, no-prop-callback-in-effect) allow arguments that only echo props through transparent paths (deep-compare memoizers, useMemo/JSON transforms, ref-stabilized values) and require equivalent local state writes before flagging lifecycle prop callbacks; memoizer-named custom hooks that actually call useState/useReducer still count as child-owned state.

Fuzz harness corpus directives can list multiple comma-separated rules; new regression/true-positive fixtures and a large react-bench-pr-488 regression suite lock behavior. Patch changeset for both oxlint-plugin-react-doctor and eslint-plugin-react-doctor.

Reviewed by Cursor Bugbot for commit 1b8c62b. Bugbot is set up for automated code reviews on this repo. Configure here.

@pkg-pr-new

pkg-pr-new Bot commented Aug 5, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/eslint-plugin-react-doctor@1579
npm i https://pkg.pr.new/oxlint-plugin-react-doctor@1579
npm i https://pkg.pr.new/react-doctor@1579

commit: 1b8c62b

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Interactive terminal E2E

React Doctor interactive terminal recording

Recorded from the built CLI at 1b8c62b in a real terminal. The fixture holds Git busy for three seconds, so Scanning... must appear immediately after project selection, then exercises the compact interactive report.

Download the GIF and MP4 artifact

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 1b8c62b.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit db0807e. Configure here.

@aidenybai
aidenybai merged commit 0efadda into main Aug 5, 2026
31 checks passed
@aidenybai
aidenybai deleted the codex/fix-react-bench-pr-488-false-positives branch August 5, 2026 06:54
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