Skip to content

feat: config foundation — extends, zod validation, concurrency, barrelAllowlist#287

Closed
aidenybai wants to merge 1 commit into
mainfrom
cursor/config-foundation-675b
Closed

feat: config foundation — extends, zod validation, concurrency, barrelAllowlist#287
aidenybai wants to merge 1 commit into
mainfrom
cursor/config-foundation-675b

Conversation

@aidenybai
Copy link
Copy Markdown
Member

First of a three-PR split of #286 ("Support mature-codebase adoption workflows natively"). This one lands the foundational config surface; the next two stack on top of it.

Why this PR exists

Three independent config knobs grouped on a shared zod-based validator. None of these change the scan execution path — they affect config loading, project orchestration, and one rule's allowlist.

What's in it

extends — config inheritance

{
  "extends": ["../../react-doctor.base.json"],
  "customRulesOnly": true
}
  • One or more parent configs, string or string array. Each parent can itself extend further.
  • Cycle and depth guards (max 16) keep pathological configs from hanging the loader.
  • Semantics match tsconfig / eslint: later entries override earlier ones on scalar conflicts; arrays concat + dedupe; nested objects merge field-by-field; the current config always wins over anything it extends.
  • Tests cover deep chains, missing parents, array concat, and cycle breakage through symlinked directories.

zod-based validation framework

Replaces ~280 lines of hand-rolled typeof === "..." / Array.isArray / isPlainObject checks in validate-config-types.ts with a declarative zod schema map.

  • One FieldDescriptor entry per ReactDoctorConfig field ({ expectedDescription, schema }).
  • One parseFieldOrWarn helper preserves the exact stderr message shape the existing --json mode and the 14 validate-config-types tests rely on (config field "X" must be …; ignoring this field).
  • filteringArrayTransform higher-order helper unifies the drop-and-warn-but-keep-valid-siblings semantics across extends, barrelAllowlist, and the surface include/exclude lists.
  • 8 boolean fields generated from a single array instead of being hand-spelled three times each.
  • zod ^4 added as a dependency of @react-doctor/core.

concurrency — parallel runner

react-doctor . --concurrency 4
  • --concurrency <n> CLI flag + top-level concurrency config field.
  • Workspace projects scan in parallel via runWithConcurrency (output ordering preserved).
  • Default 1; clamped to [1, 32].

barrelAllowlistno-barrel-import allowlist

{
  "barrelAllowlist": ["packages/*/src/index.ts", "src/components/ui/index.ts"]
}
  • Globs matched against the resolved barrel index file's project-relative path.
  • The rule reads the list from plugin settings and skips reports against any matching barrel.
  • Differs from ignore.overrides[].rules: this keys on the imported barrel path (one entry exempts every importer), whereas the override system keys on the importer (one entry per importer file).

Stats

  • 20 new tests across extends-config, merge-configs, validate-config-types, matches-barrel-allowlist, and run-with-concurrency.
  • All 1192 tests passing; lint / typecheck / format clean.

What's NOT in this PR

  • Baseline mode — in stacked PR 2.
  • Touched-line enforcement — in stacked PR 2.
  • PR comment markdown / sticky comment integration — in stacked PR 3.
  • action.yml knob additions for the new inputs — in stacked PRs 2/3.

Originally landed as part of #286; that PR is being closed in favor of this 3-way split.

Open in Web Open in Cursor 

@reactreview
Copy link
Copy Markdown

reactreview Bot commented May 17, 2026

🔴 No new issues

0/100 (unchanged)

Reviewed by react-review for commit ebb1c04. Configure here.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 17, 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 17, 2026 0:13am

Comment thread packages/core/src/load-config.ts
Comment thread packages/core/src/validate-config-types.ts
Comment thread packages/core/package.json Outdated
cursor Bot pushed a commit that referenced this pull request May 17, 2026
Second of a three-PR split of #286. Stacked on cursor/config-foundation-675b
(PR #287). Both features are scan-time filters that combine with diff mode,
both extend InspectResult / JsonReport, both touch action.yml inputs.

- Baseline mode: --baseline [path] / --update-baseline. Stable
  per-diagnostic fingerprint (plugin + rule + filepath + message;
  line / column intentionally excluded so unrelated edits don't break
  the baseline). Baseline counts surface in
  InspectResult.baselineDiagnostics, JsonReport.summary.baselineDiagnosticCount,
  and the PR comment header ("9 baseline issues, no new violations").
- Touched-line enforcement: --touched-lines. In diff or staged mode,
  restricts diagnostics to lines actually touched by the active diff
  (git diff --unified=0). DiffInfo.diffBaseRef + a HEAD baseRef for
  current-changes mode so staged-only edits aren't silently dropped.
  Hidden-by-touched-lines counts surface in the JSON report.
- action.yml: baseline + touched-lines inputs alongside the existing
  annotations input.
- 25 new tests across baseline + get-touched-lines suites.

1217 tests passing; lint / typecheck / format clean.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Comment thread packages/core/src/load-config.ts Outdated
Comment thread packages/core/package.json Outdated
@cursor cursor Bot force-pushed the cursor/config-foundation-675b branch from 9287d69 to a6a1db3 Compare May 17, 2026 09:21
cursor Bot pushed a commit that referenced this pull request May 17, 2026
Second of a three-PR split of #286. Stacked on cursor/config-foundation-675b
(PR #287). Both features are scan-time filters that combine with diff mode,
both extend InspectResult / JsonReport, both touch action.yml inputs.

- Baseline mode: --baseline [path] / --update-baseline. Stable
  per-diagnostic fingerprint (plugin + rule + filepath + message;
  line / column intentionally excluded so unrelated edits don't break
  the baseline). Baseline counts surface in
  InspectResult.baselineDiagnostics, JsonReport.summary.baselineDiagnosticCount,
  and the PR comment header ("9 baseline issues, no new violations").
- Touched-line enforcement: --touched-lines. In diff or staged mode,
  restricts diagnostics to lines actually touched by the active diff
  (git diff --unified=0). DiffInfo.diffBaseRef + a HEAD baseRef for
  current-changes mode so staged-only edits aren't silently dropped.
  Hidden-by-touched-lines counts surface in the JSON report.
- action.yml: baseline + touched-lines inputs alongside the existing
  annotations input.
- 25 new tests across baseline + get-touched-lines suites.

1217 tests passing; lint / typecheck / format clean.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Comment thread packages/core/src/validate-config-types.ts Outdated
@cursor cursor Bot force-pushed the cursor/config-foundation-675b branch from a6a1db3 to 7abb104 Compare May 17, 2026 09:51
cursor Bot pushed a commit that referenced this pull request May 17, 2026
Second of a three-PR split of #286. Stacked on cursor/config-foundation-675b
(PR #287). Both features are scan-time filters that combine with diff mode,
both extend InspectResult / JsonReport, both touch action.yml inputs.

- Baseline mode: --baseline [path] / --update-baseline. Stable
  per-diagnostic fingerprint (plugin + rule + filepath + message;
  line / column intentionally excluded so unrelated edits don't break
  the baseline). Baseline counts surface in
  InspectResult.baselineDiagnostics, JsonReport.summary.baselineDiagnosticCount,
  and the PR comment header ("9 baseline issues, no new violations").
- Touched-line enforcement: --touched-lines. In diff or staged mode,
  restricts diagnostics to lines actually touched by the active diff
  (git diff --unified=0). DiffInfo.diffBaseRef + a HEAD baseRef for
  current-changes mode so staged-only edits aren't silently dropped.
  Hidden-by-touched-lines counts surface in the JSON report.
- action.yml: baseline + touched-lines inputs alongside the existing
  annotations input.
- 25 new tests across baseline + get-touched-lines suites.

1217 tests passing; lint / typecheck / format clean.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
Comment thread packages/types/src/config.ts Outdated
@cursor cursor Bot force-pushed the cursor/config-foundation-675b branch from 7abb104 to e42aee0 Compare May 17, 2026 10:57
cursor Bot pushed a commit that referenced this pull request May 17, 2026
Second of a three-PR split of #286. Stacked on cursor/config-foundation-675b
(PR #287). Both features are scan-time filters that combine with diff mode,
both extend InspectResult / JsonReport, both touch action.yml inputs.

- Baseline mode: --baseline [path] / --update-baseline. Stable
  per-diagnostic fingerprint (plugin + rule + filepath + message;
  line / column intentionally excluded so unrelated edits don't break
  the baseline). Baseline counts surface in
  InspectResult.baselineDiagnostics, JsonReport.summary.baselineDiagnosticCount,
  and the PR comment header ("9 baseline issues, no new violations").
- Touched-line enforcement: --touched-lines. In diff or staged mode,
  restricts diagnostics to lines actually touched by the active diff
  (git diff --unified=0). DiffInfo.diffBaseRef + a HEAD baseRef for
  current-changes mode so staged-only edits aren't silently dropped.
  Hidden-by-touched-lines counts surface in the JSON report.
- action.yml: baseline + touched-lines inputs alongside the existing
  annotations input.
- 25 new tests across baseline + get-touched-lines suites.

1217 tests passing; lint / typecheck / format clean.

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

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 e42aee0. Configure here.

Comment thread packages/core/src/load-config.ts
…lAllowlist

Three independent config knobs grouped on a shared zod-based validator
foundation. None of these change the scan execution path - they affect
config loading, project orchestration, and one rule's allowlist.

- `extends`: ReactDoctorConfig grows a string | string[] field; each
  parent is loaded the same way the top-level config is. Cycle and
  depth guards keep pathological configs from hanging the loader.
  Semantics match tsconfig / eslint: later entries override earlier
  ones on scalar conflicts; arrays concat + dedupe; the current
  config always wins over anything it extends.
- zod refactor: replace ~280 lines of hand-rolled type checks in
  `validate-config-types.ts` with declarative zod schemas. One
  descriptor table per ReactDoctorConfig field, one parseFieldOrWarn
  helper that preserves the exact stderr message shape the existing
  --json mode and the 14 validate-config-types tests rely on.
  Filtering record / array transforms keep the drop-and-warn-but-keep-
  valid-siblings semantics so a single bad entry never invalidates
  the whole list.
- `concurrency`: --concurrency <n> CLI flag + top-level config field.
  Workspace projects scan in parallel via runWithConcurrency
  (output ordering preserved); default 1, clamped to 32.
- `barrelAllowlist`: glob list matched against the resolved barrel
  index file's path. no-barrel-import reads it via plugin settings
  and skips reports against any matching barrel. Differs from
  ignore.overrides[].rules because it keys on the IMPORTED barrel
  rather than every IMPORTER.

20 new tests across extends-config, merge-configs, validate-config-types,
matches-barrel-allowlist, and run-with-concurrency suites. Total 1192
tests passing.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
@cursor cursor Bot force-pushed the cursor/config-foundation-675b branch from e42aee0 to ebb1c04 Compare May 17, 2026 12:13
cursor Bot pushed a commit that referenced this pull request May 17, 2026
Second of a three-PR split of #286. Stacked on cursor/config-foundation-675b
(PR #287). Both features are scan-time filters that combine with diff mode,
both extend InspectResult / JsonReport, both touch action.yml inputs.

- Baseline mode: --baseline [path] / --update-baseline. Stable
  per-diagnostic fingerprint (plugin + rule + filepath + message;
  line / column intentionally excluded so unrelated edits don't break
  the baseline). Baseline counts surface in
  InspectResult.baselineDiagnostics, JsonReport.summary.baselineDiagnosticCount,
  and the PR comment header ("9 baseline issues, no new violations").
- Touched-line enforcement: --touched-lines. In diff or staged mode,
  restricts diagnostics to lines actually touched by the active diff
  (git diff --unified=0). DiffInfo.diffBaseRef + a HEAD baseRef for
  current-changes mode so staged-only edits aren't silently dropped.
  Hidden-by-touched-lines counts surface in the JSON report.
- action.yml: baseline + touched-lines inputs alongside the existing
  annotations input.
- 25 new tests across baseline + get-touched-lines suites.

1217 tests passing; lint / typecheck / format clean.

Co-authored-by: Aiden Bai <aidenybai@users.noreply.github.com>
@NisargIO NisargIO closed this May 20, 2026
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.

3 participants