Commit Graph

282 Commits

Author SHA1 Message Date
Aiden Bai 56f576b82c fix(native): close callback and state guard parity gaps 2026-09-05 19:44:12 -07:00
Aiden Bai 2f45687444 fix(native): harden effect and project-resolution parity 2026-09-05 18:38:22 -07:00
Aiden Bai 3ced1c98d3 fix(native): sync upstream rule boundaries 2026-09-05 16:43:28 -07:00
Aiden Bai 32377782c4 Merge commit 'ff7dd679e' into codex/oxc-source-patch 2026-09-05 14:59:28 -07:00
Aiden Bai 82a4d26458 fix(native): preserve runtime diagnostic boundaries 2026-09-05 14:59:23 -07:00
Skosh ff7dd679e8 fix(rule): recognize owned effect cleanup paths (#1762)
* test: add failing tests for issue #1756 false positives

Covers three patterns:
- Chained timer cleared by helper (timer reassigned, helper clears current value)
- Timer allocated in nested function after await with guard
- AbortController cleanup via abort event handler

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* docs: document issue #1756 root causes with failing regression tests

Three false positive patterns in effect-needs-cleanup:

1. **Chained timer**: Timer reassigned inside its own callback, cleared by
   helper. Rule doesn't recognize mutable handle semantics - clearTimeout(timer)
   clears whatever is currently in the variable.

2. **Async guarded allocation**: Guard in async caller protects sync callee
   allocation. Rule recognizes guards inside promise callbacks (#1241) but not
   guards protecting function calls that contain allocations.

3. **AbortController delegation**: signal.addEventListener('abort', ...) removes
   listener, cleanup calls controller.abort(). Rule recognizes direct {signal}
   but not event-based delegation pattern.

Tests currently fail as expected. Implementations need to extend:
- Timer cleanup to understand mutable handles
- Guard tracking to follow call boundaries
- AbortController detection to recognize abort event delegation

Related: #306, #1241, #1594, #1736

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* wip: partial AbortController delegation fix (needs debugging)

Added `hasAbortSignalDelegatedCleanup` helper to recognize the pattern:
- signal.addEventListener('abort', () => removeEventListener(...))
- cleanup calls controller.abort()

Logic handles both direct (controller.signal) and destructured
(const { signal } = controller) signal references.

Current status: Helper added and integrated into effectHasCleanupForUsage,
but tests still fail. Needs debugging of AST traversal logic to correctly
identify and match the abort listener with the cleanup abort() call.

The other two patterns (chained timer, async guard) still need implementation.

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(rule): recognize owned effect cleanup paths

* fix(rule): preserve unsafe timer diagnostics

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-09-05 14:37:32 -07:00
Skosh 6ac8b71985 fix(rule): scope GET helper safety to exact calls (#1761)
* fix(nextjs-no-side-effect-in-get-handler): track safe Headers passed through helpers

Fixes #1757

The rule now tracks when a locally-constructed safe object (like
`new Headers()`) is passed as an argument to a same-file helper
function. The corresponding parameter in that helper is treated as
safe, preventing false positives when the helper mutates the response
headers.

Added `collectHelperParameterSafeBindings` utility that maps call
arguments to helper parameters, extending the set of safe bindings
when scanning helper bodies.

Regression tests added for:
- Headers passed to helper as first parameter
- Headers passed as second parameter
- Headers passed via destructured parameter
- Module-level Map still correctly flagged (not locally scoped)

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for #1757 fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(rule): scope GET helper safety by call

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-09-05 14:29:42 -07:00
Skosh 0fbef9b011 fix(rule): narrow live cancellation guards (#1763)
* fix(async-defer-await): recognize 'live' as a liveness guard name

The async-defer-await rule was firing on post-await liveness guards that
check a 'live' flag, commonly used in React effects to detect unmounting
during async operations.

The issue: 'live' was not in the CANCELLATION_NAME_FRAGMENTS list, so
guards like 'if (!run.live) return' were not recognized as staleness
checks.

The fix adds 'live' to the fragments list so it matches patterns like:
- run.live
- isLive
- liveness
- stillLive

Closes #1758

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for async-defer-await fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(rule): narrow live cancellation guards

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-09-05 14:29:24 -07:00
Skosh 2e3f6eb98a fix(rule): narrow magic-link mutation exemption (#1760)
* fix: exempt send/resend/notify/email mutations from cache invalidation requirement

These operations are cache-effect-free (sending emails, notifications, codes)
with no server data that could go stale. Added send, resend, notify, and email
to READ_ONLY_MUTATION_WORDS alongside download, export, validate, etc.

Closes #1759

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for send/resend/notify/email exemption

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(rule): narrow magic link mutations

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-09-05 14:28:55 -07:00
Skosh 576d7563ff fix: respect 'use no memo' directive in react-compiler-no-manual-memoization rule (#1750)
* fix: respect 'use no memo' directive in react-compiler-no-manual-memoization rule

When a component has the 'use no memo' directive, React Compiler skips
optimization for that component, so manual memoization (useMemo,
useCallback, memo) is still needed.

This change adds support for detecting the 'use no memo' directive and
suppresses the react-compiler-no-manual-memoization rule in those cases.

- Add hasUseNoMemoDirective utility function
- Update rule to check for directive in enclosing function (useMemo/useCallback)
- Update rule to check for directive in wrapped component (memo)
- Add comprehensive tests including regression tests

Fixes #1749

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for use no memo directive fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix: respect React Compiler opt-out directives

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-09-05 14:22:39 -07:00
Aiden Bai 4611492b7a fix(native): preserve multiline HTML template parity 2026-09-05 12:05:00 -07:00
Aiden Bai 1b3f93d254 fix(native): harden scan parity and artifact provenance 2026-09-05 01:13:56 -07:00
Aiden Bai 0ce8d9b500 fix(native): sync rule fixes from main 2026-09-02 01:29:54 -07:00
Aiden Bai 28d4343e4d fix: recognize indirect effect cleanup (#1742) 2026-09-01 14:07:52 -07:00
Aiden Bai a04b933c02 fix: ignore vendored source map env examples (#1739) 2026-09-01 13:16:03 -07:00
Skosh 2c4560fc0a fix: classify fragment returns of translation text as text-producing (#1732)
* fix: classify fragment returns of translation text as text-producing

Fragment returns mixing translation text elements (fbt/fbs) with literal
text now classify correctly as text-producing components. The fragment
is render-transparent, so both halves land in the caller's <Text>.

Fixes #1731

- Extract isTranslationTextJsxRoot helper that recursively checks
  fragments
- Fragment children that are all translation elements (plus literals)
  pass the check
- Fragment children with non-text elements still fail (guard test added)
- Add regression coverage for the reported mixed-literal case

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for fragment translation text fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix: keep fragment translation classification conservative

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-31 21:40:35 -07:00
Skosh 025d69d701 fix: recognize global String substring lookups (#1734)
* fix: prevent false positive in js-set-map-lookups for String().includes()

- Add check to ensure String() refers to global constructor, not shadowed variable
- Add regression tests for the String() constructor case
- Add corpus regression test file

Closes #1733

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix: recognize global String substring lookups

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-31 20:59:48 -07:00
Skosh adc3a91291 fix: handle direct fbt component returns (#1730)
* fix(rn-no-raw-text): suppress diagnostic for components returning only transparent text wrappers

Components whose entire return value is a transparent text wrapper (<fbt>, <fbs>, or <Fragment>) are now classified as text-producing components. This prevents false positives when such components are consumed inside <Text> elements.

Fixes #1729

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* test(rn-no-raw-text): add regression tests for issue #1729

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for issue #1729 fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* test: update regression tests to reflect #1729 fix limitation

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix: handle direct fbt component returns

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-30 18:28:17 -07:00
Skosh 17eeeb5367 fix(rules): recognize member hook state consumption (#1717)
* fix(rerender-state-only-in-handlers): recognize state consumed via member expression hook calls

State consumed by hook calls through member expressions (e.g. styles.useVariants({ state }))
was incorrectly flagged as unused. This commonly occurs with react-native-unistyles,
where state selects style variants via StyleSheet.useVariants().

The rule now checks both direct identifier calls (useX) and member expression calls
(obj.useX) when collecting custom hook arguments, following the existing pattern used
throughout the codebase.

Fixes #1716

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for member expression hook fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* test: add edge case for non-hook member expressions

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(rules): preserve state setter bindings

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-29 22:13:41 -07:00
Aiden Bai afa1780254 fix(rule): avoid false positives in common patterns (#1706) 2026-08-29 03:48:45 -07:00
Aiden Bai 72fd97b2a3 perf(native): port functional setState rule to Rust 2026-08-23 23:09:55 +00:00
Skosh 5bc88ae6a0 fix: ignore TypeScript type-only positions in no-unguarded-browser-global-at-module-scope (#1668)
* fix: ignore TypeScript type-only positions in no-unguarded-browser-global-at-module-scope

The rule was incorrectly flagging browser-global names (window, navigator, etc.) when they appeared as property keys in TypeScript interfaces and type aliases. These are type-only positions that TypeScript erases during compilation, so no runtime reference error occurs.

Add isTypeScriptTypePosition check to skip identifiers in TS type contexts before reporting. Add regression tests covering interface properties, type alias properties, and the preserved behavior for actual runtime references.

Fixes #1667

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* chore: add changeset for #1667 fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* test: add edge case tests for TypeScript type positions

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* test: preserve type-only browser global regression

* docs(changeset): clarify type-only global fix

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
2026-08-21 18:56:00 -07:00
Aiden Bai 6416370836 feat(rules): add UI-library composition and correctness rules behind capability gates (#1654) 2026-08-16 23:29:04 -07:00
Aiden Bai 05ef98926d fix: scan standalone Three.js projects and preserve TUI layout (#1646) 2026-08-13 18:18:45 -07:00
Aiden Bai 8c2f03aea9 feat: make React cleanup first-class (#1624)
* feat: make React cleanup first-class

* refactor: remove editor integrations

* fix: harden React cleanup analysis

* fix: detect default export duplication roots

* fix: unwrap typed duplication roots

* feat: add opt-in project analysis rules

* fix: canonicalize project analysis paths

* fix: harden project analysis precision

* fix: recognize cross-platform project entries

* fix: eliminate project analysis false positives

* fix: harden project analysis reachability

* fix: canonicalize project analysis inputs

* fix: resolve project analysis review findings

* fix: eliminate residual project analysis false positives

* fix: ignore commented registry previews

* fix: eliminate project analysis false positives

* fix: normalize project analysis paths across platforms

* fix: normalize Nextra theme path identity

* test: canonicalize convention fixture paths

* fix: preserve project analysis provenance

* fix: harden project analysis precision

* fix: honor project analysis boundaries

* fix: recognize conditional config plugins

* fix: recognize executable project references

* fix: recognize Stencil tool contracts

* fix: recognize nested tool references

* fix: recognize project setup contracts

* fix: recognize generated and local package consumers

* fix: recognize static template package references

* fix: recognize nested package runtime contracts

* fix: close project analysis parser gaps

* fix: parse project conventions structurally

* refactor: replace structural scanners with parsers

* fix: recognize functional Next CSS config

* fix: close remaining project analysis gaps

* fix: apply tag filters to project analysis

* fix: preserve embedded source positions

* fix: validate static config helper bindings

* fix: bound runtime directory discovery

* fix: close final dependency analysis gaps

* fix: preserve declaration dependency references

* chore: refresh generated rule metadata

* fix: make project analysis portable and bounded

* test: stabilize cleanup scaling guard

* refactor: parse project syntax with oxc

* fix: normalize native filesystem paths

* fix: separate path identity from report paths

* fix: match project files by filesystem identity

* fix: match build glob files by package identity

* fix: use native path keys for file identity

* fix: canonicalize Windows file identities

* fix: canonicalize package ownership paths

* test: inspect Windows path identities

* test: trace Windows package ownership

* fix: keep Windows path identities consistent

* fix: classify test contracts by normalized path

* fix: scope test contracts by canonical package path

* fix: keep test package graphs conservative

* test: keep React complexity advisory
2026-08-13 16:26:08 -07:00
Aiden Bai bea01b8cf5 feat(r3f): add material rendering diagnostics (#1633) 2026-08-12 15:40:07 -07:00
Aiden Bai 8dfb013067 Add comprehensive Three.js and R3F diagnostics (#1629) 2026-08-11 15:40:53 -07:00
Aiden Bai c1611428d2 test(fuzz): complete React Bench audit corpus (#1619) 2026-08-09 02:04:45 -07:00
Aiden Bai 27a39dede7 fix(rules): recognize retained cleanup ownership (#1615)
* fix(rules): recognize retained cleanup ownership

* fix(types): normalize optional AST parents

* test: store imported corpus as source text fixtures
2026-08-08 21:50:44 -07:00
Aiden Bai 7f028ea904 fix(rules): accept compound unmount guards (#1606) 2026-08-08 06:23:37 -07:00
Aiden Bai f27fd5d136 fix(rules): close exhaustive React Bench audit gaps (#1605)
* fix(rules): close exhaustive React Bench audit gaps

* fix(core): fingerprint effect helper imports

* test(fuzz): preserve audit corpus bytes
2026-08-08 04:49:52 -07:00
Aiden Bai 6a546c2a4c test(fuzz): pin exhaustive React Bench audit corpus (#1603)
* test(fuzz): pin exhaustive React Bench audit corpus

* fix(fuzz): normalize corpus paths

* test(fuzz): normalize corpus expectations

* fix(fuzz): skip TypeScript declarations
2026-08-07 17:38:28 -07:00
Aiden Bai 65d4f46d1a test(fuzz): preserve React Bench diagnostic callsites (#1600) 2026-08-07 00:19:24 -07:00
Aiden Bai a4d2c5c8bf fix: recognize browser media lifecycles (#1599) 2026-08-06 23:51:11 -07:00
Aiden Bai 4ffeb2cb71 fix(rules): preserve state effect provenance (#1597) 2026-08-06 18:05:49 -07:00
Aiden Bai d62caa575f fix(rule): harden effect cleanup regressions (#1596)
* fix(rule): harden effect cleanup regressions

* fix(fuzz): preserve cleanup-local scope
2026-08-06 17:43:18 -07:00
Aiden Bai 0efadda676 fix(rule): preserve lifecycle synchronization semantics (#1579) 2026-08-04 23:54:24 -07:00
Skosh 881ecfe674 fix: exclude setState updater callbacks from zustand-no-fresh-selector-result (#1576)
Resolve destructured Zustand imperative APIs by binding and property identity while preserving diagnostics for legitimate bound store hooks with API-like names.
2026-08-04 14:55:58 -07:00
Aiden Bai bafef41699 RDFPFNFINAL fix benchmark rule precision and async ownership (#1574)
* chore: start hook diagnostic dedup

* chore: scaffold zod v4 subpath fix

* fix: repair benchmark rule precision

* fix: exclude repeated mount transitions

* fix(rules): require ownership guards to control clears
2026-08-04 14:15:17 -07:00
Skosh afd60dbe69 fix(effect-needs-cleanup): prove effect-owned cleanup (#1559)
* fix(effect-needs-cleanup): handle returned identifiers for addEventListener/addListener

Fixes #1558 - Part 1

- Allow returning identifiers bound to addEventListener/addListener results as valid cleanup
- Recognize calling such identifiers (e.g., ) as cleanup
- This fixes false positives for React Native's NetInfo.addEventListener and similar APIs

Remaining work: helper function cleanup and array collection cleanup

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* docs: add changeset for addEventListener cleanup fix

Co-authored-by: Skosh <skoshx@users.noreply.github.com>

* fix(effect-needs-cleanup): prove resource ownership

* fix(effect-needs-cleanup): harden ownership proofs

* fix(effect-needs-cleanup): isolate deferred ownership

* fix(effect-needs-cleanup): prove deferred timer ownership

* fix(effect-needs-cleanup): narrow invocation owners

* fix(effect-needs-cleanup): track helper collection mutations

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Skosh <skoshx@users.noreply.github.com>
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-03 13:29:06 -07:00
Aiden Bai 48ec9a8020 fix(cli): keep large workspace scans responsive (#1549)
* fix: keep large workspace scans responsive

* fix: harden large workspace scans

* test: normalize workspace path on Windows

* fix: resolve workspace exclusions after root redirects

* fix: honor workspace scan boundaries

* fix: keep bounded workspace scans responsive

* fix: preserve dead-code reachability

* refactor: tighten workspace scan controls

* fix(cli): bound staged workspace scans

* fix: eliminate pathological large-file scans

* fix: handle incomplete and conflicted scans

* test: configure conflict merge identity

* perf: cache repeated module resolution probes

* fix(cli): show all incomplete scan warnings

* fix(core): preserve cooperative scan semantics

* perf(cli): streamline workspace scan startup

* perf(cli): harden large workspace scans

* fix(cli): keep scan progress inline

* fix(scan): correct workspace result completeness

* fix(cli): simplify live scan status

* fix(core): make scan deadlines opt-in

* fix(scan): preserve complete workspace results

* perf(scan): accelerate very large workspaces

* fix(scan): yield CPU to foreground work

* perf(scan): avoid unnecessary project indexing

* fix(cli): keep final report inline

* test(cli): stabilize terminal recording setup

* fix(core): honor scan deadline during index probe

* fix(core): skip lint after incomplete index probe

* fix(core): preserve scoped lint ownership

* fix(cli): restore project picker on cancellation
2026-08-03 04:59:45 -07:00
Aiden Bai 85e1052289 FPFNFIX82 Detect passive request-owner windows (#1563)
* feat: detect passively synchronized request owners

* fix: exclude contradictory request-owner paths

* fix: exclude mismatch-branch state updates

* fix(rule): cover passive owner branches
2026-08-03 03:31:34 -07:00
Aiden Bai cc2862666b feat: detect controlled selection focus effects (#1562) 2026-08-03 03:03:44 -07:00
Aiden Bai 44922d6782 FPFNFIX82 Fix form and fragment diagnostics (#1561)
* fix(rules): correct form and fragment diagnostics

* fix(rules): handle fragment review edge cases

* fix: handle document-top fragment links

* fix(a11y): parse ids from html tags only

* fix(a11y): resolve static fragment aliases

* fix(a11y): retain known fragment targets

* fix(a11y): tokenize html id attributes

* fix: preserve known fragment IDs in mixed spreads

* fix: preserve known fragment ID defaults
2026-08-03 03:03:00 -07:00
Aiden Bai 3a93a34beb FPFNFIX82: prove effect cleanup ownership (#1564) 2026-08-02 23:39:53 -07:00
Aiden Bai 02e3188d4b Add InstancedMesh rules for Three.js and R3F (#1560) 2026-08-02 23:01:55 -07:00
Aiden Bai 4e4740dde3 FPFNFIX82: ignore type-only parent-data references (#1557)
* fix(no-pass-data-to-parent): ignore type-only refs

* fix(no-pass-data-to-parent): preserve angle assertion flow
2026-08-02 21:49:56 -07:00
Aiden Bai 4c610803cb FPFNFIX82: detect stale async request error clears (#1556)
* feat(rule): detect unowned async error clears

* fix(no-unowned-async-error-clear): require ownership guard

* fix(no-unowned-async-error-clear): preserve keyed component proof
2026-08-02 21:49:37 -07:00
Aiden Bai 37427c915c fix(effect-needs-cleanup): recognize reconnect cleanup (#1555) 2026-08-02 21:49:15 -07:00
Aiden Bai b02bc694f1 FPFNFIX82: RDFPFN82026: preserve mixed effect chains (#1545)
* fix(rules): detect mixed effect chains

* fix(no-effect-chain): preserve channel lifecycles

* fix(no-effect-chain): preserve external sync boundaries

* fix(no-effect-chain): ignore setter value helpers in cleanup
2026-08-02 07:48:32 -07:00