The composite Action is versioned independently from the npm packages via
v-prefixed semver tags (vX.Y.Z) plus a floating major (vN), distinct from
the Changesets `<pkg>@X.Y.Z` tags. Documents the bump rules, the signed-tag
gotcha, and the release/floating-major commands.
Co-authored-by: Cursor <cursoragent@cursor.com>
Replace the mutable `millionco/react-doctor@main` reference in the GitHub
Actions example with the `@v1` floating release tag, and add a note on
pinning to a full commit SHA for hardened CI (the example grants
`pull-requests: write`). Avoids running whatever `main` points at runtime.
Co-authored-by: Cursor <cursoragent@cursor.com>
`canAnimateOnboarding` only excluded CI, so a git hook invoked by an
interactive `git commit` (real inherited TTY, `GIT_DIR` set) would play
the score-bar count-up and onboarding pacing, emitting cursor escapes
into hook output (issue #293). Add `isGitHookEnvironment()` and gate it
out, while keeping the deliberate coding-agent real-TTY animation.
`--diff` now accepts git's own range syntax: two-dot `A..B` (diff A
directly against B) and three-dot `A...B` (diff from the merge-base of A
and B to B). Each endpoint is individually validated against the
anti-injection guard, so a range can't smuggle a `--upload-pack=`-style
option past it, and an empty endpoint defaults to HEAD (`main..` means
`main..HEAD`).
An invalid `--diff` value (a malformed ref/range, or a base branch that
hasn't been fetched) is now rendered as a clean, single-line message and
exits non-zero. It no longer prints the generic "Something went wrong,
open a prefilled issue" block or reports the expected user error to
Sentry: getDiffInfo now propagates the tagged ReactDoctorError so the CLI
dispatches on reason._tag via the new isUserInputError classifier.
Fixes REACT-DOCTOR-9
Co-authored-by: Cursor <cursoragent@cursor.com>
Downgrade the four `minor` changesets (CLI color/version/help,
experimental parallel lint workers, Sentry crash reporting, and
warnings-shown-by-default) to `patch` so the next release is a single
patch bump.
Co-authored-by: Cursor <cursoragent@cursor.com>
Show "warning"-severity diagnostics by default again — a scan that reports only errors is too low a bar for a health check. Warnings reach every surface (CLI, PR comment, score, --fail-on); opt out with --no-warnings or "warnings": false. Per-rule / per-category severity overrides still win.
CLI output rework:
- Inline code frames are reserved for errors; warnings list their file:line sites compactly so a long tail of low-severity findings stays scannable.
- Non-verbose warnings roll up into a capped rule×count list (+N more rules → --verbose); errors get the same overflow line past the top 3.
- Audience-aware fix links in --verbose: coding agents get a cache-busting fetch directive, humans get a "Learn more" docs link under the rule name.
- Closing Docs note pointing to CI/CD setup, config-based rule suppression, and diff/PR scanning.
Internal: a single buildSortedRuleGroups primitive backs every rule-list surface (category breakdown, top errors, warnings roll-up, verbose detail, agent handoff, on-disk dump); shared warning-header and site-badge helpers remove the duplicated rendering.
* feat(cli): add Sentry crash reporting
Capture uncaught CLI errors via @sentry/node, flushed before the process
exits and enriched with a run-context snapshot (version, node/platform/
arch, invocation command/argv, cwd, CI provider, coding agent,
interactivity, JSON mode). Initialized as the first statement of the CLI
entry and scoped to the CLI only — the @react-doctor/api library never
initializes Sentry. Opt out via --no-score (also skipped under tests).
Co-authored-by: Cursor <cursoragent@cursor.com>
* refactor(cli): consolidate CI/agent detection into is-ci-environment
build-run-context re-declared CI provider and coding-agent env-var maps
that mirrored is-ci-environment. Move the label maps and the
detectCiProvider/detectCodingAgent resolvers into is-ci-environment as the
single source of truth, derive the flat agent env-var list from the brand
map, and have isCodingAgentEnvironment derive from detectCodingAgent.
Behavior is unchanged (env-detection tests still green).
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
ascend() re-descended the same definition subtrees on every recursion step,
so the seven State & Effects rules (led by no-pass-data-to-parent) blew up
superlinearly on large effect-heavy components — re-walking and re-scoping
identical bodies across recursion, across effects, and across rules.
Cache the downstream-reference lookup per Program node in a WeakMap keyed on
the per-Program analysis singleton (GC-bound with the file, no cross-file
bleed). Callers only ever read the returned array, so sharing it is safe.
On an 866-file Next.js app this cut ~9s (~24%) off a full scan — the worst
rule on a 1,159-line / 10-effect component dropped from ~9.5s to ~0.18s, and
the hot lint batch from ~13.5s to ~2.5s — with byte-identical diagnostics
(verified by a SHA-256 fingerprint over every diagnostic before/after).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tell the handed-off agent to verify each fix against the canonical recipe
and re-run the scan (don't assume), and add a section instructing it to
explain in plain language what each issue is, why it matters, and how
severe it is in human terms.
* feat: order the diagnostics dump by rule priority
Users report that `npx react-doctor` prints a large, undifferentiated dump and
they don't know what to tackle first. The score API now returns an intrinsic
priority/tier per rule; surface it so the dump leads with what's most worth
fixing instead of ordering purely by severity.
- core: `ScoreResult` carries the API's `rules: {ruleKey: {priority, tier}}`
payload (new `RulePriority`/`RuleTier` types); `parseScoreResult` captures it.
- CLI: rule-groups and categories sort by `effectivePriority` (API priority
desc). Unranked rules get a severity-based midpoint; with no score at all
(`--no-score` / API unreachable) ordering degrades to the previous
error-before-warning + count order, so there is no regression offline.
No priority table is duplicated here — the engine remains the single source of
truth and the values arrive over the score API.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(cli): improve error handling for command execution failures
* refactor(core): validate the score API response with effect/Schema
Replace the hand-rolled type guards in `parseScoreResult`/`parseRulePriorities`
with `effect/Schema` (the schema lib already used across @react-doctor/core, see
schemas.ts) — `Schema.Struct` + `Schema.Literals` + `Schema.Record` decoded via
`decodeUnknownOption`. A malformed payload decodes to null and falls back to the
severity ordering, same as before. Result types are now `readonly` to match the
decoded shape.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>