Commit Graph

1409 Commits

Author SHA1 Message Date
github-actions[bot] fd23edca7e chore: version packages (#1649) react-doctor@0.9.13 oxlint-plugin-react-doctor@0.9.13 eslint-plugin-react-doctor@0.9.13 2026-09-01 21:34:33 -07:00
Aiden Bai ca30808bd3 feat(cli): accept positional file paths (#1746) 2026-09-01 21:23:42 -07:00
Aiden Bai 6f3dd033d5 fix: normalize diagnostic file URLs (#1743) 2026-09-01 21:01:43 -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 e1d4c51abf fix: allow fbt content in verified text wrappers (#1723)
* fix(rn-no-raw-text): exempt fbt children of text-wrapping custom components

The rule now checks auto-detected and imported text wrappers when
evaluating transparent wrapper boundaries, not just built-in text
components. This fixes a false positive where `<fbt>` (a compile-time
translation tag) inside a custom component that renders `<Text>` was
incorrectly reported as a crash.

Closes #1722

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

* chore: add changeset for #1722

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

* fix(rn-no-raw-text): verify fbt text wrappers

---------

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 17:06:43 -07:00
Skosh 6adf55ed88 fix: keep required Expo Metro config subpaths (#1728)
* fix: remove @expo/metro-config from redundant dependency check

The rule incorrectly flagged @expo/metro-config as redundant, suggesting
to use expo/metro-config instead. While expo does re-export the main entry
point, it does NOT re-export subpaths like babel-transformer.

Projects that import @expo/metro-config/babel-transformer (documented by
Expo for extending the Babel transformer) cannot use expo/metro-config/
babel-transformer as it does not exist. The suggested fix is impossible
to follow for subpath imports.

Since the static check cannot distinguish between main entry and subpath
usage, and Expo SDK upgrades keep both packages in lockstep, the version
drift risk is minimal. Removing this entry prevents false positives.

Closes #1726

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

* chore: add changeset for expo/metro-config fix

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

* fix: keep required Expo Metro config subpaths

---------

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 16:34:34 -07:00
Aiden Bai 0f59a3b84d fix: run test-noise rules in application directories (#1725) 2026-08-30 15:57:38 -07:00
Aiden Bai 9f7d26fc04 Revert "fix(ci): pin publish actions to immutable commits (#1720)" (#1721)
This reverts commit cad6b5f4e2.
2026-08-29 23:12:48 -07:00
Aiden Bai cad6b5f4e2 fix(ci): pin publish actions to immutable commits (#1720) 2026-08-29 23:10:30 -07:00
Skosh ac87f7d7f6 fix(core): preserve settings from adopted lint configs (#1695)
* fix: adopt settings from existing .oxlintrc.json

- Read settings from adopted lint configs via readAdoptedLintConfigSettings
- Merge adopted settings (e.g. tailwindcss.entryPoint) with react-doctor settings
- Exclude react-doctor settings from adoption to avoid circular override
- Add comprehensive tests for settings adoption and merging
- Add user-tailwind-config fixture to verify Tailwind settings adoption

Fixes #1694

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

* chore: add changeset for settings adoption fix

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

* fix(core): preserve adopted lint settings

---------

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:57:22 -07:00
Skosh 72a4f4684c fix(ci): prevent pull request cache writes (#1688)
* fix(ci): harden workflows against cache poisoning and document unsigned tags

- Restrict TURBO_TOKEN/TURBO_TEAM to main-branch pushes only across
  ci.yml, code-quality.yml, and react-doctor.yml. First-party PR branches
  no longer have cache write access (preventing cache poisoning attacks).
  PRs run with a cold cache.

- Add SECURITY comments in action-version-bump.yml explaining that tags
  are unsigned and recommending SHA pinning for hardened CI.

- Update install-github-workflow.ts template to include security note
  about @v2 floating major tag and SHA pinning recommendation.

Closes #1685

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

* fix(ci): make pull request cache read-only

---------

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:53:52 -07:00
Aiden Bai 71800cc5d7 test(cli): cover staged rule parity (#1719) 2026-08-29 22:53:36 -07:00
Skosh f720a50429 chore(deps): restore oxlint release-age quarantine (#1684)
* fix(supply-chain): remove oxlint/oxc from minimumReleaseAge exemption

Remove oxlint/oxc packages from minimumReleaseAgeExclude to restore
the 2-hour release quarantine for these third-party dependencies.

Oxlint/oxc is the core analysis engine of react-doctor - the exact
dependency where a compromised or bad release has maximal impact.
The exclusion was removing the one guard that protects that path.

Keep only agent-install in the exclusion list, as it's documented
as a first-party package.

Closes #1680

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

* chore: add changeset for oxlint release age fix

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

* chore(deps): keep release-age policy internal

---------

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:36:38 -07:00
Skosh 21339857fa test(core): cover directory barrel reachability (#1703)
* test: add comprehensive tests for barrel file directory imports

- Add tests for tsconfig path alias resolution to index.ts
- Add tests for baseUrl resolution to index.ts
- Add tests for relative directory imports to index.ts
- Add Next.js-specific test with auto-detected entries
- Add direct resolver tests to verify directory resolution

Tests confirm that barrel files imported via directory paths (e.g., @/features/foo -> foo/index.ts) are correctly resolved and not flagged as unused.

Related to issue #1699

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

* test: add moduleResolution bundler test for directory imports

Test confirms that directory imports work correctly with moduleResolution: bundler setting (used by Next.js).

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

* test(core): cover directory barrel reachability

---------

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:34:11 -07:00
Skosh 0557145cf3 fix(cli): check root workflow before recommending CI (#1697)
* fix: check root directory for CI config instead of project count

Multi-project scans were unconditionally recommending GitHub Actions
even when  already existed at the
repository root. The logic checked individual project directories for
the workflow, which would fail in monorepos where the workflow lives
at the root.

Fixed by checking whether CI is configured at the root directory
(where the scan is running) instead of:
1. Unconditionally for multi-project scans (projectScans.length > 1)
2. Per-project directory checks that miss root-level workflows

Closes #1696

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

* chore: add changeset for CI recommendation fix

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

* chore: format code

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

* fix(cli): measure CI recommendations

---------

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:21:32 -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
Skosh 990daafa62 fix(core): resolve local Expo Metro config wrappers (#1718)
* chore: add changeset for expo-metro-config fix

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

* fix(core): resolve local Expo Metro config wrappers

---------

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 21:50:56 -07:00
Aiden Bai 013f7373f9 fix(action): clean npm output from JSON reports (#1714) v2.2.9 v2 2026-08-29 21:16:01 -07:00
Aiden Bai 40b9d79703 fix(core): resolve typed Expo config plugins (#1713) 2026-08-29 19:04:42 -07:00
Aiden Bai afa1780254 fix(rule): avoid false positives in common patterns (#1706) 2026-08-29 03:48:45 -07:00
Skosh 4e04921205 fix(cli): explain incomplete npx installs (#1693)
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-27 17:55:02 -07:00
Skosh a163de9afa fix(core): recover audit files after interrupted scans (#1690)
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-27 17:21:09 -07:00
Skosh 1d3e4a6061 fix(deps): remove shameful hoisting (#1689)
Co-authored-by: Aiden Bai <aiden@million.dev>
2026-08-27 17:20:49 -07:00
Aiden Bai 79d8007281 fix(core): compare changed scope against remote default (#1676) 2026-08-25 12:17:47 -07:00
Aiden Bai 4bf7aff439 fix(rule): preserve Fast Refresh coverage in nested checkouts (#1673) 2026-08-24 15:19:43 -07:00
Aiden Bai bd08406381 fix(rule): correct flatMap performance advice (#1671) 2026-08-23 02:18:53 -07:00
Aiden Bai e183c35190 test: stabilize CI resource-sensitive guards 2026-08-22 05:03:20 +00:00
Aiden Bai 43e90c4244 docs: explain standalone Oxlint rule coverage (#1669) 2026-08-21 18:56:19 -07: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
Skosh 77aec24f42 fix: extract entry points from implicit sub-projects outside workspace patterns (#1666)
* fix: extract entry points from implicit sub-projects outside workspace patterns

When the root package.json declares workspaces, sub-projects outside the
declared workspace globs were discovered but their entry points (main, bin,
exports) were skipped. This caused false positives in unused-file detection.

The fix removes the isDeclaredWorkspace predicate from entry extraction -
any package with a valid package.json should have its entry points extracted
regardless of workspace pattern matching.

Fixes #1665

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

* chore: add changeset for issue #1665 fix

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

* test: consolidate implicit workspace entry regression

* docs(changeset): clarify implicit entry 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:55:41 -07:00
Skosh 905607f7fc fix: prevent stack overflow in function resolution with depth limiting (#1658)
* fix: prevent stack overflow in function resolution with depth limiting

Add depth limiting to resolveExactLocalFunction to prevent infinite
recursion when resolving function references through deeply nested
expressions, TypeScript path aliases, or complex import chains.

The function now enforces a configurable depth limit
(FUNCTION_RESOLUTION_MAX_DEPTH = 15) and returns null when exhausted
rather than continuing to recurse.

- Add FUNCTION_RESOLUTION_MAX_DEPTH constant (15 levels)
- Thread remainingDepth parameter through all resolution helpers
- Add unit tests for depth limiting
- Add regression test for zustand + Next.js + path aliases case

Closes #1657

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

* test: exercise function resolution stack guard

* refactor: share function chain fixture builder

* test: tighten function resolution regressions

---------

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:55:21 -07:00
Aiden Bai 2b0f06ec70 perf: profile and optimize rule execution (#1663) 2026-08-20 22:05:20 -07:00
Aiden Bai 3ff37f33ce chore: format improve-threejs skill table (#1656) 2026-08-17 03:22:29 -07:00
Aiden Bai 3eda608c8b feat(skills): add improve-threejs skill (#1655) 2026-08-17 02:29:01 -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 1971506440 feat(cli): add React-aware runtime traces (#1653)
* feat(cli): record React-aware browser traces

Add an interactive Playwright scanner that streams DevTools traces to disk and reports React rendering hotspots for humans and agents.

* fix(cli): use shared telemetry anonymizer

Keep runtime URL redaction on the canonical core utility after the telemetry helper consolidation.

* feat(cli): visualize component renders during traces

Flash labeled component outlines during runtime scans so users can connect slow interactions to the React work they trigger.

* feat(skill): add runtime performance workflow

Guide agents through repeatable React traces so performance findings stay tied to measured interactions.

* docs(cli): guide runtime scan setup

Explain the recording flow, browser isolation, authenticated sessions, output formats, and trace privacy directly in command help.

* fix(cli): harden runtime trace capture

Preserve evidence across navigations while keeping structured output, telemetry, trace files, and attached-browser cleanup safe under failures and cancellation.

* fix(cli): preserve latest navigation evidence

Keep cross-document layout shifts comparable and retain the most recent bounded performance entries so the recorded interaction remains represented.

* fix(cli): bound runtime scan browser resources

Prevent trace deadlocks, cross-tab capture, and unbounded browser evidence while preserving navigation data through an isolated validated relay.

* fix(cli): preserve busy-page runtime snapshots

Stop tracing concurrently with final probe collection and allow busy pages enough time to flush their bounded performance evidence.

* feat(cli): prompt for runtime scan URL

Let people start an interactive runtime scan without remembering the URL argument while keeping agents and CI deterministic.

* feat(cli): suggest local apps for runtime scans

Replace the bare URL field with a polished chooser that discovers common localhost development servers while preserving custom URL entry.

* fix(cli): use scan terminology in runtime flow

Keep the interactive copy aligned with the command users invoked instead of switching between recording and profiling language.

* fix(cli): center runtime chooser in full terminal

Render the interactive URL chooser as a terminal-sized view so it no longer appears anchored to the previous cursor position.

* fix(cli): harden runtime scan edge cases

Capture popup evidence without leaking browser pages, support redirected interactive output and IPv6 localhost apps, and keep bounded reports honest.
2026-08-16 19:34:13 -07:00
Aiden Bai 28a1a9fd35 chore: add bippy dependency 2026-08-15 00:11:03 +00:00
Aiden Bai f7efb7d1c4 fix: honor React Compiler in ESLint presets (#1652) 2026-08-14 15:42:59 -07:00
Aiden Bai ffc2d14254 chore: upgrade Oxc toolchain (#1651) 2026-08-13 23:31:27 -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 0b670aa6f5 fix(cli): run agent hooks at turn completion (#1650) 2026-08-13 17:08:53 -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 a2b460d4ae test: stabilize CI timing guards (#1645) 2026-08-13 05:38:07 -07:00
github-actions[bot] 86198f151b chore: version packages (#1618) react-doctor@0.9.12 oxlint-plugin-react-doctor@0.9.12 eslint-plugin-react-doctor@0.9.12 deslop-js@0.9.12 deslop-cli@0.9.12 2026-08-13 04:38:53 -07:00
Aiden Bai d908bb1152 fix(rules): close React Bench audit provenance gaps (#1644) 2026-08-13 04:23:03 -07:00
Aiden Bai c50e3bdbe3 fix(core): keep react detection React-specific 2026-08-13 05:02:35 +00:00