react-doctor 0.6.3-dev.ea9a775 → 0.6.3

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.
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
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]="d9c72b21-3e94-5923-b692-077f137a0078")}catch(e){}}();
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]="328318eb-6af2-5007-b816-51c953a96047")}catch(e){}}();
3
3
  import { createRequire } from "node:module";
4
4
  import * as NodeChildProcess from "node:child_process";
5
5
  import { execFile, execFileSync, spawn, spawnSync } from "node:child_process";
@@ -9,7 +9,7 @@ import * as NFS from "node:fs";
9
9
  import fs, { mkdtempSync, rmSync } from "node:fs";
10
10
  import process$1 from "node:process";
11
11
  import * as ts from "typescript";
12
- import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_DEPENDENCY_COLLECTORS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, collectCrossFileDependencyProbes, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
12
+ import reactDoctorPlugin, { ALL_REACT_DOCTOR_RULE_KEYS, CROSS_FILE_RULE_IDS, FRAMEWORK_SPECIFIC_RULE_KEYS, MOTION_LIBRARY_PACKAGES, REACT_COMPILER_RULES, REACT_DOCTOR_RULES, classifySecurityScanFile, shouldReadSecurityScanContent } from "oxlint-plugin-react-doctor";
13
13
  import * as OS from "node:os";
14
14
  import os, { tmpdir } from "node:os";
15
15
  import { parseJSON5 } from "confbox";
@@ -18,7 +18,6 @@ import { fileURLToPath, pathToFileURL } from "node:url";
18
18
  import { createJiti } from "jiti";
19
19
  import * as Crypto from "node:crypto";
20
20
  import crypto, { createHash, randomUUID } from "node:crypto";
21
- import { ANALYZED_MANIFEST_FILENAMES, DEFAULT_EXTENSIONS } from "deslop-js/analyzed-inputs";
22
21
  import { gzipSync } from "node:zlib";
23
22
  import * as Sentry from "@sentry/node";
24
23
  import { performance as performance$1 } from "node:perf_hooks";
@@ -36129,10 +36128,6 @@ const SOCKET_PACKAGE_PAGE_BASE = "https://socket.dev/npm/package";
36129
36128
  const SOCKET_FREE_USER_AGENT = "react-doctor-supply-chain";
36130
36129
  const FILE_LINT_CACHE_FILENAME = "file-lint-cache.json";
36131
36130
  const FILE_LINT_CACHE_MAX_FILE_COUNT = 5e4;
36132
- const SIDECAR_LINT_CACHE_FILENAME = "sidecar-lint-cache.json";
36133
- const CORE_PACKAGE_VERSION = "0.6.3";
36134
- const DEAD_CODE_CACHE_FILENAME = "dead-code-cache.json";
36135
- const DEAD_CODE_SUMMARY_CACHE_FILENAME = "dead-code-summaries.json";
36136
36131
  const SUPPLY_CHAIN_PLUGIN = "socket";
36137
36132
  const SUPPLY_CHAIN_RULE = "low-supply-chain-score";
36138
36133
  const SUPPLY_CHAIN_CATEGORY = "Security";
@@ -38817,48 +38812,6 @@ var PerFileLintCacheEnabled = class extends Reference("react-doctor/PerFileLintC
38817
38812
  if (CACHE_DISABLED_VALUES$1.has(noFileCache)) return false;
38818
38813
  return true;
38819
38814
  } }) {};
38820
- /**
38821
- * Whether the sidecar lint cache (`runners/oxlint/sidecar-lint-cache.ts`) is
38822
- * active. Defaults ON — warm rescans replay the cross-file rules' cached
38823
- * diagnostics for every file whose dependency fingerprint (the probe set the
38824
- * plugin's collectors recorded) still matches the tree, and re-lint only the
38825
- * rest. Only reachable when the per-file lint cache itself is on (the
38826
- * sidecar covers its cache hits), so `REACT_DOCTOR_NO_CACHE` /
38827
- * `REACT_DOCTOR_NO_FILE_CACHE` implicitly disable it too. Opt-OUT knobs:
38828
- *
38829
- * - `REACT_DOCTOR_NO_CACHE` — the global off-switch.
38830
- * - `REACT_DOCTOR_NO_SIDECAR_CACHE` — granular rollback hatch: keep the
38831
- * per-file cache but run the always-fresh sidecar over every hit
38832
- * (the pre-cache behavior).
38833
- *
38834
- * Tests override via `Layer.succeed(SidecarLintCacheEnabled, false)`.
38835
- */
38836
- var SidecarLintCacheEnabled = class extends Reference("react-doctor/SidecarLintCacheEnabled", { defaultValue: () => {
38837
- const noCache = process.env["REACT_DOCTOR_NO_CACHE"]?.toLowerCase() ?? "";
38838
- const noSidecarCache = process.env["REACT_DOCTOR_NO_SIDECAR_CACHE"]?.toLowerCase() ?? "";
38839
- if (CACHE_DISABLED_VALUES$1.has(noCache)) return false;
38840
- if (CACHE_DISABLED_VALUES$1.has(noSidecarCache)) return false;
38841
- return true;
38842
- } }) {};
38843
- /**
38844
- * Whether the whole-project dead-code result cache
38845
- * (`dead-code/dead-code-result-cache.ts`) is active. Defaults ON — a rescan
38846
- * whose inputs (source tree, manifests, configs, analyzer version) are
38847
- * unchanged replays the stored diagnostics instead of re-running the
38848
- * analysis worker. Opt-OUT, two knobs (matching the per-file lint cache):
38849
- *
38850
- * - `REACT_DOCTOR_NO_CACHE` — the global off-switch.
38851
- * - `REACT_DOCTOR_NO_DEAD_CODE_CACHE` — granular: bust only this cache.
38852
- *
38853
- * Tests override via `Layer.succeed(DeadCodeResultCacheEnabled, false)`.
38854
- */
38855
- var DeadCodeResultCacheEnabled = class extends Reference("react-doctor/DeadCodeResultCacheEnabled", { defaultValue: () => {
38856
- const noCache = process.env["REACT_DOCTOR_NO_CACHE"]?.toLowerCase() ?? "";
38857
- const noDeadCodeCache = process.env["REACT_DOCTOR_NO_DEAD_CODE_CACHE"]?.toLowerCase() ?? "";
38858
- if (CACHE_DISABLED_VALUES$1.has(noCache)) return false;
38859
- if (CACHE_DISABLED_VALUES$1.has(noDeadCodeCache)) return false;
38860
- return true;
38861
- } }) {};
38862
38815
  const DIAGNOSTIC_SURFACES = [
38863
38816
  "cli",
38864
38817
  "prComment",
@@ -40591,80 +40544,6 @@ const collectDeadCodeIgnorePatterns = (rootDirectory) => {
40591
40544
  return [...seen].filter((pattern) => pattern.length > 0);
40592
40545
  };
40593
40546
  const collectDeadCodeEntryPatterns = (rootDirectory) => [...new Set(collectKnipPatterns(rootDirectory, "entry"))].filter((pattern) => pattern.length > 0);
40594
- const atomicWriteJson = (filePath, value) => {
40595
- try {
40596
- NFS.mkdirSync(Path.dirname(filePath), { recursive: true });
40597
- const temporaryPath = `${filePath}.${process.pid}.tmp`;
40598
- NFS.writeFileSync(temporaryPath, JSON.stringify(value));
40599
- NFS.renameSync(temporaryPath, filePath);
40600
- } catch {
40601
- return;
40602
- }
40603
- };
40604
- const failOpenReadJson = (filePath, fallback) => {
40605
- try {
40606
- return JSON.parse(NFS.readFileSync(filePath, "utf8"));
40607
- } catch {
40608
- return fallback;
40609
- }
40610
- };
40611
- const ANALYZED_FILE_EXTENSIONS = new Set(DEFAULT_EXTENSIONS);
40612
- const CORE_SIDE_MANIFEST_NAMES = ["knip.json", "deno.lock"];
40613
- const ANALYZED_MANIFEST_NAMES = new Set([...ANALYZED_MANIFEST_FILENAMES, ...CORE_SIDE_MANIFEST_NAMES]);
40614
- const isTsConfigLikeFile = (fileName) => (fileName.startsWith("tsconfig") || fileName.startsWith("jsconfig")) && fileName.endsWith(".json");
40615
- const isFingerprintedFile = (fileName) => ANALYZED_FILE_EXTENSIONS.has(Path.extname(fileName).toLowerCase()) || ANALYZED_MANIFEST_NAMES.has(fileName) || isTsConfigLikeFile(fileName);
40616
- const collectAnalyzedFileFingerprints = (rootDirectory) => {
40617
- const fingerprints = [];
40618
- for (const { absolutePath, name } of walkSourceTreeFiles(rootDirectory)) {
40619
- if (!isFingerprintedFile(name)) continue;
40620
- try {
40621
- const fileStat = NFS.statSync(absolutePath);
40622
- const relativePath = Path.relative(rootDirectory, absolutePath).replace(/\\/g, "/");
40623
- fingerprints.push(`${relativePath}:${fileStat.mtimeMs}:${fileStat.size}`);
40624
- } catch {}
40625
- }
40626
- return fingerprints.sort();
40627
- };
40628
- const bundledRequire$2 = createRequire(import.meta.url);
40629
- const resolveDeslopVersion = () => {
40630
- try {
40631
- const packageJson = JSON.parse(NFS.readFileSync(bundledRequire$2.resolve("deslop-js/package.json"), "utf8"));
40632
- return isRecord$1(packageJson) && typeof packageJson.version === "string" ? packageJson.version : "unknown";
40633
- } catch {
40634
- return "unknown";
40635
- }
40636
- };
40637
- const computeDeadCodeCacheKey = (input) => crypto.createHash("sha1").update(JSON.stringify({
40638
- schemaVersion: 1,
40639
- coreVersion: input.coreVersion,
40640
- deslopVersion: resolveDeslopVersion(),
40641
- deslopJsModuleSpecifier: input.deslopJsModuleSpecifier,
40642
- entryPatterns: input.entryPatterns,
40643
- ignorePatterns: input.ignorePatterns,
40644
- tsConfigFile: input.tsConfigPath === void 0 ? null : Path.relative(input.rootDirectory, input.tsConfigPath).replace(/\\/g, "/"),
40645
- files: collectAnalyzedFileFingerprints(input.rootDirectory)
40646
- })).digest("hex");
40647
- const validateDiagnostic$2 = decodeUnknownSync(Diagnostic);
40648
- const decodeCachedDiagnostics = (raw) => {
40649
- try {
40650
- for (const entry of raw) validateDiagnostic$2(entry);
40651
- return raw;
40652
- } catch {
40653
- return null;
40654
- }
40655
- };
40656
- const lookupDeadCodeResultCache = (cacheDirectory, cacheKey) => {
40657
- const persisted = failOpenReadJson(Path.join(cacheDirectory, DEAD_CODE_CACHE_FILENAME), null);
40658
- if (persisted === null || !isRecord$1(persisted) || persisted.version !== 1 || persisted.key !== cacheKey || !Array.isArray(persisted.diagnostics)) return null;
40659
- return decodeCachedDiagnostics(persisted.diagnostics);
40660
- };
40661
- const storeDeadCodeResultCache = (cacheDirectory, cacheKey, diagnostics) => {
40662
- atomicWriteJson(Path.join(cacheDirectory, DEAD_CODE_CACHE_FILENAME), {
40663
- version: 1,
40664
- key: cacheKey,
40665
- diagnostics
40666
- });
40667
- };
40668
40547
  const readSystemFacts = () => ({
40669
40548
  availableCores: os.availableParallelism(),
40670
40549
  totalMemoryBytes: os.totalmem(),
@@ -40733,21 +40612,6 @@ const withDeadCodeWorkerSlot = async (task, abortSignal) => {
40733
40612
  releaseSlot();
40734
40613
  }
40735
40614
  };
40736
- const projectCacheSubdir = (projectDirectory) => crypto.createHash("sha256").update(projectDirectory).digest("hex").slice(0, 16);
40737
- const resolveReactDoctorCacheDir = (projectDirectory) => {
40738
- const cacheDirOverride = process.env["REACT_DOCTOR_CACHE_DIR"]?.trim();
40739
- if (cacheDirOverride) return Path.join(cacheDirOverride, projectCacheSubdir(projectDirectory));
40740
- const nodeModulesDirectory = Path.join(projectDirectory, "node_modules");
40741
- if (NFS.existsSync(nodeModulesDirectory)) return Path.join(nodeModulesDirectory, ".cache", "react-doctor");
40742
- return Path.join(os.tmpdir(), `react-doctor-cache-${resolveUserCacheScope()}`, projectCacheSubdir(projectDirectory));
40743
- };
40744
- const resolveUserCacheScope = () => {
40745
- try {
40746
- return String(process.getuid?.() ?? os.userInfo().username);
40747
- } catch {
40748
- return "shared";
40749
- }
40750
- };
40751
40615
  /**
40752
40616
  * Resolves a path to its canonical, symlink-free form, falling back to
40753
40617
  * the input when it cannot be realpath'd (broken symlink, permission
@@ -40801,14 +40665,6 @@ process.stdin.on("end", () => {
40801
40665
  circularDependencies: result.circularDependencies.map((cycle) => ({
40802
40666
  files: cycle.files,
40803
40667
  })),
40804
- ...(result.incrementalCacheStats
40805
- ? {
40806
- summaryCacheStats: {
40807
- hits: result.incrementalCacheStats.summaryHits,
40808
- misses: result.incrementalCacheStats.summaryMisses,
40809
- },
40810
- }
40811
- : {}),
40812
40668
  });
40813
40669
 
40814
40670
  const serializeError = (error) =>
@@ -40832,9 +40688,6 @@ process.stdin.on("end", () => {
40832
40688
  ...(workerInput.ignorePatterns.length > 0
40833
40689
  ? { ignorePatterns: workerInput.ignorePatterns }
40834
40690
  : {}),
40835
- ...(workerInput.incrementalCachePath
40836
- ? { incrementalCachePath: workerInput.incrementalCachePath }
40837
- : {}),
40838
40691
  // We consume only deslop's GRAPH-based findings (unusedFiles, unusedExports,
40839
40692
  // unusedDependencies, circularDependencies). Everything else deslop can compute
40840
40693
  // is pure wasted work for us, and it's the bulk of the runtime:
@@ -40845,18 +40698,12 @@ process.stdin.on("end", () => {
40845
40698
  // are the single most expensive pass — duplicate-block detection alone was
40846
40699
  // ~83s of a ~130s Sentry scan — so skipping them is an ~8.5x dead-code
40847
40700
  // speedup on a large repo.
40848
- // - reportRedundancy: the DRY-pattern detectors (duplicate types/constants,
40849
- // simplifiable functions, identity wrappers, …) — ~120 ms of discarded
40850
- // output per scan, and skipping them lets the incremental cache drop the
40851
- // DRY-pattern summary fields (the largest slice of the cache file).
40852
- // All are provably safe: the consumed graph findings are computed by their own
40701
+ // Both are provably safe: the consumed graph findings are computed by their own
40853
40702
  // detectors, independent of these passes (confirmed byte-identical on
40854
- // excalidraw + mui-material + sentry; re-verified on sentry after the
40855
- // reportRedundancy flip). tsConfigPath stays — the module resolver needs it
40856
- // for path-alias resolution in the import graph.
40703
+ // excalidraw + mui-material + sentry). tsConfigPath stays — the module resolver
40704
+ // needs it for path-alias resolution in the import graph.
40857
40705
  semantic: { enabled: false },
40858
40706
  reportCodeQuality: false,
40859
- reportRedundancy: false,
40860
40707
  };
40861
40708
  const result = await analyze(defineConfig(config));
40862
40709
  emit({ ok: true, result: normalizeResult(result) });
@@ -40940,23 +40787,13 @@ const parseCircularDependencies = (value) => {
40940
40787
  }
40941
40788
  return circularDependencies;
40942
40789
  };
40943
- const parseSummaryCacheStats = (value) => {
40944
- if (!isRecord$1(value)) return void 0;
40945
- if (typeof value.hits !== "number" || typeof value.misses !== "number") return void 0;
40946
- return {
40947
- hits: value.hits,
40948
- misses: value.misses
40949
- };
40950
- };
40951
40790
  const parseDeadCodeWorkerResult = (value) => {
40952
40791
  if (!isRecord$1(value)) throw new Error("Dead-code worker returned an invalid result.");
40953
- const summaryCacheStats = parseSummaryCacheStats(value.summaryCacheStats);
40954
40792
  return {
40955
40793
  unusedFiles: parseUnusedFiles(value.unusedFiles),
40956
40794
  unusedExports: parseUnusedExports(value.unusedExports),
40957
40795
  unusedDependencies: parseUnusedDependencies(value.unusedDependencies),
40958
- circularDependencies: parseCircularDependencies(value.circularDependencies),
40959
- ...summaryCacheStats ? { summaryCacheStats } : {}
40796
+ circularDependencies: parseCircularDependencies(value.circularDependencies)
40960
40797
  };
40961
40798
  };
40962
40799
  const parseDeadCodeWorkerError = (value) => {
@@ -41070,35 +40907,17 @@ const checkDeadCode = async (options) => {
41070
40907
  if (!NFS.existsSync(Path.join(rootDirectory, "package.json"))) return [];
41071
40908
  const entryPatterns = collectDeadCodeEntryPatterns(rootDirectory);
41072
40909
  const ignorePatterns = collectDeadCodeIgnorePatterns(rootDirectory);
41073
- const tsConfigPath = resolveTsConfigPath(rootDirectory);
41074
- const deslopJsModuleSpecifier = options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js");
41075
- const cacheKey = options.cacheEnabled ? computeDeadCodeCacheKey({
41076
- rootDirectory,
41077
- entryPatterns,
41078
- ignorePatterns,
41079
- tsConfigPath,
41080
- deslopJsModuleSpecifier,
41081
- coreVersion: CORE_PACKAGE_VERSION
41082
- }) : null;
41083
- if (cacheKey !== null) {
41084
- const cachedDiagnostics = lookupDeadCodeResultCache(resolveReactDoctorCacheDir(rootDirectory), cacheKey);
41085
- options.onCacheOutcome?.(cachedDiagnostics !== null);
41086
- if (cachedDiagnostics !== null) return [...cachedDiagnostics];
41087
- }
41088
- const incrementalCachePath = options.cacheEnabled === true ? Path.join(resolveReactDoctorCacheDir(rootDirectory), DEAD_CODE_SUMMARY_CACHE_FILENAME) : void 0;
41089
40910
  const spawnAndRun = () => {
41090
40911
  return runDeadCodeWorkerWithTimeout((options.createWorker ?? createDeadCodeWorker)({
41091
40912
  rootDirectory,
41092
40913
  entryPatterns,
41093
- tsConfigPath,
40914
+ tsConfigPath: resolveTsConfigPath(rootDirectory),
41094
40915
  ignorePatterns,
41095
- deslopJsModuleSpecifier,
41096
- parseConcurrency: options.parseConcurrency,
41097
- incrementalCachePath
40916
+ deslopJsModuleSpecifier: options.deslopJsModuleSpecifier ?? import.meta.resolve("deslop-js"),
40917
+ parseConcurrency: options.parseConcurrency
41098
40918
  }), options.workerTimeoutMs ?? 12e4, options.abortSignal);
41099
40919
  };
41100
40920
  const result = parseDeadCodeWorkerResult(options.createWorker === void 0 ? await withDeadCodeWorkerSlot(spawnAndRun, options.abortSignal) : await spawnAndRun());
41101
- if (result.summaryCacheStats !== void 0) options.onSummaryCacheStats?.(result.summaryCacheStats);
41102
40921
  const toRelative = (filePath) => toRelativeFilePath(rootDirectory, filePath);
41103
40922
  const diagnostics = [];
41104
40923
  for (const unusedFile of result.unusedFiles) diagnostics.push({
@@ -41155,7 +40974,6 @@ const checkDeadCode = async (options) => {
41155
40974
  category: DEAD_CODE_CATEGORY
41156
40975
  });
41157
40976
  }
41158
- if (cacheKey !== null) storeDeadCodeResultCache(resolveReactDoctorCacheDir(rootDirectory), cacheKey, diagnostics);
41159
40977
  return diagnostics;
41160
40978
  };
41161
40979
  const DEAD_CODE_RULE_KEY_PREFIX = `${DEAD_CODE_PLUGIN}/`;
@@ -41258,16 +41076,12 @@ var Config = class Config extends Service()("react-doctor/Config") {
41258
41076
  */
41259
41077
  var DeadCode = class DeadCode extends Service()("react-doctor/DeadCode") {
41260
41078
  static layerNode = succeed$3(DeadCode, DeadCode.of({ run: (input) => unwrap(fn("DeadCode.run")(function* () {
41261
- const cacheEnabled = yield* DeadCodeResultCacheEnabled;
41262
41079
  return yield* tryPromise({
41263
41080
  try: (signal) => checkDeadCode({
41264
41081
  rootDirectory: input.rootDirectory,
41265
41082
  parseConcurrency: input.parseConcurrency,
41266
41083
  workerTimeoutMs: input.workerTimeoutMs,
41267
- abortSignal: signal,
41268
- cacheEnabled,
41269
- onCacheOutcome: input.onCacheOutcome,
41270
- onSummaryCacheStats: input.onSummaryCacheStats
41084
+ abortSignal: signal
41271
41085
  }),
41272
41086
  catch: (cause) => new ReactDoctorError({ reason: new DeadCodeAnalysisFailed({ cause }) })
41273
41087
  }).pipe(map$3((diagnostics) => fromIterable$1(diagnostics)));
@@ -42137,7 +41951,7 @@ const buildUserPluginRules = (userPlugin, severityControls) => {
42137
41951
  }
42138
41952
  return enabled;
42139
41953
  };
42140
- const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection, sidecarRuleIdFilter }) => {
41954
+ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, extendsPaths = [], ignoredTags = /* @__PURE__ */ new Set(), serverAuthFunctionNames, severityControls, userPlugins = [], disableReactHooksJsPlugin = false, ruleSelection }) => {
42141
41955
  const reactHooksJsPlugin = disableReactHooksJsPlugin || ruleSelection === "sidecar" ? null : resolveReactHooksJsPlugin(project.hasReactCompiler, customRulesOnly);
42142
41956
  const reactCompilerRules = reactHooksJsPlugin ? applyRuleSeverityControls(filterRulesToAvailable(REACT_COMPILER_RULES, "react-hooks-js", reactHooksJsPlugin.availableRuleNames), severityControls) : {};
42143
41957
  const jsPlugins = [];
@@ -42149,7 +41963,6 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
42149
41963
  if (!rule) continue;
42150
41964
  if (ruleSelection === "cacheable" && CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
42151
41965
  if (ruleSelection === "sidecar" && !CROSS_FILE_RULE_IDS.has(registryEntry.id)) continue;
42152
- if (ruleSelection === "sidecar" && sidecarRuleIdFilter !== void 0 && !sidecarRuleIdFilter.has(registryEntry.id)) continue;
42153
41966
  if (rule.scan !== void 0) continue;
42154
41967
  if (customRulesOnly && registryEntry.originallyExternal) continue;
42155
41968
  if (rule.framework !== "global" && !rule.requires) continue;
@@ -42194,152 +42007,33 @@ const createOxlintConfig = ({ pluginPath, project, customRulesOnly = false, exte
42194
42007
  }
42195
42008
  };
42196
42009
  };
42197
- const validateDiagnostic$1 = decodeUnknownSync(Diagnostic);
42198
- const decodeFileDiagnostics = (raw) => {
42199
- if (!Array.isArray(raw)) return null;
42010
+ const atomicWriteJson = (filePath, value) => {
42200
42011
  try {
42201
- for (const entry of raw) validateDiagnostic$1(entry);
42202
- return raw;
42012
+ NFS.mkdirSync(Path.dirname(filePath), { recursive: true });
42013
+ const temporaryPath = `${filePath}.${process.pid}.tmp`;
42014
+ NFS.writeFileSync(temporaryPath, JSON.stringify(value));
42015
+ NFS.renameSync(temporaryPath, filePath);
42203
42016
  } catch {
42204
- return null;
42205
- }
42206
- };
42207
- const emptyCache$1 = () => ({
42208
- version: 1,
42209
- rulesets: {}
42210
- });
42211
- const loadRulesetEntries$1 = (cacheFilePath, rulesetHash) => {
42212
- const entries = /* @__PURE__ */ new Map();
42213
- const persisted = failOpenReadJson(cacheFilePath, emptyCache$1());
42214
- if (persisted.version !== 1 || !isRecord$1(persisted.rulesets)) return entries;
42215
- const bucket = persisted.rulesets[rulesetHash];
42216
- if (!isRecord$1(bucket) || !isRecord$1(bucket.files)) return entries;
42217
- for (const [fileKey, rawDiagnostics] of Object.entries(bucket.files)) {
42218
- const decoded = decodeFileDiagnostics(rawDiagnostics);
42219
- if (decoded !== null) entries.set(fileKey, decoded);
42017
+ return;
42220
42018
  }
42221
- return entries;
42222
42019
  };
42223
- const createFileLintCache = (cacheDirectory, rulesetHash) => {
42224
- const cacheFilePath = Path.join(cacheDirectory, FILE_LINT_CACHE_FILENAME);
42225
- const entries = loadRulesetEntries$1(cacheFilePath, rulesetHash);
42226
- return {
42227
- lookup: (fileKey) => entries.get(fileKey) ?? null,
42228
- store: (fileKey, diagnostics) => {
42229
- entries.delete(fileKey);
42230
- entries.set(fileKey, diagnostics);
42231
- },
42232
- persist: () => {
42233
- const onDisk = failOpenReadJson(cacheFilePath, emptyCache$1());
42234
- const rulesets = onDisk.version === 1 && isRecord$1(onDisk.rulesets) ? { ...onDisk.rulesets } : {};
42235
- const existingBucket = rulesets[rulesetHash];
42236
- const existingFiles = isRecord$1(existingBucket) && isRecord$1(existingBucket.files) ? existingBucket.files : {};
42237
- const ourFiles = {};
42238
- for (const [fileKey, diagnostics] of entries) ourFiles[fileKey] = diagnostics;
42239
- const cappedEntries = Object.entries({
42240
- ...existingFiles,
42241
- ...ourFiles
42242
- }).slice(-FILE_LINT_CACHE_MAX_FILE_COUNT);
42243
- rulesets[rulesetHash] = {
42244
- updatedAtMs: Date.now(),
42245
- files: Object.fromEntries(cappedEntries)
42246
- };
42247
- atomicWriteJson(cacheFilePath, {
42248
- version: 1,
42249
- rulesets: Object.fromEntries(Object.entries(rulesets).filter(([, bucket]) => isRecord$1(bucket) && typeof bucket.updatedAtMs === "number").sort(([, first], [, second]) => second.updatedAtMs - first.updatedAtMs).slice(0, 8))
42250
- });
42251
- }
42252
- };
42253
- };
42254
- const hashFileContents = (filePath) => {
42020
+ const failOpenReadJson = (filePath, fallback) => {
42255
42021
  try {
42256
- return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
42022
+ return JSON.parse(NFS.readFileSync(filePath, "utf8"));
42257
42023
  } catch {
42258
- return null;
42024
+ return fallback;
42259
42025
  }
42260
42026
  };
42261
- const ABSENT_CONTENT_ANSWER = "absent";
42262
- /**
42263
- * Answers dependency probes for the sidecar lint cache — used both when
42264
- * STORING an entry (turn the collector's probe paths into answers) and when
42265
- * VERIFYING one (re-answer each stored probe against the current tree).
42266
- * Store and verify must agree exactly, so both go through this one resolver.
42267
- *
42268
- * - `content` — SHA-1 of the file's bytes, `"absent"` when unreadable
42269
- * (missing, a directory, permission failure). Source files reuse the
42270
- * hashes the cache-partition loop already computed
42271
- * (`contentHashByRelativePath`); everything else (package.json,
42272
- * tsconfig, ignored files) is hashed on demand.
42273
- * - `exists` — the existence class a module-resolution candidate probe
42274
- * sees: `"file"`, `"dir"`, or `"none"` (missing or an exotic entry —
42275
- * `statSync` follows symlinks, matching the resolvers).
42276
- *
42277
- * Answers are memoized per scan: the filesystem is frozen for the run, and
42278
- * hot dependency paths (a barrel imported by hundreds of files, the shared
42279
- * tsconfig chain) repeat across many files' probe sets.
42280
- */
42281
- const createSidecarProbeAnswerResolver = (input) => {
42282
- const contentAnswerByPath = /* @__PURE__ */ new Map();
42283
- const existsAnswerByPath = /* @__PURE__ */ new Map();
42284
- const toRelativePath = (absolutePath) => Path.relative(input.rootDirectory, absolutePath).replaceAll("\\", "/");
42285
- const contentAnswer = (relativePath) => {
42286
- const memoized = contentAnswerByPath.get(relativePath);
42287
- if (memoized !== void 0) return memoized;
42288
- const answer = input.contentHashByRelativePath.get(relativePath) ?? hashFileContents(Path.resolve(input.rootDirectory, relativePath)) ?? ABSENT_CONTENT_ANSWER;
42289
- contentAnswerByPath.set(relativePath, answer);
42290
- return answer;
42291
- };
42292
- const existsAnswer = (relativePath) => {
42293
- const memoized = existsAnswerByPath.get(relativePath);
42294
- if (memoized !== void 0) return memoized;
42295
- let answer;
42296
- try {
42297
- const stat = NFS.statSync(Path.resolve(input.rootDirectory, relativePath));
42298
- answer = stat.isFile() ? "file" : stat.isDirectory() ? "dir" : "none";
42299
- } catch {
42300
- answer = "none";
42301
- }
42302
- existsAnswerByPath.set(relativePath, answer);
42303
- return answer;
42304
- };
42305
- return {
42306
- answerFor: (kind, relativePath) => kind === "content" ? contentAnswer(relativePath) : existsAnswer(relativePath),
42307
- toRelativePath
42308
- };
42309
- };
42310
42027
  const validateDiagnostic = decodeUnknownSync(Diagnostic);
42311
- const isProbeKind = (value) => value === "content" || value === "exists";
42312
- const decodeSidecarFileEntry = (raw) => {
42313
- if (!isRecord$1(raw) || !Array.isArray(raw.probes) || !Array.isArray(raw.diagnostics)) return null;
42314
- const probes = [];
42315
- for (const rawProbe of raw.probes) {
42316
- if (!Array.isArray(rawProbe) || rawProbe.length !== 3) return null;
42317
- const [kind, probePath, answer] = rawProbe;
42318
- if (!isProbeKind(kind) || typeof probePath !== "string" || typeof answer !== "string") return null;
42319
- probes.push({
42320
- kind,
42321
- path: probePath,
42322
- answer
42323
- });
42324
- }
42028
+ const decodeFileDiagnostics = (raw) => {
42029
+ if (!Array.isArray(raw)) return null;
42325
42030
  try {
42326
- for (const entry of raw.diagnostics) validateDiagnostic(entry);
42031
+ for (const entry of raw) validateDiagnostic(entry);
42032
+ return raw;
42327
42033
  } catch {
42328
42034
  return null;
42329
42035
  }
42330
- return {
42331
- probes,
42332
- diagnostics: raw.diagnostics
42333
- };
42334
42036
  };
42335
- const encodeSidecarFileEntry = (entry) => ({
42336
- probes: entry.probes.map((probe) => [
42337
- probe.kind,
42338
- probe.path,
42339
- probe.answer
42340
- ]),
42341
- diagnostics: entry.diagnostics
42342
- });
42343
42037
  const emptyCache = () => ({
42344
42038
  version: 1,
42345
42039
  rulesets: {}
@@ -42350,20 +42044,20 @@ const loadRulesetEntries = (cacheFilePath, rulesetHash) => {
42350
42044
  if (persisted.version !== 1 || !isRecord$1(persisted.rulesets)) return entries;
42351
42045
  const bucket = persisted.rulesets[rulesetHash];
42352
42046
  if (!isRecord$1(bucket) || !isRecord$1(bucket.files)) return entries;
42353
- for (const [fileKey, rawEntry] of Object.entries(bucket.files)) {
42354
- const decoded = decodeSidecarFileEntry(rawEntry);
42047
+ for (const [fileKey, rawDiagnostics] of Object.entries(bucket.files)) {
42048
+ const decoded = decodeFileDiagnostics(rawDiagnostics);
42355
42049
  if (decoded !== null) entries.set(fileKey, decoded);
42356
42050
  }
42357
42051
  return entries;
42358
42052
  };
42359
- const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
42360
- const cacheFilePath = Path.join(cacheDirectory, SIDECAR_LINT_CACHE_FILENAME);
42053
+ const createFileLintCache = (cacheDirectory, rulesetHash) => {
42054
+ const cacheFilePath = Path.join(cacheDirectory, FILE_LINT_CACHE_FILENAME);
42361
42055
  const entries = loadRulesetEntries(cacheFilePath, rulesetHash);
42362
42056
  return {
42363
42057
  lookup: (fileKey) => entries.get(fileKey) ?? null,
42364
- store: (fileKey, entry) => {
42058
+ store: (fileKey, diagnostics) => {
42365
42059
  entries.delete(fileKey);
42366
- entries.set(fileKey, entry);
42060
+ entries.set(fileKey, diagnostics);
42367
42061
  },
42368
42062
  persist: () => {
42369
42063
  const onDisk = failOpenReadJson(cacheFilePath, emptyCache());
@@ -42371,7 +42065,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
42371
42065
  const existingBucket = rulesets[rulesetHash];
42372
42066
  const existingFiles = isRecord$1(existingBucket) && isRecord$1(existingBucket.files) ? existingBucket.files : {};
42373
42067
  const ourFiles = {};
42374
- for (const [fileKey, entry] of entries) ourFiles[fileKey] = encodeSidecarFileEntry(entry);
42068
+ for (const [fileKey, diagnostics] of entries) ourFiles[fileKey] = diagnostics;
42375
42069
  const cappedEntries = Object.entries({
42376
42070
  ...existingFiles,
42377
42071
  ...ourFiles
@@ -42387,7 +42081,7 @@ const createSidecarLintCache = (cacheDirectory, rulesetHash) => {
42387
42081
  }
42388
42082
  };
42389
42083
  };
42390
- const bundledRequire$3 = createRequire(import.meta.url);
42084
+ const bundledRequire$2 = createRequire(import.meta.url);
42391
42085
  const childNodeVersionByBinaryPath = /* @__PURE__ */ new Map();
42392
42086
  const resolveChildNodeVersion = (nodeBinaryPath) => {
42393
42087
  if (nodeBinaryPath === process.execPath) return process.version;
@@ -42413,7 +42107,7 @@ const TOOLCHAIN_PACKAGE_SPECIFIERS$1 = [
42413
42107
  const resolveOxlintToolchainVersions = (nodeBinaryPath = process.execPath) => {
42414
42108
  const versions = [`node=${resolveChildNodeVersion(nodeBinaryPath)}`];
42415
42109
  for (const specifier of TOOLCHAIN_PACKAGE_SPECIFIERS$1) try {
42416
- const packageJson = bundledRequire$3(specifier);
42110
+ const packageJson = bundledRequire$2(specifier);
42417
42111
  const version = typeof packageJson.version === "string" ? packageJson.version : "unknown";
42418
42112
  versions.push(`${specifier}=${version}`);
42419
42113
  } catch {
@@ -43386,6 +43080,13 @@ const validateRuleRegistration = () => {
43386
43080
  ].filter((entry) => entry !== null).join("; ");
43387
43081
  console.warn(`[react-doctor] rule-registration drift: ${detail}`);
43388
43082
  };
43083
+ const hashFileContents = (filePath) => {
43084
+ try {
43085
+ return crypto.createHash("sha1").update(NFS.readFileSync(filePath)).digest("hex");
43086
+ } catch {
43087
+ return null;
43088
+ }
43089
+ };
43389
43090
  /**
43390
43091
  * Balanced LPT (longest-processing-time-first) lint batch planner. Where
43391
43092
  * `batchIncludePaths` greedily fills 100-file batches and leaves a small
@@ -43450,6 +43151,21 @@ const planLintBatches = ({ baseArgs, files, sizeByFile }) => {
43450
43151
  }
43451
43152
  return batches.filter((batch) => batch.fileIndexes.length > 0).map((batch) => batch.fileIndexes.sort((leftIndex, rightIndex) => leftIndex - rightIndex).map((fileIndex) => files[fileIndex]));
43452
43153
  };
43154
+ const projectCacheSubdir = (projectDirectory) => crypto.createHash("sha256").update(projectDirectory).digest("hex").slice(0, 16);
43155
+ const resolveReactDoctorCacheDir = (projectDirectory) => {
43156
+ const cacheDirOverride = process.env["REACT_DOCTOR_CACHE_DIR"]?.trim();
43157
+ if (cacheDirOverride) return Path.join(cacheDirOverride, projectCacheSubdir(projectDirectory));
43158
+ const nodeModulesDirectory = Path.join(projectDirectory, "node_modules");
43159
+ if (NFS.existsSync(nodeModulesDirectory)) return Path.join(nodeModulesDirectory, ".cache", "react-doctor");
43160
+ return Path.join(os.tmpdir(), `react-doctor-cache-${resolveUserCacheScope()}`, projectCacheSubdir(projectDirectory));
43161
+ };
43162
+ const resolveUserCacheScope = () => {
43163
+ try {
43164
+ return String(process.getuid?.() ?? os.userInfo().username);
43165
+ } catch {
43166
+ return "shared";
43167
+ }
43168
+ };
43453
43169
  /**
43454
43170
  * Atomically (re)writes the generated oxlintrc.json. Used twice in
43455
43171
  * the runner: once for the primary scan, once for the
@@ -43467,106 +43183,6 @@ const writeOxlintConfig = (configPath, configToWrite) => {
43467
43183
  NFS.closeSync(fileHandle);
43468
43184
  }
43469
43185
  };
43470
- /**
43471
- * Attributes diagnostics back to the file that produced them by the
43472
- * normalized path oxlint echoes. Returns `null` when ANY diagnostic can't be
43473
- * attributed — the path forms don't align, so the caller must skip its cache
43474
- * store rather than risk caching a wrong empty result for a file that
43475
- * actually had diagnostics.
43476
- */
43477
- const attributeDiagnosticsToFiles = (diagnostics, files) => {
43478
- const fileByNormalizedPath = /* @__PURE__ */ new Map();
43479
- for (const file of files) fileByNormalizedPath.set(file.replaceAll("\\", "/"), file);
43480
- const diagnosticsByFile = /* @__PURE__ */ new Map();
43481
- for (const diagnostic of diagnostics) {
43482
- const file = fileByNormalizedPath.get(diagnostic.filePath);
43483
- if (file === void 0) return null;
43484
- const fileDiagnostics = diagnosticsByFile.get(file) ?? [];
43485
- fileDiagnostics.push(diagnostic);
43486
- diagnosticsByFile.set(file, fileDiagnostics);
43487
- }
43488
- return diagnosticsByFile;
43489
- };
43490
- /**
43491
- * Collects each file's cross-file dependency probes (via the plugin's
43492
- * collectors) with their current answers. Fail-open per file: an unreadable /
43493
- * unparseable / collector-failing file maps to `null` (no entry stored — it
43494
- * re-lints next scan). The filesystem is frozen for the scan, so this can run
43495
- * CONCURRENTLY with an oxlint child-process await — the caller starts it
43496
- * unawaited before a lint pass and awaits it at store time, hiding the
43497
- * in-process parse + resolution cost under the subprocess wait. The loop
43498
- * yields on the cooperative time budget so the child's stdout handling (and
43499
- * sibling fibers) keep flowing; each per-file collection is synchronous, so
43500
- * the module-level probe recorder never sees interleaved use. Never rejects.
43501
- */
43502
- const collectSidecarProbesForFiles = async (input) => {
43503
- const buildProbes = (file) => {
43504
- const absoluteFilePath = Path.resolve(input.rootDirectory, file);
43505
- let trace;
43506
- try {
43507
- trace = collectCrossFileDependencyProbes({
43508
- absoluteFilePath,
43509
- sourceText: NFS.readFileSync(absoluteFilePath, "utf8"),
43510
- ruleIds: input.boundedSidecarRuleIds
43511
- });
43512
- } catch {
43513
- return null;
43514
- }
43515
- if (trace === null) return null;
43516
- const probes = [];
43517
- for (const contentPath of trace.contentPaths) {
43518
- const relativePath = input.probeAnswers.toRelativePath(contentPath);
43519
- probes.push({
43520
- kind: "content",
43521
- path: relativePath,
43522
- answer: input.probeAnswers.answerFor("content", relativePath)
43523
- });
43524
- }
43525
- for (const existencePath of trace.existencePaths) {
43526
- const relativePath = input.probeAnswers.toRelativePath(existencePath);
43527
- probes.push({
43528
- kind: "exists",
43529
- path: relativePath,
43530
- answer: input.probeAnswers.answerFor("exists", relativePath)
43531
- });
43532
- }
43533
- return probes;
43534
- };
43535
- const probesByFile = /* @__PURE__ */ new Map();
43536
- let collectSliceStartedAt = performance.now();
43537
- for (const file of input.files) {
43538
- probesByFile.set(file, buildProbes(file));
43539
- if (performance.now() - collectSliceStartedAt >= 12) {
43540
- await yieldToEventLoop();
43541
- collectSliceStartedAt = performance.now();
43542
- }
43543
- }
43544
- return probesByFile;
43545
- };
43546
- /**
43547
- * Stores each freshly-linted file's probe set + cross-file diagnostics so
43548
- * the next scan can replay instead of re-linting.
43549
- */
43550
- const storeSidecarEntries = (input) => {
43551
- let didStoreAnyEntry = false;
43552
- for (const pass of input.storablePasses) {
43553
- if (!pass.isTrusted) continue;
43554
- const diagnosticsByFile = attributeDiagnosticsToFiles(pass.diagnostics, pass.files);
43555
- if (diagnosticsByFile === null) continue;
43556
- for (const file of pass.files) {
43557
- const cacheKey = input.cacheKeyByFile.get(file);
43558
- if (cacheKey === void 0) continue;
43559
- const probes = pass.probesByFile.get(file);
43560
- if (probes === void 0 || probes === null) continue;
43561
- input.sidecarCache.store(cacheKey, {
43562
- probes,
43563
- diagnostics: diagnosticsByFile.get(file) ?? []
43564
- });
43565
- didStoreAnyEntry = true;
43566
- }
43567
- }
43568
- if (didStoreAnyEntry) input.sidecarCache.persist();
43569
- };
43570
43186
  const REACT_HOOKS_JS_DROP_PREFIX = "React Compiler rules (react-hooks-js/*) skipped — eslint-plugin-react-hooks failed to load in this environment";
43571
43187
  /**
43572
43188
  * Detects an oxlint config-load crash caused by the optional
@@ -43608,7 +43224,7 @@ const reactHooksJsPluginDropNote = (error) => {
43608
43224
  * 6. always restore disable directives + clean up the temp dir
43609
43225
  */
43610
43226
  const runOxlint = async (options) => {
43611
- const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false, sidecarLintCacheEnabled = false, onCacheStats, onSidecarStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
43227
+ const { rootDirectory, project, includePaths, nodeBinaryPath = process.execPath, customRulesOnly = false, respectInlineDisables = true, adoptExistingLintConfig = true, ignoredTags = /* @__PURE__ */ new Set(), userConfig, configSourceDirectory = rootDirectory, onPartialFailure, perFileLintCacheEnabled = false, onCacheStats, spawnTimeoutMs, outputMaxBytes, lintBatchOrdering = "cost" } = options;
43612
43228
  const serverAuthFunctionNames = Array.isArray(userConfig?.serverAuthFunctionNames) ? userConfig.serverAuthFunctionNames.filter((entry) => typeof entry === "string" && entry.length > 0) : void 0;
43613
43229
  const severityControls = buildRuleSeverityControls(userConfig);
43614
43230
  validateRuleRegistration();
@@ -43626,8 +43242,7 @@ const runOxlint = async (options) => {
43626
43242
  severityControls,
43627
43243
  userPlugins,
43628
43244
  disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin,
43629
- ruleSelection: overrides.ruleSelection,
43630
- sidecarRuleIdFilter: overrides.sidecarRuleIdFilter
43245
+ ruleSelection: overrides.ruleSelection
43631
43246
  });
43632
43247
  const restoreDisableDirectives = respectInlineDisables ? () => {} : await neutralizeDisableDirectives(rootDirectory, includePaths);
43633
43248
  const configDirectory = NFS.mkdtempSync(Path.join(os.tmpdir(), "react-doctor-oxlintrc-"));
@@ -43730,18 +43345,15 @@ const runOxlint = async (options) => {
43730
43345
  });
43731
43346
  const cache = createFileLintCache(resolveReactDoctorCacheDir(rootDirectory), rulesetHash);
43732
43347
  const cacheKeyByFile = /* @__PURE__ */ new Map();
43733
- const contentHashByRelativePath = /* @__PURE__ */ new Map();
43734
43348
  const missFiles = [];
43735
43349
  const replayedDiagnostics = [];
43736
43350
  let hashSliceStartedAt = performance.now();
43737
43351
  for (const candidateFile of candidateFiles) {
43738
- const absoluteCandidatePath = Path.resolve(rootDirectory, candidateFile);
43739
- const contentHash = hashFileContents(absoluteCandidatePath);
43352
+ const contentHash = hashFileContents(Path.resolve(rootDirectory, candidateFile));
43740
43353
  if (contentHash === null) {
43741
43354
  missFiles.push(candidateFile);
43742
43355
  continue;
43743
43356
  }
43744
- contentHashByRelativePath.set(Path.relative(rootDirectory, absoluteCandidatePath).replaceAll("\\", "/"), contentHash);
43745
43357
  const cacheKey = `${candidateFile.replaceAll("\\", "/")}\u0000${contentHash}`;
43746
43358
  cacheKeyByFile.set(candidateFile, cacheKey);
43747
43359
  const cachedDiagnostics = cache.lookup(cacheKey);
@@ -43753,111 +43365,43 @@ const runOxlint = async (options) => {
43753
43365
  }
43754
43366
  }
43755
43367
  const cacheHitFileCount = candidateFiles.length - missFiles.length;
43756
- const enabledSidecarRuleIds = Object.keys(buildConfig({
43757
- extendsPaths: [],
43758
- ruleSelection: "sidecar"
43759
- }).rules).map((ruleKey) => ruleKey.slice(ruleKey.lastIndexOf("/") + 1)).filter((ruleId) => CROSS_FILE_RULE_IDS.has(ruleId));
43760
- const boundedSidecarRuleIds = enabledSidecarRuleIds.filter((ruleId) => CROSS_FILE_DEPENDENCY_COLLECTORS.has(ruleId));
43761
- const boundedSidecarRuleIdSet = new Set(boundedSidecarRuleIds);
43762
- const unboundedSidecarRuleIds = enabledSidecarRuleIds.filter((ruleId) => !CROSS_FILE_DEPENDENCY_COLLECTORS.has(ruleId));
43763
- const useSidecarCache = sidecarLintCacheEnabled && boundedSidecarRuleIds.length > 0;
43764
- const sidecarCache = useSidecarCache ? createSidecarLintCache(resolveReactDoctorCacheDir(rootDirectory), computeRulesetHash({
43765
- config: buildConfig({
43766
- extendsPaths: [],
43767
- ruleSelection: "sidecar",
43768
- sidecarRuleIdFilter: boundedSidecarRuleIdSet
43769
- }),
43770
- toolchainVersions: resolveOxlintToolchainVersions(nodeBinaryPath),
43771
- ignorePatterns: combinedPatterns,
43772
- tsconfigContent
43773
- })) : null;
43774
- const probeAnswers = createSidecarProbeAnswerResolver({
43775
- rootDirectory,
43776
- contentHashByRelativePath
43777
- });
43778
- const missProbesTask = sidecarCache === null ? null : collectSidecarProbesForFiles({
43779
- files: missFiles,
43780
- rootDirectory,
43781
- boundedSidecarRuleIds,
43782
- probeAnswers
43783
- });
43784
43368
  const fullResult = await runConfigOverFiles((overrides) => buildConfig({
43785
43369
  extendsPaths: [],
43786
43370
  disableReactHooksJsPlugin: overrides.disableReactHooksJsPlugin
43787
43371
  }), "oxlintrc.full.json", missFiles, options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(scannedFileCount, candidateFiles.length)));
43788
43372
  const missFileSet = new Set(missFiles);
43789
- const hitFiles = candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile));
43790
- const sidecarReplayedDiagnostics = [];
43791
- const sidecarLintFiles = [];
43792
- if (sidecarCache === null) sidecarLintFiles.push(...hitFiles);
43793
- else {
43794
- let verifySliceStartedAt = performance.now();
43795
- for (const hitFile of hitFiles) {
43796
- const cacheKey = cacheKeyByFile.get(hitFile);
43797
- const entry = cacheKey === void 0 ? null : sidecarCache.lookup(cacheKey);
43798
- if (entry !== null && entry.probes.every((probe) => probeAnswers.answerFor(probe.kind, probe.path) === probe.answer)) sidecarReplayedDiagnostics.push(...entry.diagnostics);
43799
- else sidecarLintFiles.push(hitFile);
43800
- if (performance.now() - verifySliceStartedAt >= 12) {
43801
- await yieldToEventLoop();
43802
- verifySliceStartedAt = performance.now();
43803
- }
43804
- }
43805
- }
43806
- const sidecarProbesTask = sidecarCache === null ? null : collectSidecarProbesForFiles({
43807
- files: sidecarLintFiles,
43808
- rootDirectory,
43809
- boundedSidecarRuleIds,
43810
- probeAnswers
43811
- });
43812
- const sidecarReplayedFileCount = hitFiles.length - sidecarLintFiles.length;
43813
- if (sidecarReplayedFileCount > 0) options.onFileProgress?.(missFiles.length + sidecarReplayedFileCount, candidateFiles.length);
43814
- const boundedSidecarResult = await runConfigOverFiles(() => buildConfig({
43373
+ const sidecarResult = await runConfigOverFiles(() => buildConfig({
43815
43374
  extendsPaths: [],
43816
- ruleSelection: "sidecar",
43817
- ...useSidecarCache ? { sidecarRuleIdFilter: boundedSidecarRuleIdSet } : {}
43818
- }), "oxlintrc.sidecar.json", sidecarLintFiles, options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(missFiles.length + sidecarReplayedFileCount + scannedFileCount, candidateFiles.length)));
43819
- const unboundedSidecarResult = useSidecarCache && unboundedSidecarRuleIds.length > 0 ? await runConfigOverFiles(() => buildConfig({
43820
- extendsPaths: [],
43821
- ruleSelection: "sidecar",
43822
- sidecarRuleIdFilter: new Set(unboundedSidecarRuleIds)
43823
- }), "oxlintrc.sidecar-unbounded.json", hitFiles, void 0) : {
43824
- diagnostics: [],
43825
- didDropReactHooksJsPlugin: false,
43826
- hadPartialFailure: false
43827
- };
43375
+ ruleSelection: "sidecar"
43376
+ }), "oxlintrc.sidecar.json", candidateFiles.filter((candidateFile) => !missFileSet.has(candidateFile)), options.onFileProgress && ((scannedFileCount) => options.onFileProgress?.(missFiles.length + scannedFileCount, candidateFiles.length)));
43828
43377
  const freshCacheableDiagnostics = [];
43829
43378
  for (const diagnostic of fullResult.diagnostics) if (!CROSS_FILE_RULE_IDS.has(diagnostic.rule)) freshCacheableDiagnostics.push(diagnostic);
43830
43379
  onCacheStats?.(cacheHitFileCount, candidateFiles.length);
43831
- if (sidecarCache !== null) onSidecarStats?.(hitFiles.length - sidecarLintFiles.length, hitFiles.length);
43832
- const freshDiagnosticsByFile = attributeDiagnosticsToFiles(freshCacheableDiagnostics, missFiles);
43833
- if (!fullResult.didDropReactHooksJsPlugin && !fullResult.hadPartialFailure && freshDiagnosticsByFile !== null) {
43380
+ const missFileByNormalizedPath = /* @__PURE__ */ new Map();
43381
+ for (const missFile of missFiles) missFileByNormalizedPath.set(missFile.replaceAll("\\", "/"), missFile);
43382
+ const freshDiagnosticsByFile = /* @__PURE__ */ new Map();
43383
+ let isAttributionSound = true;
43384
+ for (const diagnostic of freshCacheableDiagnostics) {
43385
+ const missFile = missFileByNormalizedPath.get(diagnostic.filePath);
43386
+ if (missFile === void 0) {
43387
+ isAttributionSound = false;
43388
+ break;
43389
+ }
43390
+ const fileDiagnostics = freshDiagnosticsByFile.get(missFile) ?? [];
43391
+ fileDiagnostics.push(diagnostic);
43392
+ freshDiagnosticsByFile.set(missFile, fileDiagnostics);
43393
+ }
43394
+ if (!fullResult.didDropReactHooksJsPlugin && !fullResult.hadPartialFailure && isAttributionSound) {
43834
43395
  for (const missFile of missFiles) {
43835
43396
  const cacheKey = cacheKeyByFile.get(missFile);
43836
43397
  if (cacheKey !== void 0) cache.store(cacheKey, freshDiagnosticsByFile.get(missFile) ?? []);
43837
43398
  }
43838
43399
  cache.persist();
43839
43400
  }
43840
- if (sidecarCache !== null && missProbesTask !== null && sidecarProbesTask !== null) storeSidecarEntries({
43841
- sidecarCache,
43842
- cacheKeyByFile,
43843
- storablePasses: [{
43844
- files: sidecarLintFiles,
43845
- diagnostics: boundedSidecarResult.diagnostics,
43846
- isTrusted: !boundedSidecarResult.hadPartialFailure,
43847
- probesByFile: await sidecarProbesTask
43848
- }, {
43849
- files: missFiles,
43850
- diagnostics: fullResult.diagnostics.filter((diagnostic) => boundedSidecarRuleIdSet.has(diagnostic.rule)),
43851
- isTrusted: !fullResult.didDropReactHooksJsPlugin && !fullResult.hadPartialFailure,
43852
- probesByFile: await missProbesTask
43853
- }]
43854
- });
43855
43401
  return dedupeDiagnostics([
43856
43402
  ...replayedDiagnostics,
43857
43403
  ...fullResult.diagnostics,
43858
- ...sidecarReplayedDiagnostics,
43859
- ...boundedSidecarResult.diagnostics,
43860
- ...unboundedSidecarResult.diagnostics
43404
+ ...sidecarResult.diagnostics
43861
43405
  ]);
43862
43406
  }
43863
43407
  const baseArgs = makeBaseArgs(configPath);
@@ -43955,7 +43499,6 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
43955
43499
  const concurrency = yield* OxlintConcurrency;
43956
43500
  const lintBatchOrdering = yield* LintBatchOrdering;
43957
43501
  const perFileLintCacheEnabled = yield* PerFileLintCacheEnabled;
43958
- const sidecarLintCacheEnabled = yield* SidecarLintCacheEnabled;
43959
43502
  const collectedFailures = [];
43960
43503
  const diagnostics = yield* tryPromise({
43961
43504
  try: (signal) => runOxlint({
@@ -43974,9 +43517,7 @@ var Linter = class Linter extends Service()("react-doctor/Linter") {
43974
43517
  },
43975
43518
  onFileProgress: input.onFileProgress,
43976
43519
  perFileLintCacheEnabled,
43977
- sidecarLintCacheEnabled,
43978
43520
  onCacheStats: input.onCacheStats,
43979
- onSidecarStats: input.onSidecarStats,
43980
43521
  spawnTimeoutMs,
43981
43522
  outputMaxBytes,
43982
43523
  concurrency,
@@ -44751,14 +44292,7 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44751
44292
  const buildCollectDeadCode = (deadCodeTimeout) => runCollect(applyPerElementPipeline(deadCodeService.run({
44752
44293
  rootDirectory: scanDirectory,
44753
44294
  parseConcurrency: deadCodeParseConcurrency,
44754
- workerTimeoutMs: deadCodeTimeout.workerTimeoutMs,
44755
- onCacheOutcome: (didHitCache) => {
44756
- deadCodeCacheHit = didHitCache;
44757
- },
44758
- onSummaryCacheStats: (stats) => {
44759
- deadCodeSummaryCacheHits = stats.hits;
44760
- deadCodeSummaryCacheMisses = stats.misses;
44761
- }
44295
+ workerTimeoutMs: deadCodeTimeout.workerTimeoutMs
44762
44296
  }).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
44763
44297
  yield* set(deadCodeFailure, {
44764
44298
  didFail: true,
@@ -44786,11 +44320,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44786
44320
  let lastReportedTotalFileCount = 0;
44787
44321
  let lintCacheHitFileCount = null;
44788
44322
  let lintCacheTotalFileCount = null;
44789
- let lintSidecarReplayedFileCount = null;
44790
- let lintSidecarTotalFileCount = null;
44791
- let deadCodeCacheHit = null;
44792
- let deadCodeSummaryCacheHits = null;
44793
- let deadCodeSummaryCacheMisses = null;
44794
44323
  const baseLintStream = linterService.run({
44795
44324
  rootDirectory: scanDirectory,
44796
44325
  project,
@@ -44810,10 +44339,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44810
44339
  lintCacheHitFileCount = cacheHitFileCount;
44811
44340
  lintCacheTotalFileCount = totalConsideredFileCount;
44812
44341
  },
44813
- onSidecarStats: (sidecarReplayedFileCount, sidecarConsideredFileCount) => {
44814
- lintSidecarReplayedFileCount = sidecarReplayedFileCount;
44815
- lintSidecarTotalFileCount = sidecarConsideredFileCount;
44816
- },
44817
44342
  deadlineEpochMs: input.deadlineEpochMs
44818
44343
  }).pipe(catchTag("ReactDoctorError", (error) => unwrap(gen(function* () {
44819
44344
  yield* set(lintFailure, {
@@ -44924,11 +44449,6 @@ const runInspect = (input, hooks = {}) => gen(function* () {
44924
44449
  securityScanFailed,
44925
44450
  lintCacheHitFileCount,
44926
44451
  lintCacheTotalFileCount,
44927
- lintSidecarReplayedFileCount,
44928
- lintSidecarTotalFileCount,
44929
- deadCodeCacheHit: lintFailureState.didFail ? null : deadCodeCacheHit,
44930
- deadCodeSummaryCacheHits: lintFailureState.didFail ? null : deadCodeSummaryCacheHits,
44931
- deadCodeSummaryCacheMisses: lintFailureState.didFail ? null : deadCodeSummaryCacheMisses,
44932
44452
  suppressedRuleCounts: transform.summarizeSuppressions()
44933
44453
  };
44934
44454
  }).pipe(withSpan("runInspect", { attributes: {
@@ -45710,7 +45230,6 @@ const isNonInteractiveEnvironment = () => NON_INTERACTIVE_ENVIRONMENT_VARIABLES.
45710
45230
  const REACT_DOCTOR_CONFIG_PROJECT_NAME = "react-doctor";
45711
45231
  const STAGED_FILES_TEMP_DIR_PREFIX = "react-doctor-staged-";
45712
45232
  const BASELINE_FILES_TEMP_DIR_PREFIX = "react-doctor-baseline-";
45713
- const RUN_GIT_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
45714
45233
  const GH_DEFAULT_BRANCH_PROBE_TIMEOUT_MS = 5e3;
45715
45234
  const CI_TRUST_COMPANIES = "PayPal, Rippling, and Alibaba";
45716
45235
  const WELCOME_EXPLANATION_HOLD_MS = 1e3;
@@ -45801,7 +45320,7 @@ const makeNoopConsole = () => ({
45801
45320
  });
45802
45321
  //#endregion
45803
45322
  //#region src/cli/utils/version.ts
45804
- const VERSION = "0.6.3-dev.ea9a775";
45323
+ const VERSION = "0.6.3";
45805
45324
  //#endregion
45806
45325
  //#region src/cli/utils/json-mode.ts
45807
45326
  let context = null;
@@ -46170,13 +45689,13 @@ const isDevVersion = (version) => version === "0.0.0" || version.includes("-");
46170
45689
  * uploads source-map artifacts under, so stack frames symbolicate. Honors the
46171
45690
  * standard `SENTRY_RELEASE` override.
46172
45691
  */
46173
- const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.6.3-dev.ea9a775`;
45692
+ const resolveSentryRelease = () => process.env.SENTRY_RELEASE || `react-doctor@0.6.3`;
46174
45693
  /**
46175
45694
  * Deployment environment shown in Sentry's environment filter. Defaults to
46176
45695
  * `production` for tagged releases and `development` for dev/unbuilt versions,
46177
45696
  * overridable via the standard `SENTRY_ENVIRONMENT` env var.
46178
45697
  */
46179
- const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.6.3-dev.ea9a775") ? "development" : "production");
45698
+ const resolveSentryEnvironment = () => process.env.SENTRY_ENVIRONMENT || (isDevVersion("0.6.3") ? "development" : "production");
46180
45699
  /**
46181
45700
  * Performance-tracing sample rate in `[0, 1]`. Reads `SENTRY_TRACES_SAMPLE_RATE`
46182
45701
  * (set to `0` to disable tracing) and falls back to
@@ -46377,8 +45896,7 @@ const runGit = (projectRoot, args) => {
46377
45896
  "ignore",
46378
45897
  "pipe",
46379
45898
  "ignore"
46380
- ],
46381
- maxBuffer: RUN_GIT_MAX_BUFFER_BYTES
45899
+ ]
46382
45900
  }).trim();
46383
45901
  } catch {
46384
45902
  return null;
@@ -58400,17 +57918,11 @@ const buildOutcomeAttributes = (input) => {
58400
57918
  deadlineSkippedFileCount: input.lintDeadlineSkippedFileCount ?? null,
58401
57919
  cacheHitFiles: result.lintCacheHitFileCount ?? null,
58402
57920
  cacheTotalFiles: result.lintCacheTotalFileCount ?? null,
58403
- cacheHitRatio: result.lintCacheTotalFileCount != null && result.lintCacheTotalFileCount > 0 ? (result.lintCacheHitFileCount ?? 0) / result.lintCacheTotalFileCount : null,
58404
- sidecarReplayedFiles: result.lintSidecarReplayedFileCount ?? null,
58405
- sidecarTotalFiles: result.lintSidecarTotalFileCount ?? null,
58406
- sidecarReplayRatio: result.lintSidecarTotalFileCount != null && result.lintSidecarTotalFileCount > 0 ? (result.lintSidecarReplayedFileCount ?? 0) / result.lintSidecarTotalFileCount : null
57921
+ cacheHitRatio: result.lintCacheTotalFileCount != null && result.lintCacheTotalFileCount > 0 ? (result.lintCacheHitFileCount ?? 0) / result.lintCacheTotalFileCount : null
58407
57922
  }),
58408
57923
  ...withNamespace("deadCode", {
58409
57924
  failed: input.didDeadCodeFail ?? null,
58410
- overlapped: input.deadCodeOverlapped ?? null,
58411
- cacheHit: result.deadCodeCacheHit ?? null,
58412
- summaryCacheHits: result.deadCodeSummaryCacheHits ?? null,
58413
- summaryCacheMisses: result.deadCodeSummaryCacheMisses ?? null
57925
+ overlapped: input.deadCodeOverlapped ?? null
58414
57926
  }),
58415
57927
  ...withNamespace("supplyChain", { overlapTimedOut: input.supplyChainOverlapTimedOut ?? null }),
58416
57928
  ...withNamespace("securityScan", { failed: input.securityScanFailed ?? null }),
@@ -59733,89 +59245,13 @@ const stringifyStableJson = (value) => {
59733
59245
  };
59734
59246
  const hashString = (value) => crypto.createHash("sha1").update(value).digest("hex");
59735
59247
  const readHeadSha = (projectDirectory) => runGit(projectDirectory, ["rev-parse", "HEAD"]);
59736
- const parseWorktreeStatusRecords = (statusOutput) => {
59737
- const entries = [];
59738
- const tokens = statusOutput.split("\0");
59739
- for (let tokenIndex = 0; tokenIndex < tokens.length; tokenIndex += 1) {
59740
- let record = tokens[tokenIndex];
59741
- if (record.length === 0) continue;
59742
- if (record.length < 3 || record[2] !== " ") {
59743
- if (tokenIndex !== 0) return null;
59744
- record = ` ${record}`;
59745
- }
59746
- if (record.length < 4 || record[2] !== " ") return null;
59747
- const statusCode = record.slice(0, 2);
59748
- const recordPath = record.slice(3);
59749
- if (statusCode.includes("R") || statusCode.includes("C")) {
59750
- tokenIndex += 1;
59751
- const originPath = tokens[tokenIndex];
59752
- if (originPath === void 0 || originPath.length === 0) return null;
59753
- entries.push({
59754
- statusCode,
59755
- path: recordPath,
59756
- originPath
59757
- });
59758
- continue;
59759
- }
59760
- entries.push({
59761
- statusCode,
59762
- path: recordPath
59763
- });
59764
- }
59765
- return entries;
59766
- };
59767
- const buildDirtyPathContentFingerprint = (absolutePath, statusCode) => {
59768
- let stats;
59769
- try {
59770
- stats = fs.lstatSync(absolutePath);
59771
- } catch {
59772
- return statusCode.includes("D") ? "deleted" : null;
59773
- }
59774
- if (stats.isSymbolicLink()) try {
59775
- return `link:${fs.readlinkSync(absolutePath)}`;
59776
- } catch {
59777
- return null;
59778
- }
59779
- if (!stats.isFile()) return null;
59780
- if (stats.size > 10485760) return `stat:${stats.mtimeMs}:${stats.size}`;
59781
- return hashFileContents(absolutePath);
59782
- };
59783
- const buildWorktreeFingerprint = (projectDirectory) => {
59784
- const statusOutput = runGit(projectDirectory, [
59248
+ const isWorktreeClean = (projectDirectory) => {
59249
+ const status = runGit(projectDirectory, [
59785
59250
  "status",
59786
59251
  "--porcelain=v1",
59787
- "-z",
59788
- "--untracked-files=all"
59252
+ "--untracked-files=normal"
59789
59253
  ]);
59790
- if (statusOutput === null) return null;
59791
- if (statusOutput.length === 0) return [];
59792
- const statusEntries = parseWorktreeStatusRecords(statusOutput);
59793
- if (statusEntries === null) return null;
59794
- if (statusEntries.length > 300) return null;
59795
- const repositoryRoot = runGit(projectDirectory, ["rev-parse", "--show-toplevel"]);
59796
- if (repositoryRoot === null) return null;
59797
- const dirtyEntries = [];
59798
- for (const statusEntry of statusEntries) {
59799
- const contentFingerprint = buildDirtyPathContentFingerprint(path.join(repositoryRoot, statusEntry.path), statusEntry.statusCode);
59800
- if (contentFingerprint === null) return null;
59801
- dirtyEntries.push({
59802
- ...statusEntry,
59803
- contentFingerprint
59804
- });
59805
- }
59806
- return dirtyEntries.sort((firstEntry, secondEntry) => {
59807
- const firstSortKey = `${firstEntry.path}${firstEntry.statusCode}`;
59808
- const secondSortKey = `${secondEntry.path}${secondEntry.statusCode}`;
59809
- return firstSortKey < secondSortKey ? -1 : firstSortKey > secondSortKey ? 1 : 0;
59810
- });
59811
- };
59812
- const DOTENV_FILE_NAME_PATTERN = /^\.env(\.|$)/;
59813
- const resolveDotenvFingerprint = (projectDirectory) => {
59814
- try {
59815
- return fs.readdirSync(projectDirectory).filter((entryName) => DOTENV_FILE_NAME_PATTERN.test(entryName)).sort().map((entryName) => `${entryName}=${fileFingerprint(path.join(projectDirectory, entryName)) ?? "unreadable"}`);
59816
- } catch {
59817
- return [];
59818
- }
59254
+ return status !== null && status.length === 0;
59819
59255
  };
59820
59256
  const hasHiddenTrackedFileState = (projectDirectory) => {
59821
59257
  const output = runGit(projectDirectory, ["ls-files", "-v"]);
@@ -59898,9 +59334,8 @@ const resolveToolchainFingerprint = (nodeBinaryPath) => {
59898
59334
  };
59899
59335
  const buildScanResultCacheKey = (input) => {
59900
59336
  if (isScanResultCacheDisabled()) return null;
59337
+ if (!isWorktreeClean(input.projectDirectory)) return null;
59901
59338
  if (hasHiddenTrackedFileState(input.projectDirectory)) return null;
59902
- const worktreeFingerprint = buildWorktreeFingerprint(input.projectDirectory);
59903
- if (worktreeFingerprint === null) return null;
59904
59339
  const headSha = readHeadSha(input.projectDirectory);
59905
59340
  if (headSha === null) return null;
59906
59341
  if (stringifyStableJson(input.userConfig) === null) return null;
@@ -59908,8 +59343,6 @@ const buildScanResultCacheKey = (input) => {
59908
59343
  schemaVersion: 3,
59909
59344
  projectIdentity: resolveProjectIdentity(input.projectDirectory),
59910
59345
  headSha,
59911
- worktreeFingerprint,
59912
- dotenvFingerprint: resolveDotenvFingerprint(input.projectDirectory),
59913
59346
  reactDoctorVersion: input.version,
59914
59347
  nodeVersion: process.version,
59915
59348
  toolchainFingerprint: resolveToolchainFingerprint(input.nodeBinaryPath),
@@ -60302,12 +59735,7 @@ const runInspectWithRuntime = async (directory, options, userConfig, hasConfigOv
60302
59735
  scanMode: baselineDelta ? "baseline" : isDiffMode ? "diff" : "full",
60303
59736
  baselineDegraded,
60304
59737
  lintCacheHitFileCount: output.lintCacheHitFileCount,
60305
- lintCacheTotalFileCount: output.lintCacheTotalFileCount,
60306
- lintSidecarReplayedFileCount: output.lintSidecarReplayedFileCount,
60307
- lintSidecarTotalFileCount: output.lintSidecarTotalFileCount,
60308
- deadCodeCacheHit: output.deadCodeCacheHit,
60309
- deadCodeSummaryCacheHits: output.deadCodeSummaryCacheHits,
60310
- deadCodeSummaryCacheMisses: output.deadCodeSummaryCacheMisses
59738
+ lintCacheTotalFileCount: output.lintCacheTotalFileCount
60311
59739
  });
60312
59740
  recordOnboardingCompletion(options);
60313
59741
  return result;
@@ -60342,11 +59770,6 @@ const renderAndRecordScan = async (input) => {
60342
59770
  scanElapsedMilliseconds: input.payload.scanElapsedMilliseconds,
60343
59771
  lintCacheHitFileCount: input.lintCacheHitFileCount ?? null,
60344
59772
  lintCacheTotalFileCount: input.lintCacheTotalFileCount ?? null,
60345
- lintSidecarReplayedFileCount: input.lintSidecarReplayedFileCount ?? null,
60346
- lintSidecarTotalFileCount: input.lintSidecarTotalFileCount ?? null,
60347
- deadCodeCacheHit: input.deadCodeCacheHit ?? null,
60348
- deadCodeSummaryCacheHits: input.deadCodeSummaryCacheHits ?? null,
60349
- deadCodeSummaryCacheMisses: input.deadCodeSummaryCacheMisses ?? null,
60350
59773
  baselineDelta: input.payload.baselineDelta
60351
59774
  }), input.options.silent));
60352
59775
  const { workerCount: resolvedWorkerCount, parallel } = resolveWorkerTelemetry(input.payload.scanConcurrency, input.options.concurrency);
@@ -60385,7 +59808,7 @@ const renderAndRecordScan = async (input) => {
60385
59808
  return result;
60386
59809
  };
60387
59810
  const finalizeAndRender = (input) => gen(function* () {
60388
- const { options, elapsedMilliseconds, diagnostics, score, project, userConfig, didLintFail, lintFailureReason, lintPartialFailures, didDeadCodeFail, deadCodeFailureReason, directory, scannedFileCount, scannedFilePaths, scanElapsedMilliseconds, lintCacheHitFileCount, lintCacheTotalFileCount, lintSidecarReplayedFileCount, lintSidecarTotalFileCount, deadCodeCacheHit, deadCodeSummaryCacheHits, deadCodeSummaryCacheMisses, baselineDelta } = input;
59811
+ const { options, elapsedMilliseconds, diagnostics, score, project, userConfig, didLintFail, lintFailureReason, lintPartialFailures, didDeadCodeFail, deadCodeFailureReason, directory, scannedFileCount, scannedFilePaths, scanElapsedMilliseconds, lintCacheHitFileCount, lintCacheTotalFileCount, baselineDelta } = input;
60389
59812
  const { skippedChecks, skippedCheckReasons } = buildSkippedChecks({
60390
59813
  didLintFail,
60391
59814
  lintFailureReason,
@@ -60409,15 +59832,6 @@ const finalizeAndRender = (input) => gen(function* () {
60409
59832
  lintCacheHitFileCount,
60410
59833
  lintCacheTotalFileCount
60411
59834
  } : {},
60412
- ...lintSidecarTotalFileCount !== null ? {
60413
- lintSidecarReplayedFileCount,
60414
- lintSidecarTotalFileCount
60415
- } : {},
60416
- ...deadCodeCacheHit !== null ? { deadCodeCacheHit } : {},
60417
- ...deadCodeSummaryCacheHits !== null && deadCodeSummaryCacheMisses !== null ? {
60418
- deadCodeSummaryCacheHits,
60419
- deadCodeSummaryCacheMisses
60420
- } : {},
60421
59835
  ...baselineDelta ? { baselineDelta } : {}
60422
59836
  });
60423
59837
  if (options.suppressRendering) return buildResult();
@@ -64264,4 +63678,4 @@ Promise.resolve().then(() => assertNoRemovedFlags(process.argv)).then(() => prog
64264
63678
  export {};
64265
63679
 
64266
63680
  //# sourceMappingURL=cli.js.map
64267
- //# debugId=d9c72b21-3e94-5923-b692-077f137a0078
63681
+ //# debugId=328318eb-6af2-5007-b816-51c953a96047