@lzehrung/codegraph 2.3.11 → 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,10 +13552,12 @@ __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,
13558
13559
  listGitIgnoreFiles: () => listGitIgnoreFiles,
13560
+ listGitStageSpecialPaths: () => listGitStageSpecialPaths,
13559
13561
  listGitSubmoduleDirectories: () => listGitSubmoduleDirectories,
13560
13562
  listTrackedFiles: () => listTrackedFiles,
13561
13563
  listUntrackedFiles: () => listUntrackedFiles,
@@ -13604,8 +13606,9 @@ function decodeGitPath(rawPath) {
13604
13606
  }
13605
13607
  return Buffer.from(bytes).toString("utf8");
13606
13608
  }
13607
- function setGitExecutableForTests(executable) {
13609
+ function setGitExecutableForTests(executable, prefixArgs = []) {
13608
13610
  gitExecutableForTests = executable;
13611
+ gitExecutablePrefixArgsForTests = executable ? [...prefixArgs] : [];
13609
13612
  }
13610
13613
  function clearGitRepositoryCheckCacheForTests() {
13611
13614
  gitRepositoryChecks.clear();
@@ -13672,12 +13675,13 @@ async function runGit(projectRoot, args, options) {
13672
13675
  const timeoutMs = resolveGitTimeoutMs(options?.timeoutMs);
13673
13676
  const maxBuffer = options?.maxBuffer ?? 64 * 1024 * 1024;
13674
13677
  const executable = gitExecutableForTests ?? "git";
13678
+ const childArgs = gitExecutablePrefixArgsForTests.length ? [...gitExecutablePrefixArgsForTests, ...args] : args;
13675
13679
  const signal = options?.signal;
13676
13680
  if (signal?.aborted) {
13677
13681
  throw createGitError(projectRoot, args, new Error("aborted before start"));
13678
13682
  }
13679
13683
  return await new Promise((resolve, reject) => {
13680
- const child = spawn(executable, args, {
13684
+ const child = spawn(executable, childArgs, {
13681
13685
  cwd: projectRoot,
13682
13686
  env: process.env,
13683
13687
  stdio: [options?.input !== void 0 ? "pipe" : "ignore", "pipe", "pipe"],
@@ -13994,7 +13998,7 @@ async function listTrackedFiles(projectRoot, opts) {
13994
13998
  async function listGitIgnoreFiles(projectRoot, opts) {
13995
13999
  if (!(opts?.gitAvailable ?? true))
13996
14000
  return [];
13997
- const pathspec = [".gitignore", ":(glob)**/.gitignore"];
14001
+ const pathspec = [".gitignore", ":(glob)**/.gitignore", ...opts?.excludePathspecs ?? []];
13998
14002
  const commands = [
13999
14003
  ["ls-files", "--cached", "-z", "--", ...pathspec],
14000
14004
  ["ls-files", "--others", "--exclude-standard", "-z", "--", ...pathspec],
@@ -14017,31 +14021,49 @@ async function listGitIgnoreFiles(projectRoot, opts) {
14017
14021
  }
14018
14022
  return Array.from(new Set(out));
14019
14023
  }
14020
- async function listGitSubmoduleDirectories(projectRoot, opts) {
14024
+ function parseGitStageSpecialPaths(projectRoot, stdout) {
14025
+ const gitlinks = [];
14026
+ const symlinks = [];
14027
+ for (const record2 of stdout.split("\0").filter(Boolean)) {
14028
+ const tabIndex = record2.indexOf(" ");
14029
+ if (tabIndex < 0)
14030
+ continue;
14031
+ const rel = record2.slice(tabIndex + 1);
14032
+ if (!rel)
14033
+ continue;
14034
+ const abs = normalizePath(path8.resolve(projectRoot, rel));
14035
+ if (record2.startsWith("160000 "))
14036
+ gitlinks.push(abs);
14037
+ else if (record2.startsWith("120000 "))
14038
+ symlinks.push(abs);
14039
+ }
14040
+ return { gitlinks, symlinks };
14041
+ }
14042
+ async function listGitStageSpecialPaths(projectRoot, opts) {
14021
14043
  if (!(opts?.gitAvailable ?? true))
14022
- return [];
14044
+ return { gitlinks: [], symlinks: [] };
14023
14045
  const args = ["ls-files", "--stage", "-z"];
14024
14046
  try {
14025
14047
  const { stdout } = await runGit(projectRoot, args, { maxBuffer: 64 * 1024 * 1024 });
14026
- const direct = [];
14027
- for (const record2 of stdout.split("\0").filter(Boolean)) {
14028
- if (!record2.startsWith("160000 "))
14029
- continue;
14030
- const tabIndex = record2.indexOf(" ");
14031
- if (tabIndex < 0)
14032
- continue;
14033
- const rel = record2.slice(tabIndex + 1);
14034
- if (rel)
14035
- direct.push(normalizePath(path8.resolve(projectRoot, rel)));
14036
- }
14037
- if (!opts?.recurse || !direct.length)
14038
- return Array.from(new Set(direct));
14039
- const nested = await Promise.all(direct.map(async (directory) => await listGitSubmoduleDirectories(directory, opts)));
14040
- return Array.from(/* @__PURE__ */ new Set([...direct, ...nested.flat()]));
14048
+ const direct = parseGitStageSpecialPaths(projectRoot, stdout);
14049
+ if (!opts?.recurse || !direct.gitlinks.length) {
14050
+ return {
14051
+ gitlinks: Array.from(new Set(direct.gitlinks)),
14052
+ symlinks: Array.from(new Set(direct.symlinks))
14053
+ };
14054
+ }
14055
+ const nested = await Promise.all(direct.gitlinks.map(async (directory) => await listGitStageSpecialPaths(directory, opts)));
14056
+ return {
14057
+ gitlinks: Array.from(/* @__PURE__ */ new Set([...direct.gitlinks, ...nested.flatMap((entry) => entry.gitlinks)])),
14058
+ symlinks: Array.from(/* @__PURE__ */ new Set([...direct.symlinks, ...nested.flatMap((entry) => entry.symlinks)]))
14059
+ };
14041
14060
  } catch (error51) {
14042
14061
  throw createGitError(projectRoot, args, error51);
14043
14062
  }
14044
14063
  }
14064
+ async function listGitSubmoduleDirectories(projectRoot, opts) {
14065
+ return (await listGitStageSpecialPaths(projectRoot, opts)).gitlinks;
14066
+ }
14045
14067
  async function listGitExcludeFiles(projectRoot, opts) {
14046
14068
  if (!(opts?.gitAvailable ?? true))
14047
14069
  return [];
@@ -14140,6 +14162,10 @@ async function getUnifiedDiff(projectRoot, opts) {
14140
14162
  throw createGitError(projectRoot, args, error51);
14141
14163
  }
14142
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
+ }
14143
14169
  function createGitError(projectRoot, args, error51) {
14144
14170
  let detail = stringifyUnknown(error51);
14145
14171
  if (typeof error51 === "object" && error51 !== null && "stderr" in error51 && typeof error51.stderr === "string" && error51.stderr.trim()) {
@@ -14149,7 +14175,7 @@ function createGitError(projectRoot, args, error51) {
14149
14175
  }
14150
14176
  return new Error(`git ${args.join(" ")} failed in ${projectRoot}: ${detail}`);
14151
14177
  }
14152
- 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;
14153
14179
  var init_git = __esm({
14154
14180
  "dist/util/git.js"() {
14155
14181
  "use strict";
@@ -14162,6 +14188,7 @@ var init_git = __esm({
14162
14188
  gitExcludeFileChecks = /* @__PURE__ */ new Map();
14163
14189
  MAX_GIT_HASH_OBJECT_ARGUMENT_BYTES = 24 * 1024;
14164
14190
  gitExecutableForTests = null;
14191
+ gitExecutablePrefixArgsForTests = [];
14165
14192
  GIT_QUOTED_PATH_SINGLE_BYTE_ESCAPES = {
14166
14193
  a: 7,
14167
14194
  b: 8,
@@ -14194,6 +14221,13 @@ __export(projectFiles_exports, {
14194
14221
  import fs6 from "node:fs";
14195
14222
  import fsp5 from "node:fs/promises";
14196
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
+ }
14197
14231
  function createPathCheckProgressReporter(total, onProgress) {
14198
14232
  onProgress?.(0, total);
14199
14233
  let completed = 0;
@@ -14209,13 +14243,49 @@ function isPresent(value) {
14209
14243
  function normalizeGlobPattern(globPattern) {
14210
14244
  return globPattern.trim().replace(/\\/g, "/");
14211
14245
  }
14246
+ function defaultIgnoreGitExcludePathspecs(includeGlobs = []) {
14247
+ const activeIgnores = includeGlobs.length ? DEFAULT_PROJECT_FILE_IGNORES.filter((ignoreGlob) => !isIgnoreGlobReopenedByIncludes(ignoreGlob, includeGlobs)) : DEFAULT_PROJECT_FILE_IGNORES;
14248
+ return activeIgnores.map((globPattern) => `:(exclude,glob)${normalizeGlobPattern(globPattern)}`);
14249
+ }
14250
+ function couldBeDirectorySymlink(filePath) {
14251
+ const basename2 = path9.posix.basename(normalizePath(filePath));
14252
+ if (DIRECTORY_METADATA_BASENAMES.has(basename2.toLowerCase()))
14253
+ return true;
14254
+ const extension = path9.posix.extname(basename2);
14255
+ if (!extension)
14256
+ return true;
14257
+ return DIRECTORY_METADATA_EXTENSIONS.has(extension.toLowerCase());
14258
+ }
14259
+ function globLiteralPrefix(globPattern) {
14260
+ const prefix = [];
14261
+ let seenLiteral = false;
14262
+ for (const segment of globPattern.split("/")) {
14263
+ if (!segment)
14264
+ continue;
14265
+ if (!seenLiteral && segment === "**")
14266
+ continue;
14267
+ if (segment.includes("*") || segment.includes("?"))
14268
+ break;
14269
+ seenLiteral = true;
14270
+ prefix.push(segment);
14271
+ }
14272
+ return prefix;
14273
+ }
14274
+ function isSegmentPrefix(prefix, pathSegments) {
14275
+ if (!prefix.length || prefix.length > pathSegments.length)
14276
+ return false;
14277
+ return prefix.every((segment, index) => pathSegments[index] === segment);
14278
+ }
14212
14279
  function isIgnoreGlobReopenedByIncludes(ignoreGlob, includeGlobs) {
14213
- const literalSegments = ignoreGlob.split("/").filter((segment) => segment && !segment.includes("*"));
14214
- if (!literalSegments.length)
14280
+ const ignoreLiterals = ignoreGlob.split("/").filter((segment) => segment && !segment.includes("*"));
14281
+ if (!ignoreLiterals.length)
14215
14282
  return false;
14216
14283
  return includeGlobs.some((includeGlob) => {
14217
14284
  const includeSegments = includeGlob.split("/");
14218
- return literalSegments.every((segment) => includeSegments.includes(segment));
14285
+ if (ignoreLiterals.every((segment) => includeSegments.includes(segment)))
14286
+ return true;
14287
+ const includePrefix = globLiteralPrefix(includeGlob);
14288
+ return isSegmentPrefix(includePrefix, ignoreLiterals) || isSegmentPrefix(ignoreLiterals, includePrefix);
14219
14289
  });
14220
14290
  }
14221
14291
  function isLocationIndependentGlob(globPattern) {
@@ -14428,7 +14498,7 @@ function collectCandidateAncestorDirectories(root, files) {
14428
14498
  }
14429
14499
  return directories;
14430
14500
  }
14431
- async function findGitIgnoreSources(sourceRoots) {
14501
+ async function findGitIgnoreSources(sourceRoots, excludePathspecs = defaultIgnoreGitExcludePathspecs()) {
14432
14502
  const roots = Array.from(new Map(sourceRoots.map(({ path: sourceRoot, repositoryRoot }) => [
14433
14503
  fileIdentityKey(sourceRoot),
14434
14504
  { path: normalizePath(sourceRoot), repositoryRoot: normalizePath(repositoryRoot) }
@@ -14436,7 +14506,7 @@ async function findGitIgnoreSources(sourceRoots) {
14436
14506
  const sources = [];
14437
14507
  for (const { path: sourceRoot, repositoryRoot } of roots) {
14438
14508
  const [gitignoreFiles, excludeFiles] = await Promise.all([
14439
- listGitIgnoreFiles(sourceRoot),
14509
+ listGitIgnoreFiles(sourceRoot, { excludePathspecs }),
14440
14510
  listGitExcludeFiles(sourceRoot)
14441
14511
  ]);
14442
14512
  sources.push(...gitignoreFiles.map((file2) => ({
@@ -14452,7 +14522,9 @@ async function findGitIgnoreSources(sourceRoots) {
14452
14522
  }
14453
14523
  return sources;
14454
14524
  }
14455
- async function listGitCandidateFiles(root, logLevel) {
14525
+ async function listGitCandidateFiles(root, logLevel, opts) {
14526
+ let gitListStart;
14527
+ let gitIgnoreStart;
14456
14528
  try {
14457
14529
  const realRoot = normalizePath(await fsp5.realpath(root));
14458
14530
  const gitRoot = await isGitRepo(root) ? root : realRoot;
@@ -14463,11 +14535,15 @@ async function listGitCandidateFiles(root, logLevel) {
14463
14535
  const gitRepositoryRoot = await getGitRepositoryRoot(gitRoot);
14464
14536
  if (!gitRepositoryRoot)
14465
14537
  return null;
14466
- const [tracked, untracked, submoduleDirectories] = await Promise.all([
14538
+ emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git files");
14539
+ const listStartedAt = performance2.now();
14540
+ gitListStart = listStartedAt;
14541
+ const [tracked, untracked, stageSpecial] = await Promise.all([
14467
14542
  listTrackedFiles(gitRoot, { recurseSubmodules: true, ...logLevel === void 0 ? {} : { logLevel } }),
14468
14543
  listUntrackedFiles(gitRoot, { respectGitignore: true }),
14469
- listGitSubmoduleDirectories(gitRoot, { recurse: true })
14544
+ listGitStageSpecialPaths(gitRoot, { recurse: true })
14470
14545
  ]);
14546
+ const submoduleDirectories = stageSpecial.gitlinks;
14471
14547
  const submoduleRoots = await Promise.all(submoduleDirectories.map(async (logicalPath) => ({
14472
14548
  logicalPath: normalizePath(logicalPath),
14473
14549
  physicalPath: normalizePath(await fsp5.realpath(logicalPath).catch(() => logicalPath))
@@ -14476,6 +14552,8 @@ async function listGitCandidateFiles(root, logLevel) {
14476
14552
  const rawFiles = Array.from(/* @__PURE__ */ new Set([...tracked, ...untracked, ...submoduleUntracked.flat()])).sort();
14477
14553
  const needsLogicalRemap = normalizePath(gitRoot) !== normalizePath(root);
14478
14554
  const files = Array.from(new Set(rawFiles.map((file2) => needsLogicalRemap && isFilePathWithinRoot(realRoot, file2) ? normalizePath(path9.resolve(root, path9.relative(realRoot, file2))) : normalizePath(file2)))).sort();
14555
+ const remapGitPath = (file2) => needsLogicalRemap && isFilePathWithinRoot(realRoot, file2) ? normalizePath(path9.resolve(root, path9.relative(realRoot, file2))) : normalizePath(file2);
14556
+ const symlinkCandidatePaths = Array.from(/* @__PURE__ */ new Set([...stageSpecial.symlinks.map(remapGitPath), ...files.filter((file2) => couldBeDirectorySymlink(file2))])).sort();
14479
14557
  const gitignoreRoots = [gitRepositoryRoot, ...submoduleRoots.map(({ physicalPath }) => physicalPath)].map(normalizePath);
14480
14558
  const sourceRoots = [
14481
14559
  { path: root, repositoryRoot: gitRepositoryRoot },
@@ -14486,14 +14564,35 @@ async function listGitCandidateFiles(root, logLevel) {
14486
14564
  { path: physicalPath, repositoryRoot: physicalPath }
14487
14565
  ])
14488
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);
14489
14577
  return {
14490
14578
  files,
14491
- gitignoreFiles: await findGitIgnoreSources(sourceRoots),
14579
+ symlinkCandidatePaths,
14580
+ gitignoreFiles,
14492
14581
  gitignoreRoots,
14493
14582
  gitignoreAliases: sourceRoots
14494
14583
  };
14495
14584
  } catch (error51) {
14496
- 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
+ }
14497
14596
  return null;
14498
14597
  }
14499
14598
  }
@@ -14522,7 +14621,11 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14522
14621
  const useGitignore = options?.useGitignore ?? true;
14523
14622
  const realRoot = await fsp5.realpath(root);
14524
14623
  const attemptedGitCandidates = useGitignore && options?.gitignoreRoot === void 0 && normalizePath(realRoot) === normalizePath(root);
14525
- const gitCandidates = attemptedGitCandidates ? await listGitCandidateFiles(root, options?.logLevel) : 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;
14526
14629
  if (attemptedGitCandidates) {
14527
14630
  options?.onGitCandidatesDiscovered?.(gitCandidates);
14528
14631
  }
@@ -14533,13 +14636,22 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14533
14636
  const gitignoreRoot = options?.gitignoreRoot ? await ensureDirectoryReadable(options.gitignoreRoot, "Gitignore root") : root;
14534
14637
  gitignoreIndex = await loadGitignoreIndexForRootAliases(gitignoreRoot);
14535
14638
  }
14536
- const files = gitCandidates ? gitCandidates.files : await (0, import_fast_glob2.default)(patterns, {
14537
- cwd: root,
14538
- absolute: true,
14539
- dot: true,
14540
- followSymbolicLinks: false,
14541
- ignore: fastGlobIgnoreGlobs
14542
- });
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
+ }
14543
14655
  const includedOverrideFiles = includeGlobs.length && !gitCandidates ? await (0, import_fast_glob2.default)(translateGlobRootIgnoreGlobsForScanRoot(root, globRoot, includeGlobs), {
14544
14656
  cwd: root,
14545
14657
  absolute: true,
@@ -14551,7 +14663,7 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14551
14663
  const reportSourcePathChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking source file paths", current, total }) : void 0;
14552
14664
  const symlinkOptions = {
14553
14665
  globRoot,
14554
- ...gitCandidates ? { candidatePaths: gitCandidates.files } : {},
14666
+ ...gitCandidates ? { candidatePaths: gitCandidates.symlinkCandidatePaths } : {},
14555
14667
  ...options?.knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: options.knownSymlinkDirectories } : {},
14556
14668
  ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {},
14557
14669
  ...reportSourceSymlinkChecks ? { onPathCheckProgress: reportSourceSymlinkChecks } : {}
@@ -14663,7 +14775,9 @@ async function resolveSafeSymlinkDirectories(root, realRoot, ignore, options) {
14663
14775
  const relativePath3 = normalizePath(path9.relative(root, candidatePath));
14664
14776
  if (!isRelativePathInside(relativePath3))
14665
14777
  return false;
14666
- return !ignoreMatchers.some((matcher) => matcher(relativePath3));
14778
+ if (ignoreMatchers.some((matcher) => matcher(relativePath3)))
14779
+ return false;
14780
+ return true;
14667
14781
  });
14668
14782
  const discovered2 = await verifySafeSymlinkDirectories(root, realRoot, candidatePaths, options.onPathCheckProgress);
14669
14783
  options.onSymlinkDirectoriesDiscovered?.(discovered2, "git-candidates");
@@ -14781,7 +14895,10 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14781
14895
  if (options?.knownGitCandidates !== void 0) {
14782
14896
  gitCandidates = options.knownGitCandidates;
14783
14897
  } else {
14784
- 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
+ });
14785
14902
  }
14786
14903
  options?.onGitCandidatesDiscovered?.(gitCandidates);
14787
14904
  const reportMetadataSymlinkChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking project metadata symlinks", current, total }) : void 0;
@@ -14803,7 +14920,7 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14803
14920
  return normalizePath(realPath) === filePath || !isIgnoredByGitignore(realPath, gitignoreIndex, isDirectory2);
14804
14921
  }).map(({ filePath }) => filePath);
14805
14922
  const symlinkOptions = {
14806
- candidatePaths: gitCandidates.files,
14923
+ candidatePaths: gitCandidates.symlinkCandidatePaths,
14807
14924
  ...options?.knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: options.knownSymlinkDirectories } : {},
14808
14925
  ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {},
14809
14926
  ...reportMetadataSymlinkChecks ? { onPathCheckProgress: reportMetadataSymlinkChecks } : {}
@@ -14884,7 +15001,7 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14884
15001
  throw new Error(`Failed to discover project files in ${root}: ${stringifyUnknown(error51)}`);
14885
15002
  }
14886
15003
  }
14887
- var import_fast_glob2, import_picomatch, DEFAULT_PROJECT_FILE_IGNORES, DEFAULT_PROJECT_MANIFESTS, DEFAULT_PROJECT_PATTERNS, REALPATH_FILTER_CONCURRENCY, EMPTY_GITIGNORE_INDEX;
15004
+ var import_fast_glob2, import_picomatch, DEFAULT_PROJECT_FILE_IGNORES, DEFAULT_PROJECT_MANIFESTS, DEFAULT_PROJECT_PATTERNS, REALPATH_FILTER_CONCURRENCY, DIRECTORY_METADATA_EXTENSIONS, DIRECTORY_METADATA_BASENAMES, EMPTY_GITIGNORE_INDEX;
14888
15005
  var init_projectFiles = __esm({
14889
15006
  "dist/util/projectFiles.js"() {
14890
15007
  "use strict";
@@ -14986,6 +15103,23 @@ var init_projectFiles = __esm({
14986
15103
  ...DEFAULT_PROJECT_MANIFESTS.map((name) => `**/${name}`)
14987
15104
  ];
14988
15105
  REALPATH_FILTER_CONCURRENCY = 64;
15106
+ DIRECTORY_METADATA_EXTENSIONS = /* @__PURE__ */ new Set();
15107
+ DIRECTORY_METADATA_BASENAMES = /* @__PURE__ */ new Set();
15108
+ for (const definition of PROJECT_FILE_DEFINITIONS) {
15109
+ if (definition.kind !== "dir")
15110
+ continue;
15111
+ for (const pattern of definition.patterns) {
15112
+ if (!pattern.includes("*") && !pattern.includes("?")) {
15113
+ DIRECTORY_METADATA_BASENAMES.add(pattern.toLowerCase());
15114
+ continue;
15115
+ }
15116
+ const trimmed = pattern.replaceAll("*", "").replaceAll("?", "");
15117
+ const lastDot = trimmed.lastIndexOf(".");
15118
+ if (lastDot < 0)
15119
+ continue;
15120
+ DIRECTORY_METADATA_EXTENSIONS.add(trimmed.slice(lastDot).toLowerCase());
15121
+ }
15122
+ }
14989
15123
  EMPTY_GITIGNORE_INDEX = {
14990
15124
  hasRules: false,
14991
15125
  repositoryRoots: [],
@@ -53504,19 +53638,19 @@ var init_parsed_cache = __esm({
53504
53638
  });
53505
53639
 
53506
53640
  // dist/indexer/finalize.js
53507
- import { performance as performance2 } from "node:perf_hooks";
53641
+ import { performance as performance3 } from "node:perf_hooks";
53508
53642
  async function finalizeProjectIndex(args) {
53509
53643
  const discoveryTimings = args.opts?.report ? args.opts.report.timings ??= {} : void 0;
53510
- const metadataDiscoveryStart = args.projectFiles === void 0 ? performance2.now() : void 0;
53644
+ const metadataDiscoveryStart = args.projectFiles === void 0 ? performance3.now() : void 0;
53511
53645
  const projectFiles = await (args.projectFiles ?? discoverProjectFilesWithGitCandidates(args.projectRoot, {
53512
53646
  ...args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {},
53513
53647
  ...args.knownGitCandidates !== void 0 ? { knownGitCandidates: args.knownGitCandidates } : {}
53514
53648
  }));
53515
53649
  if (metadataDiscoveryStart !== void 0 && discoveryTimings) {
53516
- discoveryTimings.metadataDiscoveryMs = Math.round(performance2.now() - metadataDiscoveryStart);
53650
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance3.now() - metadataDiscoveryStart);
53517
53651
  }
53518
53652
  if (args.timings)
53519
- args.timings.totalMs = Math.round(performance2.now() - args.totalStart);
53653
+ args.timings.totalMs = Math.round(performance3.now() - args.totalStart);
53520
53654
  const languageExtensions = normalizeLanguageExtensions(args.opts?.languageExtensions);
53521
53655
  const parsed = retainedParsedCache(args.parsedMap, args.opts);
53522
53656
  return {
@@ -53554,7 +53688,7 @@ var init_finalize = __esm({
53554
53688
  // dist/indexer/build-manifest.js
53555
53689
  import fsp24 from "node:fs/promises";
53556
53690
  import path45 from "node:path";
53557
- import { performance as performance3 } from "node:perf_hooks";
53691
+ import { performance as performance4 } from "node:perf_hooks";
53558
53692
  function toManifestFileEntry(entry) {
53559
53693
  if (!entry.sig)
53560
53694
  return void 0;
@@ -53569,7 +53703,7 @@ async function writeIndexManifestSnapshot(args) {
53569
53703
  const files = args.files instanceof Map ? Object.fromEntries(args.files) : args.files;
53570
53704
  if (!Object.keys(files).length && !args.allowEmpty)
53571
53705
  return;
53572
- const writeManifestStart = performance3.now();
53706
+ const writeManifestStart = performance4.now();
53573
53707
  const lastCommit = await getGitHead(args.projectRoot);
53574
53708
  const configHashResult = await computeConfigHash(args.projectRoot, args.opts?.logLevel);
53575
53709
  const projectRootMtimeMs = args.symlinkDirectories !== void 0 ? (await fsp24.stat(args.projectRoot)).mtimeMs : void 0;
@@ -53594,7 +53728,7 @@ async function writeIndexManifestSnapshot(args) {
53594
53728
  if (manifestWritten)
53595
53729
  pruneDiskModuleCache(args.projectRoot, Object.keys(files), args.opts);
53596
53730
  if (args.timings) {
53597
- args.timings.writeManifestMs = Math.round(performance3.now() - writeManifestStart);
53731
+ args.timings.writeManifestMs = Math.round(performance4.now() - writeManifestStart);
53598
53732
  }
53599
53733
  }
53600
53734
  var init_build_manifest = __esm({
@@ -55029,7 +55163,7 @@ var init_nativeWorkerPool = __esm({
55029
55163
  });
55030
55164
 
55031
55165
  // dist/indexer/build-workers.js
55032
- import { performance as performance4 } from "node:perf_hooks";
55166
+ import { performance as performance5 } from "node:perf_hooks";
55033
55167
  function shouldEnableNativeWorkers(opts, fileCount) {
55034
55168
  if (opts?.native === "off")
55035
55169
  return false;
@@ -55123,14 +55257,14 @@ async function setupWorkerPool(opts, fileCount) {
55123
55257
  return {
55124
55258
  pool,
55125
55259
  report,
55126
- startTime: pool ? performance4.now() : 0,
55260
+ startTime: pool ? performance5.now() : 0,
55127
55261
  batchSize: NATIVE_WORKER_BATCH_SIZE
55128
55262
  };
55129
55263
  }
55130
55264
  async function teardownWorkerPool(setup, buildReport2) {
55131
55265
  if (setup.pool) {
55132
55266
  if (setup.report) {
55133
- setup.report.wallClockMs = Math.round(performance4.now() - setup.startTime);
55267
+ setup.report.wallClockMs = Math.round(performance5.now() - setup.startTime);
55134
55268
  }
55135
55269
  try {
55136
55270
  await setup.pool.destroy();
@@ -55398,7 +55532,7 @@ import crypto10 from "node:crypto";
55398
55532
  import fs23 from "node:fs";
55399
55533
  import fsp26 from "node:fs/promises";
55400
55534
  import path47 from "node:path";
55401
- import { performance as performance5 } from "node:perf_hooks";
55535
+ import { performance as performance6 } from "node:perf_hooks";
55402
55536
  function initParserBackendDegradationReport(report) {
55403
55537
  if (!report)
55404
55538
  return void 0;
@@ -55697,7 +55831,7 @@ function createIndexBuildRunState(projectRoot, opts, graphOptions = normalizeGra
55697
55831
  normalizedProjectRoot: normalizePath(path47.resolve(projectRoot)),
55698
55832
  report,
55699
55833
  timings: report?.timings,
55700
- totalStart: performance5.now(),
55834
+ totalStart: performance6.now(),
55701
55835
  cacheMode,
55702
55836
  cacheEnabled: cacheMode !== "off",
55703
55837
  graphOptions,
@@ -55742,6 +55876,31 @@ function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
55742
55876
  total
55743
55877
  });
55744
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
+ }
55745
55904
  function buildConcurrency(opts) {
55746
55905
  return resolveWorkerThreadCount({ requested: Number(opts?.threads || 0), defaultCount: 8, max: 64 });
55747
55906
  }
@@ -55783,7 +55942,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55783
55942
  const fileReport = initFileReport(report);
55784
55943
  if (fileReport)
55785
55944
  fileReport.total = normalizedFiles.length;
55786
- const manifestStart = performance5.now();
55945
+ const manifestStart = performance6.now();
55787
55946
  const manifest = useManifest && !helperOpts?.ignoreExistingManifest ? await loadManifest(projectRoot, opts, report) : null;
55788
55947
  const manifestFiles = sanitizeManifestEntriesForRoot(projectRoot, manifest?.files);
55789
55948
  const manifestOptionDiffs = manifest ? diffBuildOptions(manifest.buildOptions, opts) : [];
@@ -55798,7 +55957,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55798
55957
  }
55799
55958
  }
55800
55959
  if (timings && useManifest) {
55801
- timings.manifestMs = Math.round(performance5.now() - manifestStart);
55960
+ timings.manifestMs = Math.round(performance6.now() - manifestStart);
55802
55961
  }
55803
55962
  const edgeProbeConcurrency = buildConcurrency(opts);
55804
55963
  const staleCachedEdgeFiles = /* @__PURE__ */ new Set();
@@ -55912,7 +56071,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55912
56071
  }
55913
56072
  return matchPath;
55914
56073
  };
55915
- const parseStart = performance5.now();
56074
+ const parseStart = performance6.now();
55916
56075
  const graph = { nodes: new Set(normalizedFiles), edges: [] };
55917
56076
  const onFileEdges = manifestEntries ? (file2, entry) => {
55918
56077
  const manifestEntry = toManifestFileEntry(entry);
@@ -55926,7 +56085,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
55926
56085
  const ensureBuildProgressStarted = () => {
55927
56086
  if (buildStartedAt !== void 0)
55928
56087
  return;
55929
- buildStartedAt = performance5.now();
56088
+ buildStartedAt = performance6.now();
55930
56089
  emitIndexLifecycleProgress(opts, "start", "build", totalFiles);
55931
56090
  };
55932
56091
  const fileResults = await mapLimit(normalizedFiles, conc, async (file2) => {
@@ -56058,8 +56217,8 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56058
56217
  }
56059
56218
  });
56060
56219
  if (timings)
56061
- timings.parseMs = Math.round(performance5.now() - parseStart);
56062
- const graphStart = performance5.now();
56220
+ timings.parseMs = Math.round(performance6.now() - parseStart);
56221
+ const graphStart = performance6.now();
56063
56222
  const seenGraphEdges = /* @__PURE__ */ new Set();
56064
56223
  const appendUniqueGraphEdges = (edges) => {
56065
56224
  if (!edges.length)
@@ -56087,7 +56246,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56087
56246
  const workspaceManifestEdges = await collectWorkspaceManifestDependencyEdges(projectRoot, normalizedFiles.filter((file2) => path47.basename(file2) === "package.json"), opts?.discovery, opts?.logLevel);
56088
56247
  appendUniqueGraphEdges(workspaceManifestEdges);
56089
56248
  if (timings)
56090
- timings.graphMs = Math.round(performance5.now() - graphStart);
56249
+ timings.graphMs = Math.round(performance6.now() - graphStart);
56091
56250
  for (const jsonPath of jsonDependencies.values()) {
56092
56251
  ensureJsonModule(modules, jsonPath);
56093
56252
  }
@@ -56139,7 +56298,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56139
56298
  }
56140
56299
  if (buildStartedAt !== void 0) {
56141
56300
  const progressStartedAt = opts?.progressStartedAt ?? buildStartedAt;
56142
- emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance5.now() - progressStartedAt);
56301
+ emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance6.now() - progressStartedAt);
56143
56302
  }
56144
56303
  return index;
56145
56304
  } finally {
@@ -56148,6 +56307,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56148
56307
  }
56149
56308
  async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpts) {
56150
56309
  const timings = opts?.report ? opts.report.timings ??= {} : void 0;
56310
+ resetDiscoveryTimingSteps(timings);
56151
56311
  await initializeFileIdentityCaseSensitivity(projectRoot);
56152
56312
  try {
56153
56313
  const useDiskCache = (opts?.cache ?? "off") === "disk";
@@ -56168,19 +56328,21 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56168
56328
  discoveredGitCandidates = candidates;
56169
56329
  };
56170
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;
56171
56332
  if (helperOpts?.reportDiscoveryProgress)
56172
56333
  emitIndexCheckActivity(opts, "Discovering source files");
56173
- const sourceDiscoveryStart = performance5.now();
56334
+ const sourceDiscoveryStart = performance6.now();
56174
56335
  const discoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
56175
56336
  ...opts?.discovery,
56176
56337
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56177
56338
  ...knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories } : {},
56178
56339
  onSymlinkDirectoriesDiscovered,
56179
56340
  onGitCandidatesDiscovered,
56180
- ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
56341
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {},
56342
+ ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56181
56343
  });
56182
56344
  if (timings)
56183
- timings.sourceDiscoveryMs = Math.round(performance5.now() - sourceDiscoveryStart);
56345
+ timings.sourceDiscoveryMs = Math.round(performance6.now() - sourceDiscoveryStart);
56184
56346
  const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
56185
56347
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
56186
56348
  const additionalFiles = additionalFileCandidates.filter((file2) => additionalFileExistence.get(file2));
@@ -56189,15 +56351,16 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56189
56351
  const transientFiles = additionalFiles.filter((file2) => !discoveredFileSet.has(file2));
56190
56352
  if (helperOpts?.reportDiscoveryProgress)
56191
56353
  emitIndexCheckActivity(opts, "Discovering project metadata");
56192
- const metadataDiscoveryStart = performance5.now();
56354
+ const metadataDiscoveryStart = performance6.now();
56193
56355
  const projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56194
56356
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56195
56357
  ...discoveredSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: discoveredSymlinkDirectories } : {},
56196
56358
  ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {},
56197
- ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
56359
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {},
56360
+ ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56198
56361
  });
56199
56362
  if (timings)
56200
- timings.metadataDiscoveryMs = Math.round(performance5.now() - metadataDiscoveryStart);
56363
+ timings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56201
56364
  return await buildIndexFromFileListShared(projectRoot, files, opts, {
56202
56365
  manifestMode: useDiskCache ? "read-write" : "off",
56203
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`,
@@ -56216,11 +56379,11 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56216
56379
  async function buildProjectIndex(projectRoot, opts) {
56217
56380
  return buildProjectIndexWithManifestOptions(projectRoot, {
56218
56381
  ...opts,
56219
- progressStartedAt: opts?.progressStartedAt ?? performance5.now()
56382
+ progressStartedAt: opts?.progressStartedAt ?? performance6.now()
56220
56383
  });
56221
56384
  }
56222
56385
  async function buildProjectIndexFromFiles(projectRoot, inputFiles, rawOpts) {
56223
- const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance5.now() };
56386
+ const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now() };
56224
56387
  try {
56225
56388
  const useDiskCache = (opts?.cache ?? "off") === "disk";
56226
56389
  const normalizedInputFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, inputFiles, "Index file");
@@ -56252,7 +56415,7 @@ async function buildDeclaredScopeIndex(projectRoot, scopeFiles, opts) {
56252
56415
  async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56253
56416
  const opts = {
56254
56417
  ...rawOpts,
56255
- progressStartedAt: rawOpts?.progressStartedAt ?? performance5.now()
56418
+ progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now()
56256
56419
  };
56257
56420
  await initializeFileIdentityCaseSensitivity(projectRoot);
56258
56421
  clearResolutionCaches();
@@ -56262,6 +56425,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56262
56425
  graphOptions.fast = false;
56263
56426
  const { normalizedProjectRoot, report, timings, totalStart, cacheMode, cacheEnabled, onFallbackImportExtraction } = createIndexBuildRunState(projectRoot, opts, graphOptions);
56264
56427
  const discoveryTimings = opts?.report ? opts.report.timings ??= {} : void 0;
56428
+ resetDiscoveryTimingSteps(discoveryTimings);
56265
56429
  let checkProgressActive = false;
56266
56430
  const startCheckProgress = () => {
56267
56431
  if (checkProgressActive)
@@ -56287,7 +56451,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56287
56451
  message: "Checked project index",
56288
56452
  current: total,
56289
56453
  total,
56290
- elapsedMs: performance5.now() - totalStart
56454
+ elapsedMs: performance6.now() - totalStart
56291
56455
  });
56292
56456
  };
56293
56457
  try {
@@ -56302,10 +56466,10 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56302
56466
  return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
56303
56467
  }
56304
56468
  startCheckProgress();
56305
- const manifestStart = performance5.now();
56469
+ const manifestStart = performance6.now();
56306
56470
  const manifest = await loadManifest(projectRoot, opts, report);
56307
56471
  if (timings)
56308
- timings.manifestMs = Math.round(performance5.now() - manifestStart);
56472
+ timings.manifestMs = Math.round(performance6.now() - manifestStart);
56309
56473
  const manifestUsed = !!manifest;
56310
56474
  const manifestReport = initManifestReport(report, manifestUsed, false);
56311
56475
  if (manifestReport && !manifestUsed)
@@ -56360,11 +56524,11 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56360
56524
  if (!discoveryTimings || opts?.filesAreProjectScope)
56361
56525
  return await operation();
56362
56526
  sourceDiscoveryPerformed = true;
56363
- const start = performance5.now();
56527
+ const start = performance6.now();
56364
56528
  try {
56365
56529
  return await operation();
56366
56530
  } finally {
56367
- sourceDiscoveryMs += performance5.now() - start;
56531
+ sourceDiscoveryMs += performance6.now() - start;
56368
56532
  }
56369
56533
  };
56370
56534
  let manifestDiffFiles = [];
@@ -56456,7 +56620,10 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56456
56620
  ...!opts?.cacheStrict && manifest.symlinkDirectories !== void 0 ? { knownSymlinkDirectories: manifest.symlinkDirectories } : {},
56457
56621
  onGitCandidatesDiscovered: (candidates) => {
56458
56622
  discoveredGitCandidates = candidates;
56459
- }
56623
+ },
56624
+ ...discoveryTimings ? {
56625
+ onDiscoveryTiming: (step) => recordBuildTimingStep(discoveryTimings, step)
56626
+ } : {}
56460
56627
  }));
56461
56628
  }
56462
56629
  if (discoveryTimings && sourceDiscoveryPerformed) {
@@ -56561,13 +56728,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56561
56728
  const snapshot = snapshotLoad.index;
56562
56729
  snapshot.manifestSignaturesFresh = false;
56563
56730
  if (snapshot.projectFiles === void 0) {
56564
- const metadataDiscoveryStart = performance5.now();
56731
+ const metadataDiscoveryStart = performance6.now();
56565
56732
  snapshot.projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56566
56733
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56567
56734
  ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {}
56568
56735
  });
56569
56736
  if (discoveryTimings)
56570
- discoveryTimings.metadataDiscoveryMs = Math.round(performance5.now() - metadataDiscoveryStart);
56737
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56571
56738
  }
56572
56739
  if (opts?.cache) {
56573
56740
  snapshot.cacheMode = opts.cache;
@@ -56605,7 +56772,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56605
56772
  const snapshot = await reuseUnchangedSnapshot();
56606
56773
  if (snapshot) {
56607
56774
  if (timings)
56608
- timings.totalMs = Math.round(performance5.now() - totalStart);
56775
+ timings.totalMs = Math.round(performance6.now() - totalStart);
56609
56776
  completeCheckProgress(allFiles.size);
56610
56777
  return snapshot;
56611
56778
  }
@@ -56675,7 +56842,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56675
56842
  unchangedSnapshot.manifestEntries = new Map(Array.from(fileSignatures, ([file2, signature]) => [file2, toProjectIndexManifestEntry(signature)]));
56676
56843
  unchangedSnapshot.manifestSignaturesFresh = true;
56677
56844
  if (timings)
56678
- timings.totalMs = Math.round(performance5.now() - totalStart);
56845
+ timings.totalMs = Math.round(performance6.now() - totalStart);
56679
56846
  completeCheckProgress(allFiles.size);
56680
56847
  return unchangedSnapshot;
56681
56848
  }
@@ -56717,13 +56884,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56717
56884
  workerSetup = await setupWorkerPool(opts, countNativeWorkerEligibleFiles(changedList, opts?.languageExtensions));
56718
56885
  let updateStartedAt;
56719
56886
  if (changedList.length || deletedTrackedFiles.size) {
56720
- updateStartedAt = performance5.now();
56887
+ updateStartedAt = performance6.now();
56721
56888
  emitIndexLifecycleProgress(opts, "start", "update", changedList.length);
56722
56889
  }
56723
56890
  if (fileReport)
56724
56891
  fileReport.changed = changedList.length;
56725
56892
  if (changedList.length) {
56726
- const parseStart = performance5.now();
56893
+ const parseStart = performance6.now();
56727
56894
  let processedFiles = 0;
56728
56895
  const totalFiles = changedList.length;
56729
56896
  const fileResults = await mapLimit(changedList, conc, async (file2) => {
@@ -56786,7 +56953,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56786
56953
  writeModulesToCache(projectRoot, pendingIncrementalCacheWrites, opts);
56787
56954
  }
56788
56955
  if (timings)
56789
- timings.parseMs = Math.round(performance5.now() - parseStart);
56956
+ timings.parseMs = Math.round(performance6.now() - parseStart);
56790
56957
  }
56791
56958
  for (const jsonPath of jsonDependencies.values()) {
56792
56959
  ensureJsonModule(modules, jsonPath);
@@ -56816,7 +56983,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56816
56983
  }
56817
56984
  }
56818
56985
  const filesList = Array.from(changedFiles);
56819
- const graphStart = performance5.now();
56986
+ const graphStart = performance6.now();
56820
56987
  const graph = !filesList.length && baseGraph ? { nodes: new Set(baseGraph.nodes), edges: [...baseGraph.edges] } : await collectGraph(projectRoot, filesList, {
56821
56988
  parsed: parsedMap,
56822
56989
  fast: !!graphOptions.fast,
@@ -56842,7 +57009,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56842
57009
  }
56843
57010
  });
56844
57011
  if (timings)
56845
- timings.graphMs = Math.round(performance5.now() - graphStart);
57012
+ timings.graphMs = Math.round(performance6.now() - graphStart);
56846
57013
  for (const file2 of /* @__PURE__ */ new Set([...changedFiles, ...transientFiles])) {
56847
57014
  const signature = fileSignatures.get(file2);
56848
57015
  if (!signature || manifestEntries.has(file2))
@@ -56902,7 +57069,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56902
57069
  });
56903
57070
  await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
56904
57071
  if (updateStartedAt !== void 0) {
56905
- emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance5.now() - updateStartedAt);
57072
+ emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance6.now() - updateStartedAt);
56906
57073
  } else {
56907
57074
  completeCheckProgress(allFiles.size);
56908
57075
  }
@@ -57048,6 +57215,7 @@ async function buildGraphDelta(projectRoot, opts) {
57048
57215
  removed: removedRelative.sort(compareEdges)
57049
57216
  };
57050
57217
  }
57218
+ var DISCOVERY_TIMING_STEP_NAMES;
57051
57219
  var init_build_index = __esm({
57052
57220
  "dist/indexer/build-index.js"() {
57053
57221
  "use strict";
@@ -57087,6 +57255,7 @@ var init_build_index = __esm({
57087
57255
  init_build_workers();
57088
57256
  init_incremental_plan();
57089
57257
  init_parsed_cache();
57258
+ DISCOVERY_TIMING_STEP_NAMES = /* @__PURE__ */ new Set(["git-list", "git-ignore", "filesystem-scan"]);
57090
57259
  }
57091
57260
  });
57092
57261
 
@@ -67720,7 +67889,7 @@ var init_deleted = __esm({
67720
67889
  });
67721
67890
 
67722
67891
  // dist/review/candidates.js
67723
- import { performance as performance6 } from "node:perf_hooks";
67892
+ import { performance as performance7 } from "node:perf_hooks";
67724
67893
  function relativePath(root, file2) {
67725
67894
  return toProjectDisplayPath(root, file2);
67726
67895
  }
@@ -67753,7 +67922,7 @@ function mergeCandidateTestEntries(baseCandidates, additionalCandidates) {
67753
67922
  return Array.from(merged.values());
67754
67923
  }
67755
67924
  async function collectReviewCandidateTests(input) {
67756
- const candidateStart = performance6.now();
67925
+ const candidateStart = performance7.now();
67757
67926
  const configuredMaxCandidates = input.appliedOptions.maxCandidates;
67758
67927
  const maxCandidates = typeof configuredMaxCandidates === "number" && Number.isFinite(configuredMaxCandidates) ? Math.max(0, Math.floor(configuredMaxCandidates)) : REVIEW_DEFAULT_CANDIDATE_TEST_LIMIT;
67759
67928
  const candidateTests = mergeCandidateTestEntries(listCandidateTestFiles(input.index, input.changedFileList, input.changedSymbolIds, {
@@ -67773,7 +67942,7 @@ async function collectReviewCandidateTests(input) {
67773
67942
  return left.reason.localeCompare(right.reason);
67774
67943
  }).slice(0, maxCandidates);
67775
67944
  if (input.reviewTimings) {
67776
- input.reviewTimings.candidatesMs = Math.round(performance6.now() - candidateStart);
67945
+ input.reviewTimings.candidatesMs = Math.round(performance7.now() - candidateStart);
67777
67946
  }
67778
67947
  return candidateTests;
67779
67948
  }
@@ -68069,7 +68238,7 @@ var init_parse4 = __esm({
68069
68238
  });
68070
68239
 
68071
68240
  // dist/review/changes.js
68072
- import { performance as performance7 } from "node:perf_hooks";
68241
+ import { performance as performance8 } from "node:perf_hooks";
68073
68242
  function deletedPathsForChange(change2) {
68074
68243
  if (change2.kind === "deleted") {
68075
68244
  return [change2.path];
@@ -68087,16 +68256,16 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68087
68256
  const isIncludedReviewFile = createImpactIncludeMatcher(discoveryGlobRoot, appliedOptions.discovery?.includeGlobs ?? []);
68088
68257
  const changedFiles = /* @__PURE__ */ new Set();
68089
68258
  const explicitFiles = /* @__PURE__ */ new Set();
68090
- const changesStart = performance7.now();
68259
+ const changesStart = performance8.now();
68091
68260
  for (const file2 of appliedOptions.files ?? []) {
68092
68261
  const normalized = normalizeFile(file2, "Review file");
68093
68262
  changedFiles.add(normalized);
68094
68263
  explicitFiles.add(normalized);
68095
68264
  }
68096
68265
  if (reviewTimings) {
68097
- reviewTimings.changesMs = Math.round(performance7.now() - changesStart);
68266
+ reviewTimings.changesMs = Math.round(performance8.now() - changesStart);
68098
68267
  }
68099
- const diffStart = performance7.now();
68268
+ const diffStart = performance8.now();
68100
68269
  const shouldLoadGitDiff = Boolean(appliedOptions.gitBase || appliedOptions.changedSince);
68101
68270
  const diffText = appliedOptions.diffText ?? (shouldLoadGitDiff ? await getUnifiedDiff(projectRoot, {
68102
68271
  base: appliedOptions.gitBase,
@@ -68105,7 +68274,7 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68105
68274
  }) : "");
68106
68275
  const diff = diffText ? parseUnifiedDiff(diffText) : null;
68107
68276
  if (reviewTimings) {
68108
- reviewTimings.diffMs = Math.round(performance7.now() - diffStart);
68277
+ reviewTimings.diffMs = Math.round(performance8.now() - diffStart);
68109
68278
  }
68110
68279
  const diffHunksByFile = /* @__PURE__ */ new Map();
68111
68280
  const diffKindsByFile = /* @__PURE__ */ new Map();
@@ -69479,10 +69648,10 @@ var init_severity = __esm({
69479
69648
  });
69480
69649
 
69481
69650
  // dist/impact/budgets.js
69482
- import { performance as performance8 } from "node:perf_hooks";
69651
+ import { performance as performance9 } from "node:perf_hooks";
69483
69652
  function createImpactWorkBudget(options) {
69484
69653
  return {
69485
- ...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 } : {},
69486
69655
  ...typeof options.maxReferenceLookups === "number" && options.maxReferenceLookups >= 0 ? { maxReferenceLookups: options.maxReferenceLookups } : {},
69487
69656
  ...typeof options.maxTotalReferences === "number" && options.maxTotalReferences >= 0 ? { maxTotalReferences: options.maxTotalReferences } : {},
69488
69657
  referenceLookupsStarted: 0,
@@ -69497,7 +69666,7 @@ function isImpactDeadlineExceeded(budget) {
69497
69666
  return true;
69498
69667
  if (budget.deadlineAt === void 0)
69499
69668
  return false;
69500
- if (performance8.now() >= budget.deadlineAt) {
69669
+ if (performance9.now() >= budget.deadlineAt) {
69501
69670
  budget.deadlineExceeded = true;
69502
69671
  return true;
69503
69672
  }
@@ -71551,7 +71720,7 @@ var init_referenceCache = __esm({
71551
71720
  // dist/review/summaries.js
71552
71721
  import fsp37 from "node:fs/promises";
71553
71722
  import path70 from "node:path";
71554
- import { performance as performance9 } from "node:perf_hooks";
71723
+ import { performance as performance10 } from "node:perf_hooks";
71555
71724
  function relativePath2(root, file2) {
71556
71725
  return toProjectDisplayPath(root, file2);
71557
71726
  }
@@ -71917,7 +72086,7 @@ async function summarizeChangedFiles2(input) {
71917
72086
  }
71918
72087
  }
71919
72088
  const defsToResolve = fileEntries.flatMap((entry) => entry.locals);
71920
- const referencesStart = performance9.now();
72089
+ const referencesStart = performance10.now();
71921
72090
  const referenceResults = includeSymbolDetails && maxCallsites > 0 ? await mapLimit(defsToResolve, referenceConcurrency, async (def) => {
71922
72091
  const refs = await referenceCache.get(index, def, {
71923
72092
  maxReferences: maxCallsites + 1
@@ -71925,7 +72094,7 @@ async function summarizeChangedFiles2(input) {
71925
72094
  return { def, refs };
71926
72095
  }) : [];
71927
72096
  if (reviewTimings) {
71928
- reviewTimings.referencesMs = Math.round(performance9.now() - referencesStart);
72097
+ reviewTimings.referencesMs = Math.round(performance10.now() - referencesStart);
71929
72098
  }
71930
72099
  const referencesByHandle = /* @__PURE__ */ new Map();
71931
72100
  for (const entry of referenceResults) {
@@ -72105,7 +72274,7 @@ var init_summaries = __esm({
72105
72274
  });
72106
72275
 
72107
72276
  // dist/review.js
72108
- import { performance as performance10 } from "node:perf_hooks";
72277
+ import { performance as performance11 } from "node:perf_hooks";
72109
72278
  function mergeGraphOptions2(base, override) {
72110
72279
  if (!base)
72111
72280
  return override;
@@ -72149,7 +72318,7 @@ async function buildReviewIndex(input) {
72149
72318
  diffChangesByFile,
72150
72319
  graphOptions
72151
72320
  });
72152
- const indexStart = performance10.now();
72321
+ const indexStart = performance11.now();
72153
72322
  const indexReport = reviewReport?.indexReport ?? (reviewReport ? { timings: {} } : void 0);
72154
72323
  if (reviewReport && !reviewReport.indexReport && indexReport) {
72155
72324
  reviewReport.indexReport = indexReport;
@@ -72182,7 +72351,7 @@ async function buildReviewIndex(input) {
72182
72351
  });
72183
72352
  }
72184
72353
  if (reviewTimings) {
72185
- reviewTimings.indexMs = Math.round(performance10.now() - indexStart);
72354
+ reviewTimings.indexMs = Math.round(performance11.now() - indexStart);
72186
72355
  }
72187
72356
  return {
72188
72357
  index,
@@ -72201,7 +72370,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72201
72370
  if (reviewReport && appliedOptions.duplicateTasks === false) {
72202
72371
  delete reviewReport.duplicateAnalysis;
72203
72372
  }
72204
- const totalStart = performance10.now();
72373
+ const totalStart = performance11.now();
72205
72374
  const { changedFiles, explicitFiles, diffHunksByFile, diffKindsByFile, diffChangesByFile } = await collectReviewChanges(projectRoot, appliedOptions, reviewTimings);
72206
72375
  if (changedFiles.size === 0) {
72207
72376
  const riskSummary = computeRiskSummary({
@@ -72235,7 +72404,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72235
72404
  report2.base = appliedOptions.gitBase;
72236
72405
  report2.head = appliedOptions.gitHead ?? "HEAD";
72237
72406
  if (reviewTimings)
72238
- reviewTimings.totalMs = Math.round(performance10.now() - totalStart);
72407
+ reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72239
72408
  return report2;
72240
72409
  }
72241
72410
  const changedFileList = Array.from(changedFiles).sort(comparePaths2);
@@ -72313,7 +72482,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72313
72482
  riskRelevantParseFailures,
72314
72483
  exportedChangedCount
72315
72484
  });
72316
- const duplicateAnalysisStart = performance10.now();
72485
+ const duplicateAnalysisStart = performance11.now();
72317
72486
  if (appliedOptions.duplicateTasks !== false) {
72318
72487
  const duplicateReview = await collectReviewDuplicateTasks({
72319
72488
  projectRoot,
@@ -72334,10 +72503,10 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72334
72503
  }
72335
72504
  }
72336
72505
  if (reviewTimings && appliedOptions.duplicateTasks !== false) {
72337
- reviewTimings.duplicateAnalysisMs = Math.round(performance10.now() - duplicateAnalysisStart);
72506
+ reviewTimings.duplicateAnalysisMs = Math.round(performance11.now() - duplicateAnalysisStart);
72338
72507
  }
72339
72508
  if (reviewTimings)
72340
- reviewTimings.totalMs = Math.round(performance10.now() - totalStart);
72509
+ reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72341
72510
  return report;
72342
72511
  }
72343
72512
  function buildSymbolDefLookup(index) {
@@ -78423,7 +78592,7 @@ var search_exports = {};
78423
78592
  __export(search_exports, {
78424
78593
  handleSearchCommand: () => handleSearchCommand
78425
78594
  });
78426
- import { performance as performance11 } from "node:perf_hooks";
78595
+ import { performance as performance12 } from "node:perf_hooks";
78427
78596
  function parseAgentSearchMode(rawValue) {
78428
78597
  if (rawValue === void 0)
78429
78598
  return "hybrid";
@@ -78433,7 +78602,7 @@ function parseAgentSearchMode(rawValue) {
78433
78602
  throw new Error(`Invalid --mode value "${rawValue}". Expected hybrid, symbol, path, text, graph, or sql.`);
78434
78603
  }
78435
78604
  async function handleSearchCommand(context) {
78436
- const commandStart = performance11.now();
78605
+ const commandStart = performance12.now();
78437
78606
  const query = context.positionals.join(" ").trim();
78438
78607
  if (!query) {
78439
78608
  context.writeStderrLine(SEARCH_HELP_TEXT.trimEnd());
@@ -78457,7 +78626,7 @@ async function handleSearchCommand(context) {
78457
78626
  context.writeStdoutLine(formatAgentSearchResponse(response));
78458
78627
  }
78459
78628
  if (context.commandReport && context.writeCommandReport) {
78460
- context.commandReport.timings.commandMs = Math.round(performance11.now() - commandStart);
78629
+ context.commandReport.timings.commandMs = Math.round(performance12.now() - commandStart);
78461
78630
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
78462
78631
  await context.writeCommandReport(context.commandReport, context.reportFile);
78463
78632
  }
@@ -107438,7 +107607,7 @@ __export(graph_exports, {
107438
107607
  import fs42 from "node:fs";
107439
107608
  import fsp40 from "node:fs/promises";
107440
107609
  import path88 from "node:path";
107441
- import { performance as performance12 } from "node:perf_hooks";
107610
+ import { performance as performance13 } from "node:perf_hooks";
107442
107611
  function resolveGraphCacheMode(cache) {
107443
107612
  return cache ?? "disk";
107444
107613
  }
@@ -107578,11 +107747,11 @@ function stabilizeSymbolGraph(graph) {
107578
107747
  }
107579
107748
  async function handleGraphCommand(context) {
107580
107749
  const commandReport = context.reportEnabled ? { command: "graph", timings: {} } : void 0;
107581
- const commandStart = performance12.now();
107582
- const resolveStart = performance12.now();
107750
+ const commandStart = performance13.now();
107751
+ const resolveStart = performance13.now();
107583
107752
  const files = await context.resolveFiles();
107584
107753
  if (commandReport) {
107585
- commandReport.timings.resolveFilesMs = Math.round(performance12.now() - resolveStart);
107754
+ commandReport.timings.resolveFilesMs = Math.round(performance13.now() - resolveStart);
107586
107755
  }
107587
107756
  const hasExplicitSymbolFlag = context.hasFlag("--symbols") || context.hasFlag("--symbols-only") || context.hasFlag("--symbols-detailed");
107588
107757
  const outputArg = context.getOpt("--output") ?? context.getOpt("--out");
@@ -107624,7 +107793,7 @@ async function handleGraphCommand(context) {
107624
107793
  const finalizeReport = async () => {
107625
107794
  if (!commandReport)
107626
107795
  return;
107627
- commandReport.timings.commandMs = Math.round(performance12.now() - commandStart);
107796
+ commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
107628
107797
  commandReport.timings.totalMs = commandReport.timings.commandMs;
107629
107798
  await context.writeCommandReport(commandReport, context.reportFile);
107630
107799
  };
@@ -107844,7 +108013,7 @@ var cli_exports = {};
107844
108013
  __export(cli_exports, {
107845
108014
  handleIndexCommand: () => handleIndexCommand
107846
108015
  });
107847
- import { performance as performance13 } from "node:perf_hooks";
108016
+ import { performance as performance14 } from "node:perf_hooks";
107848
108017
  function formatIndexOutput(output) {
107849
108018
  const lines = [`Indexed ${output.files} file(s) with ${output.edges} edge(s).`];
107850
108019
  if (output.analysis.mode !== "semantic") {
@@ -107862,11 +108031,11 @@ function formatIndexOutput(output) {
107862
108031
  async function handleIndexCommand(context) {
107863
108032
  const verbose = context.hasFlag("--verbose");
107864
108033
  const commandReport = context.reportEnabled ? { command: "index", timings: {} } : void 0;
107865
- const commandStart = performance13.now();
107866
- const resolveStart = performance13.now();
108034
+ const commandStart = performance14.now();
108035
+ const resolveStart = performance14.now();
107867
108036
  const files = await context.resolveFiles();
107868
108037
  if (commandReport) {
107869
- commandReport.timings.resolveFilesMs = Math.round(performance13.now() - resolveStart);
108038
+ commandReport.timings.resolveFilesMs = Math.round(performance14.now() - resolveStart);
107870
108039
  }
107871
108040
  const threads = parseNonNegativeIntegerOption(context.getOpt("--threads"), "--threads", 0);
107872
108041
  const cache = parseCacheModeOption(context.getOpt("--cache"));
@@ -107932,7 +108101,7 @@ async function handleIndexCommand(context) {
107932
108101
  }
107933
108102
  }
107934
108103
  if (commandReport) {
107935
- commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
108104
+ commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
107936
108105
  commandReport.timings.totalMs = commandReport.timings.commandMs;
107937
108106
  await context.writeCommandReport(commandReport, context.reportFile);
107938
108107
  }
@@ -110925,7 +111094,7 @@ var review_exports = {};
110925
111094
  __export(review_exports, {
110926
111095
  handleReviewCommand: () => handleReviewCommand
110927
111096
  });
110928
- import { performance as performance14 } from "node:perf_hooks";
111097
+ import { performance as performance15 } from "node:perf_hooks";
110929
111098
  import path92 from "node:path";
110930
111099
  function parseReviewDepth(value) {
110931
111100
  if (value === "minimal" || value === "standard" || value === "deep") {
@@ -111117,7 +111286,7 @@ async function collectReviewDuplicateSummary(input) {
111117
111286
  });
111118
111287
  }
111119
111288
  async function handleReviewCommand(context) {
111120
- const commandStart = performance14.now();
111289
+ const commandStart = performance15.now();
111121
111290
  const changedSince = context.getOpt("--changed-since");
111122
111291
  const base = context.getOpt("--base") ?? (changedSince === void 0 ? "HEAD" : void 0);
111123
111292
  const head = context.getOpt("--head") ?? (changedSince === void 0 ? "WORKTREE" : void 0);
@@ -111212,7 +111381,7 @@ async function handleReviewCommand(context) {
111212
111381
  context.writeJSONLine(report);
111213
111382
  }
111214
111383
  if (context.commandReport) {
111215
- context.commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
111384
+ context.commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
111216
111385
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
111217
111386
  await context.writeCommandReport(context.commandReport, context.reportFile);
111218
111387
  }
@@ -111501,7 +111670,7 @@ __export(inspect_exports, {
111501
111670
  handleHotspotsCommand: () => handleHotspotsCommand,
111502
111671
  handleInspectCommand: () => handleInspectCommand
111503
111672
  });
111504
- import { performance as performance15 } from "node:perf_hooks";
111673
+ import { performance as performance16 } from "node:perf_hooks";
111505
111674
  import fs44 from "node:fs";
111506
111675
  import path93 from "node:path";
111507
111676
  function defaultCacheIndexPath(projectRoot, cacheDir, cacheLocation) {
@@ -111763,18 +111932,18 @@ async function buildInspectReport(projectRoot, includeRoots, files, discovery, g
111763
111932
  };
111764
111933
  }
111765
111934
  async function handleInspectCommand(context) {
111766
- const commandStart = performance15.now();
111935
+ const commandStart = performance16.now();
111767
111936
  const cache = parseCacheModeOption(context.getOpt("--cache"));
111768
111937
  const limit = parsePositiveIntegerOption(context.getOpt("--limit"), "--limit", 20);
111769
- const resolveStart = performance15.now();
111938
+ const resolveStart = performance16.now();
111770
111939
  const files = await context.resolveFilesFromRoots();
111771
111940
  if (context.commandReport) {
111772
- context.commandReport.timings.resolveFilesMs = Math.round(performance15.now() - resolveStart);
111941
+ context.commandReport.timings.resolveFilesMs = Math.round(performance16.now() - resolveStart);
111773
111942
  }
111774
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);
111775
111944
  writeCliOutput(context, report, formatInspectReport);
111776
111945
  if (context.commandReport && context.writeCommandReport) {
111777
- context.commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
111946
+ context.commandReport.timings.commandMs = Math.round(performance16.now() - commandStart);
111778
111947
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
111779
111948
  await context.writeCommandReport(context.commandReport, context.reportFile);
111780
111949
  }