react-doctor 0.9.11-dev.f1899d2 → 0.9.12-dev.0b670aa

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-CJ7k-BvF.js} +9 -10
  4. package/dist/{ci-B04VkLj2.js → ci-Dannv-cF.js} +12 -12
  5. package/dist/cli.js +30 -31
  6. package/dist/{design-AAjcvExu.js → design-9x5DReyL.js} +4 -4
  7. package/dist/{devtools-DPRVRu3S.js → devtools-D8NTVj81.js} +4 -4
  8. package/dist/{exit-gracefully-B7v9PIJk.js → exit-gracefully-ti2wONpM.js} +6 -6
  9. package/dist/index.d.ts +36 -59
  10. package/dist/index.js +54433 -54307
  11. package/dist/{inspect-CdQJI2XI.js → inspect-C3itFiEW.js} +23 -22
  12. package/dist/{install-BRU4jf-Y.js → install-CjIJL6S5.js} +8 -8
  13. package/dist/{install-doctor-script-Dn69YqKG.js → install-doctor-script-0sdZ4SY8.js} +4 -4
  14. package/dist/{install-github-workflow-BwELZAhu.js → install-github-workflow-DQ8_lhAW.js} +6 -6
  15. package/dist/{install-react-doctor-CcDiKPfC.js → install-react-doctor-DRG8hdL4.js} +47 -45
  16. package/dist/{print-branded-header-_kkHIAUd.js → print-branded-header-Dc1KdrcV.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-rblJxHxN.js} +4 -4
  20. package/dist/{record-metric-CeygoJWT.js → record-metric-Dgg2b2LG.js} +3053 -6132
  21. package/dist/{report-error-uffmJocy.js → report-error-BlOAg03W.js} +5 -5
  22. package/dist/{report-workflow-result-CMtcy7Eb.js → report-workflow-result-Dp4dCUxw.js} +5 -5
  23. package/dist/{resolve-scope-CFro-KQO.js → resolve-scope-CbeXgE9z.js} +6 -6
  24. package/dist/{rules-BkLea4GL.js → rules-ClDrNCc3.js} +6 -6
  25. package/dist/{run-scan-app-Befn2abh.js → run-scan-app-Cgn4ELJF.js} +132 -121
  26. package/dist/{scan-C00HPxuL.js → scan-Caa_ogFB.js} +8 -8
  27. package/dist/semver-DFtnEmN-.js +3219 -0
  28. package/dist/{should-fail-scan-gate-BEoC3SoQ.js → should-fail-scan-gate-BGzNJApW.js} +140 -80
  29. package/dist/{should-skip-prompts-De37OlfL.js → should-skip-prompts-Bbl0ToUI.js} +4 -4
  30. package/dist/{unref-stdin-DklpxlNQ.js → unref-stdin-C7d7_3va.js} +6 -12
  31. package/dist/{version-CRfqT5pV.js → version-Bjql-CLM.js} +4 -4
  32. package/dist/{why-BTbl-alh.js → why-BqG2EML8.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]="e9dd7060-4756-56a0-b78b-87feea53eea4")}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 discoverReactSubprojects, 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-Dgg2b2LG.js";
4
+ import { a as setActiveRunTrace, i as recordRunTraceId, o as getTelemetryContext } from "./unref-stdin-C7d7_3va.js";
5
+ import { n as buildFooterLinkLines, r as activeScanAbortRegistry, t as buildSectionDivider } from "./build-section-divider-CJ7k-BvF.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-0sdZ4SY8.js";
7
+ import { d as detectDefaultBranch, l as prompts, r as installReactDoctorWorkflow, u as isCommandAvailable } from "./install-github-workflow-DQ8_lhAW.js";
8
+ import { a as isValidBlockingLevel, c as openWorkflowPullRequest, l as stageWorkflowFile, o as pickBlockingLevel, u as toForwardSlashes } from "./resolve-scope-CbeXgE9z.js";
9
+ import { h as detectAvailableAgents, t as reportWorkflowResult } from "./report-workflow-result-Dp4dCUxw.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,7 +497,6 @@ 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);
@@ -632,12 +635,12 @@ const resolveCacheFilePath = (projectDirectory) => path.join(resolveReactDoctorC
632
635
  const readPersistedCache = (cacheFilePath) => {
633
636
  try {
634
637
  const parsed = JSON.parse(fs.readFileSync(cacheFilePath, "utf8"));
635
- if (!isRecord(parsed) || parsed.version !== 6) return {
636
- version: 6,
638
+ if (!isRecord(parsed) || parsed.version !== 7) return {
639
+ version: 7,
637
640
  entries: []
638
641
  };
639
642
  if (!Array.isArray(parsed.entries)) return {
640
- version: 6,
643
+ version: 7,
641
644
  entries: []
642
645
  };
643
646
  const entries = [];
@@ -652,12 +655,12 @@ const readPersistedCache = (cacheFilePath) => {
652
655
  });
653
656
  }
654
657
  return {
655
- version: 6,
658
+ version: 7,
656
659
  entries
657
660
  };
658
661
  } catch {
659
662
  return {
660
- version: 6,
663
+ version: 7,
661
664
  entries: []
662
665
  };
663
666
  }
@@ -665,7 +668,7 @@ const readPersistedCache = (cacheFilePath) => {
665
668
  /**
666
669
  * The global cache off-switch (`REACT_DOCTOR_NO_CACHE`), which disables every
667
670
  * 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
671
+ * sidecar caches (their `Context.Reference` defaults read the
669
672
  * same variable). Exported for the wide event's `cache.temperature`
670
673
  * derivation, which reports `"disabled"` instead of `"cold"` when the switch
671
674
  * is on. Granular knobs (`REACT_DOCTOR_NO_FILE_CACHE`, …) are deliberately
@@ -707,7 +710,7 @@ const buildScanResultCacheKey = (input) => {
707
710
  if (repositoryIdentity === null) return null;
708
711
  if (stringifyStableJson(input.userConfig) === null) return null;
709
712
  const cacheKeyJson = stringifyStableJson({
710
- schemaVersion: 6,
713
+ schemaVersion: 7,
711
714
  projectIdentity: resolveProjectIdentity(input.projectDirectory),
712
715
  headSha: repositoryIdentity.headSha,
713
716
  worktreeFingerprint: repositoryIdentity.worktreeFingerprint,
@@ -755,7 +758,7 @@ const createScanResultCache = (projectDirectory) => {
755
758
  for (const entry of readPersistedCache(cacheFilePath).entries) mergedEntries.set(entry.key, entry);
756
759
  for (const entry of entries.values()) mergedEntries.set(entry.key, entry);
757
760
  atomicWriteJson(cacheFilePath, {
758
- version: 6,
761
+ version: 7,
759
762
  entries: [...mergedEntries.values()].sort((firstEntry, secondEntry) => secondEntry.createdAtMs - firstEntry.createdAtMs).slice(0, 20)
760
763
  });
761
764
  };
@@ -790,8 +793,7 @@ const shouldBlockCi = (diagnostics, blockingLevel) => {
790
793
  /**
791
794
  * Lowercase, key-safe form of a rule category for the `diag.category.*`
792
795
  * 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.
796
+ * "Performance" → `performance`, "Dead Code" → `dead_code`).
795
797
  */
796
798
  const toCategoryKey = (category) => category.toLowerCase().replace(/[^a-z0-9]+/g, "_");
797
799
  //#endregion
@@ -821,12 +823,6 @@ const readEnvBoolean = (name) => {
821
823
  return value.toLowerCase() === "true" || value === "1";
822
824
  };
823
825
  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
826
  /**
831
827
  * One queryable cache temperature per scan, derived from the whole stack:
832
828
  *
@@ -834,8 +830,7 @@ const resolveDeadCodeReuseRatio = (result) => {
834
830
  * `wholeRepoCacheHit` flag from the CLI's cachedPayload
835
831
  * branch; no scan work ran).
836
832
  * - `"warm"` — any incremental reuse: per-file lint hits, sidecar
837
- * replays, a dead-code whole-result hit, or dead-code
838
- * summary-cache hits.
833
+ * replays.
839
834
  * - `"disabled"` — zero reuse because the global `REACT_DOCTOR_NO_CACHE`
840
835
  * off-switch is on. Granular per-cache opt-outs
841
836
  * (`REACT_DOCTOR_NO_FILE_CACHE`, …) still read warm/cold,
@@ -844,7 +839,7 @@ const resolveDeadCodeReuseRatio = (result) => {
844
839
  *
845
840
  * `cache.warmth` is the headline reuse magnitude in [0, 1]: the plain mean of
846
841
  * the subsystem reuse fractions known this run (lint hit ratio, sidecar
847
- * replay ratio, dead-code reuse), skipping subsystems that never consulted a
842
+ * replay ratio), skipping subsystems that never consulted a
848
843
  * cache; `1` on turbo, dropped when nothing consulted any cache. Deliberately
849
844
  * unweighted — the per-subsystem dims stay the precise signal; warmth is the
850
845
  * p50/p90-able summary. Emitted only on the success path.
@@ -857,11 +852,7 @@ const buildCacheAttributes = (input) => {
857
852
  warmth: 1
858
853
  });
859
854
  const result = input.result;
860
- const subsystemReuseRatios = [
861
- ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount),
862
- ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount),
863
- resolveDeadCodeReuseRatio(result)
864
- ];
855
+ const subsystemReuseRatios = [ratioOf(result.lintCacheHitFileCount, result.lintCacheTotalFileCount), ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)];
865
856
  let knownSubsystemCount = 0;
866
857
  let reuseRatioSum = 0;
867
858
  for (const reuseRatio of subsystemReuseRatios) {
@@ -1013,13 +1004,7 @@ const buildOutcomeAttributes = (input) => {
1013
1004
  sidecarTotalFiles: result.lintSidecarTotalFileCount,
1014
1005
  sidecarReplayRatio: ratioOf(result.lintSidecarReplayedFileCount, result.lintSidecarTotalFileCount)
1015
1006
  }),
1016
- ...withNamespace("deadCode", {
1017
- failed: input.didDeadCodeFail,
1018
- overlapped: input.deadCodeOverlapped,
1019
- cacheHit: result.deadCodeCacheHit,
1020
- summaryCacheHits: result.deadCodeSummaryCacheHits,
1021
- summaryCacheMisses: result.deadCodeSummaryCacheMisses
1022
- }),
1007
+ ...withNamespace("maintainability", { failed: input.didDeadCodeFail }),
1023
1008
  ...withNamespace("supplyChain", { overlapTimedOut: input.supplyChainOverlapTimedOut }),
1024
1009
  ...withNamespace("securityScan", { failed: input.securityScanFailed }),
1025
1010
  ...withNamespace("timing", {
@@ -1062,7 +1047,7 @@ const buildScanAttributes = (input) => {
1062
1047
  workerCount: input.workerCount,
1063
1048
  maxDurationMs: input.maxDurationMs,
1064
1049
  lint: input.lint,
1065
- deadCode: input.deadCode,
1050
+ maintainability: input.deadCode,
1066
1051
  supplyChain: input.supplyChain,
1067
1052
  scoreOnly: input.scoreOnly,
1068
1053
  noScore: input.noScore,
@@ -1073,6 +1058,7 @@ const buildScanAttributes = (input) => {
1073
1058
  hasCustomConfig: input.hasCustomConfig,
1074
1059
  rulesConfigured: ruleKeys.length,
1075
1060
  rulesDisabled: ruleKeys.filter((key) => ruleOverrides[key] === "off").length,
1061
+ projectAnalysisRuleCount: countOptInProjectRuleSelections(buildRuleSeverityControls(input.userConfig)),
1076
1062
  fileCount: input.result?.scannedFileCount,
1077
1063
  nonJsxFileCount: input.result?.analyzedFiles?.filter((filePath) => !JSX_FILE_PATTERN.test(filePath)).length,
1078
1064
  htmlFileCount: input.result?.analyzedFiles?.filter((filePath) => HTML_FILE_PATTERN.test(filePath)).length,
@@ -1083,7 +1069,7 @@ const buildScanAttributes = (input) => {
1083
1069
  * Projects a scan into the namespaced attribute set for its root span — the
1084
1070
  * canonical per-scan "wide event". Every attribute carries a dotted namespace
1085
1071
  * that groups it by concept (`scan.*` config, `action.*` CI knobs, `outcome.*`
1086
- * verdict, `diag.*` findings, `score.*`, `lint.*`, `deadCode.*`, `cache.*`,
1072
+ * verdict, `diag.*` findings, `score.*`, `lint.*`, `maintainability.*`, `cache.*`,
1087
1073
  * `supplyChain.*`, `timing.*`, `migration.*`, `baseline.*`) so the attributes
1088
1074
  * tree up in Sentry's attribute browser and stay filter-/group-/aggregate-able
1089
1075
  * in the Spans dataset. Pure and exported so the projection (outcome
@@ -1322,7 +1308,7 @@ const buildNoScoreMessage = (input) => {
1322
1308
  reason = input.disabledMessage ?? "Score disabled by --no-score.";
1323
1309
  break;
1324
1310
  case "analysis-incomplete":
1325
- reason = "Score not shown because lint or dead-code analysis could not complete.";
1311
+ reason = "Score not shown because lint or maintainability analysis could not complete.";
1326
1312
  break;
1327
1313
  case "api-unavailable":
1328
1314
  reason = "Score unavailable (could not reach the score API).";
@@ -1370,7 +1356,7 @@ const formatRuleSummary = (ruleKey, ruleDiagnostics) => {
1370
1356
  const ruleDumpFileName = (ruleKey) => ruleKey.replace(/\//g, "--") + ".txt";
1371
1357
  const readPreviousRuleDumpFileNames = (directory) => {
1372
1358
  try {
1373
- const previous = JSON.parse(fs$1.readFileSync(path$1.join(directory, "diagnostics.json"), "utf8"));
1359
+ const previous = JSON.parse(fs$2.readFileSync(path$1.join(directory, "diagnostics.json"), "utf8"));
1374
1360
  return new Set(previous.filter((d) => typeof d?.plugin === "string" && typeof d?.rule === "string").map((d) => ruleDumpFileName(`${d.plugin}/${d.rule}`)));
1375
1361
  } catch {
1376
1362
  return /* @__PURE__ */ new Set();
@@ -1378,10 +1364,10 @@ const readPreviousRuleDumpFileNames = (directory) => {
1378
1364
  };
1379
1365
  const writeDiagnosticsDirectory = (diagnostics, outputDirectory) => {
1380
1366
  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));
1367
+ if (outputDirectory) for (const fileName of readPreviousRuleDumpFileNames(directory)) fs$2.rmSync(path$1.join(directory, fileName), { force: true });
1368
+ fs$2.mkdirSync(directory, { recursive: true });
1369
+ for (const [ruleKey, ruleDiagnostics] of buildSortedRuleGroups(diagnostics)) fs$2.writeFileSync(path$1.join(directory, ruleDumpFileName(ruleKey)), formatRuleSummary(ruleKey, ruleDiagnostics));
1370
+ fs$2.writeFileSync(path$1.join(directory, "diagnostics.json"), JSON.stringify(diagnostics));
1385
1371
  return directory;
1386
1372
  };
1387
1373
  //#endregion
@@ -1425,6 +1411,9 @@ const formatElapsedTime = (elapsedMilliseconds) => {
1425
1411
  return `${(elapsedMilliseconds / MILLISECONDS_PER_SECOND).toFixed(1)}s`;
1426
1412
  };
1427
1413
  //#endregion
1414
+ //#region src/cli/utils/format-skipped-check-label.ts
1415
+ const formatSkippedCheckLabel = (skippedCheck) => skippedCheck === "dead-code" ? "maintainability" : skippedCheck;
1416
+ //#endregion
1428
1417
  //#region src/cli/utils/pluralize.ts
1429
1418
  const pluralize = (count, singularNoun) => `${count} ${singularNoun}${count === 1 ? "" : "s"}`;
1430
1419
  //#endregion
@@ -1473,7 +1462,7 @@ const printHeadlessReport = (input) => gen(function* () {
1473
1462
  }
1474
1463
  if (input.skippedChecks.length > 0) {
1475
1464
  yield* log("");
1476
- yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.join(" and ")} checks failed.`));
1465
+ yield* warn(highlighter.warn(`Results are incomplete: ${input.skippedChecks.map(formatSkippedCheckLabel).join(" and ")} checks failed.`));
1477
1466
  }
1478
1467
  });
1479
1468
  //#endregion
@@ -1673,12 +1662,39 @@ const renderAndRecordScan = async (input) => {
1673
1662
  didDeadCodeFail: input.payload.didDeadCodeFail,
1674
1663
  supplyChainOverlapTimedOut: input.payload.supplyChainOverlapTimedOut,
1675
1664
  securityScanFailed: input.payload.securityScanFailed,
1676
- deadCodeOverlapped: input.payload.deadCodeOverlapped,
1677
1665
  suppressedRuleCounts: input.payload.suppressedRuleCounts ?? []
1678
1666
  });
1679
1667
  return result;
1680
1668
  };
1681
1669
  //#endregion
1670
+ //#region src/cli/utils/copy-unchanged-baseline-sources.ts
1671
+ const copyUnchangedBaselineSources = async (input) => {
1672
+ const baseMaterializedFiles = new Set(input.baseMaterializedFiles.map(toForwardSlashes));
1673
+ const headChangedFiles = new Set(input.headChangedFiles.map(toForwardSlashes));
1674
+ const untrackedFiles = new Set(input.untrackedFiles.map(toForwardSlashes));
1675
+ const sourceDirectory = path$1.resolve(input.directory);
1676
+ const targetDirectory = path$1.resolve(input.tempDirectory);
1677
+ return (await mapWithConcurrency(input.sourceFiles.filter((filePath) => {
1678
+ const normalizedPath = toForwardSlashes(filePath);
1679
+ return !baseMaterializedFiles.has(normalizedPath) && !headChangedFiles.has(normalizedPath) && !untrackedFiles.has(normalizedPath);
1680
+ }), 32, async (filePath) => {
1681
+ input.signal?.throwIfAborted();
1682
+ if (input.deadlineEpochMs !== null && Date.now() >= input.deadlineEpochMs) return false;
1683
+ const sourcePath = path$1.resolve(sourceDirectory, filePath);
1684
+ const targetPath = path$1.resolve(targetDirectory, filePath);
1685
+ if (!isPathInsideDirectory(sourcePath, sourceDirectory) || !isPathInsideDirectory(targetPath, targetDirectory)) return false;
1686
+ try {
1687
+ if (!(await fs$1.lstat(sourcePath)).isFile()) return false;
1688
+ await fs$1.mkdir(path$1.dirname(targetPath), { recursive: true });
1689
+ await fs$1.copyFile(sourcePath, targetPath);
1690
+ return true;
1691
+ } catch {
1692
+ input.signal?.throwIfAborted();
1693
+ return false;
1694
+ }
1695
+ })).every(Boolean);
1696
+ };
1697
+ //#endregion
1682
1698
  //#region src/cli/utils/read-diagnostic-evidence.ts
1683
1699
  const SOURCE_EXTENSIONS = [
1684
1700
  ".ts",
@@ -2096,7 +2112,6 @@ const resolveMergeBaseRef = async (directory, ref) => {
2096
2112
  const silentConsole$1 = makeNoopConsole();
2097
2113
  const countIncompleteLintFiles = (lintPartialFailures) => countDroppedLintFiles(lintPartialFailures) + countDeadlineSkippedFiles(lintPartialFailures);
2098
2114
  const runBaselineComparison = async (input) => {
2099
- const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
2100
2115
  const baselineIncludePaths = filterPathsOutsideDirectories({
2101
2116
  rootDirectory: input.directory,
2102
2117
  relativePaths: input.options.includePaths,
@@ -2112,12 +2127,24 @@ const runBaselineComparison = async (input) => {
2112
2127
  relativePaths: input.headFiles,
2113
2128
  excludedDirectories: input.options.excludedProjectDirectories
2114
2129
  }) : void 0;
2130
+ const remainingBaselineBudgetMs = input.deadlineEpochMs === null ? null : remainingDeadlineBudgetMs(input.deadlineEpochMs);
2131
+ if (remainingBaselineBudgetMs === 0) return null;
2132
+ const baselineDeadlineSignal = remainingBaselineBudgetMs === null ? void 0 : AbortSignal.timeout(remainingBaselineBudgetMs);
2133
+ const baselineListingSignal = baselineDeadlineSignal === void 0 ? input.oxlintRuntime.abortSignal : input.oxlintRuntime.abortSignal === void 0 ? baselineDeadlineSignal : AbortSignal.any([input.oxlintRuntime.abortSignal, baselineDeadlineSignal]);
2134
+ let maintainabilitySourceFiles = [];
2135
+ if (input.options.deadCode) try {
2136
+ maintainabilitySourceFiles = (await listSourceFilesCooperative(input.directory, baselineListingSignal)).filter((filePath) => JSX_DUPLICATION_SOURCE_FILE_PATTERN.test(filePath) && classifyFileContext(filePath) === "production");
2137
+ } catch (error) {
2138
+ if (baselineDeadlineSignal?.aborted) return null;
2139
+ throw error;
2140
+ }
2141
+ const temporaryDirectory = mkdtempSync(path.join(tmpdir(), BASELINE_FILES_TEMP_DIR_PREFIX));
2115
2142
  const snapshot = await materializeBaselineFiles({
2116
2143
  directory: input.directory,
2117
2144
  ref: input.baselineRef,
2118
- files: baselineIncludePaths,
2119
- baseFiles: baselineBaseFiles,
2120
- headFiles: baselineHeadFiles,
2145
+ files: input.options.deadCode ? input.options.includePaths : baselineIncludePaths,
2146
+ baseFiles: input.options.deadCode ? input.baseFiles : baselineBaseFiles,
2147
+ headFiles: input.options.deadCode ? input.headFiles : baselineHeadFiles,
2121
2148
  tempDirectory: temporaryDirectory
2122
2149
  }).catch((error) => {
2123
2150
  rmSync(temporaryDirectory, {
@@ -2135,22 +2162,47 @@ const runBaselineComparison = async (input) => {
2135
2162
  }
2136
2163
  try {
2137
2164
  if (!snapshot.isComplete) return null;
2165
+ if (input.options.deadCode && !await copyUnchangedBaselineSources({
2166
+ directory: input.directory,
2167
+ sourceFiles: maintainabilitySourceFiles,
2168
+ baseMaterializedFiles: snapshot.materializedFiles,
2169
+ headChangedFiles: snapshot.headFiles,
2170
+ untrackedFiles: snapshot.untrackedFiles,
2171
+ tempDirectory: snapshot.tempDirectory,
2172
+ deadlineEpochMs: input.deadlineEpochMs,
2173
+ signal: input.oxlintRuntime.abortSignal
2174
+ })) return null;
2175
+ const filteredSnapshotBaseFiles = filterPathsOutsideDirectories({
2176
+ rootDirectory: input.directory,
2177
+ relativePaths: snapshot.baseFiles,
2178
+ excludedDirectories: input.options.excludedProjectDirectories
2179
+ });
2180
+ const filteredSnapshotHeadFiles = filterPathsOutsideDirectories({
2181
+ rootDirectory: input.directory,
2182
+ relativePaths: snapshot.headFiles,
2183
+ excludedDirectories: input.options.excludedProjectDirectories
2184
+ });
2138
2185
  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));
2186
+ const baseFiles = new Set((baselineBaseFiles ?? filteredSnapshotBaseFiles).map(toForwardSlashes));
2187
+ const expectedHeadFiles = new Set((baselineHeadFiles ?? filteredSnapshotHeadFiles).map(toForwardSlashes));
2141
2188
  for (const filePath of baselineIncludePaths) {
2142
2189
  const normalizedFilePath = toForwardSlashes(filePath);
2143
2190
  if (!baseFiles.has(normalizedFilePath)) expectedHeadFiles.add(normalizedFilePath);
2144
2191
  }
2145
- if (filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
2192
+ if (input.options.lint && filterSourceFiles([...expectedHeadFiles]).some((filePath) => !analyzedHeadFiles.has(filePath))) return null;
2193
+ const baselineLintPaths = new Set([...baselineIncludePaths, ...filteredSnapshotBaseFiles].map(toForwardSlashes));
2194
+ const materializedLintPaths = snapshot.materializedFiles.filter((filePath) => baselineLintPaths.has(toForwardSlashes(filePath)));
2195
+ const maintainabilityFocusPaths = [...new Set([...input.options.includePaths, ...snapshot.baseFiles].map(toForwardSlashes))];
2196
+ 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)));
2197
+ const baseIncludePaths = materializedLintPaths.length > 0 ? materializedLintPaths : maintainabilityFocusPaths;
2146
2198
  const runtimeLayers = buildRuntimeLayers({
2147
2199
  directory: snapshot.tempDirectory,
2148
2200
  hasConfigOverride: true,
2149
2201
  userConfig: input.userConfig,
2150
2202
  configSourceDirectory: input.configSourceDirectory,
2151
2203
  projectInfoOverride: input.headProjectInfo,
2152
- shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath,
2153
- shouldRunDeadCode: false,
2204
+ shouldSkipLint: !input.options.lint || !input.resolvedNodeBinaryPath || materializedLintPaths.length === 0,
2205
+ shouldRunDeadCode: input.options.deadCode,
2154
2206
  shouldRunSupplyChain: input.options.supplyChain,
2155
2207
  shouldComputeScore: false,
2156
2208
  shouldShowProgressSpinners: false,
@@ -2159,7 +2211,8 @@ const runBaselineComparison = async (input) => {
2159
2211
  });
2160
2212
  const baseOutput = await runPromise(restoreLegacyThrow(runInspect({
2161
2213
  directory: snapshot.tempDirectory,
2162
- includePaths: snapshot.materializedFiles,
2214
+ includePaths: baseIncludePaths,
2215
+ maintainabilityFocusPaths,
2163
2216
  customRulesOnly: input.options.customRulesOnly,
2164
2217
  respectInlineDisables: input.options.respectInlineDisables,
2165
2218
  warnings: input.options.warnings,
@@ -2168,7 +2221,7 @@ const runBaselineComparison = async (input) => {
2168
2221
  includedTags: input.options.includedTags,
2169
2222
  includeTagDefaults: input.options.includeTagDefaults,
2170
2223
  nodeBinaryPath: input.resolvedNodeBinaryPath ?? void 0,
2171
- runDeadCode: false,
2224
+ runDeadCode: input.options.deadCode,
2172
2225
  isCi: input.options.isCi,
2173
2226
  doctorVersion: VERSION,
2174
2227
  runId: getRunId(),
@@ -2176,10 +2229,16 @@ const runBaselineComparison = async (input) => {
2176
2229
  suppressScanSummary: true,
2177
2230
  supplyChainManifestChanged: input.options.supplyChainManifestChanged,
2178
2231
  deadlineEpochMs: input.deadlineEpochMs ?? void 0,
2179
- signal: input.oxlintRuntime.abortSignal
2232
+ signal: input.oxlintRuntime.abortSignal,
2233
+ excludedProjectDirectories: baselineExcludedProjectDirectories,
2234
+ retainExcludedProjectDeadCodeDiagnostics: input.options.retainExcludedProjectDeadCodeDiagnostics
2180
2235
  }, {}).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));
2236
+ if (baseOutput.didLintFail || baseOutput.didDeadCodeFail || countIncompleteLintFiles(baseOutput.lintPartialFailures) > 0) return null;
2237
+ const hasUnscannedUntrackedSourceFiles = filterSourceFiles(filterPathsOutsideDirectories({
2238
+ rootDirectory: input.directory,
2239
+ relativePaths: snapshot.untrackedFiles,
2240
+ excludedDirectories: input.options.excludedProjectDirectories
2241
+ }).map(toForwardSlashes)).some((filePath) => !analyzedHeadFiles.has(filePath));
2183
2242
  const diagnosticDelta = computeDiagnosticDelta({
2184
2243
  headDiagnostics: input.headDiagnostics,
2185
2244
  baseDiagnostics: baseOutput.diagnostics,
@@ -2352,6 +2411,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
2352
2411
  directory,
2353
2412
  precomputedSourceFileCount: options.precomputedSourceFileCount,
2354
2413
  includePaths: options.includePaths,
2414
+ changedLineRanges: options.changedLineRanges ?? void 0,
2355
2415
  customRulesOnly: options.customRulesOnly,
2356
2416
  respectInlineDisables: options.respectInlineDisables,
2357
2417
  warnings: options.warnings,
@@ -2382,7 +2442,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
2382
2442
  else runSync(error(highlighter.error(lintFailureReason)));
2383
2443
  let inspectDiagnostics = output.diagnostics;
2384
2444
  let baselineDelta;
2385
- if (options.baseline && isDiffMode && !didLintFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
2445
+ if (options.baseline && isDiffMode && !didLintFail && !output.didDeadCodeFail && countIncompleteLintFiles(output.lintPartialFailures) === 0) {
2386
2446
  const comparison = await runBaselineComparison({
2387
2447
  directory,
2388
2448
  options,
@@ -2535,13 +2595,13 @@ const resolveCursorBundledNode = () => {
2535
2595
  if (!localAppData) return null;
2536
2596
  const cursorAgentRoot = path$1.join(localAppData, "cursor-agent", "versions");
2537
2597
  try {
2538
- const versions = fs$1.readdirSync(cursorAgentRoot);
2598
+ const versions = fs$2.readdirSync(cursorAgentRoot);
2539
2599
  if (versions.length === 0) return null;
2540
2600
  const sortedVersions = versions.sort((a, b) => b.localeCompare(a, void 0, { numeric: true }));
2541
2601
  for (const version of sortedVersions) try {
2542
2602
  const bundledNodePath = path$1.join(cursorAgentRoot, version, "node.exe");
2543
2603
  const entryScriptPath = path$1.join(cursorAgentRoot, version, "index.js");
2544
- if (fs$1.statSync(bundledNodePath).isFile() && fs$1.statSync(entryScriptPath).isFile()) return {
2604
+ if (fs$2.statSync(bundledNodePath).isFile() && fs$2.statSync(entryScriptPath).isFile()) return {
2545
2605
  command: bundledNodePath,
2546
2606
  args: [entryScriptPath]
2547
2607
  };
@@ -2555,15 +2615,15 @@ const resolveWindowsCmdEntryScript = (command) => {
2555
2615
  for (const directory of pathDirectories) {
2556
2616
  const cmdFilePath = path$1.join(directory, `${command}.cmd`);
2557
2617
  try {
2558
- if (!fs$1.statSync(cmdFilePath).isFile()) continue;
2618
+ if (!fs$2.statSync(cmdFilePath).isFile()) continue;
2559
2619
  } catch {
2560
2620
  continue;
2561
2621
  }
2562
2622
  try {
2563
- const entryScriptMatch = fs$1.readFileSync(cmdFilePath, "utf8").match(/"%(?:~dp0|dp0%)\\([^"]+\.(?:m?js|cjs))"/);
2623
+ const entryScriptMatch = fs$2.readFileSync(cmdFilePath, "utf8").match(/"%(?:~dp0|dp0%)\\([^"]+\.(?:m?js|cjs))"/);
2564
2624
  if (!entryScriptMatch) continue;
2565
2625
  const resolvedScriptPath = path$1.resolve(directory, entryScriptMatch[1]);
2566
- if (fs$1.statSync(resolvedScriptPath).isFile()) return resolvedScriptPath;
2626
+ if (fs$2.statSync(resolvedScriptPath).isFile()) return resolvedScriptPath;
2567
2627
  } catch {}
2568
2628
  }
2569
2629
  return null;
@@ -2889,7 +2949,7 @@ const buildCodeFrame = (input) => {
2889
2949
  const absolutePath = resolveAbsolutePath(input.filePath, input.rootDirectory);
2890
2950
  let source;
2891
2951
  try {
2892
- source = fs$1.readFileSync(absolutePath, "utf8");
2952
+ source = fs$2.readFileSync(absolutePath, "utf8");
2893
2953
  } catch {
2894
2954
  return null;
2895
2955
  }
@@ -3026,7 +3086,7 @@ const shouldFailScanGate = (input) => {
3026
3086
  return shouldBlockCi(filterScansForSurface(input.scans, "ciFailure"), input.blockingLevel);
3027
3087
  };
3028
3088
  //#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 };
3089
+ 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
3090
 
3031
- //# sourceMappingURL=should-fail-scan-gate-BEoC3SoQ.js.map
3032
- //# debugId=f7f13734-adec-55f3-953d-caa4c00f9b28
3091
+ //# sourceMappingURL=should-fail-scan-gate-BGzNJApW.js.map
3092
+ //# debugId=e9dd7060-4756-56a0-b78b-87feea53eea4
@@ -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]="e5c1af83-a80c-5c40-bdcd-7071de31af74")}catch(e){}}();
3
+ import { z as isNonInteractiveEnvironment } from "./record-metric-Dgg2b2LG.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-Bbl0ToUI.js.map
10
+ //# debugId=e5c1af83-a80c-5c40-bdcd-7071de31af74
@@ -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]="7f381600-a44f-5622-afd8-ebc549ab1867")}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-Dgg2b2LG.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-C7d7_3va.js.map
221
+ //# debugId=7f381600-a44f-5622-afd8-ebc549ab1867
@@ -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]="bdca8076-6874-5f29-ade7-e7e157acb745")}catch(e){}}();
3
- import { g as VERSION, t as recordCount, w as METRIC } 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]="88ddace2-4c0d-533b-aeef-9584fb110088")}catch(e){}}();
3
+ import { g as VERSION, t as recordCount, w as METRIC } from "./record-metric-Dgg2b2LG.js";
4
4
  //#region src/cli/commands/version.ts
5
5
  /**
6
6
  * oclif-style version line. 12-factor CLI Apps (#3, "What version am I
@@ -17,5 +17,5 @@ const versionAction = () => {
17
17
  //#endregion
18
18
  export { versionAction };
19
19
 
20
- //# sourceMappingURL=version-CRfqT5pV.js.map
21
- //# debugId=bdca8076-6874-5f29-ade7-e7e157acb745
20
+ //# sourceMappingURL=version-Bjql-CLM.js.map
21
+ //# debugId=88ddace2-4c0d-533b-aeef-9584fb110088
@@ -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]="5e82f85c-9ab5-5bfa-80fc-c6cebc73cdfe")}catch(e){}}();
3
- import { t as inspectAction } from "./inspect-CdQJI2XI.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]="1350f41a-9f33-5e71-84ba-8ecdf676986b")}catch(e){}}();
3
+ import { t as inspectAction } from "./inspect-C3itFiEW.js";
4
4
  //#region src/cli/commands/why.ts
5
5
  /**
6
6
  * `why <file:line>` — explains why a rule fired (or why a suppression didn't
@@ -17,5 +17,5 @@ const whyAction = async (location, options) => {
17
17
  //#endregion
18
18
  export { whyAction };
19
19
 
20
- //# sourceMappingURL=why-BTbl-alh.js.map
21
- //# debugId=5e82f85c-9ab5-5bfa-80fc-c6cebc73cdfe
20
+ //# sourceMappingURL=why-BqG2EML8.js.map
21
+ //# debugId=1350f41a-9f33-5e71-84ba-8ecdf676986b