@lzehrung/codegraph 2.3.3 → 2.3.4

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.
@@ -45,7 +45,7 @@ Use `--root` to define the boundary for config lookup, path confinement, and out
45
45
  - `languages.extensions` maps literal suffixes such as `.tpl` to supported language IDs; longest suffix wins, while `.vue` and `.svelte` cannot be remapped.
46
46
  - CLI `--include-glob` and `--ignore-glob` values are one-off filters relative to each active scan root.
47
47
  - Use `--no-gitignore` only when ignored files are intentionally in scope.
48
- - Index-backed commands stay quiet for their first second, then write progress and a heartbeat to stderr. Use `--progress` for immediate logs or `--no-progress` to suppress feedback; JSON stdout remains unchanged.
48
+ - Index-backed commands stay quiet for their first second, then write progress and a heartbeat to stderr. Cold or incompatible rebuilds report source and metadata discovery before build progress; path checks include completed and total counts when known. Use `--progress` for immediate logs or `--no-progress` to suppress feedback; JSON stdout remains unchanged.
49
49
 
50
50
  ## Choose the Smallest Follow-up
51
51
 
package/dist/bin/cli.js CHANGED
@@ -1179,6 +1179,7 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1179
1179
  let current = 0;
1180
1180
  let total = 0;
1181
1181
  let mode = "build";
1182
+ let activity = progressAction(mode);
1182
1183
  let interval;
1183
1184
  let delay;
1184
1185
  const clear = () => {
@@ -1190,11 +1191,10 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1190
1191
  const render = () => {
1191
1192
  if (!active)
1192
1193
  return;
1193
- const action = progressAction(mode);
1194
1194
  const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
1195
1195
  frameIndex += 1;
1196
- const count = formatProgressCount(current, total);
1197
- write(`${CLEAR_LINE}${action} project index... ${frame}${count}`);
1196
+ const count = hasProgressCount(mode, current, total) ? formatProgressCount(current, total) : "";
1197
+ write(`${CLEAR_LINE}${activity}... ${frame}${count}`);
1198
1198
  rendered = true;
1199
1199
  };
1200
1200
  const stopInterval = () => {
@@ -1216,6 +1216,7 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1216
1216
  current = update.current;
1217
1217
  total = update.total;
1218
1218
  mode = update.mode ?? "build";
1219
+ activity = update.activity ?? `${progressAction(mode)} project index`;
1219
1220
  const beginRendering = () => {
1220
1221
  if (!active)
1221
1222
  return;
@@ -1262,6 +1263,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1262
1263
  current = update.current;
1263
1264
  total = update.total;
1264
1265
  mode = update.mode ?? mode;
1266
+ if (update.activity !== void 0)
1267
+ activity = update.activity;
1265
1268
  },
1266
1269
  clear,
1267
1270
  dispose: () => {
@@ -1281,12 +1284,16 @@ function formatProgressCount(current, total) {
1281
1284
  return ` ${current}/${formatFileCount(total)}`;
1282
1285
  return ` ${formatFileCount(current)} processed`;
1283
1286
  }
1287
+ function hasProgressCount(mode, current, total) {
1288
+ return mode !== "check" || current > 0 || total > 0;
1289
+ }
1284
1290
  function createLogProgressDisplay(write, delayMs = 0) {
1285
1291
  let active = false;
1286
1292
  let rendered = false;
1287
1293
  let current = 0;
1288
1294
  let total = 0;
1289
1295
  let mode = "build";
1296
+ let activity = progressAction(mode);
1290
1297
  let delay;
1291
1298
  let heartbeat;
1292
1299
  const stopTimers = () => {
@@ -1303,12 +1310,13 @@ function createLogProgressDisplay(write, delayMs = 0) {
1303
1310
  if (!active || rendered)
1304
1311
  return;
1305
1312
  rendered = true;
1306
- write(`[Progress] ${progressAction(mode)} project index.
1313
+ write(`[Progress] ${activity}.
1307
1314
  `);
1308
1315
  heartbeat = setInterval(() => {
1309
1316
  if (!active)
1310
1317
  return;
1311
- write(`[Progress] ${progressAction(mode)} project index:${formatProgressCount(current, total)}.
1318
+ const count = hasProgressCount(mode, current, total) ? `:${formatProgressCount(current, total)}` : "";
1319
+ write(`[Progress] ${activity}${count}.
1312
1320
  `);
1313
1321
  }, 1e3);
1314
1322
  heartbeat.unref();
@@ -1320,6 +1328,7 @@ function createLogProgressDisplay(write, delayMs = 0) {
1320
1328
  current = update.current;
1321
1329
  total = update.total;
1322
1330
  mode = update.mode ?? "build";
1331
+ activity = update.activity ?? `${progressAction(mode)} project index`;
1323
1332
  if (delayMs) {
1324
1333
  delay = setTimeout(renderStart, delayMs);
1325
1334
  delay.unref();
@@ -1351,13 +1360,25 @@ function createLogProgressDisplay(write, delayMs = 0) {
1351
1360
  return;
1352
1361
  start(update);
1353
1362
  }
1363
+ const previousActivity = activity;
1354
1364
  current = update.current;
1355
1365
  total = update.total;
1356
1366
  mode = update.mode ?? mode;
1367
+ if (update.activity !== void 0)
1368
+ activity = update.activity;
1369
+ if (rendered && activity !== previousActivity) {
1370
+ write(`[Progress] ${activity}.
1371
+ `);
1372
+ }
1357
1373
  const isComplete = update.total > 0 && update.current >= update.total;
1358
- if (rendered && (update.current === 1 || isComplete || update.current % 100 === 0)) {
1359
- write(`[Progress] ${formatFileCount(update.current)} processed.
1374
+ if (rendered && (update.current === 1 || isComplete || update.current > 0 && update.current % 100 === 0)) {
1375
+ if (update.activity !== void 0) {
1376
+ write(`[Progress] ${activity}:${formatProgressCount(update.current, update.total)}.
1360
1377
  `);
1378
+ } else {
1379
+ write(`[Progress] ${formatFileCount(update.current)} processed.
1380
+ `);
1381
+ }
1361
1382
  }
1362
1383
  },
1363
1384
  clear: () => {
@@ -14125,6 +14146,15 @@ __export(projectFiles_exports, {
14125
14146
  import fs6 from "node:fs";
14126
14147
  import fsp5 from "node:fs/promises";
14127
14148
  import path9 from "node:path";
14149
+ function createPathCheckProgressReporter(total, onProgress) {
14150
+ onProgress?.(0, total);
14151
+ let completed = 0;
14152
+ return () => {
14153
+ completed += 1;
14154
+ if (completed === total || completed % 100 === 0)
14155
+ onProgress?.(completed, total);
14156
+ };
14157
+ }
14128
14158
  function isPresent(value) {
14129
14159
  return value !== void 0;
14130
14160
  }
@@ -14476,11 +14506,14 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14476
14506
  followSymbolicLinks: false,
14477
14507
  ignore: translatedUserIgnoreGlobs
14478
14508
  }) : [];
14509
+ const reportSourceSymlinkChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking source symlinks", current, total }) : void 0;
14510
+ const reportSourcePathChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking source file paths", current, total }) : void 0;
14479
14511
  const symlinkOptions = {
14480
14512
  globRoot,
14481
14513
  ...gitCandidates ? { candidatePaths: gitCandidates.files } : {},
14482
14514
  ...options?.knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: options.knownSymlinkDirectories } : {},
14483
- ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {}
14515
+ ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {},
14516
+ ...reportSourceSymlinkChecks ? { onPathCheckProgress: reportSourceSymlinkChecks } : {}
14484
14517
  };
14485
14518
  const safeSymlinkDirectories = await resolveSafeSymlinkDirectories(root, realRoot, symlinkProbeIgnoreGlobs, symlinkOptions);
14486
14519
  const linkedFiles = await listEntriesFromSafeSymlinkDirectories(root, realRoot, patterns, fastGlobIgnoreGlobs, {
@@ -14493,7 +14526,7 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14493
14526
  filterIgnoreGlobs: userIgnoreGlobs,
14494
14527
  resolvedSafeSymlinkDirectories: safeSymlinkDirectories
14495
14528
  });
14496
- const rootSafeFiles = await filterRealPathsWithinRootEntries([...files, ...includedOverrideFiles, ...linkedFiles, ...linkedOverrideFiles], realRoot);
14529
+ const rootSafeFiles = await filterRealPathsWithinRootEntries([...files, ...includedOverrideFiles, ...linkedFiles, ...linkedOverrideFiles], realRoot, reportSourcePathChecks);
14497
14530
  const seen = /* @__PURE__ */ new Set();
14498
14531
  return rootSafeFiles.map(({ path: filePath, realPath }) => ({ filePath: normalizePath(filePath), realPath })).filter(({ filePath, realPath }) => {
14499
14532
  if (seen.has(filePath))
@@ -14561,10 +14594,20 @@ async function isSafeSymlinkDirectory(root, linkPath, realRoot) {
14561
14594
  return false;
14562
14595
  }
14563
14596
  }
14597
+ async function verifySafeSymlinkDirectories(root, realRoot, paths, onPathCheckProgress) {
14598
+ const reportPathCheck = createPathCheckProgressReporter(paths.length, onPathCheckProgress);
14599
+ const verified = await mapLimitSemaphore(Array.from(paths), REALPATH_FILTER_CONCURRENCY, async (linkPath) => {
14600
+ try {
14601
+ return await isSafeSymlinkDirectory(root, linkPath, realRoot) ? linkPath : null;
14602
+ } finally {
14603
+ reportPathCheck();
14604
+ }
14605
+ });
14606
+ return verified.filter((entry) => entry !== null);
14607
+ }
14564
14608
  async function resolveSafeSymlinkDirectories(root, realRoot, ignore, options) {
14565
14609
  if (options.knownSymlinkDirectories !== void 0) {
14566
- const verified = await mapLimitSemaphore(Array.from(new Set(options.knownSymlinkDirectories)), REALPATH_FILTER_CONCURRENCY, async (linkPath) => await isSafeSymlinkDirectory(root, linkPath, realRoot) ? linkPath : null);
14567
- const resolved = verified.filter((entry) => entry !== null);
14610
+ const resolved = await verifySafeSymlinkDirectories(root, realRoot, Array.from(new Set(options.knownSymlinkDirectories)), options.onPathCheckProgress);
14568
14611
  options.onSymlinkDirectoriesDiscovered?.(resolved, "known");
14569
14612
  return resolved;
14570
14613
  }
@@ -14576,8 +14619,7 @@ async function resolveSafeSymlinkDirectories(root, realRoot, ignore, options) {
14576
14619
  return false;
14577
14620
  return !ignoreMatchers.some((matcher) => matcher(relativePath3));
14578
14621
  });
14579
- const verified = await mapLimitSemaphore(candidatePaths, REALPATH_FILTER_CONCURRENCY, async (linkPath) => await isSafeSymlinkDirectory(root, linkPath, realRoot) ? linkPath : null);
14580
- const discovered2 = verified.filter((entry) => entry !== null);
14622
+ const discovered2 = await verifySafeSymlinkDirectories(root, realRoot, candidatePaths, options.onPathCheckProgress);
14581
14623
  options.onSymlinkDirectoriesDiscovered?.(discovered2, "git-candidates");
14582
14624
  return discovered2;
14583
14625
  }
@@ -14590,8 +14632,7 @@ async function resolveSafeSymlinkDirectories(root, realRoot, ignore, options) {
14590
14632
  objectMode: true,
14591
14633
  ignore
14592
14634
  });
14593
- const candidates = await mapLimitSemaphore(entries.filter((entry) => entry.dirent.isSymbolicLink()).map((entry) => entry.path), REALPATH_FILTER_CONCURRENCY, async (linkPath) => await isSafeSymlinkDirectory(root, linkPath, realRoot) ? linkPath : null);
14594
- const discovered = candidates.filter((entry) => entry !== null);
14635
+ const discovered = await verifySafeSymlinkDirectories(root, realRoot, entries.filter((entry) => entry.dirent.isSymbolicLink()).map((entry) => entry.path), options.onPathCheckProgress);
14595
14636
  options.onSymlinkDirectoriesDiscovered?.(discovered, "filesystem");
14596
14637
  return discovered;
14597
14638
  }
@@ -14623,19 +14664,22 @@ async function listEntriesFromSafeSymlinkDirectories(root, realRoot, patterns, i
14623
14664
  }
14624
14665
  return [...filesByPath.values()];
14625
14666
  }
14626
- async function filterRealPathsWithinRootEntries(paths, realRoot) {
14667
+ async function filterRealPathsWithinRootEntries(paths, realRoot, onPathCheckProgress) {
14668
+ const reportPathCheck = createPathCheckProgressReporter(paths.length, onPathCheckProgress);
14627
14669
  const filtered = await mapLimitSemaphore(paths, REALPATH_FILTER_CONCURRENCY, async (filePath) => {
14628
14670
  try {
14629
14671
  const realPath = await fsp5.realpath(filePath);
14630
14672
  return isFilePathWithinRoot(realRoot, realPath) ? { path: filePath, realPath } : null;
14631
14673
  } catch {
14632
14674
  return null;
14675
+ } finally {
14676
+ reportPathCheck();
14633
14677
  }
14634
14678
  });
14635
14679
  return filtered.filter((entry) => entry !== null);
14636
14680
  }
14637
- async function filterRealPathsWithinRoot(paths, realRoot) {
14638
- const entries = await filterRealPathsWithinRootEntries(paths, realRoot);
14681
+ async function filterRealPathsWithinRoot(paths, realRoot, onPathCheckProgress) {
14682
+ const entries = await filterRealPathsWithinRootEntries(paths, realRoot, onPathCheckProgress);
14639
14683
  return entries.map((entry) => entry.path);
14640
14684
  }
14641
14685
  function toProjectGlob(pattern) {
@@ -14694,6 +14738,9 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14694
14738
  gitCandidates = await listGitCandidateFiles(root, options?.logLevel);
14695
14739
  }
14696
14740
  options?.onGitCandidatesDiscovered?.(gitCandidates);
14741
+ const reportMetadataSymlinkChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking project metadata symlinks", current, total }) : void 0;
14742
+ const reportMetadataFileChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking project metadata files", current, total }) : void 0;
14743
+ const reportMetadataDirectoryChecks = options?.onDiscoveryProgress ? (current, total) => options.onDiscoveryProgress?.({ activity: "Checking project metadata directories", current, total }) : void 0;
14697
14744
  let rootSafeMatches;
14698
14745
  if (gitCandidates) {
14699
14746
  const gitignoreIndex = await buildGitignoreIndex(gitCandidates.gitignoreFiles, gitCandidates.gitignoreRoots, gitCandidates.gitignoreAliases);
@@ -14712,7 +14759,8 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14712
14759
  const symlinkOptions = {
14713
14760
  candidatePaths: gitCandidates.files,
14714
14761
  ...options?.knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: options.knownSymlinkDirectories } : {},
14715
- ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {}
14762
+ ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {},
14763
+ ...reportMetadataSymlinkChecks ? { onPathCheckProgress: reportMetadataSymlinkChecks } : {}
14716
14764
  };
14717
14765
  const safeSymlinkDirectories = await resolveSafeSymlinkDirectories(root, realRoot, DEFAULT_PROJECT_FILE_IGNORES, symlinkOptions);
14718
14766
  const allPatterns = PROJECT_FILE_DEFINITIONS.flatMap((definition) => definition.patterns.map(toProjectGlob));
@@ -14721,18 +14769,18 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14721
14769
  onlyFiles: false,
14722
14770
  resolvedSafeSymlinkDirectories: safeSymlinkDirectories
14723
14771
  });
14724
- const rootSafeCandidateEntries = await filterRealPathsWithinRootEntries(gitCandidates.files, realRoot);
14772
+ const rootSafeCandidateEntries = await filterRealPathsWithinRootEntries(gitCandidates.files, realRoot, reportMetadataFileChecks);
14725
14773
  const filteredFiles = filterGitIgnoredEntries(rootSafeCandidateEntries);
14726
14774
  const fileMatches = filteredFiles.filter((file2) => PROJECT_FILE_DEFINITIONS.some((definition, definitionIndex) => definition.kind === "file" && matchesDefinition(path9.basename(file2), definitionIndex)));
14727
14775
  const rawCandidateDirectories = collectCandidateAncestorDirectories(root, rootSafeCandidateEntries.map(({ path: filePath }) => filePath));
14728
14776
  const candidateDirectoryKeys = new Set(rawCandidateDirectories.map(fileIdentityKey));
14729
14777
  const safeSymlinkDirectoryKeys = new Set(safeSymlinkDirectories.map(fileIdentityKey));
14730
14778
  const directoryMatches = [
14731
- ...filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(rawCandidateDirectories, realRoot), candidateDirectoryKeys),
14732
- ...filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(safeSymlinkDirectories, realRoot), safeSymlinkDirectoryKeys)
14779
+ ...filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(rawCandidateDirectories, realRoot, reportMetadataDirectoryChecks), candidateDirectoryKeys),
14780
+ ...filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(safeSymlinkDirectories, realRoot, reportMetadataDirectoryChecks), safeSymlinkDirectoryKeys)
14733
14781
  ].filter((directory) => PROJECT_FILE_DEFINITIONS.some((definition, definitionIndex) => definition.kind === "dir" && matchesDefinition(path9.basename(directory), definitionIndex)));
14734
14782
  const linkedDirectoryKeys = new Set(linkedMatches.filter((match) => match.endsWith("/")).map((match) => fileIdentityKey(match.slice(0, -1))));
14735
- const rootSafeLinked = filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(linkedMatches.map((match) => match.endsWith("/") ? match.slice(0, -1) : match), realRoot), linkedDirectoryKeys);
14783
+ const rootSafeLinked = filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(linkedMatches.map((match) => match.endsWith("/") ? match.slice(0, -1) : match), realRoot, reportMetadataFileChecks), linkedDirectoryKeys);
14736
14784
  rootSafeMatches = [...fileMatches, ...directoryMatches, ...rootSafeLinked];
14737
14785
  } else {
14738
14786
  const allPatterns = PROJECT_FILE_DEFINITIONS.flatMap((definition) => definition.patterns.map(toProjectGlob));
@@ -14749,9 +14797,10 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14749
14797
  markDirectories: true,
14750
14798
  onlyFiles: false,
14751
14799
  ...options?.knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: options.knownSymlinkDirectories } : {},
14752
- ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {}
14800
+ ...options?.onSymlinkDirectoriesDiscovered ? { onSymlinkDirectoriesDiscovered: options.onSymlinkDirectoriesDiscovered } : {},
14801
+ ...reportMetadataSymlinkChecks ? { onPathCheckProgress: reportMetadataSymlinkChecks } : {}
14753
14802
  });
14754
- rootSafeMatches = await filterRealPathsWithinRoot([...matches, ...linkedMatches].map((match) => match.endsWith("/") ? match.slice(0, -1) : match), realRoot);
14803
+ rootSafeMatches = await filterRealPathsWithinRoot([...matches, ...linkedMatches].map((match) => match.endsWith("/") ? match.slice(0, -1) : match), realRoot, reportMetadataFileChecks);
14755
14804
  }
14756
14805
  const entries = [];
14757
14806
  const matchTasks = rootSafeMatches.map(async (cleanMatch) => {
@@ -55234,6 +55283,17 @@ function emitIndexLifecycleProgress(opts, phase, mode, total, elapsedMs2) {
55234
55283
  ...elapsedMs2 !== void 0 ? { elapsedMs: elapsedMs2 } : {}
55235
55284
  });
55236
55285
  }
55286
+ function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
55287
+ opts?.onProgress?.({
55288
+ type: "progress",
55289
+ phase: "update",
55290
+ mode: "check",
55291
+ message: activity,
55292
+ activity,
55293
+ current,
55294
+ total
55295
+ });
55296
+ }
55237
55297
  function buildConcurrency(opts) {
55238
55298
  return resolveWorkerThreadCount({ requested: Number(opts?.threads || 0), defaultCount: 8, max: 64 });
55239
55299
  }
@@ -55654,12 +55714,16 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
55654
55714
  const onGitCandidatesDiscovered = (candidates) => {
55655
55715
  discoveredGitCandidates = candidates;
55656
55716
  };
55717
+ const onDiscoveryProgress = helperOpts?.reportDiscoveryProgress ? (progress) => emitIndexCheckActivity(opts, progress.activity, progress.current, progress.total) : void 0;
55718
+ if (helperOpts?.reportDiscoveryProgress)
55719
+ emitIndexCheckActivity(opts, "Discovering source files");
55657
55720
  const discoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
55658
55721
  ...opts?.discovery,
55659
55722
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
55660
55723
  ...knownSymlinkDirectories !== void 0 ? { knownSymlinkDirectories } : {},
55661
55724
  onSymlinkDirectoriesDiscovered,
55662
- onGitCandidatesDiscovered
55725
+ onGitCandidatesDiscovered,
55726
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
55663
55727
  });
55664
55728
  const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
55665
55729
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
@@ -55667,10 +55731,13 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
55667
55731
  const discoveredFileSet = new Set(discoveredFiles);
55668
55732
  const files = Array.from(/* @__PURE__ */ new Set([...discoveredFiles, ...additionalFiles]));
55669
55733
  const transientFiles = additionalFiles.filter((file2) => !discoveredFileSet.has(file2));
55734
+ if (helperOpts?.reportDiscoveryProgress)
55735
+ emitIndexCheckActivity(opts, "Discovering project metadata");
55670
55736
  const projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
55671
55737
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
55672
55738
  ...discoveredSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: discoveredSymlinkDirectories } : {},
55673
- ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {}
55739
+ ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {},
55740
+ ...onDiscoveryProgress ? { onDiscoveryProgress } : {}
55674
55741
  });
55675
55742
  return await buildIndexFromFileListShared(projectRoot, files, opts, {
55676
55743
  manifestMode: useDiskCache ? "read-write" : "off",
@@ -55810,7 +55877,10 @@ async function buildProjectIndexIncremental(projectRoot, opts) {
55810
55877
  manifestReport.reason = reason;
55811
55878
  manifestReport.reused = false;
55812
55879
  }
55813
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
55880
+ return await buildProjectIndexFromExport(projectRoot, opts, {
55881
+ ignoreExistingManifest: true,
55882
+ reportDiscoveryProgress: true
55883
+ });
55814
55884
  }
55815
55885
  const gitAvailable = await isGitRepo(projectRoot);
55816
55886
  const hasExplicitGitRange = !!opts?.gitBase || !!opts?.gitHead;
@@ -55831,7 +55901,10 @@ async function buildProjectIndexIncremental(projectRoot, opts) {
55831
55901
  manifestReport.reused = false;
55832
55902
  }
55833
55903
  logWithLevel(opts?.logLevel, "warn", "Warning: Manifest commit is no longer available; rebuilding full index.");
55834
- const rebuiltIndex = await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
55904
+ const rebuiltIndex = await buildProjectIndexFromExport(projectRoot, opts, {
55905
+ ignoreExistingManifest: true,
55906
+ reportDiscoveryProgress: true
55907
+ });
55835
55908
  if (manifestReport) {
55836
55909
  manifestReport.reason = "staleGitCommit";
55837
55910
  manifestReport.reused = false;
@@ -55849,7 +55922,10 @@ async function buildProjectIndexIncremental(projectRoot, opts) {
55849
55922
  }
55850
55923
  if (mismatches > 0 || missing > 0) {
55851
55924
  logWithLevel(opts?.logLevel, "warn", `Warning: Manifest verification failed (mismatches: ${mismatches}, missing: ${missing}). Rebuilding full index.`);
55852
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
55925
+ return await buildProjectIndexFromExport(projectRoot, opts, {
55926
+ ignoreExistingManifest: true,
55927
+ reportDiscoveryProgress: true
55928
+ });
55853
55929
  }
55854
55930
  }
55855
55931
  const trackedEntries = sanitizeManifestEntriesForRoot(projectRoot, manifest.files);
@@ -55874,7 +55950,10 @@ async function buildProjectIndexIncremental(projectRoot, opts) {
55874
55950
  manifestReport.reused = false;
55875
55951
  }
55876
55952
  logWithLevel(opts?.logLevel, "warn", "Warning: Failed to list untracked project files via Git; rebuilding full index.", error51);
55877
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
55953
+ return await buildProjectIndexFromExport(projectRoot, opts, {
55954
+ ignoreExistingManifest: true,
55955
+ reportDiscoveryProgress: true
55956
+ });
55878
55957
  }
55879
55958
  } else if (!opts?.filesAreProjectScope) {
55880
55959
  rediscoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
@@ -21,6 +21,7 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
21
21
  let current = 0;
22
22
  let total = 0;
23
23
  let mode = "build";
24
+ let activity = progressAction(mode);
24
25
  let interval;
25
26
  let delay;
26
27
  const clear = () => {
@@ -32,11 +33,10 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
32
33
  const render = () => {
33
34
  if (!active)
34
35
  return;
35
- const action = progressAction(mode);
36
36
  const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
37
37
  frameIndex += 1;
38
- const count = formatProgressCount(current, total);
39
- write(`${CLEAR_LINE}${action} project index... ${frame}${count}`);
38
+ const count = hasProgressCount(mode, current, total) ? formatProgressCount(current, total) : "";
39
+ write(`${CLEAR_LINE}${activity}... ${frame}${count}`);
40
40
  rendered = true;
41
41
  };
42
42
  const stopInterval = () => {
@@ -58,6 +58,7 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
58
58
  current = update.current;
59
59
  total = update.total;
60
60
  mode = update.mode ?? "build";
61
+ activity = update.activity ?? `${progressAction(mode)} project index`;
61
62
  const beginRendering = () => {
62
63
  if (!active)
63
64
  return;
@@ -104,6 +105,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
104
105
  current = update.current;
105
106
  total = update.total;
106
107
  mode = update.mode ?? mode;
108
+ if (update.activity !== undefined)
109
+ activity = update.activity;
107
110
  },
108
111
  clear,
109
112
  dispose: () => {
@@ -123,12 +126,16 @@ function formatProgressCount(current, total) {
123
126
  return ` ${current}/${formatFileCount(total)}`;
124
127
  return ` ${formatFileCount(current)} processed`;
125
128
  }
129
+ function hasProgressCount(mode, current, total) {
130
+ return mode !== "check" || current > 0 || total > 0;
131
+ }
126
132
  function createLogProgressDisplay(write, delayMs = 0) {
127
133
  let active = false;
128
134
  let rendered = false;
129
135
  let current = 0;
130
136
  let total = 0;
131
137
  let mode = "build";
138
+ let activity = progressAction(mode);
132
139
  let delay;
133
140
  let heartbeat;
134
141
  const stopTimers = () => {
@@ -145,11 +152,12 @@ function createLogProgressDisplay(write, delayMs = 0) {
145
152
  if (!active || rendered)
146
153
  return;
147
154
  rendered = true;
148
- write(`[Progress] ${progressAction(mode)} project index.\n`);
155
+ write(`[Progress] ${activity}.\n`);
149
156
  heartbeat = setInterval(() => {
150
157
  if (!active)
151
158
  return;
152
- write(`[Progress] ${progressAction(mode)} project index:${formatProgressCount(current, total)}.\n`);
159
+ const count = hasProgressCount(mode, current, total) ? `:${formatProgressCount(current, total)}` : "";
160
+ write(`[Progress] ${activity}${count}.\n`);
153
161
  }, 1_000);
154
162
  heartbeat.unref();
155
163
  };
@@ -160,6 +168,7 @@ function createLogProgressDisplay(write, delayMs = 0) {
160
168
  current = update.current;
161
169
  total = update.total;
162
170
  mode = update.mode ?? "build";
171
+ activity = update.activity ?? `${progressAction(mode)} project index`;
163
172
  if (delayMs) {
164
173
  delay = setTimeout(renderStart, delayMs);
165
174
  delay.unref();
@@ -191,12 +200,23 @@ function createLogProgressDisplay(write, delayMs = 0) {
191
200
  return;
192
201
  start(update);
193
202
  }
203
+ const previousActivity = activity;
194
204
  current = update.current;
195
205
  total = update.total;
196
206
  mode = update.mode ?? mode;
207
+ if (update.activity !== undefined)
208
+ activity = update.activity;
209
+ if (rendered && activity !== previousActivity) {
210
+ write(`[Progress] ${activity}.\n`);
211
+ }
197
212
  const isComplete = update.total > 0 && update.current >= update.total;
198
- if (rendered && (update.current === 1 || isComplete || update.current % 100 === 0)) {
199
- write(`[Progress] ${formatFileCount(update.current)} processed.\n`);
213
+ if (rendered && (update.current === 1 || isComplete || (update.current > 0 && update.current % 100 === 0))) {
214
+ if (update.activity !== undefined) {
215
+ write(`[Progress] ${activity}:${formatProgressCount(update.current, update.total)}.\n`);
216
+ }
217
+ else {
218
+ write(`[Progress] ${formatFileCount(update.current)} processed.\n`);
219
+ }
200
220
  }
201
221
  },
202
222
  clear: () => { },
@@ -1 +1 @@
1
- {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/cli/progress.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"progress.js","sourceRoot":"","sources":["../../src/cli/progress.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"build-index.d.ts","sourceRoot":"","sources":["../../src/indexer/build-index.ts"],"names":[],"mappings":"AAuFA,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EAErB,KAAK,uBAAuB,EAI5B,KAAK,YAAY,EAIlB,MAAM,YAAY,CAAC;AA+iCpB;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAEvG;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,YAAY,CAAC,CAgBvB;AA4BD;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,OAAO,CAAC,YAAY,CAAC,CAksBvB;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8IpH"}
1
+ {"version":3,"file":"build-index.d.ts","sourceRoot":"","sources":["../../src/indexer/build-index.ts"],"names":[],"mappings":"AAuFA,OAAO,EACL,KAAK,YAAY,EAEjB,KAAK,gBAAgB,EAErB,KAAK,uBAAuB,EAI5B,KAAK,YAAY,EAIlB,MAAM,YAAY,CAAC;AAykCpB;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAEvG;AAED;;;;;;GAMG;AACH,wBAAsB,0BAA0B,CAC9C,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,EAAE,EACpB,IAAI,CAAC,EAAE,YAAY,GAClB,OAAO,CAAC,YAAY,CAAC,CAgBvB;AA4BD;;;;;;GAMG;AACH,wBAAsB,4BAA4B,CAChD,WAAW,EAAE,MAAM,EACnB,IAAI,CAAC,EAAE,uBAAuB,GAC7B,OAAO,CAAC,YAAY,CAAC,CA8sBvB;AAED,wBAAsB,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,uBAAuB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CA8IpH"}
@@ -392,6 +392,17 @@ function emitIndexLifecycleProgress(opts, phase, mode, total, elapsedMs) {
392
392
  ...(elapsedMs !== undefined ? { elapsedMs } : {}),
393
393
  });
394
394
  }
395
+ function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
396
+ opts?.onProgress?.({
397
+ type: "progress",
398
+ phase: "update",
399
+ mode: "check",
400
+ message: activity,
401
+ activity,
402
+ current,
403
+ total,
404
+ });
405
+ }
395
406
  function buildConcurrency(opts) {
396
407
  return resolveWorkerThreadCount({ requested: Number(opts?.threads || 0), defaultCount: 8, max: 64 });
397
408
  }
@@ -868,16 +879,22 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
868
879
  const onGitCandidatesDiscovered = (candidates) => {
869
880
  discoveredGitCandidates = candidates;
870
881
  };
882
+ const onDiscoveryProgress = helperOpts?.reportDiscoveryProgress
883
+ ? (progress) => emitIndexCheckActivity(opts, progress.activity, progress.current, progress.total)
884
+ : undefined;
871
885
  // When the hint is unknown, listProjectFiles() and discoverProjectFiles() must run
872
886
  // sequentially rather than in Promise.all to avoid duplicate full-tree probes. The Git
873
887
  // candidate callback below reuses that same listing so metadata discovery does not spawn
874
888
  // Git a second time.
889
+ if (helperOpts?.reportDiscoveryProgress)
890
+ emitIndexCheckActivity(opts, "Discovering source files");
875
891
  const discoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
876
892
  ...opts?.discovery,
877
893
  ...(opts?.logLevel ? { logLevel: opts.logLevel } : {}),
878
894
  ...(knownSymlinkDirectories !== undefined ? { knownSymlinkDirectories } : {}),
879
895
  onSymlinkDirectoriesDiscovered,
880
896
  onGitCandidatesDiscovered,
897
+ ...(onDiscoveryProgress ? { onDiscoveryProgress } : {}),
881
898
  });
882
899
  const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
883
900
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
@@ -885,10 +902,13 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
885
902
  const discoveredFileSet = new Set(discoveredFiles);
886
903
  const files = Array.from(new Set([...discoveredFiles, ...additionalFiles]));
887
904
  const transientFiles = additionalFiles.filter((file) => !discoveredFileSet.has(file));
905
+ if (helperOpts?.reportDiscoveryProgress)
906
+ emitIndexCheckActivity(opts, "Discovering project metadata");
888
907
  const projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
889
908
  ...(opts?.logLevel ? { logLevel: opts.logLevel } : {}),
890
909
  ...(discoveredSymlinkDirectories !== undefined ? { knownSymlinkDirectories: discoveredSymlinkDirectories } : {}),
891
910
  ...(discoveredGitCandidates !== undefined ? { knownGitCandidates: discoveredGitCandidates } : {}),
911
+ ...(onDiscoveryProgress ? { onDiscoveryProgress } : {}),
892
912
  });
893
913
  return await buildIndexFromFileListShared(projectRoot, files, opts, {
894
914
  manifestMode: useDiskCache ? "read-write" : "off",
@@ -1073,7 +1093,10 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1073
1093
  manifestReport.reason = reason;
1074
1094
  manifestReport.reused = false;
1075
1095
  }
1076
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
1096
+ return await buildProjectIndexFromExport(projectRoot, opts, {
1097
+ ignoreExistingManifest: true,
1098
+ reportDiscoveryProgress: true,
1099
+ });
1077
1100
  }
1078
1101
  const gitAvailable = await isGitRepo(projectRoot);
1079
1102
  const hasExplicitGitRange = !!opts?.gitBase || !!opts?.gitHead;
@@ -1103,7 +1126,10 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1103
1126
  manifestReport.reused = false;
1104
1127
  }
1105
1128
  logWithLevel(opts?.logLevel, "warn", "Warning: Manifest commit is no longer available; rebuilding full index.");
1106
- const rebuiltIndex = await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
1129
+ const rebuiltIndex = await buildProjectIndexFromExport(projectRoot, opts, {
1130
+ ignoreExistingManifest: true,
1131
+ reportDiscoveryProgress: true,
1132
+ });
1107
1133
  if (manifestReport) {
1108
1134
  manifestReport.reason = "staleGitCommit";
1109
1135
  manifestReport.reused = false;
@@ -1121,7 +1147,10 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1121
1147
  }
1122
1148
  if (mismatches > 0 || missing > 0) {
1123
1149
  logWithLevel(opts?.logLevel, "warn", `Warning: Manifest verification failed (mismatches: ${mismatches}, missing: ${missing}). Rebuilding full index.`);
1124
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
1150
+ return await buildProjectIndexFromExport(projectRoot, opts, {
1151
+ ignoreExistingManifest: true,
1152
+ reportDiscoveryProgress: true,
1153
+ });
1125
1154
  }
1126
1155
  }
1127
1156
  const trackedEntries = sanitizeManifestEntriesForRoot(projectRoot, manifest.files);
@@ -1164,7 +1193,10 @@ export async function buildProjectIndexIncremental(projectRoot, opts) {
1164
1193
  manifestReport.reused = false;
1165
1194
  }
1166
1195
  logWithLevel(opts?.logLevel, "warn", "Warning: Failed to list untracked project files via Git; rebuilding full index.", error);
1167
- return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
1196
+ return await buildProjectIndexFromExport(projectRoot, opts, {
1197
+ ignoreExistingManifest: true,
1198
+ reportDiscoveryProgress: true,
1199
+ });
1168
1200
  }
1169
1201
  }
1170
1202
  else if (!opts?.filesAreProjectScope) {