@lzehrung/codegraph 2.3.12 → 2.3.13

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/bin/cli.js CHANGED
@@ -13552,6 +13552,7 @@ __export(git_exports, {
13552
13552
  isGitPathTracked: () => isGitPathTracked,
13553
13553
  isGitProjectRootIgnored: () => isGitProjectRootIgnored,
13554
13554
  isGitRepo: () => isGitRepo,
13555
+ isGitTimeoutError: () => isGitTimeoutError,
13555
13556
  isGitWorktreeSentinel: () => isGitWorktreeSentinel,
13556
13557
  listChangedFiles: () => listChangedFiles,
13557
13558
  listGitExcludeFiles: () => listGitExcludeFiles,
@@ -13605,8 +13606,9 @@ function decodeGitPath(rawPath) {
13605
13606
  }
13606
13607
  return Buffer.from(bytes).toString("utf8");
13607
13608
  }
13608
- function setGitExecutableForTests(executable) {
13609
+ function setGitExecutableForTests(executable, prefixArgs = []) {
13609
13610
  gitExecutableForTests = executable;
13611
+ gitExecutablePrefixArgsForTests = executable ? [...prefixArgs] : [];
13610
13612
  }
13611
13613
  function clearGitRepositoryCheckCacheForTests() {
13612
13614
  gitRepositoryChecks.clear();
@@ -13673,12 +13675,13 @@ async function runGit(projectRoot, args, options) {
13673
13675
  const timeoutMs = resolveGitTimeoutMs(options?.timeoutMs);
13674
13676
  const maxBuffer = options?.maxBuffer ?? 64 * 1024 * 1024;
13675
13677
  const executable = gitExecutableForTests ?? "git";
13678
+ const childArgs = gitExecutablePrefixArgsForTests.length ? [...gitExecutablePrefixArgsForTests, ...args] : args;
13676
13679
  const signal = options?.signal;
13677
13680
  if (signal?.aborted) {
13678
13681
  throw createGitError(projectRoot, args, new Error("aborted before start"));
13679
13682
  }
13680
13683
  return await new Promise((resolve, reject) => {
13681
- const child = spawn(executable, args, {
13684
+ const child = spawn(executable, childArgs, {
13682
13685
  cwd: projectRoot,
13683
13686
  env: process.env,
13684
13687
  stdio: [options?.input !== void 0 ? "pipe" : "ignore", "pipe", "pipe"],
@@ -14159,6 +14162,10 @@ async function getUnifiedDiff(projectRoot, opts) {
14159
14162
  throw createGitError(projectRoot, args, error51);
14160
14163
  }
14161
14164
  }
14165
+ function isGitTimeoutError(error51) {
14166
+ const detail = error51 instanceof Error ? error51.message : stringifyUnknown(error51);
14167
+ return /timed out after \d+ms/i.test(detail);
14168
+ }
14162
14169
  function createGitError(projectRoot, args, error51) {
14163
14170
  let detail = stringifyUnknown(error51);
14164
14171
  if (typeof error51 === "object" && error51 !== null && "stderr" in error51 && typeof error51.stderr === "string" && error51.stderr.trim()) {
@@ -14168,7 +14175,7 @@ function createGitError(projectRoot, args, error51) {
14168
14175
  }
14169
14176
  return new Error(`git ${args.join(" ")} failed in ${projectRoot}: ${detail}`);
14170
14177
  }
14171
- var DEFAULT_GIT_TIMEOUT_MS, gitRepositoryChecks, gitDiscoveryRootIgnoredChecks, gitExcludeFileChecks, MAX_GIT_HASH_OBJECT_ARGUMENT_BYTES, gitExecutableForTests, GIT_QUOTED_PATH_SINGLE_BYTE_ESCAPES, UNSAFE_REVISION_CHARACTERS;
14178
+ var DEFAULT_GIT_TIMEOUT_MS, gitRepositoryChecks, gitDiscoveryRootIgnoredChecks, gitExcludeFileChecks, MAX_GIT_HASH_OBJECT_ARGUMENT_BYTES, gitExecutableForTests, gitExecutablePrefixArgsForTests, GIT_QUOTED_PATH_SINGLE_BYTE_ESCAPES, UNSAFE_REVISION_CHARACTERS;
14172
14179
  var init_git = __esm({
14173
14180
  "dist/util/git.js"() {
14174
14181
  "use strict";
@@ -14181,6 +14188,7 @@ var init_git = __esm({
14181
14188
  gitExcludeFileChecks = /* @__PURE__ */ new Map();
14182
14189
  MAX_GIT_HASH_OBJECT_ARGUMENT_BYTES = 24 * 1024;
14183
14190
  gitExecutableForTests = null;
14191
+ gitExecutablePrefixArgsForTests = [];
14184
14192
  GIT_QUOTED_PATH_SINGLE_BYTE_ESCAPES = {
14185
14193
  a: 7,
14186
14194
  b: 8,
@@ -14213,6 +14221,13 @@ __export(projectFiles_exports, {
14213
14221
  import fs6 from "node:fs";
14214
14222
  import fsp5 from "node:fs/promises";
14215
14223
  import path9 from "node:path";
14224
+ import { performance as performance2 } from "node:perf_hooks";
14225
+ function emitDiscoveryActivity(report, activity, current = 0, total = 0) {
14226
+ report?.({ activity, current, total });
14227
+ }
14228
+ function emitDiscoveryTiming(record2, name, startedAt) {
14229
+ record2?.({ name, ms: Math.round(performance2.now() - startedAt) });
14230
+ }
14216
14231
  function createPathCheckProgressReporter(total, onProgress) {
14217
14232
  onProgress?.(0, total);
14218
14233
  let completed = 0;
@@ -14508,6 +14523,8 @@ async function findGitIgnoreSources(sourceRoots, excludePathspecs = defaultIgnor
14508
14523
  return sources;
14509
14524
  }
14510
14525
  async function listGitCandidateFiles(root, logLevel, opts) {
14526
+ let gitListStart;
14527
+ let gitIgnoreStart;
14511
14528
  try {
14512
14529
  const realRoot = normalizePath(await fsp5.realpath(root));
14513
14530
  const gitRoot = await isGitRepo(root) ? root : realRoot;
@@ -14518,6 +14535,9 @@ async function listGitCandidateFiles(root, logLevel, opts) {
14518
14535
  const gitRepositoryRoot = await getGitRepositoryRoot(gitRoot);
14519
14536
  if (!gitRepositoryRoot)
14520
14537
  return null;
14538
+ emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git files");
14539
+ const listStartedAt = performance2.now();
14540
+ gitListStart = listStartedAt;
14521
14541
  const [tracked, untracked, stageSpecial] = await Promise.all([
14522
14542
  listTrackedFiles(gitRoot, { recurseSubmodules: true, ...logLevel === void 0 ? {} : { logLevel } }),
14523
14543
  listUntrackedFiles(gitRoot, { respectGitignore: true }),
@@ -14544,15 +14564,35 @@ async function listGitCandidateFiles(root, logLevel, opts) {
14544
14564
  { path: physicalPath, repositoryRoot: physicalPath }
14545
14565
  ])
14546
14566
  ];
14567
+ emitDiscoveryTiming(opts?.onDiscoveryTiming, "git-list", listStartedAt);
14568
+ gitListStart = void 0;
14569
+ emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git files", files.length, files.length);
14570
+ emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git ignore files");
14571
+ const ignoreStartedAt = performance2.now();
14572
+ gitIgnoreStart = ignoreStartedAt;
14573
+ const gitignoreFiles = await findGitIgnoreSources(sourceRoots, defaultIgnoreGitExcludePathspecs(opts?.includeGlobs ?? []));
14574
+ emitDiscoveryTiming(opts?.onDiscoveryTiming, "git-ignore", ignoreStartedAt);
14575
+ gitIgnoreStart = void 0;
14576
+ emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git ignore files", gitignoreFiles.length, gitignoreFiles.length);
14547
14577
  return {
14548
14578
  files,
14549
14579
  symlinkCandidatePaths,
14550
- gitignoreFiles: await findGitIgnoreSources(sourceRoots, defaultIgnoreGitExcludePathspecs(opts?.includeGlobs ?? [])),
14580
+ gitignoreFiles,
14551
14581
  gitignoreRoots,
14552
14582
  gitignoreAliases: sourceRoots
14553
14583
  };
14554
14584
  } catch (error51) {
14555
- logWithLevel(logLevel, "debug", `Git discovery unavailable for ${root}: ${stringifyUnknown(error51)}`);
14585
+ const listingTimedOut = isGitTimeoutError(error51) && (gitIgnoreStart !== void 0 || gitListStart !== void 0);
14586
+ if (gitIgnoreStart !== void 0) {
14587
+ emitDiscoveryTiming(opts?.onDiscoveryTiming, "git-ignore", gitIgnoreStart);
14588
+ } else if (gitListStart !== void 0) {
14589
+ emitDiscoveryTiming(opts?.onDiscoveryTiming, "git-list", gitListStart);
14590
+ }
14591
+ if (listingTimedOut) {
14592
+ logWithLevel(logLevel, "warn", "Warning: Git listing timed out; scanning the filesystem instead. Ignore large untracked trees in .gitignore to keep discovery fast.");
14593
+ } else {
14594
+ logWithLevel(logLevel, "debug", `Git discovery unavailable for ${root}: ${stringifyUnknown(error51)}`);
14595
+ }
14556
14596
  return null;
14557
14597
  }
14558
14598
  }
@@ -14581,7 +14621,11 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14581
14621
  const useGitignore = options?.useGitignore ?? true;
14582
14622
  const realRoot = await fsp5.realpath(root);
14583
14623
  const attemptedGitCandidates = useGitignore && options?.gitignoreRoot === void 0 && normalizePath(realRoot) === normalizePath(root);
14584
- const gitCandidates = attemptedGitCandidates ? await listGitCandidateFiles(root, options?.logLevel, { includeGlobs }) : null;
14624
+ const gitDiscoveryCallbacks = {
14625
+ ...options?.onDiscoveryProgress ? { onDiscoveryProgress: options.onDiscoveryProgress } : {},
14626
+ ...options?.onDiscoveryTiming ? { onDiscoveryTiming: options.onDiscoveryTiming } : {}
14627
+ };
14628
+ const gitCandidates = attemptedGitCandidates ? await listGitCandidateFiles(root, options?.logLevel, { includeGlobs, ...gitDiscoveryCallbacks }) : null;
14585
14629
  if (attemptedGitCandidates) {
14586
14630
  options?.onGitCandidatesDiscovered?.(gitCandidates);
14587
14631
  }
@@ -14592,13 +14636,22 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14592
14636
  const gitignoreRoot = options?.gitignoreRoot ? await ensureDirectoryReadable(options.gitignoreRoot, "Gitignore root") : root;
14593
14637
  gitignoreIndex = await loadGitignoreIndexForRootAliases(gitignoreRoot);
14594
14638
  }
14595
- const files = gitCandidates ? gitCandidates.files : await (0, import_fast_glob2.default)(patterns, {
14596
- cwd: root,
14597
- absolute: true,
14598
- dot: true,
14599
- followSymbolicLinks: false,
14600
- ignore: fastGlobIgnoreGlobs
14601
- });
14639
+ let files;
14640
+ if (gitCandidates) {
14641
+ files = gitCandidates.files;
14642
+ } else {
14643
+ emitDiscoveryActivity(options?.onDiscoveryProgress, "Scanning project files");
14644
+ const scanStart = performance2.now();
14645
+ files = await (0, import_fast_glob2.default)(patterns, {
14646
+ cwd: root,
14647
+ absolute: true,
14648
+ dot: true,
14649
+ followSymbolicLinks: false,
14650
+ ignore: fastGlobIgnoreGlobs
14651
+ });
14652
+ emitDiscoveryTiming(options?.onDiscoveryTiming, "filesystem-scan", scanStart);
14653
+ emitDiscoveryActivity(options?.onDiscoveryProgress, "Scanning project files", files.length, files.length);
14654
+ }
14602
14655
  const includedOverrideFiles = includeGlobs.length && !gitCandidates ? await (0, import_fast_glob2.default)(translateGlobRootIgnoreGlobsForScanRoot(root, globRoot, includeGlobs), {
14603
14656
  cwd: root,
14604
14657
  absolute: true,
@@ -14842,7 +14895,10 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14842
14895
  if (options?.knownGitCandidates !== void 0) {
14843
14896
  gitCandidates = options.knownGitCandidates;
14844
14897
  } else {
14845
- gitCandidates = await listGitCandidateFiles(root, options?.logLevel);
14898
+ gitCandidates = await listGitCandidateFiles(root, options?.logLevel, {
14899
+ ...options?.onDiscoveryProgress ? { onDiscoveryProgress: options.onDiscoveryProgress } : {},
14900
+ ...options?.onDiscoveryTiming ? { onDiscoveryTiming: options.onDiscoveryTiming } : {}
14901
+ });
14846
14902
  }
14847
14903
  options?.onGitCandidatesDiscovered?.(gitCandidates);
14848
14904
  const reportMetadataSymlinkChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking project metadata symlinks", current, total }) : void 0;
@@ -53582,19 +53638,19 @@ var init_parsed_cache = __esm({
53582
53638
  });
53583
53639
 
53584
53640
  // dist/indexer/finalize.js
53585
- import { performance as performance2 } from "node:perf_hooks";
53641
+ import { performance as performance3 } from "node:perf_hooks";
53586
53642
  async function finalizeProjectIndex(args) {
53587
53643
  const discoveryTimings = args.opts?.report ? args.opts.report.timings ??= {} : void 0;
53588
- const metadataDiscoveryStart = args.projectFiles === void 0 ? performance2.now() : void 0;
53644
+ const metadataDiscoveryStart = args.projectFiles === void 0 ? performance3.now() : void 0;
53589
53645
  const projectFiles = await (args.projectFiles ?? discoverProjectFilesWithGitCandidates(args.projectRoot, {
53590
53646
  ...args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {},
53591
53647
  ...args.knownGitCandidates !== void 0 ? { knownGitCandidates: args.knownGitCandidates } : {}
53592
53648
  }));
53593
53649
  if (metadataDiscoveryStart !== void 0 && discoveryTimings) {
53594
- discoveryTimings.metadataDiscoveryMs = Math.round(performance2.now() - metadataDiscoveryStart);
53650
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance3.now() - metadataDiscoveryStart);
53595
53651
  }
53596
53652
  if (args.timings)
53597
- args.timings.totalMs = Math.round(performance2.now() - args.totalStart);
53653
+ args.timings.totalMs = Math.round(performance3.now() - args.totalStart);
53598
53654
  const languageExtensions = normalizeLanguageExtensions(args.opts?.languageExtensions);
53599
53655
  const parsed = retainedParsedCache(args.parsedMap, args.opts);
53600
53656
  return {
@@ -53632,7 +53688,7 @@ var init_finalize = __esm({
53632
53688
  // dist/indexer/build-manifest.js
53633
53689
  import fsp24 from "node:fs/promises";
53634
53690
  import path45 from "node:path";
53635
- import { performance as performance3 } from "node:perf_hooks";
53691
+ import { performance as performance4 } from "node:perf_hooks";
53636
53692
  function toManifestFileEntry(entry) {
53637
53693
  if (!entry.sig)
53638
53694
  return void 0;
@@ -53647,7 +53703,7 @@ async function writeIndexManifestSnapshot(args) {
53647
53703
  const files = args.files instanceof Map ? Object.fromEntries(args.files) : args.files;
53648
53704
  if (!Object.keys(files).length && !args.allowEmpty)
53649
53705
  return;
53650
- const writeManifestStart = performance3.now();
53706
+ const writeManifestStart = performance4.now();
53651
53707
  const lastCommit = await getGitHead(args.projectRoot);
53652
53708
  const configHashResult = await computeConfigHash(args.projectRoot, args.opts?.logLevel);
53653
53709
  const projectRootMtimeMs = args.symlinkDirectories !== void 0 ? (await fsp24.stat(args.projectRoot)).mtimeMs : void 0;
@@ -53672,7 +53728,7 @@ async function writeIndexManifestSnapshot(args) {
53672
53728
  if (manifestWritten)
53673
53729
  pruneDiskModuleCache(args.projectRoot, Object.keys(files), args.opts);
53674
53730
  if (args.timings) {
53675
- args.timings.writeManifestMs = Math.round(performance3.now() - writeManifestStart);
53731
+ args.timings.writeManifestMs = Math.round(performance4.now() - writeManifestStart);
53676
53732
  }
53677
53733
  }
53678
53734
  var init_build_manifest = __esm({
@@ -55107,7 +55163,7 @@ var init_nativeWorkerPool = __esm({
55107
55163
  });
55108
55164
 
55109
55165
  // dist/indexer/build-workers.js
55110
- import { performance as performance4 } from "node:perf_hooks";
55166
+ import { performance as performance5 } from "node:perf_hooks";
55111
55167
  function shouldEnableNativeWorkers(opts, fileCount) {
55112
55168
  if (opts?.native === "off")
55113
55169
  return false;
@@ -55201,14 +55257,14 @@ async function setupWorkerPool(opts, fileCount) {
55201
55257
  return {
55202
55258
  pool,
55203
55259
  report,
55204
- startTime: pool ? performance4.now() : 0,
55260
+ startTime: pool ? performance5.now() : 0,
55205
55261
  batchSize: NATIVE_WORKER_BATCH_SIZE
55206
55262
  };
55207
55263
  }
55208
55264
  async function teardownWorkerPool(setup, buildReport2) {
55209
55265
  if (setup.pool) {
55210
55266
  if (setup.report) {
55211
- setup.report.wallClockMs = Math.round(performance4.now() - setup.startTime);
55267
+ setup.report.wallClockMs = Math.round(performance5.now() - setup.startTime);
55212
55268
  }
55213
55269
  try {
55214
55270
  await setup.pool.destroy();
@@ -55476,7 +55532,7 @@ import crypto10 from "node:crypto";
55476
55532
  import fs23 from "node:fs";
55477
55533
  import fsp26 from "node:fs/promises";
55478
55534
  import path47 from "node:path";
55479
- import { performance as performance5 } from "node:perf_hooks";
55535
+ import { performance as performance6 } from "node:perf_hooks";
55480
55536
  function initParserBackendDegradationReport(report) {
55481
55537
  if (!report)
55482
55538
  return void 0;
@@ -55775,7 +55831,7 @@ function createIndexBuildRunState(projectRoot, opts, graphOptions = normalizeGra
55775
55831
  normalizedProjectRoot: normalizePath(path47.resolve(projectRoot)),
55776
55832
  report,
55777
55833
  timings: report?.timings,
55778
- totalStart: performance5.now(),
55834
+ totalStart: performance6.now(),
55779
55835
  cacheMode,
55780
55836
  cacheEnabled: cacheMode !== "off",
55781
55837
  graphOptions,
@@ -55820,6 +55876,31 @@ function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
55820
55876
  total
55821
55877
  });
55822
55878
  }
55879
+ function resetDiscoveryTimingSteps(timings) {
55880
+ if (!timings)
55881
+ return;
55882
+ delete timings.gitListMs;
55883
+ delete timings.filesystemScanMs;
55884
+ delete timings.sourceDiscoveryMs;
55885
+ delete timings.metadataDiscoveryMs;
55886
+ const remaining = (timings.steps ?? []).filter((step) => !DISCOVERY_TIMING_STEP_NAMES.has(step.name));
55887
+ if (remaining.length) {
55888
+ timings.steps = remaining;
55889
+ return;
55890
+ }
55891
+ delete timings.steps;
55892
+ }
55893
+ function recordBuildTimingStep(timings, step) {
55894
+ if (!timings)
55895
+ return;
55896
+ (timings.steps ??= []).push(step);
55897
+ if (step.name === "git-list") {
55898
+ timings.gitListMs = step.ms;
55899
+ return;
55900
+ }
55901
+ if (step.name === "filesystem-scan")
55902
+ timings.filesystemScanMs = step.ms;
55903
+ }
55823
55904
  function buildConcurrency(opts) {
55824
55905
  return resolveWorkerThreadCount({ requested: Number(opts?.threads || 0), defaultCount: 8, max: 64 });
55825
55906
  }
@@ -55861,7 +55942,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55861
55942
  const fileReport = initFileReport(report);
55862
55943
  if (fileReport)
55863
55944
  fileReport.total = normalizedFiles.length;
55864
- const manifestStart = performance5.now();
55945
+ const manifestStart = performance6.now();
55865
55946
  const manifest = useManifest && !helperOpts?.ignoreExistingManifest ? await loadManifest(projectRoot, opts, report) : null;
55866
55947
  const manifestFiles = sanitizeManifestEntriesForRoot(projectRoot, manifest?.files);
55867
55948
  const manifestOptionDiffs = manifest ? diffBuildOptions(manifest.buildOptions, opts) : [];
@@ -55876,7 +55957,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55876
55957
  }
55877
55958
  }
55878
55959
  if (timings && useManifest) {
55879
- timings.manifestMs = Math.round(performance5.now() - manifestStart);
55960
+ timings.manifestMs = Math.round(performance6.now() - manifestStart);
55880
55961
  }
55881
55962
  const edgeProbeConcurrency = buildConcurrency(opts);
55882
55963
  const staleCachedEdgeFiles = /* @__PURE__ */ new Set();
@@ -55990,7 +56071,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55990
56071
  }
55991
56072
  return matchPath;
55992
56073
  };
55993
- const parseStart = performance5.now();
56074
+ const parseStart = performance6.now();
55994
56075
  const graph = { nodes: new Set(normalizedFiles), edges: [] };
55995
56076
  const onFileEdges = manifestEntries ? (file2, entry) => {
55996
56077
  const manifestEntry = toManifestFileEntry(entry);
@@ -56004,7 +56085,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56004
56085
  const ensureBuildProgressStarted = () => {
56005
56086
  if (buildStartedAt !== void 0)
56006
56087
  return;
56007
- buildStartedAt = performance5.now();
56088
+ buildStartedAt = performance6.now();
56008
56089
  emitIndexLifecycleProgress(opts, "start", "build", totalFiles);
56009
56090
  };
56010
56091
  const fileResults = await mapLimit(normalizedFiles, conc, async (file2) => {
@@ -56136,8 +56217,8 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56136
56217
  }
56137
56218
  });
56138
56219
  if (timings)
56139
- timings.parseMs = Math.round(performance5.now() - parseStart);
56140
- const graphStart = performance5.now();
56220
+ timings.parseMs = Math.round(performance6.now() - parseStart);
56221
+ const graphStart = performance6.now();
56141
56222
  const seenGraphEdges = /* @__PURE__ */ new Set();
56142
56223
  const appendUniqueGraphEdges = (edges) => {
56143
56224
  if (!edges.length)
@@ -56165,7 +56246,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56165
56246
  const workspaceManifestEdges = await collectWorkspaceManifestDependencyEdges(projectRoot, normalizedFiles.filter((file2) => path47.basename(file2) === "package.json"), opts?.discovery, opts?.logLevel);
56166
56247
  appendUniqueGraphEdges(workspaceManifestEdges);
56167
56248
  if (timings)
56168
- timings.graphMs = Math.round(performance5.now() - graphStart);
56249
+ timings.graphMs = Math.round(performance6.now() - graphStart);
56169
56250
  for (const jsonPath of jsonDependencies.values()) {
56170
56251
  ensureJsonModule(modules, jsonPath);
56171
56252
  }
@@ -56217,7 +56298,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56217
56298
  }
56218
56299
  if (buildStartedAt !== void 0) {
56219
56300
  const progressStartedAt = opts?.progressStartedAt ?? buildStartedAt;
56220
- emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance5.now() - progressStartedAt);
56301
+ emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance6.now() - progressStartedAt);
56221
56302
  }
56222
56303
  return index;
56223
56304
  } finally {
@@ -56226,6 +56307,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56226
56307
  }
56227
56308
  async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpts) {
56228
56309
  const timings = opts?.report ? opts.report.timings ??= {} : void 0;
56310
+ resetDiscoveryTimingSteps(timings);
56229
56311
  await initializeFileIdentityCaseSensitivity(projectRoot);
56230
56312
  try {
56231
56313
  const useDiskCache = (opts?.cache ?? "off") === "disk";
@@ -56246,19 +56328,21 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56246
56328
  discoveredGitCandidates = candidates;
56247
56329
  };
56248
56330
  const onDiscoveryProgress = helperOpts?.reportDiscoveryProgress ? (progress) => emitIndexCheckActivity(opts, progress.activity, progress.current, progress.total) : void 0;
56331
+ const onDiscoveryTiming = timings ? (step) => recordBuildTimingStep(timings, step) : void 0;
56249
56332
  if (helperOpts?.reportDiscoveryProgress)
56250
56333
  emitIndexCheckActivity(opts, "Discovering source files");
56251
- const sourceDiscoveryStart = performance5.now();
56334
+ const sourceDiscoveryStart = performance6.now();
56252
56335
  const discoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
56253
56336
  ...opts?.discovery,
56254
56337
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56255
56338
  ...knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories } : {},
56256
56339
  onSymlinkDirectoriesDiscovered,
56257
56340
  onGitCandidatesDiscovered,
56258
- ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
56341
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {},
56342
+ ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56259
56343
  });
56260
56344
  if (timings)
56261
- timings.sourceDiscoveryMs = Math.round(performance5.now() - sourceDiscoveryStart);
56345
+ timings.sourceDiscoveryMs = Math.round(performance6.now() - sourceDiscoveryStart);
56262
56346
  const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
56263
56347
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
56264
56348
  const additionalFiles = additionalFileCandidates.filter((file2) => additionalFileExistence.get(file2));
@@ -56267,15 +56351,16 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56267
56351
  const transientFiles = additionalFiles.filter((file2) => !discoveredFileSet.has(file2));
56268
56352
  if (helperOpts?.reportDiscoveryProgress)
56269
56353
  emitIndexCheckActivity(opts, "Discovering project metadata");
56270
- const metadataDiscoveryStart = performance5.now();
56354
+ const metadataDiscoveryStart = performance6.now();
56271
56355
  const projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56272
56356
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56273
56357
  ...discoveredSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: discoveredSymlinkDirectories } : {},
56274
56358
  ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {},
56275
- ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
56359
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {},
56360
+ ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56276
56361
  });
56277
56362
  if (timings)
56278
- timings.metadataDiscoveryMs = Math.round(performance5.now() - metadataDiscoveryStart);
56363
+ timings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56279
56364
  return await buildIndexFromFileListShared(projectRoot, files, opts, {
56280
56365
  manifestMode: useDiskCache ? "read-write" : "off",
56281
56366
  warnNoFilesMessage: `Warning: No files found in project root: ${projectRoot}. Check codegraph.config.json globs and CLI --include-glob/--ignore-glob filters. Diagnostic: codegraph doctor`,
@@ -56294,11 +56379,11 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56294
56379
  async function buildProjectIndex(projectRoot, opts) {
56295
56380
  return buildProjectIndexWithManifestOptions(projectRoot, {
56296
56381
  ...opts,
56297
- progressStartedAt: opts?.progressStartedAt ?? performance5.now()
56382
+ progressStartedAt: opts?.progressStartedAt ?? performance6.now()
56298
56383
  });
56299
56384
  }
56300
56385
  async function buildProjectIndexFromFiles(projectRoot, inputFiles, rawOpts) {
56301
- const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance5.now() };
56386
+ const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now() };
56302
56387
  try {
56303
56388
  const useDiskCache = (opts?.cache ?? "off") === "disk";
56304
56389
  const normalizedInputFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, inputFiles, "Index file");
@@ -56330,7 +56415,7 @@ async function buildDeclaredScopeIndex(projectRoot, scopeFiles, opts) {
56330
56415
  async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56331
56416
  const opts = {
56332
56417
  ...rawOpts,
56333
- progressStartedAt: rawOpts?.progressStartedAt ?? performance5.now()
56418
+ progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now()
56334
56419
  };
56335
56420
  await initializeFileIdentityCaseSensitivity(projectRoot);
56336
56421
  clearResolutionCaches();
@@ -56340,6 +56425,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56340
56425
  graphOptions.fast = false;
56341
56426
  const { normalizedProjectRoot, report, timings, totalStart, cacheMode, cacheEnabled, onFallbackImportExtraction } = createIndexBuildRunState(projectRoot, opts, graphOptions);
56342
56427
  const discoveryTimings = opts?.report ? opts.report.timings ??= {} : void 0;
56428
+ resetDiscoveryTimingSteps(discoveryTimings);
56343
56429
  let checkProgressActive = false;
56344
56430
  const startCheckProgress = () => {
56345
56431
  if (checkProgressActive)
@@ -56365,7 +56451,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56365
56451
  message: "Checked project index",
56366
56452
  current: total,
56367
56453
  total,
56368
- elapsedMs: performance5.now() - totalStart
56454
+ elapsedMs: performance6.now() - totalStart
56369
56455
  });
56370
56456
  };
56371
56457
  try {
@@ -56380,10 +56466,10 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56380
56466
  return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
56381
56467
  }
56382
56468
  startCheckProgress();
56383
- const manifestStart = performance5.now();
56469
+ const manifestStart = performance6.now();
56384
56470
  const manifest = await loadManifest(projectRoot, opts, report);
56385
56471
  if (timings)
56386
- timings.manifestMs = Math.round(performance5.now() - manifestStart);
56472
+ timings.manifestMs = Math.round(performance6.now() - manifestStart);
56387
56473
  const manifestUsed = !!manifest;
56388
56474
  const manifestReport = initManifestReport(report, manifestUsed, false);
56389
56475
  if (manifestReport && !manifestUsed)
@@ -56438,11 +56524,11 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56438
56524
  if (!discoveryTimings || opts?.filesAreProjectScope)
56439
56525
  return await operation();
56440
56526
  sourceDiscoveryPerformed = true;
56441
- const start = performance5.now();
56527
+ const start = performance6.now();
56442
56528
  try {
56443
56529
  return await operation();
56444
56530
  } finally {
56445
- sourceDiscoveryMs += performance5.now() - start;
56531
+ sourceDiscoveryMs += performance6.now() - start;
56446
56532
  }
56447
56533
  };
56448
56534
  let manifestDiffFiles = [];
@@ -56534,7 +56620,10 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56534
56620
  ...!opts?.cacheStrict && manifest.symlinkDirectories !== void 0 ? { knownSymlinkDirectories: manifest.symlinkDirectories } : {},
56535
56621
  onGitCandidatesDiscovered: (candidates) => {
56536
56622
  discoveredGitCandidates = candidates;
56537
- }
56623
+ },
56624
+ ...discoveryTimings ? {
56625
+ onDiscoveryTiming: (step) => recordBuildTimingStep(discoveryTimings, step)
56626
+ } : {}
56538
56627
  }));
56539
56628
  }
56540
56629
  if (discoveryTimings && sourceDiscoveryPerformed) {
@@ -56639,13 +56728,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56639
56728
  const snapshot = snapshotLoad.index;
56640
56729
  snapshot.manifestSignaturesFresh = false;
56641
56730
  if (snapshot.projectFiles === void 0) {
56642
- const metadataDiscoveryStart = performance5.now();
56731
+ const metadataDiscoveryStart = performance6.now();
56643
56732
  snapshot.projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56644
56733
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56645
56734
  ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {}
56646
56735
  });
56647
56736
  if (discoveryTimings)
56648
- discoveryTimings.metadataDiscoveryMs = Math.round(performance5.now() - metadataDiscoveryStart);
56737
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56649
56738
  }
56650
56739
  if (opts?.cache) {
56651
56740
  snapshot.cacheMode = opts.cache;
@@ -56683,7 +56772,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56683
56772
  const snapshot = await reuseUnchangedSnapshot();
56684
56773
  if (snapshot) {
56685
56774
  if (timings)
56686
- timings.totalMs = Math.round(performance5.now() - totalStart);
56775
+ timings.totalMs = Math.round(performance6.now() - totalStart);
56687
56776
  completeCheckProgress(allFiles.size);
56688
56777
  return snapshot;
56689
56778
  }
@@ -56753,7 +56842,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56753
56842
  unchangedSnapshot.manifestEntries = new Map(Array.from(fileSignatures, ([file2, signature]) => [file2, toProjectIndexManifestEntry(signature)]));
56754
56843
  unchangedSnapshot.manifestSignaturesFresh = true;
56755
56844
  if (timings)
56756
- timings.totalMs = Math.round(performance5.now() - totalStart);
56845
+ timings.totalMs = Math.round(performance6.now() - totalStart);
56757
56846
  completeCheckProgress(allFiles.size);
56758
56847
  return unchangedSnapshot;
56759
56848
  }
@@ -56795,13 +56884,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56795
56884
  workerSetup = await setupWorkerPool(opts, countNativeWorkerEligibleFiles(changedList, opts?.languageExtensions));
56796
56885
  let updateStartedAt;
56797
56886
  if (changedList.length || deletedTrackedFiles.size) {
56798
- updateStartedAt = performance5.now();
56887
+ updateStartedAt = performance6.now();
56799
56888
  emitIndexLifecycleProgress(opts, "start", "update", changedList.length);
56800
56889
  }
56801
56890
  if (fileReport)
56802
56891
  fileReport.changed = changedList.length;
56803
56892
  if (changedList.length) {
56804
- const parseStart = performance5.now();
56893
+ const parseStart = performance6.now();
56805
56894
  let processedFiles = 0;
56806
56895
  const totalFiles = changedList.length;
56807
56896
  const fileResults = await mapLimit(changedList, conc, async (file2) => {
@@ -56864,7 +56953,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56864
56953
  writeModulesToCache(projectRoot, pendingIncrementalCacheWrites, opts);
56865
56954
  }
56866
56955
  if (timings)
56867
- timings.parseMs = Math.round(performance5.now() - parseStart);
56956
+ timings.parseMs = Math.round(performance6.now() - parseStart);
56868
56957
  }
56869
56958
  for (const jsonPath of jsonDependencies.values()) {
56870
56959
  ensureJsonModule(modules, jsonPath);
@@ -56894,7 +56983,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56894
56983
  }
56895
56984
  }
56896
56985
  const filesList = Array.from(changedFiles);
56897
- const graphStart = performance5.now();
56986
+ const graphStart = performance6.now();
56898
56987
  const graph = !filesList.length && baseGraph ? { nodes: new Set(baseGraph.nodes), edges: [...baseGraph.edges] } : await collectGraph(projectRoot, filesList, {
56899
56988
  parsed: parsedMap,
56900
56989
  fast: !!graphOptions.fast,
@@ -56920,7 +57009,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56920
57009
  }
56921
57010
  });
56922
57011
  if (timings)
56923
- timings.graphMs = Math.round(performance5.now() - graphStart);
57012
+ timings.graphMs = Math.round(performance6.now() - graphStart);
56924
57013
  for (const file2 of /* @__PURE__ */ new Set([...changedFiles, ...transientFiles])) {
56925
57014
  const signature = fileSignatures.get(file2);
56926
57015
  if (!signature || manifestEntries.has(file2))
@@ -56980,7 +57069,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56980
57069
  });
56981
57070
  await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
56982
57071
  if (updateStartedAt !== void 0) {
56983
- emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance5.now() - updateStartedAt);
57072
+ emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance6.now() - updateStartedAt);
56984
57073
  } else {
56985
57074
  completeCheckProgress(allFiles.size);
56986
57075
  }
@@ -57126,6 +57215,7 @@ async function buildGraphDelta(projectRoot, opts) {
57126
57215
  removed: removedRelative.sort(compareEdges)
57127
57216
  };
57128
57217
  }
57218
+ var DISCOVERY_TIMING_STEP_NAMES;
57129
57219
  var init_build_index = __esm({
57130
57220
  "dist/indexer/build-index.js"() {
57131
57221
  "use strict";
@@ -57165,6 +57255,7 @@ var init_build_index = __esm({
57165
57255
  init_build_workers();
57166
57256
  init_incremental_plan();
57167
57257
  init_parsed_cache();
57258
+ DISCOVERY_TIMING_STEP_NAMES = /* @__PURE__ */ new Set(["git-list", "git-ignore", "filesystem-scan"]);
57168
57259
  }
57169
57260
  });
57170
57261
 
@@ -67798,7 +67889,7 @@ var init_deleted = __esm({
67798
67889
  });
67799
67890
 
67800
67891
  // dist/review/candidates.js
67801
- import { performance as performance6 } from "node:perf_hooks";
67892
+ import { performance as performance7 } from "node:perf_hooks";
67802
67893
  function relativePath(root, file2) {
67803
67894
  return toProjectDisplayPath(root, file2);
67804
67895
  }
@@ -67831,7 +67922,7 @@ function mergeCandidateTestEntries(baseCandidates, additionalCandidates) {
67831
67922
  return Array.from(merged.values());
67832
67923
  }
67833
67924
  async function collectReviewCandidateTests(input) {
67834
- const candidateStart = performance6.now();
67925
+ const candidateStart = performance7.now();
67835
67926
  const configuredMaxCandidates = input.appliedOptions.maxCandidates;
67836
67927
  const maxCandidates = typeof configuredMaxCandidates === "number" && Number.isFinite(configuredMaxCandidates) ? Math.max(0, Math.floor(configuredMaxCandidates)) : REVIEW_DEFAULT_CANDIDATE_TEST_LIMIT;
67837
67928
  const candidateTests = mergeCandidateTestEntries(listCandidateTestFiles(input.index, input.changedFileList, input.changedSymbolIds, {
@@ -67851,7 +67942,7 @@ async function collectReviewCandidateTests(input) {
67851
67942
  return left.reason.localeCompare(right.reason);
67852
67943
  }).slice(0, maxCandidates);
67853
67944
  if (input.reviewTimings) {
67854
- input.reviewTimings.candidatesMs = Math.round(performance6.now() - candidateStart);
67945
+ input.reviewTimings.candidatesMs = Math.round(performance7.now() - candidateStart);
67855
67946
  }
67856
67947
  return candidateTests;
67857
67948
  }
@@ -68147,7 +68238,7 @@ var init_parse4 = __esm({
68147
68238
  });
68148
68239
 
68149
68240
  // dist/review/changes.js
68150
- import { performance as performance7 } from "node:perf_hooks";
68241
+ import { performance as performance8 } from "node:perf_hooks";
68151
68242
  function deletedPathsForChange(change2) {
68152
68243
  if (change2.kind === "deleted") {
68153
68244
  return [change2.path];
@@ -68165,16 +68256,16 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68165
68256
  const isIncludedReviewFile = createImpactIncludeMatcher(discoveryGlobRoot, appliedOptions.discovery?.includeGlobs ?? []);
68166
68257
  const changedFiles = /* @__PURE__ */ new Set();
68167
68258
  const explicitFiles = /* @__PURE__ */ new Set();
68168
- const changesStart = performance7.now();
68259
+ const changesStart = performance8.now();
68169
68260
  for (const file2 of appliedOptions.files ?? []) {
68170
68261
  const normalized = normalizeFile(file2, "Review file");
68171
68262
  changedFiles.add(normalized);
68172
68263
  explicitFiles.add(normalized);
68173
68264
  }
68174
68265
  if (reviewTimings) {
68175
- reviewTimings.changesMs = Math.round(performance7.now() - changesStart);
68266
+ reviewTimings.changesMs = Math.round(performance8.now() - changesStart);
68176
68267
  }
68177
- const diffStart = performance7.now();
68268
+ const diffStart = performance8.now();
68178
68269
  const shouldLoadGitDiff = Boolean(appliedOptions.gitBase || appliedOptions.changedSince);
68179
68270
  const diffText = appliedOptions.diffText ?? (shouldLoadGitDiff ? await getUnifiedDiff(projectRoot, {
68180
68271
  base: appliedOptions.gitBase,
@@ -68183,7 +68274,7 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68183
68274
  }) : "");
68184
68275
  const diff = diffText ? parseUnifiedDiff(diffText) : null;
68185
68276
  if (reviewTimings) {
68186
- reviewTimings.diffMs = Math.round(performance7.now() - diffStart);
68277
+ reviewTimings.diffMs = Math.round(performance8.now() - diffStart);
68187
68278
  }
68188
68279
  const diffHunksByFile = /* @__PURE__ */ new Map();
68189
68280
  const diffKindsByFile = /* @__PURE__ */ new Map();
@@ -69557,10 +69648,10 @@ var init_severity = __esm({
69557
69648
  });
69558
69649
 
69559
69650
  // dist/impact/budgets.js
69560
- import { performance as performance8 } from "node:perf_hooks";
69651
+ import { performance as performance9 } from "node:perf_hooks";
69561
69652
  function createImpactWorkBudget(options) {
69562
69653
  return {
69563
- ...typeof options.timeBudgetMs === "number" && options.timeBudgetMs >= 0 ? { deadlineAt: performance8.now() + options.timeBudgetMs } : {},
69654
+ ...typeof options.timeBudgetMs === "number" && options.timeBudgetMs >= 0 ? { deadlineAt: performance9.now() + options.timeBudgetMs } : {},
69564
69655
  ...typeof options.maxReferenceLookups === "number" && options.maxReferenceLookups >= 0 ? { maxReferenceLookups: options.maxReferenceLookups } : {},
69565
69656
  ...typeof options.maxTotalReferences === "number" && options.maxTotalReferences >= 0 ? { maxTotalReferences: options.maxTotalReferences } : {},
69566
69657
  referenceLookupsStarted: 0,
@@ -69575,7 +69666,7 @@ function isImpactDeadlineExceeded(budget) {
69575
69666
  return true;
69576
69667
  if (budget.deadlineAt === void 0)
69577
69668
  return false;
69578
- if (performance8.now() >= budget.deadlineAt) {
69669
+ if (performance9.now() >= budget.deadlineAt) {
69579
69670
  budget.deadlineExceeded = true;
69580
69671
  return true;
69581
69672
  }
@@ -71629,7 +71720,7 @@ var init_referenceCache = __esm({
71629
71720
  // dist/review/summaries.js
71630
71721
  import fsp37 from "node:fs/promises";
71631
71722
  import path70 from "node:path";
71632
- import { performance as performance9 } from "node:perf_hooks";
71723
+ import { performance as performance10 } from "node:perf_hooks";
71633
71724
  function relativePath2(root, file2) {
71634
71725
  return toProjectDisplayPath(root, file2);
71635
71726
  }
@@ -71995,7 +72086,7 @@ async function summarizeChangedFiles2(input) {
71995
72086
  }
71996
72087
  }
71997
72088
  const defsToResolve = fileEntries.flatMap((entry) => entry.locals);
71998
- const referencesStart = performance9.now();
72089
+ const referencesStart = performance10.now();
71999
72090
  const referenceResults = includeSymbolDetails && maxCallsites > 0 ? await mapLimit(defsToResolve, referenceConcurrency, async (def) => {
72000
72091
  const refs = await referenceCache.get(index, def, {
72001
72092
  maxReferences: maxCallsites + 1
@@ -72003,7 +72094,7 @@ async function summarizeChangedFiles2(input) {
72003
72094
  return { def, refs };
72004
72095
  }) : [];
72005
72096
  if (reviewTimings) {
72006
- reviewTimings.referencesMs = Math.round(performance9.now() - referencesStart);
72097
+ reviewTimings.referencesMs = Math.round(performance10.now() - referencesStart);
72007
72098
  }
72008
72099
  const referencesByHandle = /* @__PURE__ */ new Map();
72009
72100
  for (const entry of referenceResults) {
@@ -72183,7 +72274,7 @@ var init_summaries = __esm({
72183
72274
  });
72184
72275
 
72185
72276
  // dist/review.js
72186
- import { performance as performance10 } from "node:perf_hooks";
72277
+ import { performance as performance11 } from "node:perf_hooks";
72187
72278
  function mergeGraphOptions2(base, override) {
72188
72279
  if (!base)
72189
72280
  return override;
@@ -72227,7 +72318,7 @@ async function buildReviewIndex(input) {
72227
72318
  diffChangesByFile,
72228
72319
  graphOptions
72229
72320
  });
72230
- const indexStart = performance10.now();
72321
+ const indexStart = performance11.now();
72231
72322
  const indexReport = reviewReport?.indexReport ?? (reviewReport ? { timings: {} } : void 0);
72232
72323
  if (reviewReport && !reviewReport.indexReport && indexReport) {
72233
72324
  reviewReport.indexReport = indexReport;
@@ -72260,7 +72351,7 @@ async function buildReviewIndex(input) {
72260
72351
  });
72261
72352
  }
72262
72353
  if (reviewTimings) {
72263
- reviewTimings.indexMs = Math.round(performance10.now() - indexStart);
72354
+ reviewTimings.indexMs = Math.round(performance11.now() - indexStart);
72264
72355
  }
72265
72356
  return {
72266
72357
  index,
@@ -72279,7 +72370,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72279
72370
  if (reviewReport && appliedOptions.duplicateTasks === false) {
72280
72371
  delete reviewReport.duplicateAnalysis;
72281
72372
  }
72282
- const totalStart = performance10.now();
72373
+ const totalStart = performance11.now();
72283
72374
  const { changedFiles, explicitFiles, diffHunksByFile, diffKindsByFile, diffChangesByFile } = await collectReviewChanges(projectRoot, appliedOptions, reviewTimings);
72284
72375
  if (changedFiles.size === 0) {
72285
72376
  const riskSummary = computeRiskSummary({
@@ -72313,7 +72404,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72313
72404
  report2.base = appliedOptions.gitBase;
72314
72405
  report2.head = appliedOptions.gitHead ?? "HEAD";
72315
72406
  if (reviewTimings)
72316
- reviewTimings.totalMs = Math.round(performance10.now() - totalStart);
72407
+ reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72317
72408
  return report2;
72318
72409
  }
72319
72410
  const changedFileList = Array.from(changedFiles).sort(comparePaths2);
@@ -72391,7 +72482,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72391
72482
  riskRelevantParseFailures,
72392
72483
  exportedChangedCount
72393
72484
  });
72394
- const duplicateAnalysisStart = performance10.now();
72485
+ const duplicateAnalysisStart = performance11.now();
72395
72486
  if (appliedOptions.duplicateTasks !== false) {
72396
72487
  const duplicateReview = await collectReviewDuplicateTasks({
72397
72488
  projectRoot,
@@ -72412,10 +72503,10 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72412
72503
  }
72413
72504
  }
72414
72505
  if (reviewTimings && appliedOptions.duplicateTasks !== false) {
72415
- reviewTimings.duplicateAnalysisMs = Math.round(performance10.now() - duplicateAnalysisStart);
72506
+ reviewTimings.duplicateAnalysisMs = Math.round(performance11.now() - duplicateAnalysisStart);
72416
72507
  }
72417
72508
  if (reviewTimings)
72418
- reviewTimings.totalMs = Math.round(performance10.now() - totalStart);
72509
+ reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72419
72510
  return report;
72420
72511
  }
72421
72512
  function buildSymbolDefLookup(index) {
@@ -78501,7 +78592,7 @@ var search_exports = {};
78501
78592
  __export(search_exports, {
78502
78593
  handleSearchCommand: () => handleSearchCommand
78503
78594
  });
78504
- import { performance as performance11 } from "node:perf_hooks";
78595
+ import { performance as performance12 } from "node:perf_hooks";
78505
78596
  function parseAgentSearchMode(rawValue) {
78506
78597
  if (rawValue === void 0)
78507
78598
  return "hybrid";
@@ -78511,7 +78602,7 @@ function parseAgentSearchMode(rawValue) {
78511
78602
  throw new Error(`Invalid --mode value "${rawValue}". Expected hybrid, symbol, path, text, graph, or sql.`);
78512
78603
  }
78513
78604
  async function handleSearchCommand(context) {
78514
- const commandStart = performance11.now();
78605
+ const commandStart = performance12.now();
78515
78606
  const query = context.positionals.join(" ").trim();
78516
78607
  if (!query) {
78517
78608
  context.writeStderrLine(SEARCH_HELP_TEXT.trimEnd());
@@ -78535,7 +78626,7 @@ async function handleSearchCommand(context) {
78535
78626
  context.writeStdoutLine(formatAgentSearchResponse(response));
78536
78627
  }
78537
78628
  if (context.commandReport && context.writeCommandReport) {
78538
- context.commandReport.timings.commandMs = Math.round(performance11.now() - commandStart);
78629
+ context.commandReport.timings.commandMs = Math.round(performance12.now() - commandStart);
78539
78630
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
78540
78631
  await context.writeCommandReport(context.commandReport, context.reportFile);
78541
78632
  }
@@ -107516,7 +107607,7 @@ __export(graph_exports, {
107516
107607
  import fs42 from "node:fs";
107517
107608
  import fsp40 from "node:fs/promises";
107518
107609
  import path88 from "node:path";
107519
- import { performance as performance12 } from "node:perf_hooks";
107610
+ import { performance as performance13 } from "node:perf_hooks";
107520
107611
  function resolveGraphCacheMode(cache) {
107521
107612
  return cache ?? "disk";
107522
107613
  }
@@ -107656,11 +107747,11 @@ function stabilizeSymbolGraph(graph) {
107656
107747
  }
107657
107748
  async function handleGraphCommand(context) {
107658
107749
  const commandReport = context.reportEnabled ? { command: "graph", timings: {} } : void 0;
107659
- const commandStart = performance12.now();
107660
- const resolveStart = performance12.now();
107750
+ const commandStart = performance13.now();
107751
+ const resolveStart = performance13.now();
107661
107752
  const files = await context.resolveFiles();
107662
107753
  if (commandReport) {
107663
- commandReport.timings.resolveFilesMs = Math.round(performance12.now() - resolveStart);
107754
+ commandReport.timings.resolveFilesMs = Math.round(performance13.now() - resolveStart);
107664
107755
  }
107665
107756
  const hasExplicitSymbolFlag = context.hasFlag("--symbols") || context.hasFlag("--symbols-only") || context.hasFlag("--symbols-detailed");
107666
107757
  const outputArg = context.getOpt("--output") ?? context.getOpt("--out");
@@ -107702,7 +107793,7 @@ async function handleGraphCommand(context) {
107702
107793
  const finalizeReport = async () => {
107703
107794
  if (!commandReport)
107704
107795
  return;
107705
- commandReport.timings.commandMs = Math.round(performance12.now() - commandStart);
107796
+ commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
107706
107797
  commandReport.timings.totalMs = commandReport.timings.commandMs;
107707
107798
  await context.writeCommandReport(commandReport, context.reportFile);
107708
107799
  };
@@ -107922,7 +108013,7 @@ var cli_exports = {};
107922
108013
  __export(cli_exports, {
107923
108014
  handleIndexCommand: () => handleIndexCommand
107924
108015
  });
107925
- import { performance as performance13 } from "node:perf_hooks";
108016
+ import { performance as performance14 } from "node:perf_hooks";
107926
108017
  function formatIndexOutput(output) {
107927
108018
  const lines = [`Indexed ${output.files} file(s) with ${output.edges} edge(s).`];
107928
108019
  if (output.analysis.mode !== "semantic") {
@@ -107940,11 +108031,11 @@ function formatIndexOutput(output) {
107940
108031
  async function handleIndexCommand(context) {
107941
108032
  const verbose = context.hasFlag("--verbose");
107942
108033
  const commandReport = context.reportEnabled ? { command: "index", timings: {} } : void 0;
107943
- const commandStart = performance13.now();
107944
- const resolveStart = performance13.now();
108034
+ const commandStart = performance14.now();
108035
+ const resolveStart = performance14.now();
107945
108036
  const files = await context.resolveFiles();
107946
108037
  if (commandReport) {
107947
- commandReport.timings.resolveFilesMs = Math.round(performance13.now() - resolveStart);
108038
+ commandReport.timings.resolveFilesMs = Math.round(performance14.now() - resolveStart);
107948
108039
  }
107949
108040
  const threads = parseNonNegativeIntegerOption(context.getOpt("--threads"), "--threads", 0);
107950
108041
  const cache = parseCacheModeOption(context.getOpt("--cache"));
@@ -108010,7 +108101,7 @@ async function handleIndexCommand(context) {
108010
108101
  }
108011
108102
  }
108012
108103
  if (commandReport) {
108013
- commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
108104
+ commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
108014
108105
  commandReport.timings.totalMs = commandReport.timings.commandMs;
108015
108106
  await context.writeCommandReport(commandReport, context.reportFile);
108016
108107
  }
@@ -111003,7 +111094,7 @@ var review_exports = {};
111003
111094
  __export(review_exports, {
111004
111095
  handleReviewCommand: () => handleReviewCommand
111005
111096
  });
111006
- import { performance as performance14 } from "node:perf_hooks";
111097
+ import { performance as performance15 } from "node:perf_hooks";
111007
111098
  import path92 from "node:path";
111008
111099
  function parseReviewDepth(value) {
111009
111100
  if (value === "minimal" || value === "standard" || value === "deep") {
@@ -111195,7 +111286,7 @@ async function collectReviewDuplicateSummary(input) {
111195
111286
  });
111196
111287
  }
111197
111288
  async function handleReviewCommand(context) {
111198
- const commandStart = performance14.now();
111289
+ const commandStart = performance15.now();
111199
111290
  const changedSince = context.getOpt("--changed-since");
111200
111291
  const base = context.getOpt("--base") ?? (changedSince === void 0 ? "HEAD" : void 0);
111201
111292
  const head = context.getOpt("--head") ?? (changedSince === void 0 ? "WORKTREE" : void 0);
@@ -111290,7 +111381,7 @@ async function handleReviewCommand(context) {
111290
111381
  context.writeJSONLine(report);
111291
111382
  }
111292
111383
  if (context.commandReport) {
111293
- context.commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
111384
+ context.commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
111294
111385
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
111295
111386
  await context.writeCommandReport(context.commandReport, context.reportFile);
111296
111387
  }
@@ -111579,7 +111670,7 @@ __export(inspect_exports, {
111579
111670
  handleHotspotsCommand: () => handleHotspotsCommand,
111580
111671
  handleInspectCommand: () => handleInspectCommand
111581
111672
  });
111582
- import { performance as performance15 } from "node:perf_hooks";
111673
+ import { performance as performance16 } from "node:perf_hooks";
111583
111674
  import fs44 from "node:fs";
111584
111675
  import path93 from "node:path";
111585
111676
  function defaultCacheIndexPath(projectRoot, cacheDir, cacheLocation) {
@@ -111841,18 +111932,18 @@ async function buildInspectReport(projectRoot, includeRoots, files, discovery, g
111841
111932
  };
111842
111933
  }
111843
111934
  async function handleInspectCommand(context) {
111844
- const commandStart = performance15.now();
111935
+ const commandStart = performance16.now();
111845
111936
  const cache = parseCacheModeOption(context.getOpt("--cache"));
111846
111937
  const limit = parsePositiveIntegerOption(context.getOpt("--limit"), "--limit", 20);
111847
- const resolveStart = performance15.now();
111938
+ const resolveStart = performance16.now();
111848
111939
  const files = await context.resolveFilesFromRoots();
111849
111940
  if (context.commandReport) {
111850
- context.commandReport.timings.resolveFilesMs = Math.round(performance15.now() - resolveStart);
111941
+ context.commandReport.timings.resolveFilesMs = Math.round(performance16.now() - resolveStart);
111851
111942
  }
111852
111943
  const report = await buildInspectReport(context.projectRootFs, context.includeRootsAbs, files, context.discoveryOptions, context.graphOptions, context.languageExtensions, cache, context.getOpt("--cache-dir"), context.cacheLocation, context.nativeMode, context.workerOpts, context.progressHandler, context.commandReport?.index, limit, context.hasFlag("--duplicates"), context.writeStderrLine);
111853
111944
  writeCliOutput(context, report, formatInspectReport);
111854
111945
  if (context.commandReport && context.writeCommandReport) {
111855
- context.commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
111946
+ context.commandReport.timings.commandMs = Math.round(performance16.now() - commandStart);
111856
111947
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
111857
111948
  await context.writeCommandReport(context.commandReport, context.reportFile);
111858
111949
  }