Conversation
…rall score (millionco#780) Co-authored-by: Cursor <cursoragent@cursor.com>
…ionco#776) (millionco#782) * fix(only-export-components): skip framework route/special files (millionco#776) Recognize the route/special files of every file-routing framework react-doctor covers (Next.js, Expo Router, TanStack Router, Remix / React Router) via a single `isFrameworkRouteOrSpecialFilename` helper, so the documented "co-export config/metadata next to the default component" shape no longer triggers false-positive non-component-export warnings. Fixes the `alt` / `size` / `contentType` / `revalidate` exports in `opengraph-image.tsx`. Co-authored-by: Cursor <cursoragent@cursor.com> * fix: change variable name Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com> * fix: update usages as well --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: devin-ai-integration[bot] <158243242+devin-ai-integration[bot]@users.noreply.github.com>
… metadata (millionco#784) Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
… repos (millionco#791) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… files (millionco#790) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…ths, and config `projects` (millionco#771) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
…lionco#792) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…ts (millionco#796) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…ase bindings (millionco#794) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…tic message (millionco#793) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…g enableBabelRuntime (millionco#801) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: D N <4661784+retyui@users.noreply.github.com>
…ocal node_modules (millionco#800) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…gnostics (millionco#804) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
Co-authored-by: Aiden Bai <aiden.bai05@gmail.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com>
millionco#808) (millionco#809) Co-authored-by: Aiden Bai <aiden.bai05@gmail.com>
…illionco#807) (millionco#823) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
… rules (millionco#826) * feat(rules): add 8 mined correctness, performance, a11y, and security rules Mined from a 12-cluster pass over the design/engineering brain and synthesized into docs/rule-candidates-backlog.md. Ships the highest-signal, lowest-noise batch, each with adversarial + FP-regression tests: - no-call-component-as-function (Bugs) - no-create-ref-in-function-component (Bugs) - no-async-effect-callback (Bugs) - no-json-parse-stringify-clone (Performance) - img-missing-dimensions (Performance) - no-img-lazy-with-high-fetchpriority (Performance) - dialog-has-accessible-name (Accessibility) - auth-token-in-web-storage (Security) Adds the shared has-jsx-spread-attribute util and registers the three in-house ported-bucket rules in RULES_NOT_PORTED_FROM_EXTERNAL. * fix(rules): drop img-missing-dimensions; make component rules shadow-safe - Drop `img-missing-dimensions`: width/height attributes are only one of several valid ways to reserve space (CSS aspect-ratio, container sizing), and the authoritative signal lives in stylesheets a static linter can't see. This is a runtime check (Lighthouse `unsized-images`), so a syntax rule would false-positive on any CSS-sized image. - `no-call-component-as-function`: resolve the callee through its scope symbol instead of by name, so a parameter/local shadowing a component name is no longer flagged. The component signal is the binding's declaration (same-file component returning JSX) or an imported binding also rendered as JSX. - `no-create-ref-in-function-component`: skip a shadowing local `createRef` (only flag React's import / `React.createRef`). - Adds shadow-safety regression tests for both. * fix(rules): tag no-call-component-as-function test-noise (eval finding) An OSS eval sweep (react-use, radix primitives, excalidraw, mantine; ~2.8k diagnostics) showed every real-world hit of this rule was a test render-helper (`render(Wrapper({...}))` in `.test.tsx`/`.story.tsx`) — harmless for hookless wrappers and the dominant firing surface. Tag it `test-noise` so it skips test/story/playground files and only nags shipped code. The sweep also confirmed dialog-has-accessible-name (2 real a11y bugs in excalidraw) and no-create-ref-in-function-component (1 real bug in a mantine story) as true positives with zero false positives.
…o#857) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ory (millionco#858) (millionco#860) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…illionco#864) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…lionco#861) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rops (millionco#862) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ngerouslySetInnerHTML (millionco#865) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…#866) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o#881) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… React files change (millionco#863) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ionco#883) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…positive (millionco#859) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ask (millionco#882) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…o#884) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…bump Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rency) (millionco#885) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…CLI, root-commit diff) (millionco#888) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix: skip pnpm hardening check for monorepo sub-packages Only check pnpm hardening settings at the workspace root or standalone pnpm projects. Sub-packages of a pnpm workspace inherit hardening from the workspace root's pnpm-workspace.yaml, so emitting diagnostics with synthesized file paths for each sub-package is incorrect. Fixes millionco#878 Co-authored-by: Skosh <skoshx@users.noreply.github.com> * chore: add changeset for pnpm hardening fix Co-authored-by: Skosh <skoshx@users.noreply.github.com> * chore: format test file Co-authored-by: Skosh <skoshx@users.noreply.github.com> * refactor: rename rootDirectory to scanDirectory in checkPnpmHardening The parameter name was misleading - call sites pass scanDirectory, not a root directory. Co-authored-by: Skosh <skoshx@users.noreply.github.com> * refactor: deslop pnpm-hardening monorepo-skip change Defer findMonorepoRoot inside the !hasWorkspaceFile guard so the ancestor walk only runs when its result is used, and fold the parent-workspace check into one short-circuit condition (one fewer nesting level, behavior unchanged). Extract expectMissingHardeningWarnings to collapse four repeated assertion groups in the monorepo test block. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Cursor Agent <cursoragent@cursor.com> Co-authored-by: Skosh <skoshx@users.noreply.github.com> Co-authored-by: Rayhan Noufal Arayilakath <me@rayhanadev.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…illionco#893) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rk (millionco#907) Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…l changes (millionco#906) * fix(cli): make GitHub Actions setup flow idempotent and stop bundling local changes (millionco#904) The setup flow opened duplicate PRs and swept unrelated local changes into the generated branch. Two root causes in `openWorkflowPullRequest`: 1. Non-idempotent: `findUniqueBranchName` only avoided a *local* branch collision by appending a timestamp, and nothing checked for an already-open setup PR. A re-run (the workflow file lives only on the prior PR's branch, so it's re-written each run) minted `…-<timestamp>` branches and opened a second PR. Now we `gh pr list` for an open PR whose head is under the setup prefix and surface it (`pr-exists`) instead of opening a duplicate. 2. Dirty-tree bundling: `git checkout -b <new> origin/<default>` carries the index across and the whole-index `git commit` then committed whatever the user had staged (modified app files, a deleted/rewritten lockfile). Now we bail (`working-tree-dirty`) when the tree has tracked changes other than the workflow file itself, falling back to staging the workflow file. The workflow path is excluded from the check so the v1→v2 upgrade flow (which modifies the tracked workflow in place) still works. Both callers handle the new `pr-exists` status; the runner / gh-availability probe are now injectable for hermetic tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(cli): harden setup-flow fix from adversarial review Findings from an adversarial review+deslop pass over the millionco#904 fix: - fix(correctness): normalize `workflowRelative` with `toForwardSlashes` so the `:!` exclude pathspec matches git's forward-slash repo paths on Windows. Without it, `path.relative` yields backslashes there, git's magic pathspec doesn't treat them as separators, and the upgrade flow (tracked workflow modified in place) would always report `working-tree-dirty` and never open the PR. Applied in `openWorkflowPullRequest` and `stageWorkflowFile`. - fix(correctness): on the upgrade flow's `pr-exists` path, restore the original @v1 workflow content. `pr-exists` returns without touching git state, so the @v2 edit written before the call would otherwise linger uncommitted — matching the pr-opened path's "bump lives only on the PR branch" contract. - chore: extract the `gh pr list` cap to `GH_PR_LIST_MAX` in constants.ts (AGENTS.md: no inline magic numbers). - test: assert the dirty-tree guard skips add/commit/push (not just checkout), the happy path stages ONLY the workflow file (no `git add -A`/`.`), and branch-pushed keeps the branch (no `git branch -D`) and restores HEAD. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(cli): trigger duplicate-PR guard on match presence, not URL truthiness Bot review (Cursor) flagged that the idempotency short-circuit keyed on a truthy URL: if `gh pr list` returned a matching setup head branch with a missing/empty `url`, `findExistingSetupPullRequest` returned null and the flow could still mint a branch and open a duplicate PR — the exact failure the guard exists to prevent. `gh` always populates `url` for `--json url`, so this is defensive, but the headline millionco#904 guarantee shouldn't hinge on it. Return the matched PR object and short-circuit on its existence; use its url only for the `pr-exists` message (empty when absent). Adds a regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…in (millionco#903) Integrates the 7 large-repo speedup PRs (millionco#894–millionco#900) plus the dead-code reworks done on top of them. Headline (measured on Sentry, supply-chain on): full scan ~142s → ~40s (3.6x), with dead-code findings fully intact. - deslop: skip the analysis passes react-doctor discards — the semantic TS-Program pass and the code-quality detectors (duplicate-block/complexity/ feature-flag/TS-smell/private-type-leak/re-export-cycle), gated behind a new `reportCodeQuality` flag (default on for deslop standalone). ~8.5x faster dead-code on a large repo, byte-identical consumed findings, locked by a parity test. - Dead-code runs sequentially by default with a file-count-scaled timeout, fixing a regression where overlapping it with lint oversubscribed the cores and silently dropped all dead-code findings under supply-chain. Opt-in `REACT_DOCTOR_DEAD_CODE_OVERLAP=on` now splits the core budget instead of doubling it. - Plus the merged PRs: memory-budgeted worker cap (millionco#896), bounded-phase hard timeouts (millionco#899), supply-chain∥lint overlap (millionco#894), per-file lint cache (millionco#900), deterministic diagnostics (millionco#897), module-cache dedup (millionco#895). CI: full test matrix (macOS/Ubuntu 20–26/Windows), build, typecheck, lint, and react-doctor smoke all green. The 1s "CodeQL" check is the pre-existing code-scanning-alert gate (main's CodeQL analysis is green); no security-relevant code changed.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated upstream sync.
millionco/react-doctor@mainmainis synced up to upstream627f9ca4b363.Commits this PR brings onto
pinnedpr-filespasses repo-relative paths to a subdirectory scan, so baseline reads miss and pre-existing issues are reported as new millionco/react-doctor#858) (fix(action): resolve PR changed-file paths against the scanned directory (#858) millionco/react-doctor#860) (Ray Arayilakath)why <file>:<line>(fix(cli): show the source code frame inwhy <file>:<line>millionco/react-doctor#857) (Ray Arayilakath)execute:handler key andfetchin description strings millionco/react-doctor#838) (fix(agent-tool-capability-risk): ignore capability keywords in string literals (#838) millionco/react-doctor#847) (Ray Arayilakath)ignore.filesfiles in deslop's graph (#830) millionco/react-doctor#832) (devin-ai-integration[bot]).validator()server-fn method (TanStack Start: rules still use deprecatedinputValidatorinstead ofvalidatormillionco/react-doctor#808) (fix(tanstack-start): recognize current.validator()server-fn method (#808) millionco/react-doctor#809) (devin-ai-integration[bot])react-doctor/apiimports in doctor.config.ts without local node_modules (fix: resolvereact-doctor/apiimports in doctor.config.ts without local node_modules millionco/react-doctor#800) (devin-ai-integration[bot])projects(feat: per-module scoring via diagnose({ projects }), CLI --project paths, and configprojectsmillionco/react-doctor#771) (devin-ai-integration[bot])Merge with a merge commit — do not squash or rebase. Squashing rewrites these commits
under new SHAs, so the next sync would see them as unmerged and reopen an ever-growing PR.
A merge commit keeps
main's commits reachable frompinned, which is how thisworkflow detects that the sync is done.
Conflicts on the harden commit's files are expected and shown in the PR UI; resolve them in the merge.
Opened by the
sync-upstreamworkflow. Do not auto-merge.