Skip to content

chore: version packages#603

Merged
NisargIO merged 1 commit into
mainfrom
changeset-release/main
Jun 1, 2026
Merged

chore: version packages#603
NisargIO merged 1 commit into
mainfrom
changeset-release/main

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions Bot commented May 30, 2026

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated.

Releases

eslint-plugin-react-doctor@0.2.15

Patch Changes

  • Updated dependencies [6e59f10, 75c1f99]:
    • oxlint-plugin-react-doctor@0.2.15

oxlint-plugin-react-doctor@0.2.15

Patch Changes

  • #596 6e59f10 Thanks @aidenybai! - Collapse diagnostic categories into five clear, outcome-based buckets: Security, Bugs, Performance, Accessibility, and Maintainability. The previous fine-grained labels (Correctness, State & Effects, React Compiler, Next.js, React Native, Server, TanStack Query/Start, Preact → Bugs; Bundle Size → Performance; Architecture/Design → Maintainability) now roll up so the scan output reads as plain issue types at a glance.

    This changes the category value on every diagnostic (CLI output, the per-error headline prefix like Security: Use of eval(), and JSON/programmatic output). If you key categories severity overrides off the old names, update them to the new buckets. Dead-code findings (unused files/exports/dependencies, circular imports) now report Maintainability instead of Dead Code. Bundle-size findings now sort with Performance (higher stakes) rather than near the bottom of the top-errors block.

  • #630 75c1f99 Thanks @rayhanadev! - Fix react-doctor@latest (and the ESLint/oxlint plugins) crashing before the scan starts with ERR_MODULE_NOT_FOUND: Cannot find package 'oxc-parser' under strict package managers like pnpm. The published oxlint-plugin-react-doctor/dist/index.js performs a runtime import { parseSync } from "oxc-parser" (cross-file parsing for rules like no-mutating-reducer-state) and the build intentionally keeps oxc-parser external, but the package only declared it under devDependencies, so consumers never had it installed. oxc-parser is now a real dependency. See #629.

react-doctor@0.2.15

Patch Changes

  • #612 3ceb748 Thanks @rayhanadev! - Stop flagging known public client keys in no-secrets-in-client-code. Keys that vendors design to ship in the browser bundle — RevenueCat public SDK keys (appl_/goog_/amzn_/strp_), Stripe/Clerk publishable keys (pk_live_/pk_test_), Supabase publishable keys (sb_publishable_), PostHog project keys (phc_), Stytch public tokens (public-token-), and Mapbox public access tokens (pk.) — are now allowlisted, so the variable-name heuristic no longer reports them as hardcoded secrets. Ambiguous shapes that can be either public or sensitive (Google/Firebase AIza… browser keys, and bare Supabase anon/service_role JWTs) are intentionally still flagged.

  • #596 6e59f10 Thanks @aidenybai! - Diagnostic ranking now depends solely on the score API's per-rule priority. The hand-rolled severity/category-stakes weighting (and the offline priority midpoints) is gone: when the API priority is unavailable (--no-score, offline, or API failure) rules and categories keep their scan order, with categories falling back to alphabetical for determinism.

  • #619 b3c3aa9 Thanks @aidenybai! - Treat CI=1 and CI=True as CI environments, not just CI=true. CI-only behavior (suppressing the share URL, marking the run as CI-originated for scoring) now triggers consistently across providers that set CI to a truthy value other than the literal string "true"; explicit CI=false / CI=0 are still treated as non-CI.

    A present-but-unparseable react-doctor.config.json at the scanned root no longer silently falls through to a parent directory's config. The tool stops there instead of letting an ancestor repo's config govern the project; a package.json reactDoctor config in the same directory is still used as a fallback.

  • #605 4861f37 Thanks @rayhanadev! - Update the dead-code analysis engine (deslop-js) to 0.0.14 so the published CLI's unused-file / dead-code detection runs on the latest release. The CLI previously pinned ^0.0.13 while the internal core engine was already on 0.0.14; this aligns both on a single version and drops the duplicate from the lockfile.

  • #596 6e59f10 Thanks @aidenybai! - Collapse diagnostic categories into five clear, outcome-based buckets: Security, Bugs, Performance, Accessibility, and Maintainability. The previous fine-grained labels (Correctness, State & Effects, React Compiler, Next.js, React Native, Server, TanStack Query/Start, Preact → Bugs; Bundle Size → Performance; Architecture/Design → Maintainability) now roll up so the scan output reads as plain issue types at a glance.

    This changes the category value on every diagnostic (CLI output, the per-error headline prefix like Security: Use of eval(), and JSON/programmatic output). If you key categories severity overrides off the old names, update them to the new buckets. Dead-code findings (unused files/exports/dependencies, circular imports) now report Maintainability instead of Dead Code. Bundle-size findings now sort with Performance (higher stakes) rather than near the bottom of the top-errors block.

  • #623 b9e9bcb Thanks @rayhanadev! - Align the CLI with the clig.dev and 12-factor CLI guidelines:

    • --color / --no-color flags force or disable colored output, with app-specific REACT_DOCTOR_NO_COLOR / REACT_DOCTOR_FORCE_COLOR env overrides. Flags win over env vars, which win over picocolors' built-in NO_COLOR / FORCE_COLOR / TERM / TTY detection; the preference is resolved before parsing so it reaches every surface (scan report, branded header, score, prompts, errors).
    • react-doctor --help and react-doctor install --help now lead with worked examples and link to where to report feedback.
    • New react-doctor version subcommand prints the version with Node and platform info (e.g. react-doctor/0.2.14 darwin-arm64 node-v24.14.0); -v / -V / --version stay terse for scripts.
    • react-doctor help and react-doctor help <command> now show help instead of failing by trying to scan a directory named "help".
  • #583 4bc8a73 Thanks @aidenybai! - Port expo-doctor's project-level checks as Expo-gated diagnostics. When an Expo project is detected (expoVersion !== null), react-doctor now runs the statically-determinable subset of expo-doctor's check suite during the environment-checks phase (skipped in diff/staged mode):

    • expo-no-unimodules-packages — legacy @unimodules/* / react-native-unimodules packages (IllegalPackageCheck).
    • expo-no-cli-dependenciesexpo-cli / eas-cli listed as project dependencies (GlobalPackageInstalledLocallyCheck).
    • expo-no-redundant-dependency — packages Expo installs transitively or that were removed/deprecated (expo-modules-core, @expo/metro-config, @types/react-native, expo-permissions, the expo-firebase-* family, …), each SDK-version gated (DirectPackageInstallCheck).
    • expo-no-conflicting-dependency-overrideoverrides/resolutions/pnpm.overrides that pin SDK-critical packages like @expo/cli or metro* (DependencyVersionOverrideCheck).
    • expo-router-no-react-navigation — direct @react-navigation/* alongside expo-router on the SDK 56 line only (>=56 <57, matching expo-doctor's range) (ExpoRouterReactNavigationCheck).
    • expo-vector-icons-conflict — scoped icon packages mixed with @expo/vector-icons / react-native-vector-icons (VectorIconsCheck).
    • expo-package-json-conflictexpo/react-native scripts shadowing node_modules bins, and a package name colliding with a dependency (PackageJsonCheck).
    • expo-lockfile — missing or multiple lock files at the workspace root (LockfileCheck).
    • expo-gitignore — a committed .expo/ directory, or local module native dirs that are gitignored (ProjectSetupCheck).
    • expo-env-local-not-gitignored — committed .env*.local files (EnvLocalFilesCheck).
    • expo-metro-config — a metro config that doesn't extend expo/metro-config, while tolerating known wrappers that extend it internally such as Sentry's getSentryExpoConfig (MetroConfigCheck).

    The remaining expo-doctor checks require running the Expo CLI, querying the Expo API, or inspecting native iOS/Android projects — none of which fit react-doctor's offline, static model — so they're intentionally out of scope.

  • #583 4bc8a73 Thanks @aidenybai! - Detect Expo projects independently of the single-valued framework hint. Project discovery now surfaces an expoVersion signal (the declared expo package spec, looked up in the project or any of its workspace packages, or null), paralleling reactVersion. The expo capability is keyed off expoVersion !== null rather than framework === "expo", so Expo-specific rules now load on web-rooted monorepos whose apps/mobile workspace targets Expo, and on projects that declare both expo and a web bundler (where vite / next previously won framework detection and silently dropped the expo capability). The file-level package boundary in oxlint-plugin-react-doctor still keeps Expo-only rules quiet on web workspaces.

  • #615 8b313ba Thanks @rayhanadev! - Fix two dead-code / fix-recipe papercuts surfaced on alias-heavy Next.js projects.

    Dead-code no longer mis-flags @/… (and other) imports as unused. The dead-code pass resolves imports through oxc-resolver, which returns realpath'd (symlink-free) paths, but built its module graph from the scan root as-is. When the project root sat behind a symlink — e.g. a macOS iCloud-synced ~/Documents / ~/Desktop, or a symlinked checkout — the two path spaces diverged, every import edge dropped, and files reachable only through those imports (in an alias-heavy codebase, every @/… target) were reported as "unused / unreachable". The scan root is now canonicalized before analysis so the module graph and the resolver agree. This was never specific to @/* aliases; relative imports were affected the same way.

    Per-rule fix-recipe URLs are only shown when a recipe exists. Findings advertised a "fetch the canonical fix recipe" URL (/prompts/rules/<plugin>/<rule>.md) for every diagnostic, but recipes are only published for react-doctor's own engine rules. Dead-code (deslop/*), the environment / supply-chain checks (require-reduced-motion, require-pnpm-hardening), and adopted third-party plugins (eslint, unicorn, react-hooks-js, …) have no recipe, so their links 404. The directive is now gated to engine rules, so agents are no longer sent to dead links.

  • #607 5dff3b5 Thanks @rayhanadev! - Fix react-doctor --staged (and other scans) hanging after the diagnostics summary is already printed. When an adopted lint config crashed oxlint on the first attempt, the oxlint runner's per-batch progress timer was left running while the scan silently retried with extends stripped — so the run finished and printed results, but the orphaned setInterval kept the Node event loop alive and the process never returned control to the shell. The batch loop now clears the timer in a finally, so it's always cleaned up even when a batch throws. See #599.

  • #614 daef23c Thanks @aidenybai! - jsx-key no longer reports a missing key when a list element spreads the whole iteration item — items.map((item) => <Item {...item} />). Spreading the row object is the canonical "this row carries its own identity" shape and was the dominant source of jsx-key noise on real lists, while rarely catching a genuine reorder bug. Genuine keyless lists still report: items.map((item) => <Item name={item.name} />), index keys, array literals ([<Item {...item} />]), and spreads of anything other than the iteration variable.

  • #614 daef23c Thanks @aidenybai! - App-only heuristics now stay quiet in published libraries, and React Compiler memoization-cleanup is demoted to a warning.

    • react-hooks-js/static-components and no-render-prop-children no longer fire on files in a published library — a non-private package.json that declares the publish contract (name + exports). They still fire in applications (including private monorepo apps that live under packages/ or declare a niche internal exports map) and in any package without that contract, and an explicit per-rule severity in config always re-enables them.
    • react-compiler-no-manual-memoization now defaults to warn instead of error when React Compiler is detected — redundant useMemo / useCallback / memo is correctness-neutral cleanup, so it's hidden from the default report. The external react-hooks-js/* compiler rules stay error because each marks code the compiler could not optimize (a real perf regression).
    • New buckets config field: set { "buckets": { "compiler-cleanup": "error" } } to re-enable strict errors for the redundant-memoization rule. A per-rule override still wins over a bucket.
  • #613 6448d5b Thanks @NisargIO! - Speed up scans of effect-heavy codebases by memoizing getDownstreamRefs in the State & Effects rule helpers. ascend() re-descended the same large definition subtrees on every recursion step, so the seven effect rules (led by no-pass-data-to-parent) blew up superlinearly on big components with many useEffects — re-walking and re-scoping identical bodies across recursion, across effects, and across rules. Caching the downstream-reference lookup per Program node (a WeakMap keyed on the per-Program analysis singleton, GC-bound with the file) collapses that to a single descent.

    On an 866-file Next.js app this cut ~9s (~24%) off a full scan — the worst rule on the largest file (a 1,159-line component with 10 effects) dropped from ~9.5s to ~0.18s, and the hot lint batch from ~13.5s to ~2.5s. Diagnostics are byte-identical (verified by a SHA-256 fingerprint over every diagnostic before/after); the cache only stores arrays callers already read and never mutate.

  • #616 bb15252 Thanks @rayhanadev! - Add an --experimental-parallel [workers] flag that runs the oxlint lint pass across multiple worker processes instead of one batch at a time. React Doctor's rules are oxlint JS plugins (single-threaded per process), so a serial scan only ever pins one core; --experimental-parallel fans the file batches out across the requested number of concurrent oxlint subprocesses, which scales the scan nearly linearly with CPU cores (measured ~3.5–4.6x on a 1,500-file project and ~4.6x on Sentry's 8,773 files) while producing byte-identical diagnostics.

    --experimental-parallel with no value auto-detects available cores; --experimental-parallel <n> caps the worker count; REACT_DOCTOR_PARALLEL=<n> seeds the default for flag-less / CI runs. The worker count is clamped to a safe range to bound peak memory, and the default remains serial so resource usage stays opt-in.

  • #601 5f7cc7c Thanks @rayhanadev! - Publish a JSON Schema for react-doctor.config.json at https://react.doctor/schema/config.json.

    Pointing $schema at the URL enables editor autocomplete, hover docs from the interface JSDoc, and typo warnings in any editor that understands JSON Schema. Closes #497.

    {
      "$schema": "https://react.doctor/schema/config.json",
      "lint": true
    }

    The schema is generated from packages/core/src/types/config.ts via pnpm build:schema and checked into packages/website/public/schema/config.json.

  • #606 fe01e57 Thanks @rayhanadev! - Redact secrets and PII from diagnostic output. Every diagnostic's message/help is now scrubbed for API keys, tokens, private keys, JWTs, credentialed URLs, and email addresses before it reaches the terminal, the JSON report, or the score API — so react-doctor never echoes or transmits a secret embedded in your source. Provider tokens keep their non-secret, type-identifying prefix (e.g. sk_live_<redacted>, ghp_<redacted>) so you can tell which credential leaked while the secret itself stays masked.

  • #625 bdb9e36 Thanks @rayhanadev! - Add 10 React Native & Expo diagnostics (researched against first-party docs/RFCs and validated against an OSS corpus). Six are oxlint AST rules; four are project-level checks gated on the React Native / Expo capability and run in the environment-checks phase (skipped in diff/staged mode).

    AST rules:

    • rn-no-deep-imports — deep imports of public symbols from react-native/Libraries/* (RFC 0894; breaks on upgrade). Curated to symbols re-exported from the root, with a tailored message for the relocated NewAppScreen; skips type-only imports and the Codegen/TurboModule authoring surface.
    • rn-no-set-native-propsref.current(?.).setNativeProps(...), a silent no-op under the New Architecture (Fabric).
    • rn-no-image-children — children inside react-native's <Image> (which renders none); use <ImageBackground>. Resolves the element to the react-native import so expo-image/custom Image are ignored.
    • rn-no-panresponderPanResponder imported from react-native (JS-thread gestures); use react-native-gesture-handler.
    • rn-detox-missing-await — un-awaited Detox actions / waitFor / expect(element(...)) in *.e2e.* files.
    • expo-no-non-inlined-env — computed process.env[...] and process.env destructuring, which babel-preset-expo can't inline (value is undefined at runtime); scoped to Expo client files.

    Project-level checks:

    • rn-no-metro-babel-presetmodule:metro-react-native-babel-preset in a babel config (renamed to @react-native/babel-preset; uninstalled on RN 0.73+).
    • rn-library-react-in-dependencies — a react-native-builder-bob library listing react/react-native in dependencies instead of peerDependencies (duplicate-React / duplicate-native-module crashes).
    • expo-reanimated-v4-requires-new-archreact-native-reanimated v4 with newArchEnabled: false in the app config (first-launch crash).
    • expo-updates-no-unsafe-production-configupdates.disableAntiBrickingMeasures: true in the app config (can brick installed apps).
  • #614 daef23c Thanks @aidenybai! - rn-no-raw-text now auto-detects in-file custom text wrappers, cutting false positives on design-system <Text> forwarders. A component whose returned root is a <Text> — e.g. const Banner = ({ children }) => <Text>{children}</Text> or export const Caption = (props) => <Text {...props} /> — is treated as a string-only text forwarder, so raw text passed to it (<Banner>Hello</Banner>) no longer reports. Mixed children still report (<Banner><Icon /> hi</Banner>) because a single-<Text> forwarder can't be trusted to route a JSX child into text. Components only referenced (not defined) in the file keep the existing name-heuristic behavior, and the config-driven textComponents / rawTextWrapperComponents overrides are unchanged.

  • #617 9777f1a Thanks @rayhanadev! - Configure React Doctor with doctor.config.{ts,js,mjs,cjs,mts,cts,json} (or a package.json#reactDoctor key), and add react-doctor rules commands to list, explain, and configure rules without hand-editing config.

    • TS-first config. Author doctor.config.ts (or any JS/JSON variant) — TypeScript and ESM configs load via jiti, and JSON configs allow comments and trailing commas (JSONC).
    • rules commands. rules list shows every rule and the severity it runs at; rules explain <rule> describes why a rule matters and how to tune it; and rules set / enable / disable / category / ignore-tag / unignore-tag edit your config for you. TS/JS configs are edited in place via magicast (formatting and comments preserved); JSON and package.json are edited as data; a doctor.config.json is created when no config exists. Rule references accept the full key (react-doctor/no-danger), the bare id (no-danger), or a legacy key (react/no-danger).
    • doctor-explain skill (alias doctor-config), shipped via react-doctor install, teaches coding agents to explain a rule before disabling it and to pick the narrowest control (rule severity vs category vs tag vs surfaces).

    Breaking: the config file is now doctor.config.* instead of react-doctor.config.json. The next time you run react-doctor interactively, an existing react-doctor.config.json is automatically migrated to a typed doctor.config.ts (settings preserved, $schema dropped) and you're told once — CI, coding-agent, --staged, JSON/score, and non-TTY runs are left untouched (a warning still nudges them). The package.json#reactDoctor key is unchanged.

  • #596 6e59f10 Thanks @aidenybai! - Cleaner scan output and smarter file scoping:

    • The post-scan summary now leads with a "Top errors you should fix" block — each error shows a plain-language explanation and an inline code frame, with the rule's human title prefixed by its category (e.g. Security: Use of eval()) instead of its id, so it's clear at a glance what kind of problem it is.
    • Security rules now read as security findings: dangerouslySetInnerHTML (XSS) is categorized under Security, and security messages use explicit vulnerability language (code injection, XSS, reverse tabnabbing, CSRF, secret exposure).
    • Every rule's messages were rewritten to be short, plain, and dash-free, and each rule now carries a short title.
    • Generated bundler output (*.iife.js, *.umd.js, *.global.js, *.min.js) is now excluded from scans by default. As a result project.sourceFileCount (and the scanned-file totals) no longer count these generated bundles.
    • Minified files that carry an ordinary extension (e.g. a one-line public/inject.js bundle) are now detected by content and skipped, so they no longer flood the report with noise. Any diagnostic that still lands on an overlong single line falls back to a file:line reference instead of rendering an unreadable code frame.
    • Multi-project scans now report the number of UNIQUE files scanned, so nested workspace packages (a parent whose tree contains a child package) are no longer double-counted in the "Scanned N files" total.
  • #621 24425b1 Thanks @NisargIO! - Add Sentry crash reporting to the CLI. Uncaught errors that reach the CLI's error funnels are now captured via @sentry/node and flushed before the process exits, each enriched with a run context snapshot (version, node/platform/arch, the invocation command/argv, cwd, CI provider, coding agent, interactivity, and JSON mode) to make crashes triage-able. Sentry initializes as the first statement of the CLI entry so its global handlers are armed before any command runs, and it's scoped to the CLI only — the programmatic @react-doctor/api library never initializes Sentry.

    Reporting is opt-out: pass --no-score to disable crash reporting along with the hosted score API and share URL. The SDK is also skipped under test runs (VITEST / NODE_ENV=test).

  • #628 e9e71bb Thanks @rayhanadev! - Deepen the CLI's Sentry integration: uploaded source maps, unified tracing, and richer run context.

    • Source maps: the CLI bundle is now built with source maps, and the release pipeline injects Sentry Debug IDs into dist/cli.js and uploads the maps (scripts/sentry-sourcemaps.mjs, run from pnpm release and the @dev publish job) so crash stack traces are fully de-minified. Maps are uploaded to Sentry, not shipped in the npm tarball. Wired for both tagged releases and @dev snapshots; a no-op unless the SENTRY_AUTH_TOKEN / SENTRY_ORG / SENTRY_PROJECT CI secrets are configured.
    • Tracing / OpenTelemetry: each run is now a Sentry transaction, and the existing Effect instrumentation (runInspect plus every Effect.fn("Service.method") span) is bridged straight into Sentry as one unified per-run trace. If a user has their own OTLP backend configured (REACT_DOCTOR_OTLP_*), that still wins and the Effect trace is additionally parented under the Sentry trace so the two share a trace_id. Tracing is tunable via SENTRY_TRACES_SAMPLE_RATE (set to 0 to disable; default samples every run).
    • Crash references: when an error is reported, the Sentry event id is surfaced as a reference — printed in the CLI's error output ("Reference (mention this when reporting): …") and added to the prefilled GitHub issue — so a user-reported crash can be located in Sentry by id. Errors thrown during a scan are also linked back to that run's transaction trace (same trace_id) so the crash and its spans appear together.
    • Environment / run information: events now carry a Sentry environment (production / development, overridable via SENTRY_ENVIRONMENT), a react-doctor@<version> release that matches the uploaded source-map artifacts, and the full run snapshot as searchable tags on every event (not just exceptions) — including which command ran (command, argv), where it ran (origin = cli/ci/agent/git-hook, plus ci/ciProvider), the launching package manager (invokedVia, e.g. npm vs. pnpm dlx), and Node major version.
    • Project information: the anonymous project shape we already detect during a scan is attached to crashes and the run transaction as soon as it's discovered — searchable project.* tags (framework, React major, TypeScript, React Compiler, Expo, React Native) plus a project context block (versions of React/Tailwind/Zod/Preact/Expo, TanStack Query, Reanimated, source-file count). The identifying projectName/rootDirectory are deliberately excluded; no source code or diagnostic findings are sent.
    • Anonymized by default: every event and transaction is scrubbed before it leaves the machine — sendDefaultPii is off (no IP), the hostname/server_name/device name and captured local variables are stripped, the OS username is removed from all paths (home directory → ~) across cwd, argv, stack frames, and span attributes (e.g. the inspect.directory path), and known secrets/emails are masked via the same redactor used for diagnostics. If scrubbing ever fails, the event is dropped rather than sent.
    • Configuration: SENTRY_DSN, SENTRY_ENVIRONMENT, SENTRY_RELEASE, SENTRY_TRACES_SAMPLE_RATE, and SENTRY_DEBUG are all honored at runtime.

    Reporting remains opt-out and CLI-only: --no-score disables Sentry entirely (crash reporting and tracing), it's skipped under test runs, and the programmatic @react-doctor/api library never initializes Sentry.

  • #622 0938376 Thanks @NisargIO! - Show "warning"-severity diagnostics by default again. A scan that reports only errors is too generous a bar for a health check, so warnings surface on every surface (CLI, PR comment, score, --fail-on) out of the box. Opt out with --no-warnings or "warnings": false; per-rule / per-category severity overrides still win as before.

  • #596 6e59f10 Thanks @aidenybai! - Hide warning-severity diagnostics by default — a clean scan now reports only error-severity findings (errors always show). Opt warnings back in with the --warnings flag or "warnings": true config option; --no-warnings / "warnings": false is the explicit default-off. The toggle is the master switch and runs after per-rule / per-category severity overrides, so a rule explicitly set to "warn" via rules / categories still shows even when warnings are hidden.

    Because dead-code analysis only emits warning-severity findings, it's now skipped entirely when warnings are hidden (its results would be filtered out anyway) — avoiding an expensive analysis pass on the default path. --warnings / "warnings": true (and --fail-on warning) re-enable it.

  • Updated dependencies [6e59f10, 75c1f99]:

    • oxlint-plugin-react-doctor@0.2.15

@react-doctor/api@0.2.15

Patch Changes

@react-doctor/core@0.2.15

Patch Changes

  • #596 6e59f10 Thanks @aidenybai! - Collapse diagnostic categories into five clear, outcome-based buckets: Security, Bugs, Performance, Accessibility, and Maintainability. The previous fine-grained labels (Correctness, State & Effects, React Compiler, Next.js, React Native, Server, TanStack Query/Start, Preact → Bugs; Bundle Size → Performance; Architecture/Design → Maintainability) now roll up so the scan output reads as plain issue types at a glance.

    This changes the category value on every diagnostic (CLI output, the per-error headline prefix like Security: Use of eval(), and JSON/programmatic output). If you key categories severity overrides off the old names, update them to the new buckets. Dead-code findings (unused files/exports/dependencies, circular imports) now report Maintainability instead of Dead Code. Bundle-size findings now sort with Performance (higher stakes) rather than near the bottom of the top-errors block.

  • #596 6e59f10 Thanks @aidenybai! - Fix dead-code analysis silently failing ("Scanning failed (dead-code analysis, non-fatal).") on type-heavy projects. deslop's semantic pass builds a full TypeScript program and walks every identifier through the type checker; on projects with large generic types (tRPC routers, Effect/Zod schemas, deep generics) the checker instantiates enormous types and the child process exceeds Node's default ~4 GB heap, dying with an uncatchable "JavaScript heap out of memory" that surfaced as empty worker output and a non-fatal scan failure. The dead-code worker child is now spawned with --max-old-space-size=8192 so those projects complete instead of crashing.

  • Updated dependencies [6e59f10, 75c1f99]:

    • oxlint-plugin-react-doctor@0.2.15

Note

Low Risk
The PR only updates versions and changelogs; risk to the repo is low, though the published 0.2.15 notes include a breaking config filename migration and new default telemetry unless users opt out.

Overview
This is a Changesets release PR: it removes consumed .changeset/*.md entries, bumps workspace packages from 0.2.14 → 0.2.15, and records the aggregated notes in each package CHANGELOG.md. There is no application source diff here—only versioning and release metadata.

What ships as 0.2.15 (documented in the changelogs): react-doctor and plugins gain Expo/RN diagnostics, expo-doctor-style project checks, doctor.config.* + react-doctor rules CLI, scan output and category rollup (Security / Bugs / Performance / Accessibility / Maintainability), secret redaction in diagnostics, optional Sentry crash reporting/tracing (opt-out via --no-score), --experimental-parallel, dead-code fixes (symlinked roots, 8GB worker heap), oxc-parser as a real dependency for pnpm consumers, and many rule/CLI papercuts. Breaking for users: config moves from react-doctor.config.json to doctor.config.* (interactive migration to doctor.config.ts); update categories overrides if they used old category names.

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

@github-actions github-actions Bot force-pushed the changeset-release/main branch 30 times, most recently from a041bf5 to c9ba5e1 Compare June 1, 2026 11:26
@github-actions github-actions Bot force-pushed the changeset-release/main branch from c9ba5e1 to 097854e Compare June 1, 2026 11:33
@NisargIO NisargIO merged commit 66f9d64 into main Jun 1, 2026
5 checks passed
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.

Publish a JSON schema for react-doctor.config.json

1 participant