react-doctor 0.9.11-dev.f1899d2 → 0.9.12-dev.05ef989

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/README.md +1 -1
  2. package/bin/react-doctor.js +1 -9
  3. package/dist/{build-section-divider-4ZztYtZV.js → build-section-divider-BNQmYjME.js} +9 -10
  4. package/dist/{ci-B04VkLj2.js → ci-B9ir-2Up.js} +12 -12
  5. package/dist/cli.js +30 -31
  6. package/dist/{design-AAjcvExu.js → design-DrPr5wfS.js} +4 -4
  7. package/dist/{devtools-DPRVRu3S.js → devtools-D8NTVj81.js} +4 -4
  8. package/dist/{exit-gracefully-B7v9PIJk.js → exit-gracefully-C-_jVMT3.js} +6 -6
  9. package/dist/index.d.ts +38 -61
  10. package/dist/index.js +54842 -54698
  11. package/dist/{inspect-CdQJI2XI.js → inspect-BfdplEq6.js} +24 -23
  12. package/dist/{install-BRU4jf-Y.js → install-CcPaQeBb.js} +8 -8
  13. package/dist/{install-doctor-script-Dn69YqKG.js → install-doctor-script-BlIhuJW6.js} +4 -4
  14. package/dist/{install-github-workflow-BwELZAhu.js → install-github-workflow-DbnsoR9k.js} +6 -6
  15. package/dist/{install-react-doctor-CcDiKPfC.js → install-react-doctor-COZnJROS.js} +47 -45
  16. package/dist/{print-branded-header-_kkHIAUd.js → print-branded-header-B_Cgff5S.js} +4 -4
  17. package/dist/project-analysis-worker.d.ts +1 -0
  18. package/dist/project-analysis-worker.js +51900 -0
  19. package/dist/{read-object-file-Bsov5R1-.js → read-object-file-NNLnIQKt.js} +4 -4
  20. package/dist/{record-metric-CeygoJWT.js → record-metric-fdCvvcjz.js} +2628 -5681
  21. package/dist/{report-error-uffmJocy.js → report-error-BH7DfHGY.js} +5 -5
  22. package/dist/{report-workflow-result-CMtcy7Eb.js → report-workflow-result-B3YeoXsK.js} +5 -5
  23. package/dist/{resolve-scope-CFro-KQO.js → resolve-scope-gLUuBxjI.js} +6 -6
  24. package/dist/{rules-BkLea4GL.js → rules-B5VC89MR.js} +6 -6
  25. package/dist/{run-scan-app-Befn2abh.js → run-scan-app-Cl2mqLLB.js} +137 -121
  26. package/dist/{scan-C00HPxuL.js → scan-7OBudBct.js} +8 -8
  27. package/dist/semver-DFtnEmN-.js +3219 -0
  28. package/dist/{should-fail-scan-gate-BEoC3SoQ.js → should-fail-scan-gate-Dch9vbPz.js} +151 -83
  29. package/dist/{should-skip-prompts-De37OlfL.js → should-skip-prompts-CyNdARgB.js} +4 -4
  30. package/dist/{unref-stdin-DklpxlNQ.js → unref-stdin-Cynhx9N1.js} +6 -12
  31. package/dist/{version-CRfqT5pV.js → version-axnZCkCZ.js} +4 -4
  32. package/dist/{why-BTbl-alh.js → why-Ducgj7Hu.js} +4 -4
  33. package/package.json +5 -9
  34. package/dist/chunk-q7NCDQ7-.js +0 -28
  35. package/dist/lsp.js +0 -81125
@@ -1,21 +1,22 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="f7f13734-adec-55f3-953d-caa4c00f9b28")}catch(e){}}();
3
- import { $n as orElseSucceed, An as resolveReactDoctorCacheDir, Bt as computeConfigFingerprint, Cn as mapWithConcurrency, Ct as SHARE_BASE_URL, Dt as SidecarLintCacheEnabled, E as NANOSECONDS_PER_MILLISECOND, Et as Score, Ft as buildSkippedChecks, G as isCiOrCodingAgentEnvironment, Gn as log, Gt as discoverReactSubprojects, H as ACTION_INPUT_ENVIRONMENT_VARIABLES, Hn as Console, Ht as createNodeReadFileLinesSync, It as calculateScore, Jn as decodeUnknownSync, Jt as filterSourceFiles, Kn as warn, Kt as filterDiagnosticsForSurface, Ln as summarizeDiagnostics, Lt as canonicalizeUserRuleKey, Mn as resolveScanTarget, Mt as atomicWriteJson, Nn as restoreLegacyThrow, On as resolveGithubActionsScoreMetadata, Pn as runInspect, Pt as buildRuleDocsUrl, Qn as map, R as CliInputError, St as Reporter, Tn as mergeReactDoctorConfigs, U as detectRunnerOs, Un as error, Ut as createOxlintSpawnSlots, Vn as yieldToEventLoop, Vt as computeDiagnosticDelta, W as isCiEnvironment, X as CI_URL, Xn as gen, Zn as makeSpan, _ as makeNoopConsole, _r as ParentSpan, _t as OxlintConcurrency, an as hasPublishedFixRecipe, ar as runSync, at as Files, bn as listSourceFiles, bt as Progress, c as setSentryProjectInfo, cn as highlighter, ct as Git, d as isJsonModeActive, dn as isFile, er as promise, et as Config, fn as isMonorepoRoot, fr as succeed, ft as LintPartialFailures, g as VERSION, gn as isReactDoctorError, gr as void_, gt as OXLINT_NODE_REQUIREMENT, hr as fail, ht as NodeResolver, in as groupBy, ir as runPromise, it as ENTERPRISE_CONTACT_URL, jn as resolveScanConcurrency, k as SCAN_RESULT_CACHE_FILENAME, kn as resolveLintBatchOrdering, kt as SupplyChain, l as getRunId, ln as isDirectory, lt as HTML_FILE_PATTERN, mt as MILLISECONDS_PER_SECOND, n as recordDistribution, nr as provideContext, o as buildSentryScope, or as sync, pt as Linter, qn as Diagnostic, qt as filterPathsOutsideDirectories, r as toSpanAttributes, rr as provideService, rt as DeadCode, s as buildSentryProjectContext, sn as hashFileContents, sr as try_, st as GIT_SHOW_MAX_BUFFER_BYTES, t as recordCount, tn as getDiagnosticRuleIdentity, tr as provide, tt as DIAGNOSTIC_CATEGORY_BUCKETS, ur as mergeAll, ut as JSX_FILE_PATTERN, vn as isScanComplete, vt as OxlintSpawnSlots, w as METRIC, wn as materializeSourceTree, x as BASELINE_FILES_TEMP_DIR_PREFIX, xn as listWorkspacePackages, xt as Project, yt as PerFileLintCacheEnabled, z as isNonInteractiveEnvironment, zt as collectSourceFileCountsByDirectory } from "./record-metric-CeygoJWT.js";
4
- import { a as setActiveRunTrace, i as recordRunTraceId, o as getTelemetryContext } from "./unref-stdin-DklpxlNQ.js";
5
- import { n as buildFooterLinkLines, r as activeScanAbortRegistry, t as buildSectionDivider } from "./build-section-divider-4ZztYtZV.js";
6
- import { D as getPackageJsonPath, L as cliLogger, O as isRecord, P as runGit, a as installReactDoctorScriptStep, c as spinner, n as findNearestPackageDirectory, o as isSpinnerSilent, s as setSpinnerSilent } from "./install-doctor-script-Dn69YqKG.js";
7
- import { d as detectDefaultBranch, l as prompts, r as installReactDoctorWorkflow, u as isCommandAvailable } from "./install-github-workflow-BwELZAhu.js";
8
- import { a as isValidBlockingLevel, c as openWorkflowPullRequest, l as stageWorkflowFile, o as pickBlockingLevel, u as toForwardSlashes } from "./resolve-scope-CFro-KQO.js";
9
- import { h as detectAvailableAgents, t as reportWorkflowResult } from "./report-workflow-result-CMtcy7Eb.js";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="19bff337-5a1f-5558-b6b7-bd4274f53f38")}catch(e){}}();
3
+ import { $ as Maintainability, $t as listSourceFiles, An as makeSpan, At as filterDiagnosticsForSurface, Bn as try_, Ct as computeConfigFingerprint, Dn as decodeUnknownSync, Dt as createOxlintSpawnSlots, E as NANOSECONDS_PER_MILLISECOND, En as Diagnostic, Et as createNodeReadFileLinesSync, Fn as provideContext, G as isCiOrCodingAgentEnvironment, Gn as succeed, Gt as highlighter, H as ACTION_INPUT_ENVIRONMENT_VARIABLES, Ht as hasPublishedFixRecipe, In as provideService, J as Files, Jn as fail, Kt as isMonorepoRoot, Ln as runPromise, Mn as orElseSucceed, Mt as filterSourceFiles, Nn as promise, Pn as provide, Q as Linter, R as CliInputError, Rn as runSync, Rt as getDiagnosticRuleIdentity, Sn as error, St as collectSourceFileCountsByDirectory, Tn as warn, Tt as countOptInProjectRuleSelections, U as detectRunnerOs, Un as mergeAll, Vt as groupBy, W as isCiEnvironment, Wt as hashFileContents, Xn as ParentSpan, Y as Git, Yn as void_, Yt as isReactDoctorError, Z as LintPartialFailures, Zt as isScanComplete, _ as makeNoopConsole, _n as summarizeDiagnostics, _t as buildSkippedChecks, an as mergeReactDoctorConfigs, at as Project, bn as yieldToEventLoop, br as isFile, bt as classifyFileContext, c as setSentryProjectInfo, cn as resolveLintBatchOrdering, cr as GIT_SHOW_MAX_BUFFER_BYTES, ct as SidecarLintCacheEnabled, d as isJsonModeActive, dn as resolveScanTarget, dr as JSX_FILE_PATTERN, en as listSourceFilesCooperative, er as CI_URL, et as NodeResolver, fn as restoreLegacyThrow, fr as MILLISECONDS_PER_SECOND, g as VERSION, gn as shouldUseMaintainabilityLayer, gt as buildRuleSeverityControls, ht as buildRuleDocsUrl, in as materializeSourceTree, ir as DIAGNOSTIC_CATEGORY_BUCKETS, it as Progress, jn as map, jt as filterPathsOutsideDirectories, k as SCAN_RESULT_CACHE_FILENAME, kn as gen, kt as discoverSupportedSubprojects, l as getRunId, ln as resolveReactDoctorCacheDir, lr as HTML_FILE_PATTERN, mr as SHARE_BASE_URL, n as recordDistribution, nt as OxlintSpawnSlots, o as buildSentryScope, on as remainingDeadlineBudgetMs, or as ENTERPRISE_CONTACT_URL, ot as Reporter, pn as runInspect, pr as OXLINT_NODE_REQUIREMENT, pt as atomicWriteJson, q as Config, qt as isPathInsideDirectory, r as toSpanAttributes, rn as mapWithConcurrency, rt as PerFileLintCacheEnabled, s as buildSentryProjectContext, sn as resolveGithubActionsScoreMetadata, st as Score, t as recordCount, tn as listWorkspacePackages, tt as OxlintConcurrency, un as resolveScanConcurrency, ur as JSX_DUPLICATION_SOURCE_FILE_PATTERN, ut as SupplyChain, vr as isDirectory, vt as calculateScore, w as METRIC, wn as log, wt as computeDiagnosticDelta, x as BASELINE_FILES_TEMP_DIR_PREFIX, xn as Console, yt as canonicalizeUserRuleKey, z as isNonInteractiveEnvironment, zn as sync } from "./record-metric-fdCvvcjz.js";
4
+ import { a as setActiveRunTrace, i as recordRunTraceId, o as getTelemetryContext } from "./unref-stdin-Cynhx9N1.js";
5
+ import { n as buildFooterLinkLines, r as activeScanAbortRegistry, t as buildSectionDivider } from "./build-section-divider-BNQmYjME.js";
6
+ import { D as getPackageJsonPath, L as cliLogger, O as isRecord, P as runGit, a as installReactDoctorScriptStep, c as spinner, n as findNearestPackageDirectory, o as isSpinnerSilent, s as setSpinnerSilent } from "./install-doctor-script-BlIhuJW6.js";
7
+ import { d as detectDefaultBranch, l as prompts, r as installReactDoctorWorkflow, u as isCommandAvailable } from "./install-github-workflow-DbnsoR9k.js";
8
+ import { a as isValidBlockingLevel, c as openWorkflowPullRequest, l as stageWorkflowFile, o as pickBlockingLevel, u as toForwardSlashes } from "./resolve-scope-gLUuBxjI.js";
9
+ import { h as detectAvailableAgents, t as reportWorkflowResult } from "./report-workflow-result-B3YeoXsK.js";
10
10
  import { createRequire } from "node:module";
11
11
  import { spawn } from "node:child_process";
12
12
  import * as path$1 from "node:path";
13
13
  import path from "node:path";
14
- import * as fs$1 from "node:fs";
14
+ import * as fs$2 from "node:fs";
15
15
  import fs, { mkdtempSync, rmSync } from "node:fs";
16
- import crypto, { randomUUID } from "node:crypto";
17
16
  import ts from "typescript";
17
+ import crypto, { randomUUID } from "node:crypto";
18
18
  import { tmpdir } from "node:os";
19
+ import * as fs$1 from "node:fs/promises";
19
20
  import { performance } from "node:perf_hooks";
20
21
  //#region src/cli/utils/apply-observability.ts
21
22
  /**
@@ -83,7 +84,10 @@ const buildSpinnerProgressHandle = (text) => {
83
84
  */
84
85
  const buildRuntimeLayers = (input) => {
85
86
  const linterLayer = input.shouldSkipLint ? Linter.layerOf([]) : Linter.layerOxlint;
86
- const deadCodeLayer = input.shouldRunDeadCode ? DeadCode.layerNode : DeadCode.layerOf([]);
87
+ const maintainabilityLayer = shouldUseMaintainabilityLayer({
88
+ shouldRunDuplicateJsx: input.shouldRunDeadCode,
89
+ userConfig: input.userConfig
90
+ }) ? Maintainability.layerNode : Maintainability.layerOf([]);
87
91
  const scoreLayer = input.shouldComputeScore ? Score.layerHttp : Score.layerOf(null);
88
92
  const supplyChainLayer = input.shouldRunSupplyChain ? SupplyChain.layerNode : SupplyChain.layerOf([]);
89
93
  const projectLayer = input.projectInfoOverride === void 0 ? Project.layerNode : Project.layerOf(input.projectInfoOverride);
@@ -93,7 +97,7 @@ const buildRuntimeLayers = (input) => {
93
97
  config: input.userConfig,
94
98
  resolvedDirectory: input.directory,
95
99
  configSourceDirectory: input.configSourceDirectory
96
- }) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive, deadCodeLayer, progressLayer, reporterLayer, scoreLayer, supplyChainLayer);
100
+ }) : Config.layerNode, Files.layerNode, Git.layerNode, linterLayer, LintPartialFailures.layerLive, maintainabilityLayer, progressLayer, reporterLayer, scoreLayer, supplyChainLayer);
97
101
  const layersWithConcurrency = input.oxlintConcurrency === void 0 ? baseLayers : mergeAll(baseLayers, succeed(OxlintConcurrency, input.oxlintConcurrency));
98
102
  return input.oxlintSpawnSlots === void 0 ? layersWithConcurrency : mergeAll(layersWithConcurrency, succeed(OxlintSpawnSlots, input.oxlintSpawnSlots));
99
103
  };
@@ -309,7 +313,7 @@ const recordScanMetrics = (input) => {
309
313
  recordCount(METRIC.scanCompleted, 1, {
310
314
  mode: input.mode,
311
315
  lint: input.lint,
312
- deadCode: input.deadCode,
316
+ maintainability: input.deadCode,
313
317
  parallel: input.parallel,
314
318
  scoreOnly: input.scoreOnly,
315
319
  didLintFail: input.didLintFail,
@@ -349,7 +353,7 @@ const recordScanMetrics = (input) => {
349
353
  else if (!input.noScore && !input.didLintFail && !input.didDeadCodeFail) recordCount(METRIC.scoreUnavailable, 1, { mode: input.mode });
350
354
  if (input.baselineDegraded) recordCount(METRIC.baselineDegraded, 1);
351
355
  if (input.didLintFail) recordCount(METRIC.lintFailed, 1, { reasonKind: input.lintFailureReasonKind });
352
- if (input.didDeadCodeFail) recordCount(METRIC.deadCodeFailed, 1);
356
+ if (input.didDeadCodeFail) recordCount(METRIC.maintainabilityFailed, 1);
353
357
  for (const check of result.skippedChecks) recordCount(METRIC.scanCheckSkipped, 1, {
354
358
  check,
355
359
  reason: result.skippedCheckReasons?.[check] ?? null
@@ -493,10 +497,16 @@ const CACHE_DISABLED_VALUES = new Set(["1", "true"]);
493
497
  const TOOLCHAIN_PACKAGE_SPECIFIERS = [
494
498
  "oxlint/package.json",
495
499
  "oxlint-plugin-react-doctor/package.json",
496
- "deslop-js/package.json",
497
500
  "eslint-plugin-react-hooks/package.json"
498
501
  ];
499
502
  const bundledRequire = createRequire(import.meta.url);
503
+ const RULE_PLUGIN_CONTENT_FINGERPRINT = (() => {
504
+ try {
505
+ return `oxlint-plugin-react-doctor#fingerprint=${hashFileContents(bundledRequire.resolve("oxlint-plugin-react-doctor")) ?? "unreadable"}`;
506
+ } catch {
507
+ return "oxlint-plugin-react-doctor#fingerprint=unresolved";
508
+ }
509
+ })();
500
510
  const normalizeForStableJson = (value) => {
501
511
  if (value === null) return null;
502
512
  if (value === void 0) return void 0;
@@ -632,12 +642,12 @@ const resolveCacheFilePath = (projectDirectory) => path.join(resolveReactDoctorC
632
642
  const readPersistedCache = (cacheFilePath) => {
633
643
  try {
634
644
  const parsed = JSON.parse(fs.readFileSync(cacheFilePath, "utf8"));
635
- if (!isRecord(parsed) || parsed.version !== 6) return {
636
- version: 6,
645
+ if (!isRecord(parsed) || parsed.version !== 7) return {
646
+ version: 7,
637
647
  entries: []
638
648
  };
639
649
  if (!Array.isArray(parsed.entries)) return {
640
- version: 6,
650
+ version: 7,
641
651
  entries: []
642
652
  };
643
653
  const entries = [];
@@ -652,12 +662,12 @@ const readPersistedCache = (cacheFilePath) => {
652
662
  });
653
663
  }
654
664
  return {
655
- version: 6,
665
+ version: 7,
656
666
  entries
657
667
  };
658
668
  } catch {
659
669
  return {
660
- version: 6,
670
+ version: 7,
661
671
  entries: []
662
672
  };
663
673
  }
@@ -665,7 +675,7 @@ const readPersistedCache = (cacheFilePath) => {
665
675
  /**
666
676
  * The global cache off-switch (`REACT_DOCTOR_NO_CACHE`), which disables every
667
677
  * cache subsystem: this whole-repo scan cache plus core's per-file lint,
668
- * sidecar, and dead-code caches (their `Context.Reference` defaults read the
678
+ * sidecar caches (their `Context.Reference` defaults read the
669
679
  * same variable). Exported for the wide event's `cache.temperature`
670
680
  * derivation, which reports `"disabled"` instead of `"cold"` when the switch
671
681
  * is on. Granular knobs (`REACT_DOCTOR_NO_FILE_CACHE`, …) are deliberately
@@ -688,7 +698,7 @@ const fileFingerprint = (filePath) => {
688
698
  return null;
689
699
  }
690
700
  };
691
- const resolveToolchainFingerprint = (nodeBinaryPath) => {
701
+ const resolveScanResultToolchainFingerprint = (nodeBinaryPath) => {
692
702
  const fingerprints = [];
693
703
  if (nodeBinaryPath !== null) fingerprints.push(nodeBinaryPath === process.execPath ? `node=${process.version}` : `node=${fileFingerprint(nodeBinaryPath) ?? "unreadable"}`);
694
704
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS) try {
@@ -698,6 +708,7 @@ const resolveToolchainFingerprint = (nodeBinaryPath) => {
698
708
  } catch {
699
709
  fingerprints.push(`${specifier}=missing`);
700
710
  }
711
+ fingerprints.push(RULE_PLUGIN_CONTENT_FINGERPRINT);
701
712
  return fingerprints;
702
713
  };
703
714
  const buildScanResultCacheKey = (input) => {
@@ -707,14 +718,14 @@ const buildScanResultCacheKey = (input) => {
707
718
  if (repositoryIdentity === null) return null;
708
719
  if (stringifyStableJson(input.userConfig) === null) return null;
709
720
  const cacheKeyJson = stringifyStableJson({
710
- schemaVersion: 6,
721
+ schemaVersion: 7,
711
722
  projectIdentity: resolveProjectIdentity(input.projectDirectory),
712
723
  headSha: repositoryIdentity.headSha,
713
724
  worktreeFingerprint: repositoryIdentity.worktreeFingerprint,
714
725
  dotenvFingerprint: resolveDotenvFingerprint(input.projectDirectory),
715
726
  reactDoctorVersion: input.version,
716
727
  nodeVersion: process.version,
717
- toolchainFingerprint: resolveToolchainFingerprint(input.nodeBinaryPath),
728
+ toolchainFingerprint: resolveScanResultToolchainFingerprint(input.nodeBinaryPath),
718
729
  configFingerprint: computeConfigFingerprint(input.projectDirectory, input.version),
719
730
  hasConfigOverride: input.hasConfigOverride,
720
731
  configSourceDirectory: input.configSourceDirectory,
@@ -755,7 +766,7 @@ const createScanResultCache = (projectDirectory) => {
755
766
  for (const entry of readPersistedCache(cacheFilePath).entries) mergedEntries.set(entry.key, entry);
756
767
  for (const entry of entries.values()) mergedEntries.set(entry.key, entry);
757
768
  atomicWriteJson(cacheFilePath, {
758
- version: 6,
769
+ version: 7,
759
770
  entries: [...mergedEntries.values()].sort((firstEntry, secondEntry) => secondEntry.createdAtMs - firstEntry.createdAtMs).slice(0, 20)
760
771
  });
761
772
  };
@@ -790,8 +801,7 @@ const shouldBlockCi = (diagnostics, blockingLevel) => {
790
801
  /**
791
802
  * Lowercase, key-safe form of a rule category for the `diag.category.*`
792
803
  * telemetry attribute namespace (categories carry spaces / capitals, e.g.
793
- * "Performance" → `performance`, "Dead Code" → `dead_code`). Shared by the
794
- * CLI run event and the editor LSP wide event so both namespace identically.
804
+ * "Performance" → `performance`, "Dead Code" → `dead_code`).
795
805
  */
796
806
  const toCategoryKey = (category) => category.toLowerCase().replace(/[^a-z0-9]+/g, "_");
797
807
  //#endregion
@@ -821,12 +831,6 @@ const readEnvBoolean = (name) => {
821
831
  return value.toLowerCase() === "true" || value === "1";
822
832
  };
823
833
  const ratioOf = (numerator, denominator) => denominator != null && denominator > 0 ? (numerator ?? 0) / denominator : null;
824
- const resolveDeadCodeReuseRatio = (result) => {
825
- if (result.deadCodeCacheHit === true) return 1;
826
- const summaryTotal = (result.deadCodeSummaryCacheHits ?? 0) + (result.deadCodeSummaryCacheMisses ?? 0);
827
- if (summaryTotal > 0) return (result.deadCodeSummaryCacheHits ?? 0) / summaryTotal;
828
- return result.deadCodeCacheHit === false ? 0 : null;
829
- };
830
834
  /**
831
835
  * One queryable cache temperature per scan, derived from the whole stack:
832
836
  *
@@ -834,8 +838,7 @@ const resolveDeadCodeReuseRatio = (result) => {
834
838
  * `wholeRepoCacheHit` flag from the CLI's cachedPayload
835
839
  * branch; no scan work ran).
836
840
  * - `"warm"` — any incremental reuse: per-file lint hits, sidecar
837
- * replays, a dead-code whole-result hit, or dead-code
838
- * summary-cache hits.
841
+ * replays.
839
842
  * - `"disabled"` — zero reuse because the global `REACT_DOCTOR_NO_CACHE`
840
843
  * off-switch is on. Granular per-cache opt-outs
841
844
  * (`REACT_DOCTOR_NO_FILE_CACHE`, …) still read warm/cold,
@@ -844,7 +847,7 @@ const resolveDeadCodeReuseRatio = (result) => {
844
847
  *
845
848
  * `cache.warmth` is the headline reuse magnitude in [0, 1]: the plain mean of
846
849
  * the subsystem reuse fractions known this run (lint hit ratio, sidecar
847
- * replay ratio, dead-code reuse), skipping subsystems that never consulted a
850
+ * replay ratio), skipping subsystems that never consulted a
848
851
  * cache; `1` on turbo, dropped when nothing consulted any cache. Deliberately
849
852
  * unweighted — the per-subsystem dims stay the precise signal; warmth is the
850
853
  * p50/p90-able summary. Emitted only on the success path.
@@ -857,11 +860,7 @@ const buildCacheAttributes = (input) => {
857
860
  warmth: 1
858
861
  });
859
862
  const result = input.result;
860
- const subsystemReuseRatios = [
861
- ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount),
862
- ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount),
863
- resolveDeadCodeReuseRatio(result)
864
- ];
863
+ const subsystemReuseRatios = [ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount), ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)];
865
864
  let knownSubsystemCount = 0;
866
865
  let reuseRatioSum = 0;
867
866
  for (const reuseRatio of subsystemReuseRatios) {
@@ -1013,13 +1012,7 @@ const buildOutcomeAttributes = (input) => {
1013
1012
  sidecarTotalFiles: result.lintSidecarTotalFileCount,
1014
1013
  sidecarReplayRatio: ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)
1015
1014
  }),
1016
- ...withNamespace("deadCode", {
1017
- failed: input.didDeadCodeFail,
1018
- overlapped: input.deadCodeOverlapped,
1019
- cacheHit: result.deadCodeCacheHit,
1020
- summaryCacheHits: result.deadCodeSummaryCacheHits,
1021
- summaryCacheMisses: result.deadCodeSummaryCacheMisses
1022
- }),
1015
+ ...withNamespace("maintainability", { failed: input.didDeadCodeFail }),
1023
1016
  ...withNamespace("supplyChain", { overlapTimedOut: input.supplyChainOverlapTimedOut }),
1024
1017
  ...withNamespace("securityScan", { failed: input.securityScanFailed }),
1025
1018
  ...withNamespace("timing", {
@@ -1062,7 +1055,7 @@ const buildScanAttributes = (input) => {
1062
1055
  workerCount: input.workerCount,
1063
1056
  maxDurationMs: input.maxDurationMs,
1064
1057
  lint: input.lint,
1065
- deadCode: input.deadCode,
1058
+ maintainability: input.deadCode,
1066
1059
  supplyChain: input.supplyChain,
1067
1060
  scoreOnly: input.scoreOnly,
1068
1061
  noScore: input.noScore,
@@ -1073,6 +1066,7 @@ const buildScanAttributes = (input) => {
1073
1066
  hasCustomConfig: input.hasCustomConfig,
1074
1067
  rulesConfigured: ruleKeys.length,
1075
1068
  rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
1069
+ projectAnalysisRuleCount: countOptInProjectRuleSelections(buildRuleSeverityControls(input.userConfig)),
1076
1070
  fileCount: input.result?.scannedFileCount,
1077
1071
  nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length,
1078
1072
  htmlFileCount: input.result?.analyzedFiles?.filter((filePath) => HTML_FILE_PATTERN.test(filePath)).length,
@@ -1083,7 +1077,7 @@ const buildScanAttributes = (input) => {
1083
1077
  * Projects a scan into the namespaced attribute set for its root span — the
1084
1078
  * canonical per-scan "wide event". Every attribute carries a dotted namespace
1085
1079
  * that groups it by concept (`scan.*` config, `action.*` CI knobs, `outcome.*`
1086
- * verdict, `diag.*` findings, `score.*`, `lint.*`, `deadCode.*`, `cache.*`,
1080
+ * verdict, `diag.*` findings, `score.*`, `lint.*`, `maintainability.*`, `cache.*`,
1087
1081
  * `supplyChain.*`, `timing.*`, `migration.*`, `baseline.*`) so the attributes
1088
1082
  * tree up in Sentry's attribute browser and stay filter-/group-/aggregate-able
1089
1083
  * in the Spans dataset. Pure and exported so the projection (outcome
@@ -1322,7 +1316,7 @@ const buildNoScoreMessage = (input) => {
1322
1316
  reason = input.disabledMessage ?? "Score disabled by --no-score.";
1323
1317
  break;
1324
1318
  case "analysis-incomplete":
1325
- reason = "Score not shown because lint or dead-code analysis could not complete.";
1319
+ reason = "Score not shown because lint or maintainability analysis could not complete.";
1326
1320
  break;
1327
1321
  case "api-unavailable":
1328
1322
  reason = "Score unavailable (could not reach the score API).";
@@ -1370,7 +1364,7 @@ const formatRuleSummary = (ruleKey, ruleDiagnostics) => {
1370
1364
  const ruleDumpFileName = (ruleKey) => ruleKey.replace(/\//g, "--") + ".txt";
1371
1365
  const readPreviousRuleDumpFileNames = (directory) => {
1372
1366
  try {
1373
- const previous = JSON.parse(fs$1.readFileSync(path$1.join(directory, "diagnostics.json"), "utf8"));
1367
+ const previous = JSON.parse(fs$2.readFileSync(path$1.join(directory, "diagnostics.json"), "utf8"));
1374
1368
  return new Set(previous.filter((d) => typeof d?.plugin === "string" && typeof d?.rule === "string").map((d) => ruleDumpFileName(`${d.plugin}/${d.rule}`)));
1375
1369
  } catch {
1376
1370
  return /* @__PURE__ */ new Set();
@@ -1378,10 +1372,10 @@ const readPreviousRuleDumpFileNames = (directory) => {
1378
1372
  };
1379
1373
  const writeDiagnosticsDirectory = (diagnostics, outputDirectory) => {
1380
1374
  const directory = outputDirectory ? path$1.resolve(outputDirectory) : path$1.join(tmpdir(), `react-doctor-${randomUUID()}`);
1381
- if (outputDirectory) for (const fileName of readPreviousRuleDumpFileNames(directory)) fs$1.rmSync(path$1.join(directory, fileName), { force: true });
1382
- fs$1.mkdirSync(directory, { recursive: true });
1383
- for (const [ruleKey, ruleDiagnostics] of buildSortedRuleGroups(diagnostics)) fs$1.writeFileSync(path$1.join(directory, ruleDumpFileName(ruleKey)), formatRuleSummary(ruleKey, ruleDiagnostics));
1384
- fs$1.writeFileSync(path$1.join(directory, "diagnostics.json"), JSON.stringify(diagnostics));
1375
+ if (outputDirectory) for (const fileName of readPreviousRuleDumpFileNames(directory)) fs$2.rmSync(path$1.join(directory, fileName), { force: true });
1376
+ fs$2.mkdirSync(directory, { recursive: true });
1377
+ for (const [ruleKey, ruleDiagnostics] of buildSortedRuleGroups(diagnostics)) fs$2.writeFileSync(path$1.join(directory, ruleDumpFileName(ruleKey)), formatRuleSummary(ruleKey, ruleDiagnostics));
1378
+ fs$2.writeFileSync(path$1.join(directory, "diagnostics.json"), JSON.stringify(diagnostics));
1385
1379
  return directory;
1386
1380
  };
1387
1381
  //#endregion
@@ -1425,6 +1419,9 @@ const formatElapsedTime = (elapsedMilliseconds) => {
1425
1419
  return `${(elapsedMilliseconds / MILLISECONDS_PER_SECOND).toFixed(1)}s`;
1426
1420
  };
1427
1421
  //#endregion
1422
+ //#region src/cli/utils/format-skipped-check-label.ts
1423
+ const formatSkippedCheckLabel = (skippedCheck) => skippedCheck === "dead-code" ? "maintainability" : skippedCheck;
1424
+ //#endregion
1428
1425
  //#region src/cli/utils/pluralize.ts
1429
1426
  const pluralize = (count, singularNoun) => `${count} ${singularNoun}${count === 1 ? "" : "s"}`;
1430
1427
  //#endregion
@@ -1473,7 +1470,7 @@ const printHeadlessReport = (input) => gen(function* () {
1473
1470
  }
1474
1471
  if (input.skippedChecks.length > 0) {
1475
1472
  yield* log("");
1476
- yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.join(" and ")} checks failed.`));
1473
+ yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.map(formatSkippedCheckLabel).join(" and ")} checks failed.`));
1477
1474
  }
1478
1475
  });
1479
1476
  //#endregion
@@ -1673,12 +1670,39 @@ const renderAndRecordScan = async (input) => {
1673
1670
  didDeadCodeFail: input.payload.didDeadCodeFail,
1674
1671
  supplyChainOverlapTimedOut: input.payload.supplyChainOverlapTimedOut,
1675
1672
  securityScanFailed: input.payload.securityScanFailed,
1676
- deadCodeOverlapped: input.payload.deadCodeOverlapped,
1677
1673
  suppressedRuleCounts: input.payload.suppressedRuleCounts ?? []
1678
1674
  });
1679
1675
  return result;
1680
1676
  };
1681
1677
  //#endregion
1678
+ //#region src/cli/utils/copy-unchanged-baseline-sources.ts
1679
+ const copyUnchangedBaselineSources = async (input) => {
1680
+ const baseMaterializedFiles = new Set(input.baseMaterializedFiles.map(toForwardSlashes));
1681
+ const headChangedFiles = new Set(input.headChangedFiles.map(toForwardSlashes));
1682
+ const untrackedFiles = new Set(input.untrackedFiles.map(toForwardSlashes));
1683
+ const sourceDirectory = path$1.resolve(input.directory);
1684
+ const targetDirectory = path$1.resolve(input.tempDirectory);
1685
+ return (await mapWithConcurrency(input.sourceFiles.filter((filePath) => {
1686
+ const normalizedPath = toForwardSlashes(filePath);
1687
+ return !baseMaterializedFiles.has(normalizedPath) && !headChangedFiles.has(normalizedPath) && !untrackedFiles.has(normalizedPath);
1688
+ }), 32, async (filePath) => {
1689
+ input.signal?.throwIfAborted();
1690
+ if (input.deadlineEpochMs !== null && Date.now() >= input.deadlineEpochMs) return false;
1691
+ const sourcePath = path$1.resolve(sourceDirectory, filePath);
1692
+ const targetPath = path$1.resolve(targetDirectory, filePath);
1693
+ if (!isPathInsideDirectory(sourcePath, sourceDirectory) || !isPathInsideDirectory(targetPath, targetDirectory)) return false;
1694
+ try {
1695
+ if (!(await fs$1.lstat(sourcePath)).isFile()) return false;
1696
+ await fs$1.mkdir(path$1.dirname(targetPath), { recursive: true });
1697
+ await fs$1.copyFile(sourcePath, targetPath);
1698
+ return true;
1699
+ } catch {
1700
+ input.signal?.throwIfAborted();
1701
+ return false;
1702
+ }
1703
+ })).every(Boolean);
1704
+ };
1705
+ //#endregion
1682
1706
  //#region src/cli/utils/read-diagnostic-evidence.ts
1683
1707
  const SOURCE_EXTENSIONS = [
1684
1708
  ".ts",
@@ -2096,7 +2120,6 @@ const resolveMergeBaseRef = async (directory, ref) => {
2096
2120
  const silentConsole$1 = makeNoopConsole();
2097
2121
  const countIncompleteLintFiles = (lintPartialFailures) => countDroppedLintFiles(lintPartialFailures) + countDeadlineSkippedFiles(lintPartialFailures);
2098
2122
  const runBaselineComparison = async (input) => {
2099
- const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
2100
2123
  const baselineIncludePaths = filterPathsOutsideDirectories({
2101
2124
  rootDirectory: input.directory,
2102
2125
  relativePaths: input.options.includePaths,
@@ -2112,12 +2135,24 @@ const runBaselineComparison = async (input) => {
2112
2135
  relativePaths: input.headFiles,
2113
2136
  excludedDirectories: input.options.excludedProjectDirectories
2114
2137
  }) : void 0;
2138
+ const remainingBaselineBudgetMs = input.deadlineEpochMs === null ? null : remainingDeadlineBudgetMs(input.deadlineEpochMs);
2139
+ if (remainingBaselineBudgetMs === 0) return null;
2140
+ const baselineDeadlineSignal = remainingBaselineBudgetMs === null ? void 0 : AbortSignal.timeout(remainingBaselineBudgetMs);
2141
+ const baselineListingSignal = baselineDeadlineSignal === void 0 ? input.oxlintRuntime.abortSignal : input.oxlintRuntime.abortSignal === void 0 ? baselineDeadlineSignal : AbortSignal.any([input.oxlintRuntime.abortSignal, baselineDeadlineSignal]);
2142
+ let maintainabilitySourceFiles = [];
2143
+ if (input.options.deadCode) try {
2144
+ maintainabilitySourceFiles = (await listSourceFilesCooperative(input.directory, baselineListingSignal)).filter((filePath) => JSX_DUPLICATION_SOURCE_FILE_PATTERN.test(filePath) && classifyFileContext(filePath) === "production");
2145
+ } catch (error) {
2146
+ if (baselineDeadlineSignal?.aborted) return null;
2147
+ throw error;
2148
+ }
2149
+ const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
2115
2150
  const snapshot = await materializeBaselineFiles({
2116
2151
  directory: input.directory,
2117
2152
  ref: input.baselineRef,
2118
- files: baselineIncludePaths,
2119
- baseFiles: baselineBaseFiles,
2120
- headFiles: baselineHeadFiles,
2153
+ files: input.options.deadCode ? input.options.includePaths : baselineIncludePaths,
2154
+ baseFiles: input.options.deadCode ? input.baseFiles : baselineBaseFiles,
2155
+ headFiles: input.options.deadCode ? input.headFiles : baselineHeadFiles,
2121
2156
  tempDirectory: temporaryDirectory
2122
2157
  }).catch((error) => {
2123
2158
  rmSync(temporaryDirectory, {
@@ -2135,22 +2170,47 @@ const runBaselineComparison = async (input) => {
2135
2170
  }
2136
2171
  try {
2137
2172
  if (!snapshot.isComplete) return null;
2173
+ if (input.options.deadCode && !await copyUnchangedBaselineSources({
2174
+ directory: input.directory,
2175
+ sourceFiles: maintainabilitySourceFiles,
2176
+ baseMaterializedFiles: snapshot.materializedFiles,
2177
+ headChangedFiles: snapshot.headFiles,
2178
+ untrackedFiles: snapshot.untrackedFiles,
2179
+ tempDirectory: snapshot.tempDirectory,
2180
+ deadlineEpochMs: input.deadlineEpochMs,
2181
+ signal: input.oxlintRuntime.abortSignal
2182
+ })) return null;
2183
+ const filteredSnapshotBaseFiles = filterPathsOutsideDirectories({
2184
+ rootDirectory: input.directory,
2185
+ relativePaths: snapshot.baseFiles,
2186
+ excludedDirectories: input.options.excludedProjectDirectories
2187
+ });
2188
+ const filteredSnapshotHeadFiles = filterPathsOutsideDirectories({
2189
+ rootDirectory: input.directory,
2190
+ relativePaths: snapshot.headFiles,
2191
+ excludedDirectories: input.options.excludedProjectDirectories
2192
+ });
2138
2193
  const analyzedHeadFiles = new Set(input.headAnalyzedFiles.map(toForwardSlashes));
2139
- const baseFiles = new Set(snapshot.baseFiles.map(toForwardSlashes));
2140
- const expectedHeadFiles = new Set(snapshot.headFiles.map(toForwardSlashes));
2194
+ const baseFiles = new Set((baselineBaseFiles ?? filteredSnapshotBaseFiles).map(toForwardSlashes));
2195
+ const expectedHeadFiles = new Set((baselineHeadFiles ?? filteredSnapshotHeadFiles).map(toForwardSlashes));
2141
2196
  for (const filePath of baselineIncludePaths) {
2142
2197
  const normalizedFilePath = toForwardSlashes(filePath);
2143
2198
  if (!baseFiles.has(normalizedFilePath)) expectedHeadFiles.add(normalizedFilePath);
2144
2199
  }
2145
- if (filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
2200
+ if (input.options.lint && filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
2201
+ const baselineLintPaths = new Set([...baselineIncludePaths, ...filteredSnapshotBaseFiles].map(toForwardSlashes));
2202
+ const materializedLintPaths = snapshot.materializedFiles.filter((filePath) => baselineLintPaths.has(toForwardSlashes(filePath)));
2203
+ const maintainabilityFocusPaths = [...new Set([...input.options.includePaths, ...snapshot.baseFiles].map(toForwardSlashes))];
2204
+ const baselineExcludedProjectDirectories = input.options.excludedProjectDirectories.map((excludedDirectory) => path.resolve(excludedDirectory)).filter((excludedDirectory) => isPathInsideDirectory(excludedDirectory, input.directory)).map((excludedDirectory) => path.resolve(snapshot.tempDirectory, path.relative(input.directory, excludedDirectory)));
2205
+ const baseIncludePaths = materializedLintPaths.length > 0 ? materializedLintPaths : maintainabilityFocusPaths;
2146
2206
  const runtimeLayers = buildRuntimeLayers({
2147
2207
  directory: snapshot.tempDirectory,
2148
2208
  hasConfigOverride: true,
2149
2209
  userConfig: input.userConfig,
2150
2210
  configSourceDirectory: input.configSourceDirectory,
2151
2211
  projectInfoOverride: input.headProjectInfo,
2152
- shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath,
2153
- shouldRunDeadCode: false,
2212
+ shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath || materializedLintPaths.length === 0,
2213
+ shouldRunDeadCode: input.options.deadCode,
2154
2214
  shouldRunSupplyChain: input.options.supplyChain,
2155
2215
  shouldComputeScore: false,
2156
2216
  shouldShowProgressSpinners: false,
@@ -2159,7 +2219,8 @@ const runBaselineComparison = async (input) => {
2159
2219
  });
2160
2220
  const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
2161
2221
  directory: snapshot.tempDirectory,
2162
- includePaths: snapshot.materializedFiles,
2222
+ includePaths: baseIncludePaths,
2223
+ maintainabilityFocusPaths,
2163
2224
  customRulesOnly: input.options.customRulesOnly,
2164
2225
  respectInlineDisables: input.options.respectInlineDisables,
2165
2226
  warnings: input.options.warnings,
@@ -2168,7 +2229,7 @@ const runBaselineComparison = async (input) => {
2168
2229
  includedTags: input.options.includedTags,
2169
2230
  includeTagDefaults: input.options.includeTagDefaults,
2170
2231
  nodeBinaryPath: input.resolvedNodeBinaryPath ?? void 0,
2171
- runDeadCode: false,
2232
+ runDeadCode: input.options.deadCode,
2172
2233
  isCi: input.options.isCi,
2173
2234
  doctorVersion: VERSION,
2174
2235
  runId: getRunId(),
@@ -2176,10 +2237,16 @@ const runBaselineComparison = async (input) => {
2176
2237
  suppressScanSummary: true,
2177
2238
  supplyChainManifestChanged: input.options.supplyChainManifestChanged,
2178
2239
  deadlineEpochMs: input.deadlineEpochMs ?? void 0,
2179
- signal: input.oxlintRuntime.abortSignal
2240
+ signal: input.oxlintRuntime.abortSignal,
2241
+ excludedProjectDirectories: baselineExcludedProjectDirectories,
2242
+ retainExcludedProjectDeadCodeDiagnostics: input.options.retainExcludedProjectDeadCodeDiagnostics
2180
2243
  }, {}).pipe(provide(runtimeLayers), provideService(PerFileLintCacheEnabled, false), provideService(SidecarLintCacheEnabled, false), provideService(Console, silentConsole$1))), { signal: input.oxlintRuntime.abortSignal });
2181
- if (baseOutput.didLintFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
2182
- const hasUnscannedUntrackedSourceFiles = filterSourceFiles(snapshot.untrackedFiles.map(toForwardSlashes)).some((filePath) => !analyzedHeadFiles.has(filePath));
2244
+ if (baseOutput.didLintFail || baseOutput.didDeadCodeFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
2245
+ const hasUnscannedUntrackedSourceFiles = filterSourceFiles(filterPathsOutsideDirectories({
2246
+ rootDirectory: input.directory,
2247
+ relativePaths: snapshot.untrackedFiles,
2248
+ excludedDirectories: input.options.excludedProjectDirectories
2249
+ }).map(toForwardSlashes)).some((filePath) => !analyzedHeadFiles.has(filePath));
2183
2250
  const diagnosticDelta = computeDiagnosticDelta({
2184
2251
  headDiagnostics: input.headDiagnostics,
2185
2252
  baseDiagnostics: baseOutput.diagnostics,
@@ -2352,6 +2419,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
2352
2419
  directory,
2353
2420
  precomputedSourceFileCount: options.precomputedSourceFileCount,
2354
2421
  includePaths: options.includePaths,
2422
+ changedLineRanges: options.changedLineRanges ?? void 0,
2355
2423
  customRulesOnly: options.customRulesOnly,
2356
2424
  respectInlineDisables: options.respectInlineDisables,
2357
2425
  warnings: options.warnings,
@@ -2382,7 +2450,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
2382
2450
  else runSync(error(highlighter.error(lintFailureReason)));
2383
2451
  let inspectDiagnostics = output.diagnostics;
2384
2452
  let baselineDelta;
2385
- if (options.baseline && isDiffMode && !didLintFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
2453
+ if (options.baseline && isDiffMode && !didLintFail && !output.didDeadCodeFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
2386
2454
  const comparison = await runBaselineComparison({
2387
2455
  directory,
2388
2456
  options,
@@ -2535,13 +2603,13 @@ const resolveCursorBundledNode = () => {
2535
2603
  if (!localAppData) return null;
2536
2604
  const cursorAgentRoot = path$1.join(localAppData, "cursor-agent", "versions");
2537
2605
  try {
2538
- const versions = fs$1.readdirSync(cursorAgentRoot);
2606
+ const versions = fs$2.readdirSync(cursorAgentRoot);
2539
2607
  if (versions.length === 0) return null;
2540
2608
  const sortedVersions = versions.sort((a, b) => b.localeCompare(a, void 0, { numeric: true }));
2541
2609
  for (const version of sortedVersions) try {
2542
2610
  const bundledNodePath = path$1.join(cursorAgentRoot, version, "node.exe");
2543
2611
  const entryScriptPath = path$1.join(cursorAgentRoot, version, "index.js");
2544
- if (fs$1.statSync(bundledNodePath).isFile() && fs$1.statSync(entryScriptPath).isFile()) return {
2612
+ if (fs$2.statSync(bundledNodePath).isFile() && fs$2.statSync(entryScriptPath).isFile()) return {
2545
2613
  command: bundledNodePath,
2546
2614
  args: [entryScriptPath]
2547
2615
  };
@@ -2555,15 +2623,15 @@ const resolveWindowsCmdEntryScript = (command) => {
2555
2623
  for (const directory of pathDirectories) {
2556
2624
  const cmdFilePath = path$1.join(directory, `${command}.cmd`);
2557
2625
  try {
2558
- if (!fs$1.statSync(cmdFilePath).isFile()) continue;
2626
+ if (!fs$2.statSync(cmdFilePath).isFile()) continue;
2559
2627
  } catch {
2560
2628
  continue;
2561
2629
  }
2562
2630
  try {
2563
- const entryScriptMatch = fs$1.readFileSync(cmdFilePath, "utf8").match(/"%(?:~dp0|dp0%)\\([^"]+\.(?:m?js|cjs))"/);
2631
+ const entryScriptMatch = fs$2.readFileSync(cmdFilePath, "utf8").match(/"%(?:~dp0|dp0%)\\([^"]+\.(?:m?js|cjs))"/);
2564
2632
  if (!entryScriptMatch) continue;
2565
2633
  const resolvedScriptPath = path$1.resolve(directory, entryScriptMatch[1]);
2566
- if (fs$1.statSync(resolvedScriptPath).isFile()) return resolvedScriptPath;
2634
+ if (fs$2.statSync(resolvedScriptPath).isFile()) return resolvedScriptPath;
2567
2635
  } catch {}
2568
2636
  }
2569
2637
  return null;
@@ -2889,7 +2957,7 @@ const buildCodeFrame = (input) => {
2889
2957
  const absolutePath = resolveAbsolutePath(input.filePath, input.rootDirectory);
2890
2958
  let source;
2891
2959
  try {
2892
- source = fs$1.readFileSync(absolutePath, "utf8");
2960
+ source = fs$2.readFileSync(absolutePath, "utf8");
2893
2961
  } catch {
2894
2962
  return null;
2895
2963
  }
@@ -2910,7 +2978,7 @@ const buildCodeFrame = (input) => {
2910
2978
  const discoverWorkspacePackages = (rootDirectory) => {
2911
2979
  const hasRootPackageJson = isFile(path$1.join(rootDirectory, "package.json"));
2912
2980
  const packages = listWorkspacePackages(rootDirectory);
2913
- if (packages.length === 0 && (!hasRootPackageJson || isMonorepoRoot(rootDirectory))) return discoverReactSubprojects(rootDirectory);
2981
+ if (packages.length === 0 && (!hasRootPackageJson || isMonorepoRoot(rootDirectory))) return discoverSupportedSubprojects(rootDirectory);
2914
2982
  return packages;
2915
2983
  };
2916
2984
  const selectProjects = async (rootDirectory, projectFlag, skipPrompts, configProjects) => {
@@ -3026,7 +3094,7 @@ const shouldFailScanGate = (input) => {
3026
3094
  return shouldBlockCi(filterScansForSurface(input.scans, "ciFailure"), input.blockingLevel);
3027
3095
  };
3028
3096
  //#endregion
3029
- export { resolveMergeBaseRef as A, buildEmptyReportMessage as B, copyToClipboard as C, deduplicateProjectScans as D, collectProjectSourceFileCounts as E, printDiagnosticsDump as F, formatLearnMoreLine as G, buildRulePriorityMap as H, formatDiagnosticSite as I, hasIncompleteScoreAnalysis as L, pluralize as M, formatElapsedTime as N, createInvocationInspect as O, printFooter as P, filterDiagnosticsByCategories as R, CLI_AGENT_BINARIES as S, buildHandoffPayload as T, buildSortedRuleGroups as U, hasLintHardFailure as V, formatFixRecipeLine as W, resolveCliInspectOptions as _, projectManifestChanged as a, setUpGitHubActions as b, selectProjects as c, resolveProjectChangedLineRanges as d, resolveProjectDiffIncludePaths as f, resolveWorkspaceDeadCodeOwner as g, retryMissingProjectScores as h, validateModeFlags as i, printHeadlessReport as j, inspect as k, buildCodeFrame as l, resolveProjectRelativeDirectory as m, formatSkippedProjectsMessage as n, partitionProjectScanOutcomes as o, resolveProjectSourceFilePaths as p, validateIncludeUntrackedScope as r, discoverWorkspacePackages as s, shouldFailScanGate as t, resolveProjectScan as u, filterScansForSurface as v, launchCliAgent as w, detectLaunchableAgents as x, countUniqueScannedFiles as y, buildNoScoreMessage as z };
3097
+ export { resolveMergeBaseRef as A, buildNoScoreMessage as B, copyToClipboard as C, deduplicateProjectScans as D, collectProjectSourceFileCounts as E, printFooter as F, formatFixRecipeLine as G, hasLintHardFailure as H, printDiagnosticsDump as I, formatLearnMoreLine as K, formatDiagnosticSite as L, pluralize as M, formatSkippedCheckLabel as N, createInvocationInspect as O, formatElapsedTime as P, hasIncompleteScoreAnalysis as R, CLI_AGENT_BINARIES as S, buildHandoffPayload as T, buildRulePriorityMap as U, buildEmptyReportMessage as V, buildSortedRuleGroups as W, resolveCliInspectOptions as _, projectManifestChanged as a, setUpGitHubActions as b, selectProjects as c, resolveProjectChangedLineRanges as d, resolveProjectDiffIncludePaths as f, resolveWorkspaceDeadCodeOwner as g, retryMissingProjectScores as h, validateModeFlags as i, printHeadlessReport as j, inspect as k, buildCodeFrame as l, resolveProjectRelativeDirectory as m, formatSkippedProjectsMessage as n, partitionProjectScanOutcomes as o, resolveProjectSourceFilePaths as p, validateIncludeUntrackedScope as r, discoverWorkspacePackages as s, shouldFailScanGate as t, resolveProjectScan as u, filterScansForSurface as v, launchCliAgent as w, detectLaunchableAgents as x, countUniqueScannedFiles as y, filterDiagnosticsByCategories as z };
3030
3098
 
3031
- //# sourceMappingURL=should-fail-scan-gate-BEoC3SoQ.js.map
3032
- //# debugId=f7f13734-adec-55f3-953d-caa4c00f9b28
3099
+ //# sourceMappingURL=should-fail-scan-gate-Dch9vbPz.js.map
3100
+ //# debugId=19bff337-5a1f-5558-b6b7-bd4274f53f38
@@ -1,10 +1,10 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="6c5caf85-a05b-5e6e-93c2-2a1cbc505a42")}catch(e){}}();
3
- import { z as isNonInteractiveEnvironment } from "./record-metric-CeygoJWT.js";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="1835ead5-8913-5fe5-a0fa-4de3e400bee0")}catch(e){}}();
3
+ import { z as isNonInteractiveEnvironment } from "./record-metric-fdCvvcjz.js";
4
4
  //#region src/cli/utils/should-skip-prompts.ts
5
5
  const shouldSkipPrompts = (input = {}) => Boolean(input.yes) || Boolean(input.json) || isNonInteractiveEnvironment() || !process.stdin.isTTY;
6
6
  //#endregion
7
7
  export { shouldSkipPrompts as t };
8
8
 
9
- //# sourceMappingURL=should-skip-prompts-De37OlfL.js.map
10
- //# debugId=6c5caf85-a05b-5e6e-93c2-2a1cbc505a42
9
+ //# sourceMappingURL=should-skip-prompts-CyNdARgB.js.map
10
+ //# debugId=1835ead5-8913-5fe5-a0fa-4de3e400bee0
@@ -1,6 +1,6 @@
1
1
 
2
- !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="ac6b3308-25c4-5c04-9d6a-cf365c6f83f0")}catch(e){}}();
3
- import { En as messageFromUnknown, R as CliInputError, Yn as make, ar as runSync, g as VERSION, gn as isReactDoctorError, gr as void_, hn as isProjectDiscoveryError, i as isTelemetryEnabled, ir as runPromise, lr as buildWithScope, mr as makeUnsafe, pr as close, un as isErrnoException, yn as layerObservability } from "./record-metric-CeygoJWT.js";
2
+ !function(){try{var e="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof globalThis?globalThis:"undefined"!=typeof self?self:{},n=(new e.Error).stack;n&&(e._sentryDebugIds=e._sentryDebugIds||{},e._sentryDebugIds[n]="9c17a65b-1eeb-5572-8f88-8abf23cb6ab2")}catch(e){}}();
3
+ import { Hn as buildWithScope, Jt as isProjectDiscoveryError, Kn as close, Ln as runPromise, On as make, Qt as layerObservability, R as CliInputError, Rn as runSync, Sr as messageFromUnknown, Yn as void_, Yt as isReactDoctorError, g as VERSION, i as isTelemetryEnabled, qn as makeUnsafe, yr as isErrnoException } from "./record-metric-fdCvvcjz.js";
4
4
  //#region src/cli/utils/is-environment-error.ts
5
5
  const ENVIRONMENT_ERROR_CODES = new Set([
6
6
  "EACCES",
@@ -153,11 +153,8 @@ let pendingShutdown = null;
153
153
  *
154
154
  * Returns `null` when telemetry is disabled or unconfigured, which is what keeps
155
155
  * `--no-telemetry` and unconfigured builds from opening a scope at all.
156
- *
157
- * `exportIntervalMs` lets a long-running process (the language server) ship
158
- * telemetry periodically instead of only at shutdown.
159
156
  */
160
- const getTelemetryContext = (overrides = {}) => {
157
+ const getTelemetryContext = () => {
161
158
  if (isBuilt) return telemetryContext;
162
159
  isBuilt = true;
163
160
  if (!isTelemetryEnabled()) return null;
@@ -165,10 +162,7 @@ const getTelemetryContext = (overrides = {}) => {
165
162
  if (options === null && !isUserOtlpConfigured()) return null;
166
163
  try {
167
164
  const scope = makeUnsafe();
168
- telemetryContext = runSync(buildWithScope(layerObservability(options === null ? null : {
169
- ...options,
170
- ...overrides
171
- }), scope));
165
+ telemetryContext = runSync(buildWithScope(layerObservability(options), scope));
172
166
  telemetryScope = scope;
173
167
  } catch {
174
168
  telemetryContext = null;
@@ -223,5 +217,5 @@ const unrefStdin = () => {
223
217
  //#endregion
224
218
  export { setActiveRunTrace as a, isExpectedUserError as c, recordRunTraceId as i, formatEnvironmentError as l, getActiveRunTrace as n, getTelemetryContext as o, getLastRunTraceId as r, shutdownTelemetry as s, unrefStdin as t, isEnvironmentError as u };
225
219
 
226
- //# sourceMappingURL=unref-stdin-DklpxlNQ.js.map
227
- //# debugId=ac6b3308-25c4-5c04-9d6a-cf365c6f83f0
220
+ //# sourceMappingURL=unref-stdin-Cynhx9N1.js.map
221
+ //# debugId=9c17a65b-1eeb-5572-8f88-8abf23cb6ab2