Skip to content

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

Merged
aidenybai merged 13 commits into
mainfrom
feat/user-feedback-issues
May 12, 2026
Merged

feat: address user feedback — reduce false positives, improve scoring transparency, and add config options#208
aidenybai merged 13 commits into
mainfrom
feat/user-feedback-issues

Conversation

@aidenybai
Copy link
Copy Markdown
Member

@aidenybai aidenybai commented May 11, 2026

Summary

  • Reduce false positives: suppress React 19 deprecation rules (forwardRef, defaultProps) on React 18 via new migration-hint version gate; add sleep/delay and paginated-fetch heuristics to asyncAwaitInLoop; skip rn-no-raw-text for .web.* files; remove the noEmDashInJsxText rule (em dashes are standard punctuation)
  • Add config options: offline (score locally without API), designRules (toggle opinionated design rules), entryFiles (tell knip about runner entry points to avoid dead-code false positives)
  • Scoring transparency: export calculateScoreBreakdown, show the formula and contributing rules in --verbose output, document the scoring formula in README
  • Documentation: add Scoring, Diff/staged modes, and Agent/CI integration sections to README
  • Release process: switch to @changesets/changelog-github for PR-linked entries, add release.yml workflow for automatic GitHub Releases on publish

Test plan

  • pnpm typecheck passes
  • pnpm lint passes
  • pnpm format:check passes
  • pnpm test passes (706 tests, 51 files)
  • Verify --verbose shows score breakdown on a real project
  • Verify designRules: false in config suppresses design rules
  • Verify .web.tsx files are not flagged by rn-no-raw-text
  • Verify entryFiles config forwards to knip correctly

Made with Cursor


Note

Medium Risk
Moderate risk: changes rule enablement/gating and diagnostic filtering (including new auto-suppression heuristics) plus introduces new browser build artifacts and release automation, which could alter lint/score outputs and publishing behavior.

Overview
Adds automated publishing via a new GitHub Actions release workflow and switches Changesets to @changesets/changelog-github for PR-linked changelogs.

Reduces noisy diagnostics and makes scoring more controllable: introduces config options for offline scoring, ignore.tags (tag-based rule suppression, e.g. design rules), and entryFiles forwarded to knip; refactors oxlint rule selection to a capability/metadata model (React/Tailwind/framework gates) and updates React major detection to respect peer ranges.

Improves output transparency and resilience: prints a verbose score formula + contributing rules, exports calculateScoreBreakdown, auto-suppresses test-noise-tagged rules in test-like paths and suppresses knip “unused file” hits that look like build entry points, and tweaks several rules to reduce false positives (e.g. asyncAwaitInLoop, rn-no-raw-text for .web.*). Also removes the design-no-em-dash-in-jsx-text rule and adds an experimental browser-poc entry/bundle (with wasm loader) for in-browser diagnostics collection.

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

aidenybai and others added 2 commits May 10, 2026 01:33
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>
… 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>
@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 11, 2026

React health score gauge

React Review found 0 ❌ errors and 7 ⚠️ warnings. This PR leaves the React health score unchanged.

Copy prompt for agent
Check if these React Review issues are valid. If so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issues instead of changing or suppressing the rules.

React Review found 0 errors and 7 warnings. This PR leaves the React health score unchanged.

<file name="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx">

<violation number="1" location="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx:57">
Severity: Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a `for…of` loop or `await Promise.all(items.map(async (item) => {...}))`

Collect the items and use `await Promise.all(items.map(...))` to run independent operations concurrently

Rule: `async-await-in-loop`
</violation>

<violation number="2" location="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx:69">
Severity: Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a `for…of` loop or `await Promise.all(items.map(async (item) => {...}))`

Collect the items and use `await Promise.all(items.map(...))` to run independent operations concurrently

Rule: `async-await-in-loop`
</violation>

</file>

<file name="packages/react-doctor/tests/fixtures/browser-poc/app.tsx">

<violation number="1" location="packages/react-doctor/tests/fixtures/browser-poc/app.tsx:17">
Severity: Warning

fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component

Use `useQuery()` from @tanstack/react-query, `useSWR()`, or fetch in a Server Component instead

Rule: `no-fetch-in-effect`
</violation>

</file>

<file name="packages/react-doctor/src/browser-poc.ts">

<violation number="1" location="packages/react-doctor/src/browser-poc.ts:16">
Severity: Warning

Import from barrel/index file — import directly from the source module for better tree-shaking

Import from the direct path: `import { Button } from './components/Button'` instead of `./components`

Rule: `no-barrel-import`
</violation>

<violation number="2" location="packages/react-doctor/src/browser-poc.ts:204">
Severity: Warning

array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

Use a `Set` or `Map` for repeated membership tests / keyed lookups — `Array.includes`/`find` is O(n) per call

Rule: `js-set-map-lookups`
</violation>

</file>

<file name="packages/react-doctor/src/utils/calculate-score-locally.ts">

<violation number="1" location="packages/react-doctor/src/utils/calculate-score-locally.ts:62">
Severity: Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use `array.toSorted()` (ES2023) instead of `[...array].sort()` for immutable sorting without the spread allocation

Rule: `js-tosorted-immutable`
</violation>

<violation number="2" location="packages/react-doctor/src/utils/calculate-score-locally.ts:63">
Severity: Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use `array.toSorted()` (ES2023) instead of `[...array].sort()` for immutable sorting without the spread allocation

Rule: `js-tosorted-immutable`
</violation>

</file>

Reviewed by react-review for commit 44ee9ae. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 11, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
react-doctor-website Ready Ready Preview, Comment May 12, 2026 2:46am

} from "bippy";
import { initSync, parseSync } from "@oxc-parser/wasm/web/oxc_parser_wasm.js";
import oxcParserWasmBytes from "@oxc-parser/wasm/web/oxc_parser_wasm_bg.wasm";
import reactDoctorPlugin from "./plugin/index.js";
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Import from barrel/index file — import directly from the source module for better tree-shaking

Import from the direct path: import { Button } from './components/Button' instead of ./components

Rule: no-barrel-import

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/src/browser-poc.ts">

<violation number="1" location="packages/react-doctor/src/browser-poc.ts:16">
Severity: Warning

Import from barrel/index file — import directly from the source module for better tree-shaking

Import from the direct path: `import { Button } from './components/Button'` instead of `./components`

Rule: `no-barrel-import`
</violation>

</file>

Reviewed by react-review for commit 381b4fb. Configure here.

const lineNumber = Number(match[2]);
const columnNumber = Number(match[3]);
if (!fileName || !Number.isFinite(lineNumber)) continue;
if (fileName.includes("/node_modules/")) continue;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

Use a Set or Map for repeated membership tests / keyed lookups — Array.includes/find is O(n) per call

Rule: js-set-map-lookups

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/src/browser-poc.ts">

<violation number="1" location="packages/react-doctor/src/browser-poc.ts:204">
Severity: Warning

array.includes() in a loop is O(n) per call — convert to a Set for O(1) lookups

Use a `Set` or `Map` for repeated membership tests / keyed lookups — `Array.includes`/`find` is O(n) per call

Rule: `js-set-map-lookups`
</violation>

</file>

Reviewed by react-review for commit 381b4fb. Configure here.

const totalPenalty = errorPenalty + warningPenalty;
const score = Math.max(0, Math.round(PERFECT_SCORE - totalPenalty));
return {
errorRules: [...errorRules].sort(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use array.toSorted() (ES2023) instead of [...array].sort() for immutable sorting without the spread allocation

Rule: js-tosorted-immutable

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/src/utils/calculate-score-locally.ts">

<violation number="1" location="packages/react-doctor/src/utils/calculate-score-locally.ts:62">
Severity: Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use `array.toSorted()` (ES2023) instead of `[...array].sort()` for immutable sorting without the spread allocation

Rule: `js-tosorted-immutable`
</violation>

</file>

Reviewed by react-review for commit 381b4fb. Configure here.

const score = Math.max(0, Math.round(PERFECT_SCORE - totalPenalty));
return {
errorRules: [...errorRules].sort(),
warningRules: [...warningRules].sort(),
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use array.toSorted() (ES2023) instead of [...array].sort() for immutable sorting without the spread allocation

Rule: js-tosorted-immutable

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/src/utils/calculate-score-locally.ts">

<violation number="1" location="packages/react-doctor/src/utils/calculate-score-locally.ts:63">
Severity: Warning

[...array].sort() — use array.toSorted() for immutable sorting (ES2023)

Use `array.toSorted()` (ES2023) instead of `[...array].sort()` for immutable sorting without the spread allocation

Rule: `js-tosorted-immutable`
</violation>

</file>

Reviewed by react-review for commit 381b4fb. Configure here.

const DemoUserCard = ({ userID }: DemoUserCardProps) => {
const [name, setName] = React.useState("loading");

React.useEffect(() => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component

Use useQuery() from @tanstack/react-query, useSWR(), or fetch in a Server Component instead

Rule: no-fetch-in-effect

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/tests/fixtures/browser-poc/app.tsx">

<violation number="1" location="packages/react-doctor/tests/fixtures/browser-poc/app.tsx:17">
Severity: Warning

fetch() inside useEffect — use a data fetching library (react-query, SWR) or server component

Use `useQuery()` from @tanstack/react-query, `useSWR()`, or fetch in a Server Component instead

Rule: `no-fetch-in-effect`
</violation>

</file>

Reviewed by react-review for commit 381b4fb. Configure here.

Comment thread packages/react-doctor/src/scan.ts Outdated
Comment thread packages/react-doctor/src/oxlint-config.ts Outdated
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>
Comment thread packages/react-doctor/src/utils/discover-project.ts Outdated
Comment thread packages/react-doctor/README.md Outdated
- 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>
framework: projectInfo.framework,
hasReactCompiler: projectInfo.hasReactCompiler,
hasTanStackQuery: projectInfo.hasTanStackQuery,
reactMajorVersion: parseReactMajor(projectInfo.reactVersion),
Copy link
Copy Markdown

@vercel vercel Bot May 12, 2026

Choose a reason for hiding this comment

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

The programmatic API diagnose() ignores ignore.tags and entryFiles config options that the CLI correctly handles

Fix on Vercel

Keep capabilities-based architecture, incorporate Tailwind version
detection and test file from merged branch. Fix Tailwind null vs
unparseable distinction in buildCapabilities.

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/react-doctor/src/utils/is-likely-build-entry.ts
- 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>
Comment thread packages/react-doctor/src/oxlint-config.ts Outdated
Comment thread packages/react-doctor/src/utils/merge-and-filter-diagnostics.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/react-doctor/src/plugin/rules/js-performance.ts Outdated
Comment thread packages/react-doctor/src/utils/parse-react-peer-range.ts Outdated
Comment thread packages/react-doctor/src/oxlint-config.ts
…new Promise false negative

Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/react-doctor/src/index.ts
Comment thread packages/react-doctor/src/index.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/react-doctor/src/plugin/rules/js-performance.ts
Comment thread packages/react-doctor/src/scan.ts
Co-authored-by: Cursor <cursoragent@cursor.com>
Comment thread packages/react-doctor/src/plugin/rules/js-performance.ts
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>

export const throttledForEach = (items: string[]) => {
items.forEach(async (item) => {
await sleep(500);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a for…of loop or await Promise.all(items.map(async (item) => {...}))

Collect the items and use await Promise.all(items.map(...)) to run independent operations concurrently

Rule: async-await-in-loop

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx">

<violation number="1" location="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx:57">
Severity: Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a `for…of` loop or `await Promise.all(items.map(async (item) => {...}))`

Collect the items and use `await Promise.all(items.map(...))` to run independent operations concurrently

Rule: `async-await-in-loop`
</violation>

</file>

Reviewed by react-review for commit 37461a8. Configure here.

export const paginatedForEach = async (cursors: string[]) => {
let token = "start";
cursors.forEach(async () => {
const page = await fetchPage(token);
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a for…of loop or await Promise.all(items.map(async (item) => {...}))

Collect the items and use await Promise.all(items.map(...)) to run independent operations concurrently

Rule: async-await-in-loop

Copy prompt for agent
Check if this React Review issue is valid. If so, understand the root cause and fix it.

Run this before and after your changes to verify the result:
npx react-doctor@latest --verbose --diff

Do not modify the react-doctor configuration unless explicitly asked.
Fix the underlying code issue instead of changing or suppressing the rule.

<file name="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx">

<violation number="1" location="packages/react-doctor/tests/fixtures/basic-react/src/async-and-handler-issues.tsx:69">
Severity: Warning

Async callback in .forEach — return values are dropped, so awaits don't actually wait. Use a `for…of` loop or `await Promise.all(items.map(async (item) => {...}))`

Collect the items and use `await Promise.all(items.map(...))` to run independent operations concurrently

Rule: `async-await-in-loop`
</violation>

</file>

Reviewed by react-review for commit 37461a8. Configure here.

gh release create "$TAG" \
--title "$TAG" \
--generate-notes \
--target main || true
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

GitHub Actions shell injection via direct output interpolation

Low Severity

The ${{ steps.changesets.outputs.publishedPackages }} value is interpolated directly into a run: shell script. If a package name or version in the output contains shell metacharacters (e.g., a single quote), it could break out of the echo '...' command and execute arbitrary shell commands. The safer pattern is to pass the output via an environment variable (e.g., env: PACKAGES: ${{ steps.changesets.outputs.publishedPackages }}) and reference $PACKAGES in the script, which avoids shell interpretation of the value.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 37461a8. Configure here.

Comment thread packages/react-doctor/src/plugin/index.ts
Comment thread packages/react-doctor/src/oxlint-config.ts
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>
Comment thread packages/react-doctor/src/utils/run-oxlint.ts
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.

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

@cursor cursor Bot left a comment

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 and found 2 potential issues.

There are 3 total unresolved issues (including 1 from previous review).

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 44ee9ae. Configure here.

const timings = getTimings(fiber);
record.selfTime = timings.selfTime;
record.totalTime = timings.totalTime;
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Browser POC overwrites timing instead of accumulating

Low Severity

In collectFiber, selfTime and totalTime are assigned (overwritten) on each call, while instanceCount and commitCount are accumulated with += 1. When multiple fiber instances share the same component type, only the last-visited instance's timing survives. This inconsistency means timing data is silently lost for all but one instance, making the BrowserPocComponentRecord report unreliable aggregated counts but single-instance timings.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 44ee9ae. Configure here.

const record = getRecord(fiber);
if (!record) return;
record.instanceCount += 1;
record.commitCount += 1;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Browser POC commitCount overcounts per fiber instance

Low Severity

record.commitCount += 1 increments once per fiber instance during each tree traversal, not once per commit cycle. A component type with 5 mounted instances increments commitCount by 5 each commit, making the value represent "total instance-visits across all commits" rather than "number of commits involving this component." The field name and interface documentation suggest per-commit granularity.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 44ee9ae. Configure here.

@aidenybai aidenybai merged commit 8556b31 into main May 12, 2026
6 checks passed
cursor Bot pushed a commit that referenced this pull request May 12, 2026
…rebase)

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
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