8 Commits

Author SHA1 Message Date
Aiden Bai ca0ba6ea03 refactor(rules): colocate recommendation text with each defineRule call (#228)
* refactor(rules): colocate recommendation text with each defineRule call

Drops the 375-line `RULE_HELP_MAP` table in `run-oxlint.ts` and moves every
entry onto the matching rule's `defineRule({...})` call as a
`recommendation: "..."` field. `run-oxlint.ts` now reads the recommendation
off the plugin registry at lookup time, so the diagnostic-rendering path is
unchanged but each new rule has a single obvious place to put its
recommendation text (next to the rule logic it describes).

178 rule files updated; `run-oxlint.ts` shrinks by 365 net lines. No
behavior or output change — same recommendation strings, same registration
validator (now warning on any rule whose `defineRule` call doesn't ship a
`recommendation`).

* fix(plugin): move plugin object out of plugin/index.ts to avoid barrel-import warning

Renames `plugin/index.ts` → `plugin/react-doctor-plugin.ts` (where it's
actually constructed) and updates the 3 consumers (`eslint-plugin.ts`,
`run-oxlint.ts`, `vite.config.ts`) to import from the direct path. The
file's only export was the plugin object built in-place, so this isn't a
re-export barrel — but the `/index.js` suffix tripped react-doctor's own
`no-barrel-import` rule once a second importer landed in this PR.
Fixes the React Review warning at `run-oxlint.ts:22` introduced by the
previous commit.

* pub
2026-05-13 11:27:08 -07:00
Aiden Bai 8556b31d8e feat: address user feedback — reduce false positives, improve scoring transparency, and add config options (#208)
* feat(browser-poc): add AST normalizers for production React analysis

Add 12 AST normalizers that transform minified production code into
patterns the react-doctor plugin rules can analyze. Enables 30+ rules
to fire on production bundles with 0 parse errors and 0 rule failures
across 6 tested sites (vercel, notion, linear, discord, shopify, ami).

Normalizers: SequenceExpression callee unwrap, OXC literal type
normalization, boolean/void recovery, return/expression sequence
splitting, JSX reconstruction (jsx/jsxs/createElement → JSXElement
tree with Fragment, ExpressionContainer, key extraction), setter
binding + reference rename, and component name uppercase recovery.

Also adds parent reference tracking in visitAst, "use client"
directive injection, WASM failure caching for CSP-blocked sites,
truncated source skip, score calculation, and a null-safety fix
for prefer-useReducer.

Co-authored-by: Cursor <cursoragent@cursor.com>

* feat: address user feedback — reduce false positives, improve scoring transparency, and add config options

- Add `offline`, `designRules`, and `entryFiles` config options
- Suppress React 19 deprecation rules on React 18 (migration-hint gate)
- Skip `rn-no-raw-text` for `.web.*` files (RN platform convention)
- Add sleep/delay and paginated-fetch heuristics to `asyncAwaitInLoop`
- Remove `noEmDashInJsxText` rule (em dashes are standard punctuation)
- Add `designRules` toggle to disable opinionated design rules
- Thread `entryFiles` to knip for dead-code false positive reduction
- Export `calculateScoreBreakdown` and show formula in `--verbose`
- Document scoring formula, diff/staged modes, and agent integration
- Switch to `@changesets/changelog-github` for richer changelogs
- Add GitHub Releases workflow

Co-authored-by: Cursor <cursoragent@cursor.com>

* refactor: capabilities-based rule gating system

Replace bespoke flags and filter functions with a unified
capabilities + tags system:

- Add buildCapabilities(project) that derives a flat Set<string>
  from ProjectInfo (react:19, nextjs, tanstack-query, etc.)
- Add RULE_METADATA map with requires[] (capability gates) and
  tags (static classification like "design", "test-noise")
- Replace filterRulesByReactMajor, filterDesignRules, VERSION_GATED_RULE_IDS,
  VersionGateMode, and conditional spreads with one shouldEnableRule predicate
- Replace 9 individual fields on RunOxlintOptions/OxlintConfigOptions
  with project: ProjectInfo
- Add ignore.tags to user config (replaces designRules boolean)
- Cherry-pick from cursor/library-aware-deprecation-rules-ec3b:
  peerRangeSupportsLegacyReact, isTestFilePath, isLikelyBuildEntry,
  parseTailwindMajorMinor, isLikelyStringReceiver (js-set-map-lookups fix)
- Compute effective React version from min(installed, peerRangeFloor)
  so library-targeting-legacy is handled by version gating alone

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: library peer-range detection + README designRules cleanup

- Fix Bugbot: peerRangeMinMajor computes the floor major from the peer
  range so effective version is min(installed, peerFloor) instead of null
- Fix Bugbot: replace designRules config key with ignore.tags in README
- Add peerRangeMinMajor tests

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: wire isLikelyBuildEntry + isTestFilePath into post-scan suppression

- Add auto-suppression in mergeAndFilterDiagnostics: suppress knip/files
  diagnostics when a matching build artifact exists, suppress test-noise
  tagged rules in test/fixture files
- Tag deprecation and design rules with "test-noise" in RULE_METADATA
- Fixes Bugbot: isLikelyBuildEntry is no longer dead code

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: remove dead DESIGN_TAGS constant, clear auto-suppression caches

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: remove dead peerRangeSupportsLegacyReact, unused ruleKey param, new Promise false negative

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: forward ignoredTags and entryFiles in diagnose() programmatic API

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: handle destructuring in loop-carried dependency detection

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: apply sleep/dependency heuristics to callback-based iteration

The loopBodyHasOnlySleepLikeAwaits and hasLoopCarriedDependency checks
were only applied in inspectLoopBody (for/while/do-while) but skipped
for callback-based iteration (.forEach, .map, etc.), causing false
positives on patterns like arr.forEach(async item => { await sleep(500) }).

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: guard framework-specific rules against missing RULE_METADATA

Rules from framework-specific maps (NEXTJS_RULES, REACT_NATIVE_RULES,
etc.) without a RULE_METADATA entry were unconditionally enabled for
all projects. Now they are skipped at runtime, and
validateRuleRegistration warns about the gap at dev time.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: scope RULE_METADATA validation to framework-specific rules only

Global rules intentionally omit RULE_METADATA entries since they're
unconditionally enabled. Extracted FRAMEWORK_SPECIFIC_RULE_KEYS to
share the set between the runtime guard and the validation check.


---------
2026-05-11 21:29:34 -07:00
Cursor Agent 90e3303935 fix(ci): scope leaderboard workflow change-detection to the README path
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
2026-05-08 13:01:32 +00:00
Aiden Bai 914e5f3aee feat: leaderboard in README + dedicated /leaderboard page (#176)
* docs(readme): add leaderboard section with top 10 from benchmarks repo

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* ci(leaderboard): refresh README leaderboard from benchmarks json on schedule

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* feat(website): add /leaderboard page driven by react-doctor-benchmarks

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* chore(scripts): drop bench:scores in favor of leaderboard.json

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* docs(readme): trim leaderboard table to repo + score

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* docs(readme): drop raw-results link from leaderboard section

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* fix(scripts): make update-leaderboard idempotent against formatter

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

* refactor(website): extract score thresholds, color, label, doctor face to shared utils

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
2026-05-08 05:58:36 -07:00
Aiden Bai 03a94351c7 Address review-report.md findings + self-review regressions (#140) 2026-04-30 23:12:50 -07:00
Aiden Bai 47105e9619 Fix false positives for Next.js redirect guidance and React Compiler detection (#129)
Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
2026-04-14 19:23:54 -07:00
Aiden Bai 5688c1f69d fix 2026-02-17 07:52:05 -08:00
Aiden Bai b1f1abcff8 add CI workflow for e2e tests, lint, and format
Generated with [Ami](https://ami.dev)
Co-Authored-By: Ami <noreply@ami.dev>
2026-02-16 05:50:11 -08:00