@lzehrung/codegraph 2.3.14 → 2.3.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/README.md +1 -1
  2. package/codegraph-skill/codegraph/SKILL.md +11 -3
  3. package/dist/agent/query-index/workerPool.d.ts.map +1 -1
  4. package/dist/agent/query-index/workerPool.js +2 -0
  5. package/dist/agent/query-index/workerPool.js.map +1 -1
  6. package/dist/bin/cli.js +381 -174
  7. package/dist/bin/queryIndexWorker.js +30 -0
  8. package/dist/bin/rawQueryWorker.js +34 -0
  9. package/dist/cli/commandTable.d.ts.map +1 -1
  10. package/dist/cli/commandTable.js +14 -1
  11. package/dist/cli/commandTable.js.map +1 -1
  12. package/dist/cli/help.d.ts +4 -4
  13. package/dist/cli/help.d.ts.map +1 -1
  14. package/dist/cli/help.js +8 -7
  15. package/dist/cli/help.js.map +1 -1
  16. package/dist/cli/mcp.js +11 -6
  17. package/dist/cli/mcp.js.map +1 -1
  18. package/dist/cli/options.d.ts.map +1 -1
  19. package/dist/cli/options.js +3 -2
  20. package/dist/cli/options.js.map +1 -1
  21. package/dist/cli/orient.d.ts +6 -2
  22. package/dist/cli/orient.d.ts.map +1 -1
  23. package/dist/cli/orient.js +13 -1
  24. package/dist/cli/orient.js.map +1 -1
  25. package/dist/cli/progress.d.ts.map +1 -1
  26. package/dist/cli/progress.js +21 -7
  27. package/dist/cli/progress.js.map +1 -1
  28. package/dist/cli/server.d.ts.map +1 -1
  29. package/dist/cli/server.js +6 -2
  30. package/dist/cli/server.js.map +1 -1
  31. package/dist/indexer/build-index.d.ts.map +1 -1
  32. package/dist/indexer/build-index.js +148 -28
  33. package/dist/indexer/build-index.js.map +1 -1
  34. package/dist/indexer/types.d.ts +2 -0
  35. package/dist/indexer/types.d.ts.map +1 -1
  36. package/dist/mcp/handlers.d.ts +6 -1
  37. package/dist/mcp/handlers.d.ts.map +1 -1
  38. package/dist/mcp/handlers.js +13 -9
  39. package/dist/mcp/handlers.js.map +1 -1
  40. package/dist/mcp/protocol.d.ts.map +1 -1
  41. package/dist/mcp/protocol.js +1 -1
  42. package/dist/mcp/protocol.js.map +1 -1
  43. package/dist/native/runtime.d.ts.map +1 -1
  44. package/dist/native/runtime.js +2 -0
  45. package/dist/native/runtime.js.map +1 -1
  46. package/dist/sqlite/rawQueryWorkerPool.d.ts.map +1 -1
  47. package/dist/sqlite/rawQueryWorkerPool.js +10 -6
  48. package/dist/sqlite/rawQueryWorkerPool.js.map +1 -1
  49. package/dist/sqlite-driver.d.ts +1 -0
  50. package/dist/sqlite-driver.d.ts.map +1 -1
  51. package/dist/sqlite-driver.js +6 -0
  52. package/dist/sqlite-driver.js.map +1 -1
  53. package/dist/util/projectFiles.d.ts.map +1 -1
  54. package/dist/util/projectFiles.js +10 -1
  55. package/dist/util/projectFiles.js.map +1 -1
  56. package/dist/util/windowsProcessDrain.d.ts +23 -0
  57. package/dist/util/windowsProcessDrain.d.ts.map +1 -0
  58. package/dist/util/windowsProcessDrain.js +51 -0
  59. package/dist/util/windowsProcessDrain.js.map +1 -0
  60. package/dist/worker/nativeWorkerPool.d.ts.map +1 -1
  61. package/dist/worker/nativeWorkerPool.js +2 -0
  62. package/dist/worker/nativeWorkerPool.js.map +1 -1
  63. package/docs/mcp.md +9 -9
  64. package/package.json +3 -3
package/dist/bin/cli.js CHANGED
@@ -932,7 +932,7 @@ var init_options = __esm({
932
932
  ],
933
933
  [
934
934
  "mcp",
935
- commandSchema([...SHARED_BUILD_FLAGS, "--allow-build", "--stdio", "--warmup", "--warmup-symbols"], [...SHARED_BUILD_OPTIONS, "--artifact", "--host", "--port", "--idle-timeout-ms"], {
935
+ commandSchema([...SHARED_BUILD_FLAGS, "--allow-build", "--stdio", "--warmup", "--warmup-symbols", "--no-warmup"], [...SHARED_BUILD_OPTIONS, "--artifact", "--host", "--port", "--idle-timeout-ms"], {
936
936
  kind: "max",
937
937
  max: 1,
938
938
  usage: "Usage: codegraph mcp [serve] [--root <path>] [--stdio | --port <number>]"
@@ -947,6 +947,7 @@ var init_options = __esm({
947
947
  "--replace",
948
948
  "--warmup",
949
949
  "--warmup-symbols",
950
+ "--no-warmup",
950
951
  "--workers",
951
952
  ...JSON_OUTPUT_FLAGS
952
953
  ], [
@@ -969,7 +970,7 @@ var init_options = __esm({
969
970
  ],
970
971
  [
971
972
  "orient",
972
- commandSchema([...SHARED_BUILD_FLAGS, ...JSON_OUTPUT_FLAGS], [...SHARED_BUILD_OPTIONS, "--budget", "--health"], {
973
+ commandSchema([...SHARED_BUILD_FLAGS, ...JSON_OUTPUT_FLAGS, ...REPORT_FLAGS], [...SHARED_BUILD_OPTIONS, ...REPORT_OPTIONS, "--budget", "--health"], {
973
974
  kind: "any"
974
975
  })
975
976
  ],
@@ -1159,6 +1160,7 @@ var init_options = __esm({
1159
1160
  });
1160
1161
 
1161
1162
  // dist/cli/progress.js
1163
+ import { performance as performance2 } from "node:perf_hooks";
1162
1164
  function resolveCliProgressPresentation(input) {
1163
1165
  if (input.policy === "never")
1164
1166
  return "off";
@@ -1181,7 +1183,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1181
1183
  let mode = "build";
1182
1184
  let activity = progressAction(mode);
1183
1185
  let interval;
1184
- let delay;
1186
+ let delay2;
1187
+ let phaseStartedAt = performance2.now();
1185
1188
  const clear = () => {
1186
1189
  if (!rendered)
1187
1190
  return;
@@ -1194,7 +1197,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1194
1197
  const frame = SPINNER_FRAMES[frameIndex % SPINNER_FRAMES.length];
1195
1198
  frameIndex += 1;
1196
1199
  const count = hasProgressCount(mode, current, total) ? formatProgressCount(current, total) : "";
1197
- write(`${CLEAR_LINE}${activity}... ${frame}${count}`);
1200
+ const elapsed = ` (${formatDuration(performance2.now() - phaseStartedAt)})`;
1201
+ write(`${CLEAR_LINE}${activity}... ${frame}${count}${elapsed}`);
1198
1202
  rendered = true;
1199
1203
  };
1200
1204
  const stopInterval = () => {
@@ -1202,9 +1206,9 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1202
1206
  clearInterval(interval);
1203
1207
  interval = void 0;
1204
1208
  }
1205
- if (delay !== void 0) {
1206
- clearTimeout(delay);
1207
- delay = void 0;
1209
+ if (delay2 !== void 0) {
1210
+ clearTimeout(delay2);
1211
+ delay2 = void 0;
1208
1212
  }
1209
1213
  };
1210
1214
  const start = (update) => {
@@ -1217,6 +1221,7 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1217
1221
  total = update.total;
1218
1222
  mode = update.mode ?? "build";
1219
1223
  activity = update.activity ?? `${progressAction(mode)} project index`;
1224
+ phaseStartedAt = performance2.now();
1220
1225
  const beginRendering = () => {
1221
1226
  if (!active)
1222
1227
  return;
@@ -1225,8 +1230,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1225
1230
  interval.unref();
1226
1231
  };
1227
1232
  if (delayMs) {
1228
- delay = setTimeout(beginRendering, delayMs);
1229
- delay.unref();
1233
+ delay2 = setTimeout(beginRendering, delayMs);
1234
+ delay2.unref();
1230
1235
  } else {
1231
1236
  beginRendering();
1232
1237
  }
@@ -1263,6 +1268,8 @@ function createInteractiveProgressDisplay(write, delayMs = 0) {
1263
1268
  current = update.current;
1264
1269
  total = update.total;
1265
1270
  mode = update.mode ?? mode;
1271
+ if (update.activity !== void 0 && update.activity !== activity)
1272
+ phaseStartedAt = performance2.now();
1266
1273
  if (update.activity !== void 0)
1267
1274
  activity = update.activity;
1268
1275
  },
@@ -1294,12 +1301,13 @@ function createLogProgressDisplay(write, delayMs = 0) {
1294
1301
  let total = 0;
1295
1302
  let mode = "build";
1296
1303
  let activity = progressAction(mode);
1297
- let delay;
1304
+ let delay2;
1298
1305
  let heartbeat;
1306
+ let phaseStartedAt = performance2.now();
1299
1307
  const stopTimers = () => {
1300
- if (delay !== void 0) {
1301
- clearTimeout(delay);
1302
- delay = void 0;
1308
+ if (delay2 !== void 0) {
1309
+ clearTimeout(delay2);
1310
+ delay2 = void 0;
1303
1311
  }
1304
1312
  if (heartbeat !== void 0) {
1305
1313
  clearInterval(heartbeat);
@@ -1316,7 +1324,8 @@ function createLogProgressDisplay(write, delayMs = 0) {
1316
1324
  if (!active)
1317
1325
  return;
1318
1326
  const count = hasProgressCount(mode, current, total) ? `:${formatProgressCount(current, total)}` : "";
1319
- write(`[Progress] ${activity}${count}.
1327
+ const elapsed = formatDuration(performance2.now() - phaseStartedAt);
1328
+ write(`[Progress] ${activity}${count}. (${elapsed})
1320
1329
  `);
1321
1330
  }, 1e3);
1322
1331
  heartbeat.unref();
@@ -1329,9 +1338,10 @@ function createLogProgressDisplay(write, delayMs = 0) {
1329
1338
  total = update.total;
1330
1339
  mode = update.mode ?? "build";
1331
1340
  activity = update.activity ?? `${progressAction(mode)} project index`;
1341
+ phaseStartedAt = performance2.now();
1332
1342
  if (delayMs) {
1333
- delay = setTimeout(renderStart, delayMs);
1334
- delay.unref();
1343
+ delay2 = setTimeout(renderStart, delayMs);
1344
+ delay2.unref();
1335
1345
  } else {
1336
1346
  renderStart();
1337
1347
  }
@@ -1366,17 +1376,22 @@ function createLogProgressDisplay(write, delayMs = 0) {
1366
1376
  mode = update.mode ?? mode;
1367
1377
  if (update.activity !== void 0)
1368
1378
  activity = update.activity;
1369
- if (rendered && activity !== previousActivity) {
1379
+ const activityChanged = activity !== previousActivity;
1380
+ if (activityChanged)
1381
+ phaseStartedAt = performance2.now();
1382
+ const isComplete = update.total > 0 && update.current >= update.total;
1383
+ const shouldPrintCount = rendered && (update.current === 1 || isComplete || update.current > 0 && update.current % 100 === 0);
1384
+ if (rendered && activityChanged && !shouldPrintCount) {
1370
1385
  write(`[Progress] ${activity}.
1371
1386
  `);
1372
1387
  }
1373
- const isComplete = update.total > 0 && update.current >= update.total;
1374
- if (rendered && (update.current === 1 || isComplete || update.current > 0 && update.current % 100 === 0)) {
1388
+ if (shouldPrintCount) {
1389
+ const elapsed = formatDuration(performance2.now() - phaseStartedAt);
1375
1390
  if (update.activity !== void 0) {
1376
- write(`[Progress] ${activity}:${formatProgressCount(update.current, update.total)}.
1391
+ write(`[Progress] ${activity}:${formatProgressCount(update.current, update.total)}. (${elapsed})
1377
1392
  `);
1378
1393
  } else {
1379
- write(`[Progress] ${formatFileCount(update.current)} processed.
1394
+ write(`[Progress] ${formatFileCount(update.current)} processed. (${elapsed})
1380
1395
  `);
1381
1396
  }
1382
1397
  }
@@ -14221,12 +14236,12 @@ __export(projectFiles_exports, {
14221
14236
  import fs6 from "node:fs";
14222
14237
  import fsp5 from "node:fs/promises";
14223
14238
  import path9 from "node:path";
14224
- import { performance as performance2 } from "node:perf_hooks";
14239
+ import { performance as performance3 } from "node:perf_hooks";
14225
14240
  function emitDiscoveryActivity(report, activity, current = 0, total = 0) {
14226
14241
  report?.({ activity, current, total });
14227
14242
  }
14228
14243
  function emitDiscoveryTiming(record2, name, startedAt) {
14229
- record2?.({ name, ms: Math.round(performance2.now() - startedAt) });
14244
+ record2?.({ name, ms: Math.round(performance3.now() - startedAt) });
14230
14245
  }
14231
14246
  function createPathCheckProgressReporter(total, onProgress) {
14232
14247
  onProgress?.(0, total);
@@ -14252,6 +14267,13 @@ function couldBeDirectorySymlink(filePath) {
14252
14267
  return true;
14253
14268
  return DIRECTORY_METADATA_EXTENSIONS.has(extension.toLowerCase());
14254
14269
  }
14270
+ function isProjectMetadataDirectoryName(dirPath) {
14271
+ const basename2 = path9.posix.basename(normalizePath(dirPath));
14272
+ if (DIRECTORY_METADATA_BASENAMES.has(basename2.toLowerCase()))
14273
+ return true;
14274
+ const extension = path9.posix.extname(basename2);
14275
+ return Boolean(extension) && DIRECTORY_METADATA_EXTENSIONS.has(extension.toLowerCase());
14276
+ }
14255
14277
  function globLiteralPrefix(globPattern) {
14256
14278
  const prefix = [];
14257
14279
  let seenLiteral = false;
@@ -14584,7 +14606,7 @@ async function listGitCandidateFiles(root, logLevel, opts) {
14584
14606
  if (!gitRepositoryRoot)
14585
14607
  return null;
14586
14608
  emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git files");
14587
- const listStartedAt = performance2.now();
14609
+ const listStartedAt = performance3.now();
14588
14610
  gitListStart = listStartedAt;
14589
14611
  const [tracked, untracked, stageSpecial] = await Promise.all([
14590
14612
  listTrackedFiles(gitRoot, { recurseSubmodules: true, ...logLevel === void 0 ? {} : { logLevel } }),
@@ -14616,7 +14638,7 @@ async function listGitCandidateFiles(root, logLevel, opts) {
14616
14638
  gitListStart = void 0;
14617
14639
  emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git files", files.length, files.length);
14618
14640
  emitDiscoveryActivity(opts?.onDiscoveryProgress, "Listing Git ignore files");
14619
- const ignoreStartedAt = performance2.now();
14641
+ const ignoreStartedAt = performance3.now();
14620
14642
  gitIgnoreStart = ignoreStartedAt;
14621
14643
  const gitignoreFiles = await findGitIgnoreSources(sourceRoots, files);
14622
14644
  emitDiscoveryTiming(opts?.onDiscoveryTiming, "git-ignore", ignoreStartedAt);
@@ -14689,7 +14711,7 @@ async function listProjectFilesInternal(projectRoot, patterns = DEFAULT_PROJECT_
14689
14711
  files = gitCandidates.files;
14690
14712
  } else {
14691
14713
  emitDiscoveryActivity(options?.onDiscoveryProgress, "Scanning project files");
14692
- const scanStart = performance2.now();
14714
+ const scanStart = performance3.now();
14693
14715
  files = await (0, import_fast_glob2.default)(patterns, {
14694
14716
  cwd: root,
14695
14717
  absolute: true,
@@ -14983,7 +15005,7 @@ async function discoverProjectFilesInternal(projectRoot, options) {
14983
15005
  const candidateFiles = Array.from(new Set(gitCandidates.files.map(normalizePath)));
14984
15006
  const metadataCandidates = candidateFiles.filter((file2) => PROJECT_FILE_DEFINITIONS.some((definition, definitionIndex) => definition.kind === "file" && matchesDefinition(path9.basename(file2), definitionIndex)));
14985
15007
  const fileMatches = filterGitIgnoredEntries(await filterRealPathsWithinRootEntries(metadataCandidates, realRoot, reportMetadataFileChecks));
14986
- const rawCandidateDirectories = collectCandidateAncestorDirectories(root, candidateFiles);
15008
+ const rawCandidateDirectories = collectCandidateAncestorDirectories(root, candidateFiles).filter(isProjectMetadataDirectoryName);
14987
15009
  const candidateDirectoryKeys = new Set(rawCandidateDirectories.map(fileIdentityKey));
14988
15010
  const safeSymlinkDirectoryKeys = new Set(safeSymlinkDirectories.map(fileIdentityKey));
14989
15011
  const directoryMatches = [
@@ -20580,6 +20602,40 @@ var init_bindingLoader = __esm({
20580
20602
  }
20581
20603
  });
20582
20604
 
20605
+ // dist/util/windowsProcessDrain.js
20606
+ function markWindowsProcessDrainRequired() {
20607
+ drainRequired = true;
20608
+ ensureWindowsProcessDrainHook();
20609
+ }
20610
+ function delay(ms) {
20611
+ return new Promise((resolve) => {
20612
+ setTimeout(resolve, ms);
20613
+ });
20614
+ }
20615
+ function ensureWindowsProcessDrainHook() {
20616
+ if (process.platform !== "win32" || beforeExitListener)
20617
+ return;
20618
+ beforeExitListener = () => {
20619
+ void drainWindowsProcessHandles();
20620
+ };
20621
+ process.once("beforeExit", beforeExitListener);
20622
+ }
20623
+ async function drainWindowsProcessHandles(options) {
20624
+ const platform = options?.platform ?? process.platform;
20625
+ const required2 = options?.required ?? drainRequired;
20626
+ if (platform !== "win32" || !required2)
20627
+ return;
20628
+ await (options?.wait ?? delay)(WINDOWS_LIBUV_EXIT_DRAIN_MS);
20629
+ }
20630
+ var WINDOWS_LIBUV_EXIT_DRAIN_MS, drainRequired, beforeExitListener;
20631
+ var init_windowsProcessDrain = __esm({
20632
+ "dist/util/windowsProcessDrain.js"() {
20633
+ "use strict";
20634
+ WINDOWS_LIBUV_EXIT_DRAIN_MS = 100;
20635
+ drainRequired = false;
20636
+ }
20637
+ });
20638
+
20583
20639
  // dist/native/runtime.js
20584
20640
  import fs14 from "node:fs";
20585
20641
  import path25 from "node:path";
@@ -20608,6 +20664,7 @@ function loadBinding() {
20608
20664
  });
20609
20665
  if (loaded.binding) {
20610
20666
  const supportedLanguageIds = new Set(loaded.binding.supportedLanguageIds());
20667
+ markWindowsProcessDrainRequired();
20611
20668
  bindingState = {
20612
20669
  loaded: true,
20613
20670
  binding: loaded.binding,
@@ -20832,6 +20889,7 @@ var init_runtime = __esm({
20832
20889
  init_ast();
20833
20890
  init_bindingLoader();
20834
20891
  init_runtimeCache();
20892
+ init_windowsProcessDrain();
20835
20893
  require2 = createRequire2(import.meta.url);
20836
20894
  localNativePackageRoot = path25.resolve(path25.dirname(fileURLToPath2(import.meta.url)), "../../packages/codegraph-native");
20837
20895
  NATIVE_REQUIRED_ERROR_PREFIX = "native tree-sitter required by explicit option but unavailable";
@@ -32065,6 +32123,7 @@ var init_sqlite_driver = __esm({
32065
32123
  "dist/sqlite-driver.js"() {
32066
32124
  "use strict";
32067
32125
  init_errors();
32126
+ init_windowsProcessDrain();
32068
32127
  requireNodeModule = createRequire4(import.meta.url);
32069
32128
  reportedReadonlyAuthorizerDegradation = false;
32070
32129
  READONLY_AUTHORIZER_CONSTANTS = [
@@ -32123,6 +32182,7 @@ var init_sqlite_driver = __esm({
32123
32182
  SqliteDatabase = class {
32124
32183
  db;
32125
32184
  statements = /* @__PURE__ */ new Map();
32185
+ closed = false;
32126
32186
  constructor(filePath, options) {
32127
32187
  if (!isNodeSqliteUsable()) {
32128
32188
  throw nodeSqliteUnavailableError() ?? new Error("node:sqlite is unavailable");
@@ -32132,6 +32192,7 @@ var init_sqlite_driver = __esm({
32132
32192
  readOnly: options?.readonly,
32133
32193
  timeout: options?.timeout ?? 5e3
32134
32194
  });
32195
+ markWindowsProcessDrainRequired();
32135
32196
  if (options?.readonly) {
32136
32197
  const { constants: constants2 } = sqlite;
32137
32198
  if (this.db.setAuthorizer && canInstallReadonlyAuthorizer(constants2)) {
@@ -32176,8 +32237,11 @@ var init_sqlite_driver = __esm({
32176
32237
  };
32177
32238
  }
32178
32239
  close() {
32240
+ if (this.closed)
32241
+ return;
32179
32242
  this.statements.clear();
32180
32243
  this.db.close();
32244
+ this.closed = true;
32181
32245
  }
32182
32246
  };
32183
32247
  }
@@ -53704,19 +53768,19 @@ var init_parsed_cache = __esm({
53704
53768
  });
53705
53769
 
53706
53770
  // dist/indexer/finalize.js
53707
- import { performance as performance3 } from "node:perf_hooks";
53771
+ import { performance as performance4 } from "node:perf_hooks";
53708
53772
  async function finalizeProjectIndex(args) {
53709
53773
  const discoveryTimings = args.opts?.report ? args.opts.report.timings ??= {} : void 0;
53710
- const metadataDiscoveryStart = args.projectFiles === void 0 ? performance3.now() : void 0;
53774
+ const metadataDiscoveryStart = args.projectFiles === void 0 ? performance4.now() : void 0;
53711
53775
  const projectFiles = await (args.projectFiles ?? discoverProjectFilesWithGitCandidates(args.projectRoot, {
53712
53776
  ...args.opts?.logLevel ? { logLevel: args.opts.logLevel } : {},
53713
53777
  ...args.knownGitCandidates !== void 0 ? { knownGitCandidates: args.knownGitCandidates } : {}
53714
53778
  }));
53715
53779
  if (metadataDiscoveryStart !== void 0 && discoveryTimings) {
53716
- discoveryTimings.metadataDiscoveryMs = Math.round(performance3.now() - metadataDiscoveryStart);
53780
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance4.now() - metadataDiscoveryStart);
53717
53781
  }
53718
53782
  if (args.timings)
53719
- args.timings.totalMs = Math.round(performance3.now() - args.totalStart);
53783
+ args.timings.totalMs = Math.round(performance4.now() - args.totalStart);
53720
53784
  const languageExtensions = normalizeLanguageExtensions(args.opts?.languageExtensions);
53721
53785
  const parsed = retainedParsedCache(args.parsedMap, args.opts);
53722
53786
  return {
@@ -53754,7 +53818,7 @@ var init_finalize = __esm({
53754
53818
  // dist/indexer/build-manifest.js
53755
53819
  import fsp24 from "node:fs/promises";
53756
53820
  import path45 from "node:path";
53757
- import { performance as performance4 } from "node:perf_hooks";
53821
+ import { performance as performance5 } from "node:perf_hooks";
53758
53822
  function toManifestFileEntry(entry) {
53759
53823
  if (!entry.sig)
53760
53824
  return void 0;
@@ -53769,7 +53833,7 @@ async function writeIndexManifestSnapshot(args) {
53769
53833
  const files = args.files instanceof Map ? Object.fromEntries(args.files) : args.files;
53770
53834
  if (!Object.keys(files).length && !args.allowEmpty)
53771
53835
  return;
53772
- const writeManifestStart = performance4.now();
53836
+ const writeManifestStart = performance5.now();
53773
53837
  const lastCommit = await getGitHead(args.projectRoot);
53774
53838
  const configHashResult = await computeConfigHash(args.projectRoot, args.opts?.logLevel);
53775
53839
  const projectRootMtimeMs = args.symlinkDirectories !== void 0 ? (await fsp24.stat(args.projectRoot)).mtimeMs : void 0;
@@ -53794,7 +53858,7 @@ async function writeIndexManifestSnapshot(args) {
53794
53858
  if (manifestWritten)
53795
53859
  pruneDiskModuleCache(args.projectRoot, Object.keys(files), args.opts);
53796
53860
  if (args.timings) {
53797
- args.timings.writeManifestMs = Math.round(performance4.now() - writeManifestStart);
53861
+ args.timings.writeManifestMs = Math.round(performance5.now() - writeManifestStart);
53798
53862
  }
53799
53863
  }
53800
53864
  var init_build_manifest = __esm({
@@ -55208,6 +55272,7 @@ function createNativeWorkerPool(opts) {
55208
55272
  const bounded = typeof requestedMax === "number" && Number.isFinite(requestedMax) && requestedMax > 0 ? Math.max(1, Math.floor(requestedMax)) : HARD_MAX_THREADS;
55209
55273
  const threads = Math.min(resolveThreadCount(opts?.threads), bounded);
55210
55274
  const workerPath = resolveNativeWorkerPath();
55275
+ markWindowsProcessDrainRequired();
55211
55276
  return new Piscina({
55212
55277
  filename: workerPath,
55213
55278
  minThreads: 1,
@@ -55223,13 +55288,14 @@ var init_nativeWorkerPool = __esm({
55223
55288
  "use strict";
55224
55289
  init_esm_wrapper();
55225
55290
  init_workerThreads();
55291
+ init_windowsProcessDrain();
55226
55292
  HARD_MAX_THREADS = 64;
55227
55293
  DEFAULT_NATIVE_THREAD_CAP = 8;
55228
55294
  }
55229
55295
  });
55230
55296
 
55231
55297
  // dist/indexer/build-workers.js
55232
- import { performance as performance5 } from "node:perf_hooks";
55298
+ import { performance as performance6 } from "node:perf_hooks";
55233
55299
  function shouldEnableNativeWorkers(opts, fileCount) {
55234
55300
  if (opts?.native === "off")
55235
55301
  return false;
@@ -55323,14 +55389,14 @@ async function setupWorkerPool(opts, fileCount) {
55323
55389
  return {
55324
55390
  pool,
55325
55391
  report,
55326
- startTime: pool ? performance5.now() : 0,
55392
+ startTime: pool ? performance6.now() : 0,
55327
55393
  batchSize: NATIVE_WORKER_BATCH_SIZE
55328
55394
  };
55329
55395
  }
55330
55396
  async function teardownWorkerPool(setup, buildReport2) {
55331
55397
  if (setup.pool) {
55332
55398
  if (setup.report) {
55333
- setup.report.wallClockMs = Math.round(performance5.now() - setup.startTime);
55399
+ setup.report.wallClockMs = Math.round(performance6.now() - setup.startTime);
55334
55400
  }
55335
55401
  try {
55336
55402
  await setup.pool.destroy();
@@ -55598,7 +55664,7 @@ import crypto10 from "node:crypto";
55598
55664
  import fs23 from "node:fs";
55599
55665
  import fsp26 from "node:fs/promises";
55600
55666
  import path47 from "node:path";
55601
- import { performance as performance6 } from "node:perf_hooks";
55667
+ import { performance as performance7 } from "node:perf_hooks";
55602
55668
  function initParserBackendDegradationReport(report) {
55603
55669
  if (!report)
55604
55670
  return void 0;
@@ -55897,7 +55963,7 @@ function createIndexBuildRunState(projectRoot, opts, graphOptions = normalizeGra
55897
55963
  normalizedProjectRoot: normalizePath(path47.resolve(projectRoot)),
55898
55964
  report,
55899
55965
  timings: report?.timings,
55900
- totalStart: performance6.now(),
55966
+ totalStart: performance7.now(),
55901
55967
  cacheMode,
55902
55968
  cacheEnabled: cacheMode !== "off",
55903
55969
  graphOptions,
@@ -55942,14 +56008,45 @@ function emitIndexCheckActivity(opts, activity, current = 0, total = 0) {
55942
56008
  total
55943
56009
  });
55944
56010
  }
55945
- function resetDiscoveryTimingSteps(timings) {
56011
+ function emitIndexBuildActivity(opts, activity, current, total) {
56012
+ opts?.onProgress?.({
56013
+ type: "progress",
56014
+ phase: "update",
56015
+ mode: "build",
56016
+ message: activity,
56017
+ activity,
56018
+ current,
56019
+ total
56020
+ });
56021
+ }
56022
+ async function timeIndexBuildPhase(args) {
56023
+ if (args.buildStartedAt !== void 0) {
56024
+ emitIndexBuildActivity(args.opts, args.activity, args.current, args.total);
56025
+ }
56026
+ const startedAt = performance7.now();
56027
+ const result = await args.fn();
56028
+ recordBuildTimingStep(args.timings, { name: args.stepName, ms: Math.round(performance7.now() - startedAt) });
56029
+ return result;
56030
+ }
56031
+ function createCountedCheckProgress(opts, activity, total) {
56032
+ emitIndexCheckActivity(opts, activity, 0, total);
56033
+ let completed = 0;
56034
+ return () => {
56035
+ completed += 1;
56036
+ if (completed === total || completed % 100 === 0) {
56037
+ emitIndexCheckActivity(opts, activity, completed, total);
56038
+ }
56039
+ };
56040
+ }
56041
+ function resetTransientBuildTimings(timings) {
55946
56042
  if (!timings)
55947
56043
  return;
55948
56044
  delete timings.gitListMs;
55949
56045
  delete timings.filesystemScanMs;
55950
56046
  delete timings.sourceDiscoveryMs;
55951
56047
  delete timings.metadataDiscoveryMs;
55952
- const remaining = (timings.steps ?? []).filter((step) => !DISCOVERY_TIMING_STEP_NAMES.has(step.name));
56048
+ delete timings.cacheProbeMs;
56049
+ const remaining = (timings.steps ?? []).filter((step) => !Object.hasOwn(TRANSIENT_BUILD_TIMING_STEP_NAMES, step.name));
55953
56050
  if (remaining.length) {
55954
56051
  timings.steps = remaining;
55955
56052
  return;
@@ -56008,7 +56105,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56008
56105
  const fileReport = initFileReport(report);
56009
56106
  if (fileReport)
56010
56107
  fileReport.total = normalizedFiles.length;
56011
- const manifestStart = performance6.now();
56108
+ const manifestStart = performance7.now();
56012
56109
  const manifest = useManifest && !helperOpts?.ignoreExistingManifest ? await loadManifest(projectRoot, opts, report) : null;
56013
56110
  const manifestFiles = sanitizeManifestEntriesForRoot(projectRoot, manifest?.files);
56014
56111
  const manifestOptionDiffs = manifest ? diffBuildOptions(manifest.buildOptions, opts) : [];
@@ -56023,7 +56120,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56023
56120
  }
56024
56121
  }
56025
56122
  if (timings && useManifest) {
56026
- timings.manifestMs = Math.round(performance6.now() - manifestStart);
56123
+ timings.manifestMs = Math.round(performance7.now() - manifestStart);
56027
56124
  }
56028
56125
  const edgeProbeConcurrency = buildConcurrency(opts);
56029
56126
  const staleCachedEdgeFiles = /* @__PURE__ */ new Set();
@@ -56049,6 +56146,10 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56049
56146
  }
56050
56147
  const manifestEntriesForIndex = useManifest ? projectIndexManifestEntries2(cachedGraphEntries ?? []) : /* @__PURE__ */ new Map();
56051
56148
  const modules = /* @__PURE__ */ new Map();
56149
+ const moduleCacheAvailable = opts?.cache !== "disk" || diskModuleCacheExists(projectRoot, opts);
56150
+ const shouldReportFileCacheCheck = Boolean(helperOpts?.reportDiscoveryProgress);
56151
+ const reportFileCacheCheck = shouldReportFileCacheCheck ? createCountedCheckProgress(opts, "Checking file cache", normalizedFiles.length) : () => void 0;
56152
+ const cacheProbeStart = performance7.now();
56052
56153
  const gitAvailable = await isGitRepo(projectRoot);
56053
56154
  const needsPersistentSignatures = cacheEnabled || useManifest;
56054
56155
  const useGitSignatures = gitAvailable && needsPersistentSignatures;
@@ -56088,7 +56189,6 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56088
56189
  return !(matchesGitSig || cachedEdgesEntry.sig === sigInfo.sig);
56089
56190
  };
56090
56191
  const jsonDependencies = /* @__PURE__ */ new Map();
56091
- const moduleCacheAvailable = opts?.cache !== "disk" || diskModuleCacheExists(projectRoot, opts);
56092
56192
  const cacheProbes = new Map(await mapLimit(normalizedFiles, conc, async (file2) => {
56093
56193
  try {
56094
56194
  let sigInfo = fileSignatures.get(file2);
@@ -56117,8 +56217,15 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56117
56217
  return [file2, { sigInfo, mod: mod2 }];
56118
56218
  } catch (error51) {
56119
56219
  return [file2, { error: error51 }];
56220
+ } finally {
56221
+ reportFileCacheCheck();
56120
56222
  }
56121
56223
  }));
56224
+ if (timings) {
56225
+ const cacheProbeMs = Math.round(performance7.now() - cacheProbeStart);
56226
+ timings.cacheProbeMs = cacheProbeMs;
56227
+ recordBuildTimingStep(timings, { name: "cache-probe", ms: cacheProbeMs });
56228
+ }
56122
56229
  const cacheMisses = Array.from(cacheProbes, ([file2, probe]) => !("error" in probe) && !probe.mod ? file2 : null).filter((file2) => file2 !== null);
56123
56230
  const workerSetup = await setupWorkerPool(opts, countNativeWorkerEligibleFiles(cacheMisses, opts?.languageExtensions));
56124
56231
  try {
@@ -56137,7 +56244,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56137
56244
  }
56138
56245
  return matchPath;
56139
56246
  };
56140
- const parseStart = performance6.now();
56247
+ const parseStart = performance7.now();
56141
56248
  const graph = { nodes: new Set(normalizedFiles), edges: [] };
56142
56249
  const onFileEdges = manifestEntries ? (file2, entry) => {
56143
56250
  const manifestEntry = toManifestFileEntry(entry);
@@ -56151,9 +56258,11 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56151
56258
  const ensureBuildProgressStarted = () => {
56152
56259
  if (buildStartedAt !== void 0)
56153
56260
  return;
56154
- buildStartedAt = performance6.now();
56261
+ buildStartedAt = performance7.now();
56155
56262
  emitIndexLifecycleProgress(opts, "start", "build", totalFiles);
56156
56263
  };
56264
+ if (cacheMisses.length)
56265
+ ensureBuildProgressStarted();
56157
56266
  const fileResults = await mapLimit(normalizedFiles, conc, async (file2) => {
56158
56267
  try {
56159
56268
  const cacheProbe = cacheProbes.get(file2);
@@ -56283,8 +56392,8 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56283
56392
  }
56284
56393
  });
56285
56394
  if (timings)
56286
- timings.parseMs = Math.round(performance6.now() - parseStart);
56287
- const graphStart = performance6.now();
56395
+ timings.parseMs = Math.round(performance7.now() - parseStart);
56396
+ const graphStart = performance7.now();
56288
56397
  const seenGraphEdges = /* @__PURE__ */ new Set();
56289
56398
  const appendUniqueGraphEdges = (edges) => {
56290
56399
  if (!edges.length)
@@ -56307,12 +56416,34 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56307
56416
  pendingCacheWrites.push(cacheWrite);
56308
56417
  }
56309
56418
  if (pendingCacheWrites.length) {
56310
- writeModulesToCache(projectRoot, pendingCacheWrites, opts);
56419
+ if (opts?.cache === "disk") {
56420
+ await timeIndexBuildPhase({
56421
+ opts,
56422
+ timings,
56423
+ buildStartedAt,
56424
+ stepName: "persist-cache",
56425
+ activity: "Writing disk cache",
56426
+ current: totalFiles,
56427
+ total: totalFiles,
56428
+ fn: () => writeModulesToCache(projectRoot, pendingCacheWrites, opts)
56429
+ });
56430
+ } else {
56431
+ writeModulesToCache(projectRoot, pendingCacheWrites, opts);
56432
+ }
56311
56433
  }
56312
- const workspaceManifestEdges = await collectWorkspaceManifestDependencyEdges(projectRoot, normalizedFiles.filter((file2) => path47.basename(file2) === "package.json"), opts?.discovery, opts?.logLevel);
56434
+ const workspaceManifestEdges = await timeIndexBuildPhase({
56435
+ opts,
56436
+ timings,
56437
+ buildStartedAt,
56438
+ stepName: "workspace-manifests",
56439
+ activity: "Resolving workspace manifests",
56440
+ current: totalFiles,
56441
+ total: totalFiles,
56442
+ fn: () => collectWorkspaceManifestDependencyEdges(projectRoot, normalizedFiles.filter((file2) => path47.basename(file2) === "package.json"), opts?.discovery, opts?.logLevel)
56443
+ });
56313
56444
  appendUniqueGraphEdges(workspaceManifestEdges);
56314
56445
  if (timings)
56315
- timings.graphMs = Math.round(performance6.now() - graphStart);
56446
+ timings.graphMs = Math.round(performance7.now() - graphStart);
56316
56447
  for (const jsonPath of jsonDependencies.values()) {
56317
56448
  ensureJsonModule(modules, jsonPath);
56318
56449
  }
@@ -56329,42 +56460,69 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56329
56460
  }
56330
56461
  }
56331
56462
  if (manifestEntries) {
56332
- await writeIndexManifestSnapshot({
56333
- projectRoot,
56463
+ await timeIndexBuildPhase({
56334
56464
  opts,
56335
- graphOptions,
56336
- ...resolverEnvironmentFingerprint ? { resolverEnvironmentFingerprint } : {},
56337
- files: manifestEntries,
56338
56465
  timings,
56339
- manifestReport: report?.manifest,
56340
- ...helperOpts?.transientFiles !== void 0 ? { transientFiles: helperOpts.transientFiles } : {},
56341
- ...helperOpts?.symlinkDirectories !== void 0 ? { symlinkDirectories: helperOpts.symlinkDirectories } : {}
56466
+ buildStartedAt,
56467
+ stepName: "index-manifest",
56468
+ activity: "Writing index manifest",
56469
+ current: totalFiles,
56470
+ total: totalFiles,
56471
+ fn: () => writeIndexManifestSnapshot({
56472
+ projectRoot,
56473
+ opts,
56474
+ graphOptions,
56475
+ ...resolverEnvironmentFingerprint ? { resolverEnvironmentFingerprint } : {},
56476
+ files: manifestEntries,
56477
+ timings,
56478
+ manifestReport: report?.manifest,
56479
+ ...helperOpts?.transientFiles !== void 0 ? { transientFiles: helperOpts.transientFiles } : {},
56480
+ ...helperOpts?.symlinkDirectories !== void 0 ? { symlinkDirectories: helperOpts.symlinkDirectories } : {}
56481
+ })
56342
56482
  });
56343
56483
  }
56344
56484
  const indexManifestEntries = manifestEntries ? projectIndexManifestEntries2(Array.from(manifestEntries, ([file2, entry]) => {
56345
56485
  const cacheSig = fileSignatures.get(file2)?.cacheSig;
56346
56486
  return [file2, { ...entry, ...cacheSig ? { cacheSig } : {} }];
56347
56487
  })) : manifestEntriesForIndex;
56348
- const index = await finalizeProjectIndex({
56349
- projectRoot,
56350
- normalizedProjectRoot,
56488
+ const index = await timeIndexBuildPhase({
56351
56489
  opts,
56352
56490
  timings,
56353
- totalStart,
56354
- graph,
56355
- modules,
56356
- parsedMap,
56357
- bloomFilterCache,
56358
- ...projectFiles !== void 0 ? { projectFiles } : {},
56359
- buildReport: report,
56360
- manifestEntries: indexManifestEntries
56491
+ buildStartedAt,
56492
+ stepName: "finalize",
56493
+ activity: "Finalizing project graph",
56494
+ current: totalFiles,
56495
+ total: totalFiles,
56496
+ fn: () => finalizeProjectIndex({
56497
+ projectRoot,
56498
+ normalizedProjectRoot,
56499
+ opts,
56500
+ timings,
56501
+ totalStart,
56502
+ graph,
56503
+ modules,
56504
+ parsedMap,
56505
+ bloomFilterCache,
56506
+ ...projectFiles !== void 0 ? { projectFiles } : {},
56507
+ buildReport: report,
56508
+ manifestEntries: indexManifestEntries
56509
+ })
56361
56510
  });
56362
56511
  if (manifestEntries) {
56363
- await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
56512
+ await timeIndexBuildPhase({
56513
+ opts,
56514
+ timings,
56515
+ buildStartedAt,
56516
+ stepName: "snapshot-write",
56517
+ activity: "Writing project snapshot",
56518
+ current: totalFiles,
56519
+ total: totalFiles,
56520
+ fn: () => writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot))
56521
+ });
56364
56522
  }
56365
56523
  if (buildStartedAt !== void 0) {
56366
56524
  const progressStartedAt = opts?.progressStartedAt ?? buildStartedAt;
56367
- emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance6.now() - progressStartedAt);
56525
+ emitIndexLifecycleProgress(opts, "complete", "build", index.byFile.size, performance7.now() - progressStartedAt);
56368
56526
  }
56369
56527
  return index;
56370
56528
  } finally {
@@ -56373,7 +56531,7 @@ async function buildIndexFromFileListShared(projectRoot, rawFiles, opts, helperO
56373
56531
  }
56374
56532
  async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpts) {
56375
56533
  const timings = opts?.report ? opts.report.timings ??= {} : void 0;
56376
- resetDiscoveryTimingSteps(timings);
56534
+ resetTransientBuildTimings(timings);
56377
56535
  await initializeFileIdentityCaseSensitivity(projectRoot);
56378
56536
  try {
56379
56537
  const useDiskCache = (opts?.cache ?? "off") === "disk";
@@ -56397,7 +56555,7 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56397
56555
  const onDiscoveryTiming = timings ? (step) => recordBuildTimingStep(timings, step) : void 0;
56398
56556
  if (helperOpts?.reportDiscoveryProgress)
56399
56557
  emitIndexCheckActivity(opts, "Discovering source files");
56400
- const sourceDiscoveryStart = performance6.now();
56558
+ const sourceDiscoveryStart = performance7.now();
56401
56559
  const discoveredFiles = await listProjectFilesWithGitCandidates(projectRoot, projectPatternsForLanguageExtensions(opts), {
56402
56560
  ...opts?.discovery,
56403
56561
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
@@ -56408,7 +56566,7 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56408
56566
  ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56409
56567
  });
56410
56568
  if (timings)
56411
- timings.sourceDiscoveryMs = Math.round(performance6.now() - sourceDiscoveryStart);
56569
+ timings.sourceDiscoveryMs = Math.round(performance7.now() - sourceDiscoveryStart);
56412
56570
  const additionalFileCandidates = await normalizeIndexedFileInputsWithinRoot(projectRoot, opts?.additionalFiles ?? [], "Additional index file");
56413
56571
  const additionalFileExistence = await probePathExistence(additionalFileCandidates, buildConcurrency(opts));
56414
56572
  const additionalFiles = additionalFileCandidates.filter((file2) => additionalFileExistence.get(file2));
@@ -56417,7 +56575,7 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56417
56575
  const transientFiles = additionalFiles.filter((file2) => !discoveredFileSet.has(file2));
56418
56576
  if (helperOpts?.reportDiscoveryProgress)
56419
56577
  emitIndexCheckActivity(opts, "Discovering project metadata");
56420
- const metadataDiscoveryStart = performance6.now();
56578
+ const metadataDiscoveryStart = performance7.now();
56421
56579
  const projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56422
56580
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56423
56581
  ...discoveredSymlinkDirectories !== void 0 ? { knownSymlinkDirectories: discoveredSymlinkDirectories } : {},
@@ -56426,11 +56584,12 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56426
56584
  ...onDiscoveryTiming ? { onDiscoveryTiming } : {}
56427
56585
  });
56428
56586
  if (timings)
56429
- timings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56587
+ timings.metadataDiscoveryMs = Math.round(performance7.now() - metadataDiscoveryStart);
56430
56588
  return await buildIndexFromFileListShared(projectRoot, files, opts, {
56431
56589
  manifestMode: useDiskCache ? "read-write" : "off",
56432
56590
  warnNoFilesMessage: `Warning: No files found in project root: ${projectRoot}. Check codegraph.config.json globs and CLI --include-glob/--ignore-glob filters. Diagnostic: codegraph doctor`,
56433
56591
  ...helperOpts?.ignoreExistingManifest ? { ignoreExistingManifest: true } : {},
56592
+ ...helperOpts?.reportDiscoveryProgress ? { reportDiscoveryProgress: true } : {},
56434
56593
  projectFiles,
56435
56594
  transientFiles,
56436
56595
  ...discoveredSymlinkDirectories !== void 0 ? { symlinkDirectories: discoveredSymlinkDirectories } : {}
@@ -56445,11 +56604,11 @@ async function buildProjectIndexWithManifestOptions(projectRoot, opts, helperOpt
56445
56604
  async function buildProjectIndex(projectRoot, opts) {
56446
56605
  return buildProjectIndexWithManifestOptions(projectRoot, {
56447
56606
  ...opts,
56448
- progressStartedAt: opts?.progressStartedAt ?? performance6.now()
56607
+ progressStartedAt: opts?.progressStartedAt ?? performance7.now()
56449
56608
  });
56450
56609
  }
56451
56610
  async function buildProjectIndexFromFiles(projectRoot, inputFiles, rawOpts) {
56452
- const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now() };
56611
+ const opts = { ...rawOpts, progressStartedAt: rawOpts?.progressStartedAt ?? performance7.now() };
56453
56612
  try {
56454
56613
  const useDiskCache = (opts?.cache ?? "off") === "disk";
56455
56614
  const normalizedInputFiles = await normalizeIndexedFileInputsWithinRoot(projectRoot, inputFiles, "Index file");
@@ -56481,7 +56640,7 @@ async function buildDeclaredScopeIndex(projectRoot, scopeFiles, opts) {
56481
56640
  async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56482
56641
  const opts = {
56483
56642
  ...rawOpts,
56484
- progressStartedAt: rawOpts?.progressStartedAt ?? performance6.now()
56643
+ progressStartedAt: rawOpts?.progressStartedAt ?? performance7.now()
56485
56644
  };
56486
56645
  await initializeFileIdentityCaseSensitivity(projectRoot);
56487
56646
  clearResolutionCaches();
@@ -56491,7 +56650,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56491
56650
  graphOptions.fast = false;
56492
56651
  const { normalizedProjectRoot, report, timings, totalStart, cacheMode, cacheEnabled, onFallbackImportExtraction } = createIndexBuildRunState(projectRoot, opts, graphOptions);
56493
56652
  const discoveryTimings = opts?.report ? opts.report.timings ??= {} : void 0;
56494
- resetDiscoveryTimingSteps(discoveryTimings);
56653
+ resetTransientBuildTimings(discoveryTimings);
56495
56654
  let checkProgressActive = false;
56496
56655
  const startCheckProgress = () => {
56497
56656
  if (checkProgressActive)
@@ -56517,7 +56676,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56517
56676
  message: "Checked project index",
56518
56677
  current: total,
56519
56678
  total,
56520
- elapsedMs: performance6.now() - totalStart
56679
+ elapsedMs: performance7.now() - totalStart
56521
56680
  });
56522
56681
  };
56523
56682
  try {
@@ -56532,10 +56691,10 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56532
56691
  return await buildProjectIndexFromExport(projectRoot, opts, { ignoreExistingManifest: true });
56533
56692
  }
56534
56693
  startCheckProgress();
56535
- const manifestStart = performance6.now();
56694
+ const manifestStart = performance7.now();
56536
56695
  const manifest = await loadManifest(projectRoot, opts, report);
56537
56696
  if (timings)
56538
- timings.manifestMs = Math.round(performance6.now() - manifestStart);
56697
+ timings.manifestMs = Math.round(performance7.now() - manifestStart);
56539
56698
  const manifestUsed = !!manifest;
56540
56699
  const manifestReport = initManifestReport(report, manifestUsed, false);
56541
56700
  if (manifestReport && !manifestUsed)
@@ -56590,11 +56749,11 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56590
56749
  if (!discoveryTimings || opts?.filesAreProjectScope)
56591
56750
  return await operation();
56592
56751
  sourceDiscoveryPerformed = true;
56593
- const start = performance6.now();
56752
+ const start = performance7.now();
56594
56753
  try {
56595
56754
  return await operation();
56596
56755
  } finally {
56597
- sourceDiscoveryMs += performance6.now() - start;
56756
+ sourceDiscoveryMs += performance7.now() - start;
56598
56757
  }
56599
56758
  };
56600
56759
  let manifestDiffFiles = [];
@@ -56794,13 +56953,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56794
56953
  const snapshot = snapshotLoad.index;
56795
56954
  snapshot.manifestSignaturesFresh = false;
56796
56955
  if (snapshot.projectFiles === void 0) {
56797
- const metadataDiscoveryStart = performance6.now();
56956
+ const metadataDiscoveryStart = performance7.now();
56798
56957
  snapshot.projectFiles = await discoverProjectFilesWithGitCandidates(projectRoot, {
56799
56958
  ...opts?.logLevel ? { logLevel: opts.logLevel } : {},
56800
56959
  ...discoveredGitCandidates !== void 0 ? { knownGitCandidates: discoveredGitCandidates } : {}
56801
56960
  });
56802
56961
  if (discoveryTimings)
56803
- discoveryTimings.metadataDiscoveryMs = Math.round(performance6.now() - metadataDiscoveryStart);
56962
+ discoveryTimings.metadataDiscoveryMs = Math.round(performance7.now() - metadataDiscoveryStart);
56804
56963
  }
56805
56964
  if (opts?.cache) {
56806
56965
  snapshot.cacheMode = opts.cache;
@@ -56838,7 +56997,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56838
56997
  const snapshot = await reuseUnchangedSnapshot();
56839
56998
  if (snapshot) {
56840
56999
  if (timings)
56841
- timings.totalMs = Math.round(performance6.now() - totalStart);
57000
+ timings.totalMs = Math.round(performance7.now() - totalStart);
56842
57001
  completeCheckProgress(allFiles.size);
56843
57002
  return snapshot;
56844
57003
  }
@@ -56908,7 +57067,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56908
57067
  unchangedSnapshot.manifestEntries = new Map(Array.from(fileSignatures, ([file2, signature]) => [file2, toProjectIndexManifestEntry(signature)]));
56909
57068
  unchangedSnapshot.manifestSignaturesFresh = true;
56910
57069
  if (timings)
56911
- timings.totalMs = Math.round(performance6.now() - totalStart);
57070
+ timings.totalMs = Math.round(performance7.now() - totalStart);
56912
57071
  completeCheckProgress(allFiles.size);
56913
57072
  return unchangedSnapshot;
56914
57073
  }
@@ -56950,13 +57109,13 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
56950
57109
  workerSetup = await setupWorkerPool(opts, countNativeWorkerEligibleFiles(changedList, opts?.languageExtensions));
56951
57110
  let updateStartedAt;
56952
57111
  if (changedList.length || deletedTrackedFiles.size) {
56953
- updateStartedAt = performance6.now();
57112
+ updateStartedAt = performance7.now();
56954
57113
  emitIndexLifecycleProgress(opts, "start", "update", changedList.length);
56955
57114
  }
56956
57115
  if (fileReport)
56957
57116
  fileReport.changed = changedList.length;
56958
57117
  if (changedList.length) {
56959
- const parseStart = performance6.now();
57118
+ const parseStart = performance7.now();
56960
57119
  let processedFiles = 0;
56961
57120
  const totalFiles = changedList.length;
56962
57121
  const fileResults = await mapLimit(changedList, conc, async (file2) => {
@@ -57019,7 +57178,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
57019
57178
  writeModulesToCache(projectRoot, pendingIncrementalCacheWrites, opts);
57020
57179
  }
57021
57180
  if (timings)
57022
- timings.parseMs = Math.round(performance6.now() - parseStart);
57181
+ timings.parseMs = Math.round(performance7.now() - parseStart);
57023
57182
  }
57024
57183
  for (const jsonPath of jsonDependencies.values()) {
57025
57184
  ensureJsonModule(modules, jsonPath);
@@ -57049,7 +57208,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
57049
57208
  }
57050
57209
  }
57051
57210
  const filesList = Array.from(changedFiles);
57052
- const graphStart = performance6.now();
57211
+ const graphStart = performance7.now();
57053
57212
  const graph = !filesList.length && baseGraph ? { nodes: new Set(baseGraph.nodes), edges: [...baseGraph.edges] } : await collectGraph(projectRoot, filesList, {
57054
57213
  parsed: parsedMap,
57055
57214
  fast: !!graphOptions.fast,
@@ -57075,7 +57234,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
57075
57234
  }
57076
57235
  });
57077
57236
  if (timings)
57078
- timings.graphMs = Math.round(performance6.now() - graphStart);
57237
+ timings.graphMs = Math.round(performance7.now() - graphStart);
57079
57238
  for (const file2 of /* @__PURE__ */ new Set([...changedFiles, ...transientFiles])) {
57080
57239
  const signature = fileSignatures.get(file2);
57081
57240
  if (!signature || manifestEntries.has(file2))
@@ -57135,7 +57294,7 @@ async function buildProjectIndexIncremental(projectRoot, rawOpts) {
57135
57294
  });
57136
57295
  await writeProjectIndexSnapshot(projectRoot, opts, index, projectSnapshotFilesSignature(manifestEntries, projectRoot));
57137
57296
  if (updateStartedAt !== void 0) {
57138
- emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance6.now() - updateStartedAt);
57297
+ emitIndexLifecycleProgress(opts, "complete", "update", index.byFile.size, performance7.now() - updateStartedAt);
57139
57298
  } else {
57140
57299
  completeCheckProgress(allFiles.size);
57141
57300
  }
@@ -57281,7 +57440,7 @@ async function buildGraphDelta(projectRoot, opts) {
57281
57440
  removed: removedRelative.sort(compareEdges)
57282
57441
  };
57283
57442
  }
57284
- var DISCOVERY_TIMING_STEP_NAMES;
57443
+ var TRANSIENT_BUILD_TIMING_STEP_NAMES;
57285
57444
  var init_build_index = __esm({
57286
57445
  "dist/indexer/build-index.js"() {
57287
57446
  "use strict";
@@ -57321,7 +57480,17 @@ var init_build_index = __esm({
57321
57480
  init_build_workers();
57322
57481
  init_incremental_plan();
57323
57482
  init_parsed_cache();
57324
- DISCOVERY_TIMING_STEP_NAMES = /* @__PURE__ */ new Set(["git-list", "git-ignore", "filesystem-scan"]);
57483
+ TRANSIENT_BUILD_TIMING_STEP_NAMES = {
57484
+ "git-list": true,
57485
+ "git-ignore": true,
57486
+ "filesystem-scan": true,
57487
+ "cache-probe": true,
57488
+ "persist-cache": true,
57489
+ "workspace-manifests": true,
57490
+ "index-manifest": true,
57491
+ finalize: true,
57492
+ "snapshot-write": true
57493
+ };
57325
57494
  }
57326
57495
  });
57327
57496
 
@@ -63284,12 +63453,15 @@ function resolveRawSqlQueryWorkerPath() {
63284
63453
  }
63285
63454
  async function runRawSqlQueryInWorker(task, deadlineMs, signal) {
63286
63455
  const workerPath = resolveRawSqlQueryWorkerPath();
63287
- return await rawSqlQueryWorkerLifecycle.run(task, deadlineMs, signal, () => new Piscina({
63288
- filename: workerPath,
63289
- minThreads: 1,
63290
- maxThreads: 1,
63291
- idleTimeout: 5e3
63292
- }));
63456
+ return await rawSqlQueryWorkerLifecycle.run(task, deadlineMs, signal, () => {
63457
+ markWindowsProcessDrainRequired();
63458
+ return new Piscina({
63459
+ filename: workerPath,
63460
+ minThreads: 1,
63461
+ maxThreads: 1,
63462
+ idleTimeout: 5e3
63463
+ });
63464
+ });
63293
63465
  }
63294
63466
  var MAX_RAW_SQL_QUERY_WORKERS, SqliteQueryDeadlineExceededError, SqliteQueryCancelledError, SqliteQueryWorkerCleanupCapacityExceededError, RawSqlQueryWorkerLifecycle, rawSqlQueryWorkerLifecycle;
63295
63467
  var init_rawQueryWorkerPool = __esm({
@@ -63297,6 +63469,7 @@ var init_rawQueryWorkerPool = __esm({
63297
63469
  "use strict";
63298
63470
  init_esm_wrapper();
63299
63471
  init_packageInfo();
63472
+ init_windowsProcessDrain();
63300
63473
  MAX_RAW_SQL_QUERY_WORKERS = 2;
63301
63474
  SqliteQueryDeadlineExceededError = class extends Error {
63302
63475
  constructor(deadlineMs) {
@@ -67955,7 +68128,7 @@ var init_deleted = __esm({
67955
68128
  });
67956
68129
 
67957
68130
  // dist/review/candidates.js
67958
- import { performance as performance7 } from "node:perf_hooks";
68131
+ import { performance as performance8 } from "node:perf_hooks";
67959
68132
  function relativePath(root, file2) {
67960
68133
  return toProjectDisplayPath(root, file2);
67961
68134
  }
@@ -67988,7 +68161,7 @@ function mergeCandidateTestEntries(baseCandidates, additionalCandidates) {
67988
68161
  return Array.from(merged.values());
67989
68162
  }
67990
68163
  async function collectReviewCandidateTests(input) {
67991
- const candidateStart = performance7.now();
68164
+ const candidateStart = performance8.now();
67992
68165
  const configuredMaxCandidates = input.appliedOptions.maxCandidates;
67993
68166
  const maxCandidates = typeof configuredMaxCandidates === "number" && Number.isFinite(configuredMaxCandidates) ? Math.max(0, Math.floor(configuredMaxCandidates)) : REVIEW_DEFAULT_CANDIDATE_TEST_LIMIT;
67994
68167
  const candidateTests = mergeCandidateTestEntries(listCandidateTestFiles(input.index, input.changedFileList, input.changedSymbolIds, {
@@ -68008,7 +68181,7 @@ async function collectReviewCandidateTests(input) {
68008
68181
  return left.reason.localeCompare(right.reason);
68009
68182
  }).slice(0, maxCandidates);
68010
68183
  if (input.reviewTimings) {
68011
- input.reviewTimings.candidatesMs = Math.round(performance7.now() - candidateStart);
68184
+ input.reviewTimings.candidatesMs = Math.round(performance8.now() - candidateStart);
68012
68185
  }
68013
68186
  return candidateTests;
68014
68187
  }
@@ -68304,7 +68477,7 @@ var init_parse4 = __esm({
68304
68477
  });
68305
68478
 
68306
68479
  // dist/review/changes.js
68307
- import { performance as performance8 } from "node:perf_hooks";
68480
+ import { performance as performance9 } from "node:perf_hooks";
68308
68481
  function deletedPathsForChange(change2) {
68309
68482
  if (change2.kind === "deleted") {
68310
68483
  return [change2.path];
@@ -68322,16 +68495,16 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68322
68495
  const isIncludedReviewFile = createImpactIncludeMatcher(discoveryGlobRoot, appliedOptions.discovery?.includeGlobs ?? []);
68323
68496
  const changedFiles = /* @__PURE__ */ new Set();
68324
68497
  const explicitFiles = /* @__PURE__ */ new Set();
68325
- const changesStart = performance8.now();
68498
+ const changesStart = performance9.now();
68326
68499
  for (const file2 of appliedOptions.files ?? []) {
68327
68500
  const normalized = normalizeFile(file2, "Review file");
68328
68501
  changedFiles.add(normalized);
68329
68502
  explicitFiles.add(normalized);
68330
68503
  }
68331
68504
  if (reviewTimings) {
68332
- reviewTimings.changesMs = Math.round(performance8.now() - changesStart);
68505
+ reviewTimings.changesMs = Math.round(performance9.now() - changesStart);
68333
68506
  }
68334
- const diffStart = performance8.now();
68507
+ const diffStart = performance9.now();
68335
68508
  const shouldLoadGitDiff = Boolean(appliedOptions.gitBase || appliedOptions.changedSince);
68336
68509
  const diffText = appliedOptions.diffText ?? (shouldLoadGitDiff ? await getUnifiedDiff(projectRoot, {
68337
68510
  base: appliedOptions.gitBase,
@@ -68340,7 +68513,7 @@ async function collectReviewChanges(projectRoot, appliedOptions, reviewTimings)
68340
68513
  }) : "");
68341
68514
  const diff = diffText ? parseUnifiedDiff(diffText) : null;
68342
68515
  if (reviewTimings) {
68343
- reviewTimings.diffMs = Math.round(performance8.now() - diffStart);
68516
+ reviewTimings.diffMs = Math.round(performance9.now() - diffStart);
68344
68517
  }
68345
68518
  const diffHunksByFile = /* @__PURE__ */ new Map();
68346
68519
  const diffKindsByFile = /* @__PURE__ */ new Map();
@@ -69714,10 +69887,10 @@ var init_severity = __esm({
69714
69887
  });
69715
69888
 
69716
69889
  // dist/impact/budgets.js
69717
- import { performance as performance9 } from "node:perf_hooks";
69890
+ import { performance as performance10 } from "node:perf_hooks";
69718
69891
  function createImpactWorkBudget(options) {
69719
69892
  return {
69720
- ...typeof options.timeBudgetMs === "number" && options.timeBudgetMs >= 0 ? { deadlineAt: performance9.now() + options.timeBudgetMs } : {},
69893
+ ...typeof options.timeBudgetMs === "number" && options.timeBudgetMs >= 0 ? { deadlineAt: performance10.now() + options.timeBudgetMs } : {},
69721
69894
  ...typeof options.maxReferenceLookups === "number" && options.maxReferenceLookups >= 0 ? { maxReferenceLookups: options.maxReferenceLookups } : {},
69722
69895
  ...typeof options.maxTotalReferences === "number" && options.maxTotalReferences >= 0 ? { maxTotalReferences: options.maxTotalReferences } : {},
69723
69896
  referenceLookupsStarted: 0,
@@ -69732,7 +69905,7 @@ function isImpactDeadlineExceeded(budget) {
69732
69905
  return true;
69733
69906
  if (budget.deadlineAt === void 0)
69734
69907
  return false;
69735
- if (performance9.now() >= budget.deadlineAt) {
69908
+ if (performance10.now() >= budget.deadlineAt) {
69736
69909
  budget.deadlineExceeded = true;
69737
69910
  return true;
69738
69911
  }
@@ -71786,7 +71959,7 @@ var init_referenceCache = __esm({
71786
71959
  // dist/review/summaries.js
71787
71960
  import fsp37 from "node:fs/promises";
71788
71961
  import path70 from "node:path";
71789
- import { performance as performance10 } from "node:perf_hooks";
71962
+ import { performance as performance11 } from "node:perf_hooks";
71790
71963
  function relativePath2(root, file2) {
71791
71964
  return toProjectDisplayPath(root, file2);
71792
71965
  }
@@ -72152,7 +72325,7 @@ async function summarizeChangedFiles2(input) {
72152
72325
  }
72153
72326
  }
72154
72327
  const defsToResolve = fileEntries.flatMap((entry) => entry.locals);
72155
- const referencesStart = performance10.now();
72328
+ const referencesStart = performance11.now();
72156
72329
  const referenceResults = includeSymbolDetails && maxCallsites > 0 ? await mapLimit(defsToResolve, referenceConcurrency, async (def) => {
72157
72330
  const refs = await referenceCache.get(index, def, {
72158
72331
  maxReferences: maxCallsites + 1
@@ -72160,7 +72333,7 @@ async function summarizeChangedFiles2(input) {
72160
72333
  return { def, refs };
72161
72334
  }) : [];
72162
72335
  if (reviewTimings) {
72163
- reviewTimings.referencesMs = Math.round(performance10.now() - referencesStart);
72336
+ reviewTimings.referencesMs = Math.round(performance11.now() - referencesStart);
72164
72337
  }
72165
72338
  const referencesByHandle = /* @__PURE__ */ new Map();
72166
72339
  for (const entry of referenceResults) {
@@ -72340,7 +72513,7 @@ var init_summaries = __esm({
72340
72513
  });
72341
72514
 
72342
72515
  // dist/review.js
72343
- import { performance as performance11 } from "node:perf_hooks";
72516
+ import { performance as performance12 } from "node:perf_hooks";
72344
72517
  function mergeGraphOptions2(base, override) {
72345
72518
  if (!base)
72346
72519
  return override;
@@ -72384,7 +72557,7 @@ async function buildReviewIndex(input) {
72384
72557
  diffChangesByFile,
72385
72558
  graphOptions
72386
72559
  });
72387
- const indexStart = performance11.now();
72560
+ const indexStart = performance12.now();
72388
72561
  const indexReport = reviewReport?.indexReport ?? (reviewReport ? { timings: {} } : void 0);
72389
72562
  if (reviewReport && !reviewReport.indexReport && indexReport) {
72390
72563
  reviewReport.indexReport = indexReport;
@@ -72417,7 +72590,7 @@ async function buildReviewIndex(input) {
72417
72590
  });
72418
72591
  }
72419
72592
  if (reviewTimings) {
72420
- reviewTimings.indexMs = Math.round(performance11.now() - indexStart);
72593
+ reviewTimings.indexMs = Math.round(performance12.now() - indexStart);
72421
72594
  }
72422
72595
  return {
72423
72596
  index,
@@ -72436,7 +72609,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72436
72609
  if (reviewReport && appliedOptions.duplicateTasks === false) {
72437
72610
  delete reviewReport.duplicateAnalysis;
72438
72611
  }
72439
- const totalStart = performance11.now();
72612
+ const totalStart = performance12.now();
72440
72613
  const { changedFiles, explicitFiles, diffHunksByFile, diffKindsByFile, diffChangesByFile } = await collectReviewChanges(projectRoot, appliedOptions, reviewTimings);
72441
72614
  if (changedFiles.size === 0) {
72442
72615
  const riskSummary = computeRiskSummary({
@@ -72470,7 +72643,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72470
72643
  report2.base = appliedOptions.gitBase;
72471
72644
  report2.head = appliedOptions.gitHead ?? "HEAD";
72472
72645
  if (reviewTimings)
72473
- reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72646
+ reviewTimings.totalMs = Math.round(performance12.now() - totalStart);
72474
72647
  return report2;
72475
72648
  }
72476
72649
  const changedFileList = Array.from(changedFiles).sort(comparePaths2);
@@ -72548,7 +72721,7 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72548
72721
  riskRelevantParseFailures,
72549
72722
  exportedChangedCount
72550
72723
  });
72551
- const duplicateAnalysisStart = performance11.now();
72724
+ const duplicateAnalysisStart = performance12.now();
72552
72725
  if (appliedOptions.duplicateTasks !== false) {
72553
72726
  const duplicateReview = await collectReviewDuplicateTasks({
72554
72727
  projectRoot,
@@ -72569,10 +72742,10 @@ async function buildReviewReport(projectRoot, opts = {}, cached2) {
72569
72742
  }
72570
72743
  }
72571
72744
  if (reviewTimings && appliedOptions.duplicateTasks !== false) {
72572
- reviewTimings.duplicateAnalysisMs = Math.round(performance11.now() - duplicateAnalysisStart);
72745
+ reviewTimings.duplicateAnalysisMs = Math.round(performance12.now() - duplicateAnalysisStart);
72573
72746
  }
72574
72747
  if (reviewTimings)
72575
- reviewTimings.totalMs = Math.round(performance11.now() - totalStart);
72748
+ reviewTimings.totalMs = Math.round(performance12.now() - totalStart);
72576
72749
  return report;
72577
72750
  }
72578
72751
  function buildSymbolDefLookup(index) {
@@ -75707,6 +75880,7 @@ async function prepareQueryIndexFilesInWorker(projectRoot, files) {
75707
75880
  } catch {
75708
75881
  return await prepareQueryIndexFilesInProcess(projectRoot, files);
75709
75882
  }
75883
+ markWindowsProcessDrainRequired();
75710
75884
  const pool = new Piscina({
75711
75885
  filename: workerPath,
75712
75886
  minThreads: 1,
@@ -75747,6 +75921,7 @@ var init_workerPool = __esm({
75747
75921
  init_content();
75748
75922
  init_paths2();
75749
75923
  init_workerThreads();
75924
+ init_windowsProcessDrain();
75750
75925
  QUERY_INDEX_MAX_THREADS = 4;
75751
75926
  QUERY_INDEX_WORKER_MIN_FILES = 512;
75752
75927
  }
@@ -78198,7 +78373,7 @@ ${SHARED_INDEX_OPTIONS_HELP}
78198
78373
  `;
78199
78374
  ORIENT_HELP_TEXT = `codegraph orient - Build a compact first-turn packet for agent repo context
78200
78375
 
78201
- Usage: codegraph orient [roots...] [--root <path>] [--budget small|medium|large] [--health skip|summary|full] [--json | --pretty]
78376
+ Usage: codegraph orient [roots...] [--root <path>] [--budget small|medium|large] [--health skip|summary|full] [--report [--report-file <path>]] [--json | --pretty]
78202
78377
 
78203
78378
  Output:
78204
78379
  Orientation includes summary bullets, ranked focus targets with follow-up commands, a bounded project tree, budgeted health counts, and omission counts.
@@ -78255,13 +78430,13 @@ ${SHARED_INDEX_OPTIONS_HELP}
78255
78430
  SERVER_HELP_TEXT = `codegraph server - Manage a shared project-local MCP HTTP server
78256
78431
 
78257
78432
  Usage:
78258
- codegraph server start [--root <path>] [--host <host>] [--port <1-65535>] [--startup-timeout-ms <1-86400000>] [--json] [--replace] [--warmup | --warmup-symbols]
78433
+ codegraph server start [--root <path>] [--host <host>] [--port <1-65535>] [--startup-timeout-ms <1-86400000>] [--json] [--replace] [--warmup | --warmup-symbols | --no-warmup]
78259
78434
  codegraph server status [--root <path>] [--json | --pretty]
78260
78435
  codegraph server stop [--root <path>]
78261
78436
 
78262
78437
  Behavior:
78263
78438
  start runs codegraph mcp serve in a separate process, waits for a challenged /health proof, then writes .codegraph/server.json. --json emits the started registry with status and update fields; startup diagnostics go to .codegraph/server.log.
78264
- The default server listens on 127.0.0.1:7331. A public bind requires an explicit --host. --startup-timeout-ms defaults to 15000 and allows up to 86400000 for long warmups.
78439
+ The default server listens on 127.0.0.1:7331. A public bind requires an explicit --host. --startup-timeout-ms defaults to 15000 and allows up to 86400000 for long warmups. Startup warms the base session cache by default; --no-warmup starts lazily instead, and --warmup-symbols also warms the detailed symbol graph.
78265
78440
  status retries proven health checks and reports a verification remedy for an unreachable or mismatched server. stop removes only confirmed stale registries or signals a Codegraph server whose root, process, and startup time match the registry.
78266
78441
 
78267
78442
  Forwarded startup options:
@@ -78273,13 +78448,14 @@ Safety:
78273
78448
  `;
78274
78449
  MCP_HELP_TEXT = `codegraph mcp - Serve MCP tools for agent graph navigation
78275
78450
 
78276
- Usage: codegraph mcp [serve] [--root <path>] [--artifact <path>] [--stdio | --port <number>] [--host <host>] [--idle-timeout-ms <ms>] [--allow-build] [--warmup | --warmup-symbols]
78451
+ Usage: codegraph mcp [serve] [--root <path>] [--artifact <path>] [--stdio | --port <number>] [--host <host>] [--idle-timeout-ms <ms>] [--allow-build] [--warmup | --warmup-symbols | --no-warmup]
78277
78452
 
78278
78453
  Transports:
78279
78454
  --stdio Serve MCP over stdio (default)
78280
78455
  --port <number> Serve Streamable HTTP at /mcp
78281
- --warmup Build the base session cache at startup
78456
+ --warmup Build the base session cache at startup (default)
78282
78457
  --warmup-symbols Build the base cache and detailed symbol graph at startup
78458
+ --no-warmup Skip startup warmup; the first tool call pays for discovery and building
78283
78459
 
78284
78460
  Index Options:
78285
78461
  --cache <mode> Session cache mode: disk, memory, off
@@ -78298,7 +78474,7 @@ Tools are read-only unless --allow-build is passed.
78298
78474
  `;
78299
78475
  MCP_SERVE_HELP_TEXT = `codegraph mcp serve - MCP server for agent graph navigation
78300
78476
 
78301
- Usage: codegraph mcp [serve] [--root <path>] [--artifact <path>] [--stdio | --port <number>] [--host <host>] [--idle-timeout-ms <ms>] [--allow-build] [--warmup | --warmup-symbols]
78477
+ Usage: codegraph mcp [serve] [--root <path>] [--artifact <path>] [--stdio | --port <number>] [--host <host>] [--idle-timeout-ms <ms>] [--allow-build] [--warmup | --warmup-symbols | --no-warmup]
78302
78478
 
78303
78479
  Tools:
78304
78480
  orient Build a compact first-turn repo packet
@@ -78333,7 +78509,7 @@ Index Options:
78333
78509
  Defaults:
78334
78510
  Transport defaults to stdio.
78335
78511
  HTTP transport binds to 127.0.0.1 unless --host is passed and serves /mcp.
78336
- Startup is lazy unless --warmup or --warmup-symbols is passed.
78512
+ Startup warms the base session cache by default. --warmup-symbols also warms the detailed symbol graph. --no-warmup starts lazily instead, leaving the first tool call to pay for discovery and building.
78337
78513
  Warmup uses the configured session cache and shared index flags.
78338
78514
  Tools are read-only unless --allow-build is passed.
78339
78515
  `;
@@ -78658,7 +78834,7 @@ var search_exports = {};
78658
78834
  __export(search_exports, {
78659
78835
  handleSearchCommand: () => handleSearchCommand
78660
78836
  });
78661
- import { performance as performance12 } from "node:perf_hooks";
78837
+ import { performance as performance13 } from "node:perf_hooks";
78662
78838
  function parseAgentSearchMode(rawValue) {
78663
78839
  if (rawValue === void 0)
78664
78840
  return "hybrid";
@@ -78668,7 +78844,7 @@ function parseAgentSearchMode(rawValue) {
78668
78844
  throw new Error(`Invalid --mode value "${rawValue}". Expected hybrid, symbol, path, text, graph, or sql.`);
78669
78845
  }
78670
78846
  async function handleSearchCommand(context) {
78671
- const commandStart = performance12.now();
78847
+ const commandStart = performance13.now();
78672
78848
  const query = context.positionals.join(" ").trim();
78673
78849
  if (!query) {
78674
78850
  context.writeStderrLine(SEARCH_HELP_TEXT.trimEnd());
@@ -78692,7 +78868,7 @@ async function handleSearchCommand(context) {
78692
78868
  context.writeStdoutLine(formatAgentSearchResponse(response));
78693
78869
  }
78694
78870
  if (context.commandReport && context.writeCommandReport) {
78695
- context.commandReport.timings.commandMs = Math.round(performance12.now() - commandStart);
78871
+ context.commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
78696
78872
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
78697
78873
  await context.writeCommandReport(context.commandReport, context.reportFile);
78698
78874
  }
@@ -85073,6 +85249,7 @@ __export(orient_exports, {
85073
85249
  formatAgentOrientation: () => formatAgentOrientation,
85074
85250
  handleOrientCommand: () => handleOrientCommand
85075
85251
  });
85252
+ import { performance as performance14 } from "node:perf_hooks";
85076
85253
  function parseAgentOrientBudget(rawValue) {
85077
85254
  if (rawValue === void 0)
85078
85255
  return "small";
@@ -85090,9 +85267,15 @@ function parseAgentOrientHealthMode(rawValue) {
85090
85267
  throw new Error(`Invalid --health value "${rawValue}". Expected skip, summary, or full.`);
85091
85268
  }
85092
85269
  async function handleOrientCommand(context) {
85270
+ const commandStart = performance14.now();
85093
85271
  const healthMode = parseAgentOrientHealthMode(context.getOpt("--health"));
85094
85272
  const writesJson = context.hasFlag("--json");
85095
- const buildOptions = { ...context.buildOptions ?? {}, logLevel: "silent" };
85273
+ const indexReport = context.commandReport?.index;
85274
+ const buildOptions = {
85275
+ ...context.buildOptions ?? {},
85276
+ logLevel: "silent",
85277
+ ...indexReport ? { report: indexReport } : {}
85278
+ };
85096
85279
  const response = await orientCodegraph({
85097
85280
  root: context.root,
85098
85281
  includeRoots: context.positionals,
@@ -85105,6 +85288,11 @@ async function handleOrientCommand(context) {
85105
85288
  } else {
85106
85289
  context.writeStdoutLine(formatAgentOrientation(response));
85107
85290
  }
85291
+ if (context.commandReport && context.writeCommandReport) {
85292
+ context.commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
85293
+ context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
85294
+ await context.writeCommandReport(context.commandReport, context.reportFile);
85295
+ }
85108
85296
  }
85109
85297
  function formatAgentOrientation(response) {
85110
85298
  const lines = ["Summary", ...response.summary.map((entry) => `- ${entry}`)];
@@ -101592,19 +101780,19 @@ function createCodegraphMcpSession(options, root) {
101592
101780
  freshness: { policy: "auto" }
101593
101781
  });
101594
101782
  }
101595
- function startCodegraphMcpWarmup(session, warmup) {
101596
- if (warmup === "base") {
101597
- return session.loadProject({ symbolGraph: "skip" });
101598
- }
101599
- if (warmup === "symbols") {
101783
+ function startCodegraphMcpWarmup(session, warmup, sessionProvidedExplicitly) {
101784
+ const mode = warmup ?? (sessionProvidedExplicitly ? "off" : "base");
101785
+ if (mode === "off")
101786
+ return void 0;
101787
+ if (mode === "symbols")
101600
101788
  return session.loadProject();
101601
- }
101602
- return void 0;
101789
+ return session.loadProject({ symbolGraph: "skip" });
101603
101790
  }
101604
101791
  async function createWarmedCodegraphMcpResources(options) {
101605
101792
  const root = path85.resolve(options.root);
101793
+ const sessionProvidedExplicitly = options.session !== void 0;
101606
101794
  const session = createCodegraphMcpSession(options, root);
101607
- await startCodegraphMcpWarmup(session, options.warmup);
101795
+ await startCodegraphMcpWarmup(session, options.warmup, sessionProvidedExplicitly);
101608
101796
  const { warmup, host, port, onHttpListen, ...handlerOptions } = options;
101609
101797
  void warmup;
101610
101798
  void host;
@@ -102112,7 +102300,7 @@ function createCodegraphMcpHandlersForSession(options, session) {
102112
102300
  sqlitePath = configuredSqlitePath;
102113
102301
  sqliteOutDir = configuredSqliteOutDir;
102114
102302
  sqliteCanRefresh = configuredSqliteCanRefresh;
102115
- await startCodegraphMcpWarmup(session, warmup);
102303
+ await startCodegraphMcpWarmup(session, warmup, true);
102116
102304
  })();
102117
102305
  refreshPromise = refresh;
102118
102306
  try {
@@ -105636,7 +105824,7 @@ var init_protocol = __esm({
105636
105824
  init_runtime();
105637
105825
  init_runtimeIdentity();
105638
105826
  init_legacySessions();
105639
- DEFAULT_MCP_TOOL_TIMEOUT_MS = 30 * 60 * 1e3;
105827
+ DEFAULT_MCP_TOOL_TIMEOUT_MS = 5 * 60 * 1e3;
105640
105828
  MAX_MCP_TOOL_TIMEOUT_MS = 2147483647;
105641
105829
  MAX_MCP_STDIO_FRAME_BYTES = 10 * 1024 * 1024;
105642
105830
  DEFAULT_MCP_TOOL_CONCURRENCY = 4;
@@ -106215,7 +106403,7 @@ async function handleMcpServeCommand(context) {
106215
106403
  ...host !== void 0 ? { host } : {},
106216
106404
  ...artifactPath !== void 0 ? { artifactPath } : {},
106217
106405
  ...context.buildOptions !== void 0 ? { buildOptions: context.buildOptions } : {},
106218
- ...warmup !== void 0 ? { warmup } : {},
106406
+ warmup,
106219
106407
  ...idleTimeoutMs !== void 0 ? { idleTimeoutMs } : {},
106220
106408
  onHttpListen: (info) => {
106221
106409
  context.writeStderrLine(`Codegraph MCP HTTP server listening at ${info.url}`);
@@ -106223,15 +106411,20 @@ async function handleMcpServeCommand(context) {
106223
106411
  });
106224
106412
  }
106225
106413
  function parseMcpWarmupMode(context) {
106226
- if (context.hasFlag("--warmup") && context.hasFlag("--warmup-symbols")) {
106227
- context.writeStderrLine("Choose either --warmup or --warmup-symbols for mcp serve startup.");
106414
+ const explicit = [
106415
+ context.hasFlag("--warmup"),
106416
+ context.hasFlag("--warmup-symbols"),
106417
+ context.hasFlag("--no-warmup")
106418
+ ].filter(Boolean).length;
106419
+ if (explicit > 1) {
106420
+ context.writeStderrLine("Choose only one of --warmup, --warmup-symbols, or --no-warmup for mcp serve startup.");
106228
106421
  context.exit(2);
106229
106422
  }
106230
106423
  if (context.hasFlag("--warmup-symbols"))
106231
106424
  return "symbols";
106232
- if (context.hasFlag("--warmup"))
106233
- return "base";
106234
- return void 0;
106425
+ if (context.hasFlag("--no-warmup"))
106426
+ return "off";
106427
+ return "base";
106235
106428
  }
106236
106429
  var init_mcp = __esm({
106237
106430
  "dist/cli/mcp.js"() {
@@ -106312,8 +106505,8 @@ function parseServerStartOptions(context) {
106312
106505
  }
106313
106506
  }
106314
106507
  async function startServerForRoot(context, root, options) {
106315
- if (context.hasFlag("--warmup") && context.hasFlag("--warmup-symbols")) {
106316
- throw new ServerUsageError("Choose either --warmup or --warmup-symbols for server start.");
106508
+ if ([context.hasFlag("--warmup"), context.hasFlag("--warmup-symbols"), context.hasFlag("--no-warmup")].filter(Boolean).length > 1) {
106509
+ throw new ServerUsageError("Choose only one of --warmup, --warmup-symbols, or --no-warmup for server start.");
106317
106510
  }
106318
106511
  const existingStatus = await readServerStatus(root);
106319
106512
  if (existingStatus.status === "live") {
@@ -106592,6 +106785,8 @@ async function spawnServerProcess(root, host, port, lifecycleCredential, context
106592
106785
  args.push("--warmup");
106593
106786
  if (context.hasFlag("--warmup-symbols"))
106594
106787
  args.push("--warmup-symbols");
106788
+ if (context.hasFlag("--no-warmup"))
106789
+ args.push("--no-warmup");
106595
106790
  for (const flag of FORWARDED_FLAGS) {
106596
106791
  if (context.hasFlag(flag))
106597
106792
  args.push(flag);
@@ -107084,6 +107279,7 @@ var init_server2 = __esm({
107084
107279
  "--replace",
107085
107280
  "--warmup",
107086
107281
  "--warmup-symbols",
107282
+ "--no-warmup",
107087
107283
  "--workers",
107088
107284
  "--json",
107089
107285
  "--pretty"
@@ -107673,7 +107869,7 @@ __export(graph_exports, {
107673
107869
  import fs42 from "node:fs";
107674
107870
  import fsp40 from "node:fs/promises";
107675
107871
  import path88 from "node:path";
107676
- import { performance as performance13 } from "node:perf_hooks";
107872
+ import { performance as performance15 } from "node:perf_hooks";
107677
107873
  function resolveGraphCacheMode(cache) {
107678
107874
  return cache ?? "disk";
107679
107875
  }
@@ -107813,11 +108009,11 @@ function stabilizeSymbolGraph(graph) {
107813
108009
  }
107814
108010
  async function handleGraphCommand(context) {
107815
108011
  const commandReport = context.reportEnabled ? { command: "graph", timings: {} } : void 0;
107816
- const commandStart = performance13.now();
107817
- const resolveStart = performance13.now();
108012
+ const commandStart = performance15.now();
108013
+ const resolveStart = performance15.now();
107818
108014
  const files = await context.resolveFiles();
107819
108015
  if (commandReport) {
107820
- commandReport.timings.resolveFilesMs = Math.round(performance13.now() - resolveStart);
108016
+ commandReport.timings.resolveFilesMs = Math.round(performance15.now() - resolveStart);
107821
108017
  }
107822
108018
  const hasExplicitSymbolFlag = context.hasFlag("--symbols") || context.hasFlag("--symbols-only") || context.hasFlag("--symbols-detailed");
107823
108019
  const outputArg = context.getOpt("--output") ?? context.getOpt("--out");
@@ -107859,7 +108055,7 @@ async function handleGraphCommand(context) {
107859
108055
  const finalizeReport = async () => {
107860
108056
  if (!commandReport)
107861
108057
  return;
107862
- commandReport.timings.commandMs = Math.round(performance13.now() - commandStart);
108058
+ commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
107863
108059
  commandReport.timings.totalMs = commandReport.timings.commandMs;
107864
108060
  await context.writeCommandReport(commandReport, context.reportFile);
107865
108061
  };
@@ -108079,7 +108275,7 @@ var cli_exports = {};
108079
108275
  __export(cli_exports, {
108080
108276
  handleIndexCommand: () => handleIndexCommand
108081
108277
  });
108082
- import { performance as performance14 } from "node:perf_hooks";
108278
+ import { performance as performance16 } from "node:perf_hooks";
108083
108279
  function formatIndexOutput(output) {
108084
108280
  const lines = [`Indexed ${output.files} file(s) with ${output.edges} edge(s).`];
108085
108281
  if (output.analysis.mode !== "semantic") {
@@ -108097,11 +108293,11 @@ function formatIndexOutput(output) {
108097
108293
  async function handleIndexCommand(context) {
108098
108294
  const verbose = context.hasFlag("--verbose");
108099
108295
  const commandReport = context.reportEnabled ? { command: "index", timings: {} } : void 0;
108100
- const commandStart = performance14.now();
108101
- const resolveStart = performance14.now();
108296
+ const commandStart = performance16.now();
108297
+ const resolveStart = performance16.now();
108102
108298
  const files = await context.resolveFiles();
108103
108299
  if (commandReport) {
108104
- commandReport.timings.resolveFilesMs = Math.round(performance14.now() - resolveStart);
108300
+ commandReport.timings.resolveFilesMs = Math.round(performance16.now() - resolveStart);
108105
108301
  }
108106
108302
  const threads = parseNonNegativeIntegerOption(context.getOpt("--threads"), "--threads", 0);
108107
108303
  const cache = parseCacheModeOption(context.getOpt("--cache"));
@@ -108167,7 +108363,7 @@ async function handleIndexCommand(context) {
108167
108363
  }
108168
108364
  }
108169
108365
  if (commandReport) {
108170
- commandReport.timings.commandMs = Math.round(performance14.now() - commandStart);
108366
+ commandReport.timings.commandMs = Math.round(performance16.now() - commandStart);
108171
108367
  commandReport.timings.totalMs = commandReport.timings.commandMs;
108172
108368
  await context.writeCommandReport(commandReport, context.reportFile);
108173
108369
  }
@@ -111160,7 +111356,7 @@ var review_exports = {};
111160
111356
  __export(review_exports, {
111161
111357
  handleReviewCommand: () => handleReviewCommand
111162
111358
  });
111163
- import { performance as performance15 } from "node:perf_hooks";
111359
+ import { performance as performance17 } from "node:perf_hooks";
111164
111360
  import path92 from "node:path";
111165
111361
  function parseReviewDepth(value) {
111166
111362
  if (value === "minimal" || value === "standard" || value === "deep") {
@@ -111352,7 +111548,7 @@ async function collectReviewDuplicateSummary(input) {
111352
111548
  });
111353
111549
  }
111354
111550
  async function handleReviewCommand(context) {
111355
- const commandStart = performance15.now();
111551
+ const commandStart = performance17.now();
111356
111552
  const changedSince = context.getOpt("--changed-since");
111357
111553
  const base = context.getOpt("--base") ?? (changedSince === void 0 ? "HEAD" : void 0);
111358
111554
  const head = context.getOpt("--head") ?? (changedSince === void 0 ? "WORKTREE" : void 0);
@@ -111447,7 +111643,7 @@ async function handleReviewCommand(context) {
111447
111643
  context.writeJSONLine(report);
111448
111644
  }
111449
111645
  if (context.commandReport) {
111450
- context.commandReport.timings.commandMs = Math.round(performance15.now() - commandStart);
111646
+ context.commandReport.timings.commandMs = Math.round(performance17.now() - commandStart);
111451
111647
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
111452
111648
  await context.writeCommandReport(context.commandReport, context.reportFile);
111453
111649
  }
@@ -111736,7 +111932,7 @@ __export(inspect_exports, {
111736
111932
  handleHotspotsCommand: () => handleHotspotsCommand,
111737
111933
  handleInspectCommand: () => handleInspectCommand
111738
111934
  });
111739
- import { performance as performance16 } from "node:perf_hooks";
111935
+ import { performance as performance18 } from "node:perf_hooks";
111740
111936
  import fs44 from "node:fs";
111741
111937
  import path93 from "node:path";
111742
111938
  function defaultCacheIndexPath(projectRoot, cacheDir, cacheLocation) {
@@ -111998,18 +112194,18 @@ async function buildInspectReport(projectRoot, includeRoots, files, discovery, g
111998
112194
  };
111999
112195
  }
112000
112196
  async function handleInspectCommand(context) {
112001
- const commandStart = performance16.now();
112197
+ const commandStart = performance18.now();
112002
112198
  const cache = parseCacheModeOption(context.getOpt("--cache"));
112003
112199
  const limit = parsePositiveIntegerOption(context.getOpt("--limit"), "--limit", 20);
112004
- const resolveStart = performance16.now();
112200
+ const resolveStart = performance18.now();
112005
112201
  const files = await context.resolveFilesFromRoots();
112006
112202
  if (context.commandReport) {
112007
- context.commandReport.timings.resolveFilesMs = Math.round(performance16.now() - resolveStart);
112203
+ context.commandReport.timings.resolveFilesMs = Math.round(performance18.now() - resolveStart);
112008
112204
  }
112009
112205
  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);
112010
112206
  writeCliOutput(context, report, formatInspectReport);
112011
112207
  if (context.commandReport && context.writeCommandReport) {
112012
- context.commandReport.timings.commandMs = Math.round(performance16.now() - commandStart);
112208
+ context.commandReport.timings.commandMs = Math.round(performance18.now() - commandStart);
112013
112209
  context.commandReport.timings.totalMs = context.commandReport.timings.commandMs;
112014
112210
  await context.writeCommandReport(context.commandReport, context.reportFile);
112015
112211
  }
@@ -112353,8 +112549,19 @@ var init_commandTable = __esm({
112353
112549
  orient: {
112354
112550
  stage: "project",
112355
112551
  run: async (ctx) => {
112552
+ const commandReport = ctx.reportEnabled ? { command: "orient", timings: {} } : void 0;
112553
+ const indexReport = ctx.reportEnabled ? { timings: {} } : void 0;
112554
+ if (commandReport && indexReport)
112555
+ commandReport.index = indexReport;
112356
112556
  const { handleOrientCommand: handleOrientCommand2 } = await Promise.resolve().then(() => (init_orient2(), orient_exports));
112357
- await handleOrientCommand2({ ...agentIo(ctx), positionals: ctx.includeRoots, ...agentIoWriters });
112557
+ await handleOrientCommand2({
112558
+ ...agentIo(ctx),
112559
+ positionals: ctx.includeRoots,
112560
+ reportFile: ctx.reportFile,
112561
+ commandReport,
112562
+ writeCommandReport,
112563
+ ...agentIoWriters
112564
+ });
112358
112565
  }
112359
112566
  },
112360
112567
  packet: {