@vibgrate/cli 2026.731.3 → 2026.803.1

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 (116) hide show
  1. package/dist/agent-HNV2VUCO.js +24 -0
  2. package/dist/{agent-6XOI7RVW.js.map → agent-HNV2VUCO.js.map} +1 -1
  3. package/dist/baseline-6WTULHM5.js +9 -0
  4. package/dist/{baseline-PY6TETA5.js.map → baseline-6WTULHM5.js.map} +1 -1
  5. package/dist/{chunk-B6S2DSBS.js → chunk-2TLQDF6C.js} +129 -20
  6. package/dist/chunk-2TLQDF6C.js.map +1 -0
  7. package/dist/{chunk-X634FZVG.js → chunk-3LOWJSAF.js} +11 -16
  8. package/dist/{chunk-X634FZVG.js.map → chunk-3LOWJSAF.js.map} +1 -1
  9. package/dist/{chunk-BMUTNUB7.js → chunk-4HFSUIIN.js} +117 -6
  10. package/dist/chunk-4HFSUIIN.js.map +1 -0
  11. package/dist/{chunk-3VSU7G75.js → chunk-536J6HUR.js} +235 -13
  12. package/dist/chunk-536J6HUR.js.map +1 -0
  13. package/dist/{chunk-EETK7S43.js → chunk-5VH3Y4QC.js} +111 -33
  14. package/dist/chunk-5VH3Y4QC.js.map +1 -0
  15. package/dist/{chunk-PHGAUWWF.js → chunk-6I4TXAI6.js} +3 -3
  16. package/dist/{chunk-PHGAUWWF.js.map → chunk-6I4TXAI6.js.map} +1 -1
  17. package/dist/{chunk-FF5ZQ6KI.js → chunk-6JP7HGIF.js} +4 -4
  18. package/dist/{chunk-FF5ZQ6KI.js.map → chunk-6JP7HGIF.js.map} +1 -1
  19. package/dist/chunk-AJ2KE3NT.js +446 -0
  20. package/dist/chunk-AJ2KE3NT.js.map +1 -0
  21. package/dist/{chunk-WK52LWRX.js → chunk-B2KLJPFY.js} +5 -5
  22. package/dist/{chunk-WK52LWRX.js.map → chunk-B2KLJPFY.js.map} +1 -1
  23. package/dist/{chunk-Z7VH4RPO.js → chunk-BBFQZ7CA.js} +4 -4
  24. package/dist/{chunk-Z7VH4RPO.js.map → chunk-BBFQZ7CA.js.map} +1 -1
  25. package/dist/{chunk-FHJBGPJZ.js → chunk-BWMMR5XA.js} +4 -4
  26. package/dist/{chunk-FHJBGPJZ.js.map → chunk-BWMMR5XA.js.map} +1 -1
  27. package/dist/{chunk-KLO2XBUX.js → chunk-CC6F75GI.js} +14 -7
  28. package/dist/chunk-CC6F75GI.js.map +1 -0
  29. package/dist/{chunk-SCTLOFNH.js → chunk-CE45STY5.js} +4 -4
  30. package/dist/{chunk-SCTLOFNH.js.map → chunk-CE45STY5.js.map} +1 -1
  31. package/dist/{chunk-MOLBANFB.js → chunk-DIU3MXB3.js} +4 -4
  32. package/dist/{chunk-MOLBANFB.js.map → chunk-DIU3MXB3.js.map} +1 -1
  33. package/dist/{chunk-5IA2TA57.js → chunk-FKFRASAB.js} +323 -152
  34. package/dist/chunk-FKFRASAB.js.map +1 -0
  35. package/dist/{chunk-EVLS2M5G.js → chunk-JFE7XCAE.js} +3 -3
  36. package/dist/{chunk-EVLS2M5G.js.map → chunk-JFE7XCAE.js.map} +1 -1
  37. package/dist/{chunk-RGEVBSLK.js → chunk-JUSXLCSE.js} +3 -3
  38. package/dist/{chunk-RGEVBSLK.js.map → chunk-JUSXLCSE.js.map} +1 -1
  39. package/dist/{chunk-7G5S5KZN.js → chunk-KUZLILN3.js} +16 -3
  40. package/dist/chunk-KUZLILN3.js.map +1 -0
  41. package/dist/{chunk-AVCBKQKA.js → chunk-N4IDP2M2.js} +218 -51
  42. package/dist/chunk-N4IDP2M2.js.map +1 -0
  43. package/dist/{chunk-XRN7DQGR.js → chunk-NJFQCDGA.js} +3 -3
  44. package/dist/{chunk-XRN7DQGR.js.map → chunk-NJFQCDGA.js.map} +1 -1
  45. package/dist/{chunk-LTTVCI5C.js → chunk-O7MTBC52.js} +134 -9
  46. package/dist/chunk-O7MTBC52.js.map +1 -0
  47. package/dist/chunk-QT2PMGN3.js +6 -0
  48. package/dist/{chunk-DEKGSQHL.js.map → chunk-QT2PMGN3.js.map} +1 -1
  49. package/dist/{chunk-5XIEVZLW.js → chunk-S4NSF5AZ.js} +6 -6
  50. package/dist/{chunk-5XIEVZLW.js.map → chunk-S4NSF5AZ.js.map} +1 -1
  51. package/dist/{chunk-TRKRRX2S.js → chunk-SJFBXCII.js} +35 -6
  52. package/dist/chunk-SJFBXCII.js.map +1 -0
  53. package/dist/{chunk-RIWLXMMT.js → chunk-SNKTD23L.js} +109 -10
  54. package/dist/chunk-SNKTD23L.js.map +1 -0
  55. package/dist/{chunk-IPICO2RV.js → chunk-VIWZ4QT7.js} +14 -3
  56. package/dist/chunk-VIWZ4QT7.js.map +1 -0
  57. package/dist/{chunk-US2DAKCM.js → chunk-Y7YKUZ3T.js} +8 -7
  58. package/dist/chunk-Y7YKUZ3T.js.map +1 -0
  59. package/dist/cli.js +732 -347
  60. package/dist/cli.js.map +1 -1
  61. package/dist/ensure-map-5YEI7R7V.js +29 -0
  62. package/dist/{ensure-map-UQL7SM34.js.map → ensure-map-5YEI7R7V.js.map} +1 -1
  63. package/dist/{graph-backend-G5Y6QQV4.js → graph-backend-CPHLUKUC.js} +5 -5
  64. package/dist/{graph-backend-G5Y6QQV4.js.map → graph-backend-CPHLUKUC.js.map} +1 -1
  65. package/dist/index.d.ts +127 -9
  66. package/dist/index.js +17 -16
  67. package/dist/index.js.map +1 -1
  68. package/dist/{interactive-QWT7ERXJ.js → interactive-TNRE4OEK.js} +46 -33
  69. package/dist/interactive-TNRE4OEK.js.map +1 -0
  70. package/dist/{llm-host-DZBD5D36.js → llm-host-XFYFOAAX.js} +4 -4
  71. package/dist/{llm-host-DZBD5D36.js.map → llm-host-XFYFOAAX.js.map} +1 -1
  72. package/dist/load-MWG6WZTK.js +10 -0
  73. package/dist/{load-WA53B3GW.js.map → load-MWG6WZTK.js.map} +1 -1
  74. package/dist/model-manager-GJ2YSTSK.js +1 -1
  75. package/dist/{run-outcome-J2IDIVYI.js → run-outcome-375HMSQG.js} +6 -6
  76. package/dist/{run-outcome-J2IDIVYI.js.map → run-outcome-375HMSQG.js.map} +1 -1
  77. package/dist/runtime-session-3MPWXNRL.js +20 -0
  78. package/dist/{runtime-session-52P2Y5LX.js.map → runtime-session-3MPWXNRL.js.map} +1 -1
  79. package/dist/session-2NGJLI5Y.js +15 -0
  80. package/dist/{session-L7SJNE55.js.map → session-2NGJLI5Y.js.map} +1 -1
  81. package/dist/session-store-F7NX7SZN.js +4 -0
  82. package/dist/{session-store-SQECEXUU.js.map → session-store-F7NX7SZN.js.map} +1 -1
  83. package/dist/{stream-json-TSGYC2MQ.js → stream-json-AUMU3NLV.js} +48 -16
  84. package/dist/stream-json-AUMU3NLV.js.map +1 -0
  85. package/dist/{vg-mcp-bridge-IFAXEQMZ.js → vg-mcp-bridge-D463EHQI.js} +13 -11
  86. package/dist/vg-mcp-bridge-D463EHQI.js.map +1 -0
  87. package/dist/{vgd-PNR7UKLL.js → vgd-Z23PXSP4.js} +10 -10
  88. package/dist/vgd-Z23PXSP4.js.map +1 -0
  89. package/package.json +4 -2
  90. package/dist/agent-6XOI7RVW.js +0 -22
  91. package/dist/baseline-PY6TETA5.js +0 -9
  92. package/dist/chunk-3VSU7G75.js.map +0 -1
  93. package/dist/chunk-5IA2TA57.js.map +0 -1
  94. package/dist/chunk-7G5S5KZN.js.map +0 -1
  95. package/dist/chunk-AVCBKQKA.js.map +0 -1
  96. package/dist/chunk-B6S2DSBS.js.map +0 -1
  97. package/dist/chunk-BMUTNUB7.js.map +0 -1
  98. package/dist/chunk-DEKGSQHL.js +0 -6
  99. package/dist/chunk-EETK7S43.js.map +0 -1
  100. package/dist/chunk-IPICO2RV.js.map +0 -1
  101. package/dist/chunk-KLO2XBUX.js.map +0 -1
  102. package/dist/chunk-LTTVCI5C.js.map +0 -1
  103. package/dist/chunk-RIWLXMMT.js.map +0 -1
  104. package/dist/chunk-TRKRRX2S.js.map +0 -1
  105. package/dist/chunk-US2DAKCM.js.map +0 -1
  106. package/dist/chunk-ZKNB4YH4.js +0 -102
  107. package/dist/chunk-ZKNB4YH4.js.map +0 -1
  108. package/dist/ensure-map-UQL7SM34.js +0 -28
  109. package/dist/interactive-QWT7ERXJ.js.map +0 -1
  110. package/dist/load-WA53B3GW.js +0 -10
  111. package/dist/runtime-session-52P2Y5LX.js +0 -20
  112. package/dist/session-L7SJNE55.js +0 -13
  113. package/dist/session-store-SQECEXUU.js +0 -4
  114. package/dist/stream-json-TSGYC2MQ.js.map +0 -1
  115. package/dist/vg-mcp-bridge-IFAXEQMZ.js.map +0 -1
  116. package/dist/vgd-PNR7UKLL.js.map +0 -1
@@ -1,16 +1,16 @@
1
- import { FREE_PACK, navigationToolsetConfig, deferredToolNames, HOT_TOOLS } from './chunk-RIWLXMMT.js';
2
- import { edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-IPICO2RV.js';
1
+ import { FREE_PACK, navigationToolsetConfig, deferredToolNames, HOT_TOOLS } from './chunk-SNKTD23L.js';
2
+ import { edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-VIWZ4QT7.js';
3
3
  import { init_cli_invocation, whichOnPath, isInstalledOwnBinary } from './chunk-3LSG7Z4I.js';
4
- import { indexFor } from './chunk-EETK7S43.js';
4
+ import { indexFor } from './chunk-5VH3Y4QC.js';
5
5
  import { langById, grammarSetVersion, langForExtension, setGrammarsOverride, parseSource } from './chunk-UTNNGKKX.js';
6
6
  import { redactSecrets } from './chunk-RXP66R2E.js';
7
- import { writeGraphIndex, SCHEMA_VERSION, loadGraph } from './chunk-MOLBANFB.js';
8
- import { ensureVibgrateGitignore } from './chunk-AVCBKQKA.js';
9
- import { VERSION } from './chunk-DEKGSQHL.js';
10
- import { loadCache, serializeGraph, cacheDir, stableStringify } from './chunk-ZKNB4YH4.js';
7
+ import { writeGraphIndex, SCHEMA_VERSION, loadGraph } from './chunk-DIU3MXB3.js';
8
+ import { ensureVibgrateGitignore } from './chunk-N4IDP2M2.js';
9
+ import { VERSION } from './chunk-QT2PMGN3.js';
10
+ import { loadCache, serializeGraph, cacheDir, stableStringify } from './chunk-AJ2KE3NT.js';
11
11
  import { shortId, canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
12
- import * as fs10 from 'fs';
13
- import * as path10 from 'path';
12
+ import * as fs11 from 'fs';
13
+ import * as path11 from 'path';
14
14
  import ignore from 'ignore';
15
15
  import * as v8 from 'v8';
16
16
  import Graph from 'graphology';
@@ -21,7 +21,8 @@ import louvain from 'graphology-communities-louvain';
21
21
  import * as os from 'os';
22
22
  import { fileURLToPath } from 'url';
23
23
  import ts from 'typescript';
24
- import * as fs7 from 'fs/promises';
24
+ import * as crypto from 'crypto';
25
+ import * as fs8 from 'fs/promises';
25
26
 
26
27
  var SKIP_DIRS = /* @__PURE__ */ new Set([
27
28
  // Version control, IDE & tool metadata
@@ -186,19 +187,19 @@ var SKIP_FILES = /* @__PURE__ */ new Set([
186
187
  "flake.lock"
187
188
  ]);
188
189
  function toPosix(p) {
189
- return p.split(path10.sep).join("/");
190
+ return p.split(path11.sep).join("/");
190
191
  }
191
192
  function buildRootIgnore(root, exclude) {
192
193
  const ig = ignore();
193
- const gitignorePath = path10.join(root, ".gitignore");
194
- if (fs10.existsSync(gitignorePath)) {
195
- ig.add(fs10.readFileSync(gitignorePath, "utf8"));
194
+ const gitignorePath = path11.join(root, ".gitignore");
195
+ if (fs11.existsSync(gitignorePath)) {
196
+ ig.add(fs11.readFileSync(gitignorePath, "utf8"));
196
197
  }
197
198
  if (exclude.length) ig.add(exclude);
198
199
  return ig;
199
200
  }
200
201
  function discover(options) {
201
- const root = path10.resolve(options.root);
202
+ const root = path11.resolve(options.root);
202
203
  const onlyLangs = (options.only ?? []).filter(Boolean);
203
204
  const allowLang = (lang) => onlyLangs.length === 0 || onlyLangs.includes(lang.id);
204
205
  for (const id of onlyLangs) {
@@ -207,27 +208,27 @@ function discover(options) {
207
208
  }
208
209
  }
209
210
  const rootIg = buildRootIgnore(root, options.exclude ?? []);
210
- const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path10.resolve(root, p)) : [root]).filter((p) => fs10.existsSync(p));
211
+ const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path11.resolve(root, p)) : [root]).filter((p) => fs11.existsSync(p));
211
212
  const found = /* @__PURE__ */ new Map();
212
213
  const considerFile = (abs) => {
213
- const rel2 = toPosix(path10.relative(root, abs));
214
+ const rel2 = toPosix(path11.relative(root, abs));
214
215
  if (rel2.startsWith("..")) return;
215
216
  if (rel2 === "" || rootIg.ignores(rel2)) return;
216
- if (SKIP_FILES.has(path10.basename(abs).toLowerCase())) return;
217
- const lang = langForExtension(path10.extname(abs));
217
+ if (SKIP_FILES.has(path11.basename(abs).toLowerCase())) return;
218
+ const lang = langForExtension(path11.extname(abs));
218
219
  if (!lang || !allowLang(lang)) return;
219
220
  found.set(rel2, { rel: rel2, abs, lang });
220
221
  };
221
222
  const walk = (dir) => {
222
223
  let entries;
223
224
  try {
224
- entries = fs10.readdirSync(dir, { withFileTypes: true });
225
+ entries = fs11.readdirSync(dir, { withFileTypes: true });
225
226
  } catch {
226
227
  return;
227
228
  }
228
229
  for (const entry of entries) {
229
- const abs = path10.join(dir, entry.name);
230
- const rel2 = toPosix(path10.relative(root, abs));
230
+ const abs = path11.join(dir, entry.name);
231
+ const rel2 = toPosix(path11.relative(root, abs));
231
232
  if (entry.isDirectory()) {
232
233
  if (isSkippedDirName(entry.name)) continue;
233
234
  if (rel2 && rootIg.ignores(`${rel2}/`)) continue;
@@ -238,7 +239,7 @@ function discover(options) {
238
239
  }
239
240
  };
240
241
  for (const scope of scopeAbs) {
241
- const stat = fs10.statSync(scope);
242
+ const stat = fs11.statSync(scope);
242
243
  if (stat.isDirectory()) walk(scope);
243
244
  else if (stat.isFile()) considerFile(scope);
244
245
  }
@@ -720,14 +721,14 @@ var DEFAULT_PATHS = [
720
721
  ];
721
722
  function loadCoverage(root, explicit) {
722
723
  const candidates = (explicit && explicit.length ? explicit : DEFAULT_PATHS).map(
723
- (p) => path10.resolve(root, p)
724
+ (p) => path11.resolve(root, p)
724
725
  );
725
- const found = candidates.filter((p) => fs10.existsSync(p));
726
+ const found = candidates.filter((p) => fs11.existsSync(p));
726
727
  if (found.length === 0) return null;
727
728
  const map = /* @__PURE__ */ new Map();
728
729
  for (const file of found) {
729
730
  try {
730
- const text = fs10.readFileSync(file, "utf8");
731
+ const text = fs11.readFileSync(file, "utf8");
731
732
  if (file.endsWith(".json")) mergeIstanbul(map, text, root);
732
733
  else mergeLcov(map, text, root);
733
734
  } catch {
@@ -736,8 +737,8 @@ function loadCoverage(root, explicit) {
736
737
  return map.size ? map : null;
737
738
  }
738
739
  function rel(root, p) {
739
- const abs = path10.isAbsolute(p) ? p : path10.resolve(root, p);
740
- return path10.relative(root, abs).split(path10.sep).join("/");
740
+ const abs = path11.isAbsolute(p) ? p : path11.resolve(root, p);
741
+ return path11.relative(root, abs).split(path11.sep).join("/");
741
742
  }
742
743
  function bump(map, file, line, hits) {
743
744
  let lh = map.get(file);
@@ -948,7 +949,7 @@ async function parseInline(files, options) {
948
949
  onProgress?.(0, files.length);
949
950
  for (const file of files) {
950
951
  try {
951
- const source = fs10.readFileSync(file.abs, "utf8");
952
+ const source = fs11.readFileSync(file.abs, "utf8");
952
953
  out.push(await parseSource(file.rel, file.lang.id, source));
953
954
  } catch (err) {
954
955
  out.push(emptyParse(file, `parse failed: ${err.message}`));
@@ -1003,9 +1004,9 @@ function isWorkerOom(err) {
1003
1004
  return e?.code === "ERR_WORKER_OUT_OF_MEMORY" || /out of memory/i.test(e?.message ?? "");
1004
1005
  }
1005
1006
  function resolveWorkerFile() {
1006
- const here = path10.dirname(fileURLToPath(import.meta.url));
1007
- const candidate = path10.join(here, "parse-worker.js");
1008
- return fs10.existsSync(candidate) ? candidate : null;
1007
+ const here = path11.dirname(fileURLToPath(import.meta.url));
1008
+ const candidate = path11.join(here, "parse-worker.js");
1009
+ return fs11.existsSync(candidate) ? candidate : null;
1009
1010
  }
1010
1011
  function chunk(items, buckets) {
1011
1012
  const out = Array.from({ length: Math.min(buckets, items.length || 1) }, () => []);
@@ -1032,20 +1033,18 @@ function emptyParse(file, warning) {
1032
1033
  };
1033
1034
  }
1034
1035
  var PRECISE_KIND = "tsc";
1035
- function tsResolveEdges(root, tsFiles, nodes) {
1036
- const empty = {
1037
- edges: [],
1038
- coveredFiles: /* @__PURE__ */ new Set(),
1039
- stats: { files: 0, calls: 0, jsx: 0, heritage: 0, resolved: 0 }
1040
- };
1041
- if (tsFiles.length === 0) return empty;
1042
- const absToRel = new Map(tsFiles.map((f) => [normalize2(f.abs), f.rel]));
1036
+ function tsWalkFiles(root, walkFiles, mapFiles, extraRootFiles, nodes) {
1037
+ const partials = /* @__PURE__ */ new Map();
1038
+ if (walkFiles.length === 0) return partials;
1039
+ const absToRel = new Map(mapFiles.map((f) => [normalize2(f.abs), f.rel]));
1043
1040
  const options = compilerOptions(root);
1041
+ const rootAbs = new Set(walkFiles.map((f) => f.abs));
1042
+ for (const f of extraRootFiles) rootAbs.add(f.abs);
1044
1043
  let program;
1045
1044
  try {
1046
- program = ts.createProgram(tsFiles.map((f) => f.abs), options);
1045
+ program = ts.createProgram([...rootAbs], options);
1047
1046
  } catch {
1048
- return empty;
1047
+ return partials;
1049
1048
  }
1050
1049
  const checker = program.getTypeChecker();
1051
1050
  const nodesByFile = /* @__PURE__ */ new Map();
@@ -1061,17 +1060,20 @@ function tsResolveEdges(root, tsFiles, nodes) {
1061
1060
  else nodesByFile.set(n.file, [n]);
1062
1061
  }
1063
1062
  const relForAbs = (abs) => absToRel.get(normalize2(abs));
1064
- const edges = /* @__PURE__ */ new Map();
1065
- const covered = /* @__PURE__ */ new Set();
1066
- const stats = empty.stats;
1067
- const interfaceCalls = [];
1068
- const byId = /* @__PURE__ */ new Map();
1069
- for (const list of nodesByFile.values()) for (const n of list) byId.set(n.id, n);
1070
- for (const file of tsFiles) {
1063
+ for (const file of walkFiles) {
1071
1064
  const sf = program.getSourceFile(file.abs);
1072
- if (!sf) continue;
1073
- covered.add(file.rel);
1074
- stats.files++;
1065
+ if (!sf) {
1066
+ partials.set(file.rel, {
1067
+ covered: false,
1068
+ edges: [],
1069
+ interfaceCalls: [],
1070
+ stats: { calls: 0, jsx: 0, heritage: 0, resolved: 0 }
1071
+ });
1072
+ continue;
1073
+ }
1074
+ const edges = /* @__PURE__ */ new Map();
1075
+ const stats = { calls: 0, jsx: 0, heritage: 0, resolved: 0 };
1076
+ const interfaceCalls = [];
1075
1077
  const fileNodes = nodesByFile.get(file.rel) ?? [];
1076
1078
  const fileNode = fileNodeByRel.get(file.rel);
1077
1079
  const lineOf = (pos) => sf.getLineAndCharacterOfPosition(pos).line + 1;
@@ -1119,6 +1121,35 @@ function tsResolveEdges(root, tsFiles, nodes) {
1119
1121
  ts.forEachChild(node, visit);
1120
1122
  };
1121
1123
  visit(sf);
1124
+ partials.set(file.rel, { covered: true, edges: [...edges.values()], interfaceCalls, stats });
1125
+ }
1126
+ return partials;
1127
+ }
1128
+ function assembleTsResult(orderedRels, partials, nodes) {
1129
+ const nodesByFile = /* @__PURE__ */ new Map();
1130
+ for (const n of nodes) {
1131
+ if (n.kind === "file" || n.kind === "external") continue;
1132
+ const list = nodesByFile.get(n.file);
1133
+ if (list) list.push(n);
1134
+ else nodesByFile.set(n.file, [n]);
1135
+ }
1136
+ const byId = /* @__PURE__ */ new Map();
1137
+ for (const list of nodesByFile.values()) for (const n of list) byId.set(n.id, n);
1138
+ const edges = /* @__PURE__ */ new Map();
1139
+ const covered = /* @__PURE__ */ new Set();
1140
+ const stats = { files: 0, calls: 0, jsx: 0, heritage: 0, resolved: 0 };
1141
+ const interfaceCalls = [];
1142
+ for (const rel2 of orderedRels) {
1143
+ const p = partials.get(rel2);
1144
+ if (!p || !p.covered) continue;
1145
+ covered.add(rel2);
1146
+ stats.files++;
1147
+ stats.calls += p.stats.calls;
1148
+ stats.jsx += p.stats.jsx;
1149
+ stats.heritage += p.stats.heritage;
1150
+ stats.resolved += p.stats.resolved;
1151
+ for (const e of p.edges) edges.set(e.id, { ...e });
1152
+ interfaceCalls.push(...p.interfaceCalls);
1122
1153
  }
1123
1154
  const implsByInterface = /* @__PURE__ */ new Map();
1124
1155
  for (const e of edges.values()) {
@@ -1254,7 +1285,117 @@ function enclosing3(nodes, line) {
1254
1285
  return best;
1255
1286
  }
1256
1287
  function normalize2(p) {
1257
- return path10.resolve(p).split(path10.sep).join("/");
1288
+ return path11.resolve(p).split(path11.sep).join("/");
1289
+ }
1290
+ var TSC_CACHE_VERSION = "vg-tsc-cache/1";
1291
+ var AMBIENT_RE = /\bdeclare\s+(global|module)\b/;
1292
+ function tscCachePath(root) {
1293
+ return path11.join(cacheDir(root), "tsc-cache.json");
1294
+ }
1295
+ function loadTscCache(root, opts) {
1296
+ const file = tscCachePath(root);
1297
+ let data = {
1298
+ version: TSC_CACHE_VERSION,
1299
+ toolVersion: opts.toolVersion,
1300
+ ts: ts.version,
1301
+ entries: {}
1302
+ };
1303
+ if (!opts.disabled && fs11.existsSync(file)) {
1304
+ try {
1305
+ const loaded = JSON.parse(fs11.readFileSync(file, "utf8"));
1306
+ if (loaded.version === TSC_CACHE_VERSION && loaded.toolVersion === opts.toolVersion && loaded.ts === ts.version && loaded.entries) {
1307
+ data = loaded;
1308
+ }
1309
+ } catch {
1310
+ }
1311
+ }
1312
+ return {
1313
+ get(rel2, key) {
1314
+ if (opts.disabled) return void 0;
1315
+ const entry = data.entries[rel2];
1316
+ return entry && entry.key === key ? entry.partial : void 0;
1317
+ },
1318
+ set(rel2, hash, key, partial) {
1319
+ const ambient = data.entries[rel2]?.hash === hash ? data.entries[rel2].ambient : detectAmbient(rel2, abs$(root, rel2));
1320
+ data.entries[rel2] = { hash, ambient, key, partial };
1321
+ },
1322
+ isAmbient(rel2, hash, abs) {
1323
+ const entry = data.entries[rel2];
1324
+ if (entry && entry.hash === hash) return entry.ambient;
1325
+ const ambient = detectAmbient(rel2, abs);
1326
+ data.entries[rel2] = { hash, ambient };
1327
+ return ambient;
1328
+ },
1329
+ prune(currentRels) {
1330
+ for (const rel2 of Object.keys(data.entries)) {
1331
+ if (!currentRels.has(rel2)) delete data.entries[rel2];
1332
+ }
1333
+ },
1334
+ save() {
1335
+ if (opts.disabled) return;
1336
+ fs11.mkdirSync(cacheDir(root), { recursive: true });
1337
+ fs11.writeFileSync(file, stableStringify(data, 0));
1338
+ }
1339
+ };
1340
+ }
1341
+ function abs$(root, rel2) {
1342
+ return path11.join(root, rel2);
1343
+ }
1344
+ function detectAmbient(rel2, abs) {
1345
+ if (rel2.endsWith(".d.ts")) return true;
1346
+ try {
1347
+ return AMBIENT_RE.test(fs11.readFileSync(abs, "utf8"));
1348
+ } catch {
1349
+ return true;
1350
+ }
1351
+ }
1352
+ function tsConfigFingerprint(root) {
1353
+ const configPath = ts.findConfigFile(root, ts.sys.fileExists, "tsconfig.json") ?? ts.findConfigFile(root, ts.sys.fileExists, "tsconfig.base.json");
1354
+ if (!configPath) return sha("none");
1355
+ try {
1356
+ const host = {
1357
+ ...ts.sys,
1358
+ onUnRecoverableConfigFileDiagnostic: () => {
1359
+ }
1360
+ };
1361
+ const parsed = ts.getParsedCommandLineOfConfigFile(configPath, {}, host);
1362
+ return sha(stableStringify(parsed?.options ?? "unparsed", 0));
1363
+ } catch {
1364
+ return sha("unparsed");
1365
+ }
1366
+ }
1367
+ function tscKeys(rels, hashes, importsByFile, ambientHash) {
1368
+ const keys = /* @__PURE__ */ new Map();
1369
+ for (const rel2 of rels) {
1370
+ const closure = [];
1371
+ const visited = /* @__PURE__ */ new Set([rel2]);
1372
+ const queue = [rel2];
1373
+ while (queue.length) {
1374
+ const cur = queue.pop();
1375
+ for (const dep of importsByFile.get(cur) ?? []) {
1376
+ if (visited.has(dep)) continue;
1377
+ visited.add(dep);
1378
+ if (hashes.has(dep)) closure.push(dep);
1379
+ queue.push(dep);
1380
+ }
1381
+ }
1382
+ closure.sort();
1383
+ const lines = closure.map((c) => `${c}\0${hashes.get(c)}`);
1384
+ keys.set(rel2, sha(`${TSC_CACHE_VERSION}
1385
+ ${ambientHash}
1386
+ ${rel2}\0${hashes.get(rel2)}
1387
+ ${lines.join("\n")}`));
1388
+ }
1389
+ return keys;
1390
+ }
1391
+ function ambientFingerprint(ambient, configFingerprint) {
1392
+ const lines = ambient.map((a) => `${a.rel}\0${a.hash}`).sort().join("\n");
1393
+ return sha(`${configFingerprint}
1394
+ ${ts.version}
1395
+ ${lines}`);
1396
+ }
1397
+ function sha(s) {
1398
+ return crypto.createHash("sha256").update(s).digest("hex");
1258
1399
  }
1259
1400
 
1260
1401
  // src/engine/epistemic.ts
@@ -1497,14 +1638,14 @@ var IMPORTANCE = {
1497
1638
  "other-config": 0.08
1498
1639
  };
1499
1640
  function toPosix2(p) {
1500
- return p.split(path10.sep).join("/");
1641
+ return p.split(path11.sep).join("/");
1501
1642
  }
1502
1643
  function buildRootIgnore2(root, exclude) {
1503
1644
  const ig = ignore();
1504
- const gitignorePath = path10.join(root, ".gitignore");
1505
- if (fs10.existsSync(gitignorePath)) {
1645
+ const gitignorePath = path11.join(root, ".gitignore");
1646
+ if (fs11.existsSync(gitignorePath)) {
1506
1647
  try {
1507
- ig.add(fs10.readFileSync(gitignorePath, "utf8"));
1648
+ ig.add(fs11.readFileSync(gitignorePath, "utf8"));
1508
1649
  } catch {
1509
1650
  }
1510
1651
  }
@@ -1513,7 +1654,7 @@ function buildRootIgnore2(root, exclude) {
1513
1654
  }
1514
1655
  function classifyProjectContext(relOrName) {
1515
1656
  const rel2 = relOrName.replace(/\\/g, "/");
1516
- const base = path10.basename(rel2);
1657
+ const base = path11.basename(rel2);
1517
1658
  const baseLower = base.toLowerCase();
1518
1659
  if (/^\.env($|\.)/i.test(base) && !isEnvExampleName(baseLower)) return null;
1519
1660
  if (SKIP_FILES.has(baseLower)) return null;
@@ -1526,7 +1667,7 @@ function classifyProjectContext(relOrName) {
1526
1667
  for (const { re, category } of PATH_PATTERNS) {
1527
1668
  if (re.test(rel2)) return category;
1528
1669
  }
1529
- const ext = path10.extname(baseLower);
1670
+ const ext = path11.extname(baseLower);
1530
1671
  if (DOC_EXTENSIONS.has(ext)) return ext === ".txt" ? "text" : "markdown";
1531
1672
  if (API_EXTENSIONS.has(ext)) return "api-contract";
1532
1673
  if ((ext === ".yaml" || ext === ".yml" || ext === ".json") && /openapi|swagger|asyncapi/i.test(base)) {
@@ -1544,24 +1685,24 @@ function isEnvExampleName(baseLower) {
1544
1685
  return false;
1545
1686
  }
1546
1687
  function discoverDocs(options) {
1547
- const root = path10.resolve(options.root);
1688
+ const root = path11.resolve(options.root);
1548
1689
  const maxFiles = options.maxFiles ?? DOC_MAX_FILES;
1549
1690
  const rootIg = buildRootIgnore2(root, options.exclude ?? []);
1550
- const scopeAbs = (options.paths?.length ? options.paths.map((p) => path10.resolve(root, p)) : [root]).filter(
1551
- (p) => fs10.existsSync(p)
1691
+ const scopeAbs = (options.paths?.length ? options.paths.map((p) => path11.resolve(root, p)) : [root]).filter(
1692
+ (p) => fs11.existsSync(p)
1552
1693
  );
1553
1694
  const found = /* @__PURE__ */ new Map();
1554
1695
  const consider = (abs) => {
1555
1696
  if (found.size >= maxFiles) return;
1556
- const rel2 = toPosix2(path10.relative(root, abs));
1697
+ const rel2 = toPosix2(path11.relative(root, abs));
1557
1698
  if (!rel2 || rel2.startsWith("..")) return;
1558
1699
  if (rootIg.ignores(rel2)) return;
1559
- const base = path10.basename(abs);
1700
+ const base = path11.basename(abs);
1560
1701
  if (SKIP_FILES.has(base.toLowerCase())) return;
1561
1702
  const category = classifyProjectContext(rel2);
1562
1703
  if (!category) return;
1563
1704
  try {
1564
- const st = fs10.statSync(abs);
1705
+ const st = fs11.statSync(abs);
1565
1706
  if (!st.isFile() || st.size > DOC_FILE_MAX_BYTES) return;
1566
1707
  if (st.size === 0) return;
1567
1708
  } catch {
@@ -1573,14 +1714,14 @@ function discoverDocs(options) {
1573
1714
  if (found.size >= maxFiles || depth > 12) return;
1574
1715
  let entries;
1575
1716
  try {
1576
- entries = fs10.readdirSync(dir, { withFileTypes: true });
1717
+ entries = fs11.readdirSync(dir, { withFileTypes: true });
1577
1718
  } catch {
1578
1719
  return;
1579
1720
  }
1580
1721
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
1581
1722
  if (found.size >= maxFiles) return;
1582
- const abs = path10.join(dir, entry.name);
1583
- const rel2 = toPosix2(path10.relative(root, abs));
1723
+ const abs = path11.join(dir, entry.name);
1724
+ const rel2 = toPosix2(path11.relative(root, abs));
1584
1725
  if (entry.isDirectory()) {
1585
1726
  if (isSkippedDirName(entry.name)) continue;
1586
1727
  if (rel2 && rootIg.ignores(`${rel2}/`) && !rel2.startsWith(".github")) continue;
@@ -1592,7 +1733,7 @@ function discoverDocs(options) {
1592
1733
  };
1593
1734
  for (const scope of scopeAbs) {
1594
1735
  try {
1595
- const st = fs10.statSync(scope);
1736
+ const st = fs11.statSync(scope);
1596
1737
  if (st.isDirectory()) walk(scope, 0);
1597
1738
  else if (st.isFile()) consider(scope);
1598
1739
  } catch {
@@ -1603,7 +1744,7 @@ function discoverDocs(options) {
1603
1744
  function prepareDocBody(rel2, raw, category) {
1604
1745
  const scrubbed = redactSecrets(raw);
1605
1746
  if (scrubbed.length <= DOC_BODY_MAX_CHARS) return scrubbed;
1606
- if (category === "manifest" && path10.basename(rel2).toLowerCase() === "package.json") {
1747
+ if (category === "manifest" && path11.basename(rel2).toLowerCase() === "package.json") {
1607
1748
  return summarizePackageJson(scrubbed);
1608
1749
  }
1609
1750
  if (category === "api-contract" && /\.(ya?ml|json)$/i.test(rel2)) {
@@ -1649,14 +1790,14 @@ function documentNodesFromDocs(docs) {
1649
1790
  for (const d of docs) {
1650
1791
  let raw = "";
1651
1792
  try {
1652
- raw = fs10.readFileSync(d.abs, "utf8");
1793
+ raw = fs11.readFileSync(d.abs, "utf8");
1653
1794
  } catch {
1654
1795
  continue;
1655
1796
  }
1656
1797
  const category = d.category ?? d.kind;
1657
1798
  const scrubbed = prepareDocBody(d.rel, raw, category);
1658
1799
  if (!scrubbed.trim()) continue;
1659
- const name = path10.basename(d.rel);
1800
+ const name = path11.basename(d.rel);
1660
1801
  const qualifiedName = d.rel.replace(/\\/g, "/");
1661
1802
  const id = nodeId({
1662
1803
  kind: "document",
@@ -1690,7 +1831,7 @@ function shardTsProjects(root, files) {
1690
1831
  const cache = /* @__PURE__ */ new Map();
1691
1832
  const byKey = /* @__PURE__ */ new Map();
1692
1833
  for (const f of files) {
1693
- const dir = path10.dirname(f.abs);
1834
+ const dir = path11.dirname(f.abs);
1694
1835
  const key = nearestProjectKey(root, dir, cache);
1695
1836
  const list = byKey.get(key);
1696
1837
  if (list) list.push(f);
@@ -1705,22 +1846,22 @@ function nearestProjectKey(root, startDir, cache) {
1705
1846
  const hit = cache.get(startDir);
1706
1847
  if (hit !== void 0) return hit;
1707
1848
  let dir = startDir;
1708
- const rootAbs = path10.resolve(root);
1849
+ const rootAbs = path11.resolve(root);
1709
1850
  while (true) {
1710
- if (fs10.existsSync(path10.join(dir, "tsconfig.json")) || fs10.existsSync(path10.join(dir, "tsconfig.base.json")) || fs10.existsSync(path10.join(dir, "package.json"))) {
1711
- const key = toPosix3(path10.relative(rootAbs, dir)) || ".";
1851
+ if (fs11.existsSync(path11.join(dir, "tsconfig.json")) || fs11.existsSync(path11.join(dir, "tsconfig.base.json")) || fs11.existsSync(path11.join(dir, "package.json"))) {
1852
+ const key = toPosix3(path11.relative(rootAbs, dir)) || ".";
1712
1853
  cache.set(startDir, key);
1713
1854
  return key;
1714
1855
  }
1715
- if (dir === rootAbs || path10.dirname(dir) === dir) {
1856
+ if (dir === rootAbs || path11.dirname(dir) === dir) {
1716
1857
  cache.set(startDir, ".");
1717
1858
  return ".";
1718
1859
  }
1719
- dir = path10.dirname(dir);
1860
+ dir = path11.dirname(dir);
1720
1861
  }
1721
1862
  }
1722
1863
  function toPosix3(p) {
1723
- return p.split(path10.sep).join("/");
1864
+ return p.split(path11.sep).join("/");
1724
1865
  }
1725
1866
 
1726
1867
  // src/engine/timing.ts
@@ -1812,9 +1953,9 @@ var emptyNode = (partial) => ({
1812
1953
  tested: null
1813
1954
  });
1814
1955
  function extractManifests(root, opts = {}) {
1815
- const absRoot = path10.resolve(root);
1956
+ const absRoot = path11.resolve(root);
1816
1957
  const ig = buildRootIgnore3(absRoot, opts.exclude ?? []);
1817
- const scopes = (opts.paths?.length ? opts.paths : ["."]).map((p) => path10.resolve(absRoot, p)).filter((p) => fs10.existsSync(p));
1958
+ const scopes = (opts.paths?.length ? opts.paths : ["."]).map((p) => path11.resolve(absRoot, p)).filter((p) => fs11.existsSync(p));
1818
1959
  const found = /* @__PURE__ */ new Map();
1819
1960
  for (const scope of scopes) {
1820
1961
  walkManifests(absRoot, scope, ig, found);
@@ -1824,7 +1965,7 @@ function extractManifests(root, opts = {}) {
1824
1965
  let deps = 0;
1825
1966
  for (const rel2 of [...found.keys()].sort()) {
1826
1967
  const abs = found.get(rel2);
1827
- const base = path10.posix.basename(rel2);
1968
+ const base = path11.posix.basename(rel2);
1828
1969
  try {
1829
1970
  if (base === "package.json") {
1830
1971
  deps += ingestPackageJson(rel2, abs, nodes, edges);
@@ -1844,8 +1985,8 @@ function extractManifests(root, opts = {}) {
1844
1985
  };
1845
1986
  }
1846
1987
  function ingestPackageJson(rel2, abs, nodes, edges) {
1847
- const raw = JSON.parse(fs10.readFileSync(abs, "utf8"));
1848
- const pkgName = raw.name && String(raw.name).trim() || path10.posix.dirname(rel2) || ".";
1988
+ const raw = JSON.parse(fs11.readFileSync(abs, "utf8"));
1989
+ const pkgName = raw.name && String(raw.name).trim() || path11.posix.dirname(rel2) || ".";
1849
1990
  const localId = nodeId({ kind: "package", qualifiedName: pkgName, file: rel2 });
1850
1991
  nodes.set(
1851
1992
  localId,
@@ -1864,7 +2005,7 @@ function ingestPackageJson(rel2, abs, nodes, edges) {
1864
2005
  emptyNode({
1865
2006
  id: fileId,
1866
2007
  kind: "file",
1867
- name: path10.posix.basename(rel2),
2008
+ name: path11.posix.basename(rel2),
1868
2009
  qualifiedName: rel2,
1869
2010
  file: rel2,
1870
2011
  lang: "json"
@@ -1888,8 +2029,8 @@ function ingestPackageJson(rel2, abs, nodes, edges) {
1888
2029
  return n;
1889
2030
  }
1890
2031
  function ingestGoMod(rel2, abs, nodes, edges) {
1891
- const text = fs10.readFileSync(abs, "utf8");
1892
- let moduleName = path10.posix.dirname(rel2) || ".";
2032
+ const text = fs11.readFileSync(abs, "utf8");
2033
+ let moduleName = path11.posix.dirname(rel2) || ".";
1893
2034
  const moduleMatch = /^\s*module\s+(\S+)/m.exec(text);
1894
2035
  if (moduleMatch) moduleName = moduleMatch[1];
1895
2036
  const localId = nodeId({ kind: "package", qualifiedName: moduleName, file: rel2 });
@@ -1910,7 +2051,7 @@ function ingestGoMod(rel2, abs, nodes, edges) {
1910
2051
  emptyNode({
1911
2052
  id: fileId,
1912
2053
  kind: "file",
1913
- name: path10.posix.basename(rel2),
2054
+ name: path11.posix.basename(rel2),
1914
2055
  qualifiedName: rel2,
1915
2056
  file: rel2,
1916
2057
  lang: "go"
@@ -1971,10 +2112,10 @@ function addEdge(edges, kind, src, dst, confidence) {
1971
2112
  }
1972
2113
  function buildRootIgnore3(root, exclude) {
1973
2114
  const ig = ignore();
1974
- const gitignorePath = path10.join(root, ".gitignore");
1975
- if (fs10.existsSync(gitignorePath)) {
2115
+ const gitignorePath = path11.join(root, ".gitignore");
2116
+ if (fs11.existsSync(gitignorePath)) {
1976
2117
  try {
1977
- ig.add(fs10.readFileSync(gitignorePath, "utf8"));
2118
+ ig.add(fs11.readFileSync(gitignorePath, "utf8"));
1978
2119
  } catch {
1979
2120
  }
1980
2121
  }
@@ -1984,13 +2125,13 @@ function buildRootIgnore3(root, exclude) {
1984
2125
  function walkManifests(root, dir, ig, found) {
1985
2126
  let entries;
1986
2127
  try {
1987
- entries = fs10.readdirSync(dir, { withFileTypes: true });
2128
+ entries = fs11.readdirSync(dir, { withFileTypes: true });
1988
2129
  } catch {
1989
2130
  return;
1990
2131
  }
1991
2132
  for (const entry of entries) {
1992
- const abs = path10.join(dir, entry.name);
1993
- const rel2 = path10.relative(root, abs).split(path10.sep).join("/");
2133
+ const abs = path11.join(dir, entry.name);
2134
+ const rel2 = path11.relative(root, abs).split(path11.sep).join("/");
1994
2135
  if (entry.isDirectory()) {
1995
2136
  if (isSkippedDirName(entry.name)) continue;
1996
2137
  if (rel2 && ig.ignores(`${rel2}/`)) continue;
@@ -2017,7 +2158,7 @@ async function hashFilesParallel(jobs, concurrency) {
2017
2158
  if (i >= jobs.length) return;
2018
2159
  const job = jobs[i];
2019
2160
  try {
2020
- const buf = await fs7.readFile(job.abs);
2161
+ const buf = await fs8.readFile(job.abs);
2021
2162
  out[i] = { rel: job.rel, hash: hashBytes(buf), ok: true };
2022
2163
  } catch {
2023
2164
  out[i] = { rel: job.rel, hash: "", ok: false };
@@ -2032,7 +2173,7 @@ async function hashFilesParallel(jobs, concurrency) {
2032
2173
  async function buildGraph(options) {
2033
2174
  const timer = new StageTimer();
2034
2175
  timer.start("total");
2035
- const root = path10.resolve(options.root);
2176
+ const root = path11.resolve(options.root);
2036
2177
  timer.start("discover");
2037
2178
  const files = discover({
2038
2179
  root,
@@ -2065,7 +2206,7 @@ async function buildGraph(options) {
2065
2206
  for (const file of files) {
2066
2207
  let stat;
2067
2208
  try {
2068
- stat = fs10.statSync(file.abs);
2209
+ stat = fs11.statSync(file.abs);
2069
2210
  } catch {
2070
2211
  continue;
2071
2212
  }
@@ -2192,10 +2333,37 @@ async function buildGraph(options) {
2192
2333
  let jsx = 0;
2193
2334
  let heritage = 0;
2194
2335
  let resolvedCount = 0;
2336
+ let tscReusedFiles = 0;
2195
2337
  const coveredAll = /* @__PURE__ */ new Set();
2196
2338
  const preciseAll = [];
2339
+ const tscCache = loadTscCache(root, { toolVersion: VERSION, disabled: options.noCache });
2340
+ const cfgFingerprint = tsConfigFingerprint(root);
2197
2341
  for (const shard of shards) {
2198
- const res = tsResolveEdges(root, shard.files, resolved.nodes);
2342
+ const ambientFiles = shard.files.filter((f) => tscCache.isAmbient(f.rel, hashes.get(f.rel), f.abs));
2343
+ const ambientHash = ambientFingerprint(
2344
+ ambientFiles.map((f) => ({ rel: f.rel, hash: hashes.get(f.rel) })),
2345
+ cfgFingerprint
2346
+ );
2347
+ const keys = tscKeys(shard.files.map((f) => f.rel), hashes, resolved.importsByFile, ambientHash);
2348
+ const partials = /* @__PURE__ */ new Map();
2349
+ const walkFiles = [];
2350
+ for (const f of shard.files) {
2351
+ const cached = tscCache.get(f.rel, keys.get(f.rel));
2352
+ if (cached) {
2353
+ partials.set(f.rel, cached);
2354
+ tscReusedFiles++;
2355
+ } else {
2356
+ walkFiles.push(f);
2357
+ }
2358
+ }
2359
+ const walkRels = new Set(walkFiles.map((f) => f.rel));
2360
+ const extraRoots = ambientFiles.filter((f) => !walkRels.has(f.rel));
2361
+ const fresh = tsWalkFiles(root, walkFiles, shard.files, extraRoots, resolved.nodes);
2362
+ for (const [rel2, partial] of fresh) {
2363
+ partials.set(rel2, partial);
2364
+ tscCache.set(rel2, hashes.get(rel2), keys.get(rel2), partial);
2365
+ }
2366
+ const res = assembleTsResult(shard.files.map((f) => f.rel), partials, resolved.nodes);
2199
2367
  if (res.stats.files === 0) continue;
2200
2368
  filesCovered += res.stats.files;
2201
2369
  calls += res.stats.calls;
@@ -2205,6 +2373,8 @@ async function buildGraph(options) {
2205
2373
  for (const f of res.coveredFiles) coveredAll.add(f);
2206
2374
  preciseAll.push(...res.edges);
2207
2375
  }
2376
+ tscCache.prune(new Set(tsFiles.map((f) => f.rel)));
2377
+ tscCache.save();
2208
2378
  if (filesCovered > 0) {
2209
2379
  edges = mergePreciseEdges(edges, preciseAll, coveredAll, nodeFileById);
2210
2380
  for (const f of coveredAll) preciseCoveredFiles.add(f);
@@ -2215,7 +2385,8 @@ async function buildGraph(options) {
2215
2385
  jsx,
2216
2386
  heritage,
2217
2387
  resolved: resolvedCount,
2218
- shards: shards.length
2388
+ shards: shards.length,
2389
+ reusedFiles: tscReusedFiles
2219
2390
  };
2220
2391
  }
2221
2392
  checkMemoryBudget("typescript resolution", limits.memoryBudgetMb);
@@ -2241,8 +2412,8 @@ async function buildGraph(options) {
2241
2412
  });
2242
2413
  for (const d of docs) {
2243
2414
  try {
2244
- const st = fs10.statSync(d.abs);
2245
- const hash = hashBytes(fs10.readFileSync(d.abs));
2415
+ const st = fs11.statSync(d.abs);
2416
+ const hash = hashBytes(fs11.readFileSync(d.abs));
2246
2417
  hashes.set(d.rel, hash);
2247
2418
  fileStats.push({ rel: d.rel, size: st.size, mtimeMs: st.mtimeMs, hash });
2248
2419
  } catch {
@@ -2283,7 +2454,7 @@ async function buildGraph(options) {
2283
2454
  toolchain
2284
2455
  },
2285
2456
  meta: {
2286
- root: path10.basename(root) === "" ? "." : ".",
2457
+ root: path11.basename(root) === "" ? "." : ".",
2287
2458
  languages,
2288
2459
  analysisTier: analysis.tier,
2289
2460
  counts: {
@@ -2342,14 +2513,14 @@ function toRepoRel(p) {
2342
2513
  function loadScipIndex(root, explicit) {
2343
2514
  const candidates = [
2344
2515
  explicit,
2345
- path10.join(root, "index.scip"),
2346
- path10.join(root, ".vibgrate", "index.scip")
2516
+ path11.join(root, "index.scip"),
2517
+ path11.join(root, ".vibgrate", "index.scip")
2347
2518
  ].filter((p) => Boolean(p));
2348
2519
  for (const file of candidates) {
2349
- const abs = path10.isAbsolute(file) ? file : path10.resolve(root, file);
2350
- if (!fs10.existsSync(abs)) continue;
2520
+ const abs = path11.isAbsolute(file) ? file : path11.resolve(root, file);
2521
+ if (!fs11.existsSync(abs)) continue;
2351
2522
  try {
2352
- const index = decodeScipIndex(new Uint8Array(fs10.readFileSync(abs)));
2523
+ const index = decodeScipIndex(new Uint8Array(fs11.readFileSync(abs)));
2353
2524
  if (index.documents.length) {
2354
2525
  return { index, tool: index.toolVersion ? `${index.toolName} ${index.toolVersion}` : index.toolName };
2355
2526
  }
@@ -2464,21 +2635,21 @@ function usageError(message) {
2464
2635
  }
2465
2636
  var SNAPSHOT_VERSION = "vg-freshness/1";
2466
2637
  function snapshotPath(root) {
2467
- return path10.join(cacheDir(root), "freshness.json");
2638
+ return path11.join(cacheDir(root), "freshness.json");
2468
2639
  }
2469
2640
  function writeSnapshot(root, corpusHash, fileStats, scope = {}) {
2470
2641
  const files = {};
2471
2642
  for (const f of fileStats) files[f.rel] = { size: f.size, mtimeMs: f.mtimeMs, hash: f.hash };
2472
2643
  const snapshot = { version: SNAPSHOT_VERSION, corpusHash, scope: pruneScope(scope), files };
2473
2644
  try {
2474
- fs10.mkdirSync(cacheDir(root), { recursive: true });
2475
- fs10.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2645
+ fs11.mkdirSync(cacheDir(root), { recursive: true });
2646
+ fs11.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2476
2647
  } catch {
2477
2648
  }
2478
2649
  }
2479
2650
  function loadSnapshot(root) {
2480
2651
  try {
2481
- const loaded = JSON.parse(fs10.readFileSync(snapshotPath(root), "utf8"));
2652
+ const loaded = JSON.parse(fs11.readFileSync(snapshotPath(root), "utf8"));
2482
2653
  if (loaded.version === SNAPSHOT_VERSION && loaded.files && typeof loaded.corpusHash === "string") {
2483
2654
  return { ...loaded, scope: loaded.scope ?? {} };
2484
2655
  }
@@ -2521,7 +2692,7 @@ function probeFreshness(root) {
2521
2692
  }
2522
2693
  let stat;
2523
2694
  try {
2524
- stat = fs10.statSync(file.abs);
2695
+ stat = fs11.statSync(file.abs);
2525
2696
  } catch {
2526
2697
  drift.removed.push(file.rel);
2527
2698
  continue;
@@ -2539,7 +2710,7 @@ function probeFreshness(root) {
2539
2710
  }
2540
2711
  let hash = "";
2541
2712
  try {
2542
- hash = hashBytes(fs10.readFileSync(file.abs));
2713
+ hash = hashBytes(fs11.readFileSync(file.abs));
2543
2714
  } catch {
2544
2715
  drift.removed.push(file.rel);
2545
2716
  continue;
@@ -2556,7 +2727,7 @@ function probeFreshness(root) {
2556
2727
  }
2557
2728
  if (absorbed && !hasDrift(drift)) {
2558
2729
  try {
2559
- fs10.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2730
+ fs11.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2560
2731
  } catch {
2561
2732
  }
2562
2733
  }
@@ -2787,12 +2958,12 @@ function detectAssistants(root, opts = {}) {
2787
2958
  const which = opts.which ?? whichOnPath;
2788
2959
  const found = [];
2789
2960
  for (const assistant of ASSISTANTS) {
2790
- const repoHit = (assistant.markers ?? []).find((m) => fs10.existsSync(path10.join(root, m)));
2961
+ const repoHit = (assistant.markers ?? []).find((m) => fs11.existsSync(path11.join(root, m)));
2791
2962
  if (repoHit) {
2792
2963
  found.push({ assistant, via: "repo", marker: repoHit });
2793
2964
  continue;
2794
2965
  }
2795
- const homeHit = (assistant.homeMarkers ?? []).find((m) => fs10.existsSync(path10.join(home, m)));
2966
+ const homeHit = (assistant.homeMarkers ?? []).find((m) => fs11.existsSync(path11.join(home, m)));
2796
2967
  if (homeHit) {
2797
2968
  found.push({ assistant, via: "home", marker: homeHit });
2798
2969
  continue;
@@ -2824,19 +2995,19 @@ function installAssistant(a, opts) {
2824
2995
  const skipped = [];
2825
2996
  let note;
2826
2997
  if (a.skill) {
2827
- writeFileEnsured(path10.join(opts.root, a.skill), skillMarkdown(a.id));
2998
+ writeFileEnsured(path11.join(opts.root, a.skill), skillMarkdown(a.id));
2828
2999
  wrote.push(a.skill);
2829
3000
  }
2830
3001
  if (a.mcp) {
2831
3002
  const launch = opts.launch ?? detectServeLaunch();
2832
- upsertMcp(path10.join(opts.root, a.mcp.file), a.mcp, launch);
3003
+ upsertMcp(path11.join(opts.root, a.mcp.file), a.mcp, launch);
2833
3004
  wrote.push(a.mcp.file);
2834
3005
  note = launch.note;
2835
3006
  } else {
2836
3007
  skipped.push("mcp (host-specific setup)");
2837
3008
  }
2838
3009
  if (a.nudge && opts.hook !== false) {
2839
- writeNudge(path10.join(opts.root, a.nudge.file), a.nudge, opts.smallRepo, a.id);
3010
+ writeNudge(path11.join(opts.root, a.nudge.file), a.nudge, opts.smallRepo, a.id);
2840
3011
  wrote.push(a.nudge.file);
2841
3012
  } else if (a.nudge) {
2842
3013
  skipped.push("nudge (--no-hook)");
@@ -2846,32 +3017,32 @@ function installAssistant(a, opts) {
2846
3017
  function uninstallAssistant(a, root, purge) {
2847
3018
  const removed = [];
2848
3019
  if (a.mcp) {
2849
- const file = path10.join(root, a.mcp.file);
3020
+ const file = path11.join(root, a.mcp.file);
2850
3021
  if (removeMcp(file, a.mcp)) removed.push(a.mcp.file);
2851
3022
  }
2852
3023
  if (a.nudge) {
2853
- const file = path10.join(root, a.nudge.file);
3024
+ const file = path11.join(root, a.nudge.file);
2854
3025
  if (a.nudge.kind === "block") {
2855
3026
  if (removeBlock(file)) removed.push(a.nudge.file);
2856
- } else if (fs10.existsSync(file)) {
2857
- fs10.rmSync(file);
3027
+ } else if (fs11.existsSync(file)) {
3028
+ fs11.rmSync(file);
2858
3029
  removed.push(a.nudge.file);
2859
3030
  }
2860
3031
  }
2861
3032
  if (purge && a.skill) {
2862
- const file = path10.join(root, a.skill);
2863
- if (fs10.existsSync(file)) {
2864
- fs10.rmSync(file);
3033
+ const file = path11.join(root, a.skill);
3034
+ if (fs11.existsSync(file)) {
3035
+ fs11.rmSync(file);
2865
3036
  removed.push(a.skill);
2866
3037
  }
2867
3038
  }
2868
3039
  return removed;
2869
3040
  }
2870
3041
  function isAssistantInstalled(a, root) {
2871
- if (a.skill && fs10.existsSync(path10.join(root, a.skill))) return true;
3042
+ if (a.skill && fs11.existsSync(path11.join(root, a.skill))) return true;
2872
3043
  if (a.mcp) {
2873
- const file = path10.join(root, a.mcp.file);
2874
- if (fs10.existsSync(file)) {
3044
+ const file = path11.join(root, a.mcp.file);
3045
+ if (fs11.existsSync(file)) {
2875
3046
  try {
2876
3047
  const config = readJson(file);
2877
3048
  const bag = config[a.mcp.key];
@@ -2881,8 +3052,8 @@ function isAssistantInstalled(a, root) {
2881
3052
  }
2882
3053
  }
2883
3054
  if (a.nudge) {
2884
- const file = path10.join(root, a.nudge.file);
2885
- if (!fs10.existsSync(file)) return false;
3055
+ const file = path11.join(root, a.nudge.file);
3056
+ if (!fs11.existsSync(file)) return false;
2886
3057
  const text = readTextSafe(file);
2887
3058
  if (!text) return false;
2888
3059
  if (a.nudge.kind === "block") return text.includes(NUDGE_BEGIN);
@@ -2891,19 +3062,19 @@ function isAssistantInstalled(a, root) {
2891
3062
  return false;
2892
3063
  }
2893
3064
  function writeFileEnsured(file, content) {
2894
- fs10.mkdirSync(path10.dirname(file), { recursive: true });
2895
- fs10.writeFileSync(file, content);
3065
+ fs11.mkdirSync(path11.dirname(file), { recursive: true });
3066
+ fs11.writeFileSync(file, content);
2896
3067
  }
2897
3068
  function writeNavigationConfig(root) {
2898
3069
  ensureVibgrateGitignore(root);
2899
- const rel2 = path10.join(".vibgrate", "mcp-navigation.json");
3070
+ const rel2 = path11.join(".vibgrate", "mcp-navigation.json");
2900
3071
  const doc = {
2901
3072
  _readme: "Deferred-loading config for agents embedding `vg serve` via the Claude API (defer_loading + tool-search). The hot navigation core stays in context; the rest load on demand \u2014 ~350-450 schema tokens/step vs ~1,881 for the full set. Hosts without defer_loading ignore this and serve the whole (already optimized) tool set. See docs/graph/VG-NAVIGATION-PROFILE.md.",
2902
3073
  hot_core: [...HOT_TOOLS],
2903
3074
  deferred: deferredToolNames(),
2904
3075
  toolset: navigationToolsetConfig()
2905
3076
  };
2906
- writeFileEnsured(path10.join(root, rel2), `${JSON.stringify(doc, null, 2)}
3077
+ writeFileEnsured(path11.join(root, rel2), `${JSON.stringify(doc, null, 2)}
2907
3078
  `);
2908
3079
  return rel2;
2909
3080
  }
@@ -2918,7 +3089,7 @@ function upsertMcp(file, target, launch) {
2918
3089
  `);
2919
3090
  }
2920
3091
  function removeMcp(file, target) {
2921
- if (!fs10.existsSync(file)) return false;
3092
+ if (!fs11.existsSync(file)) return false;
2922
3093
  const config = readJson(file);
2923
3094
  const bag = config[target.key];
2924
3095
  if (!bag || !(bag.vg !== void 0)) return false;
@@ -2937,8 +3108,8 @@ function refreshInstalledInstructions(root, smallRepo) {
2937
3108
  };
2938
3109
  for (const a of ASSISTANTS) {
2939
3110
  if (a.skill) {
2940
- const file = path10.join(root, a.skill);
2941
- if (fs10.existsSync(file)) {
3111
+ const file = path11.join(root, a.skill);
3112
+ if (fs11.existsSync(file)) {
2942
3113
  const text = readTextSafe(file);
2943
3114
  const from = text === null ? null : staleVersion(text, "# vg \u2014 the code map");
2944
3115
  if (from !== null) {
@@ -2948,8 +3119,8 @@ function refreshInstalledInstructions(root, smallRepo) {
2948
3119
  }
2949
3120
  }
2950
3121
  if (a.nudge) {
2951
- const file = path10.join(root, a.nudge.file);
2952
- if (!fs10.existsSync(file)) continue;
3122
+ const file = path11.join(root, a.nudge.file);
3123
+ if (!fs11.existsSync(file)) continue;
2953
3124
  const text = readTextSafe(file);
2954
3125
  if (text === null) continue;
2955
3126
  if (a.nudge.kind === "block") {
@@ -2973,7 +3144,7 @@ function refreshInstalledInstructions(root, smallRepo) {
2973
3144
  }
2974
3145
  function readTextSafe(file) {
2975
3146
  try {
2976
- return fs10.readFileSync(file, "utf8");
3147
+ return fs11.readFileSync(file, "utf8");
2977
3148
  } catch {
2978
3149
  return null;
2979
3150
  }
@@ -2992,8 +3163,8 @@ ${stripMarkers(nudgeMarkdown(smallRepo, client))}` : stripMarkers(nudgeMarkdown(
2992
3163
  upsertBlock(file, nudgeMarkdown(smallRepo, client));
2993
3164
  }
2994
3165
  function upsertBlock(file, block) {
2995
- fs10.mkdirSync(path10.dirname(file), { recursive: true });
2996
- let existing = fs10.existsSync(file) ? fs10.readFileSync(file, "utf8") : "";
3166
+ fs11.mkdirSync(path11.dirname(file), { recursive: true });
3167
+ let existing = fs11.existsSync(file) ? fs11.readFileSync(file, "utf8") : "";
2997
3168
  const re = new RegExp(`${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}`);
2998
3169
  if (re.test(existing)) existing = existing.replace(re, block);
2999
3170
  else existing = existing.length ? `${existing.replace(/\s*$/, "")}
@@ -3001,20 +3172,20 @@ function upsertBlock(file, block) {
3001
3172
  ${block}
3002
3173
  ` : `${block}
3003
3174
  `;
3004
- fs10.writeFileSync(file, existing);
3175
+ fs11.writeFileSync(file, existing);
3005
3176
  }
3006
3177
  function removeBlock(file) {
3007
- if (!fs10.existsSync(file)) return false;
3008
- const existing = fs10.readFileSync(file, "utf8");
3178
+ if (!fs11.existsSync(file)) return false;
3179
+ const existing = fs11.readFileSync(file, "utf8");
3009
3180
  const re = new RegExp(`\\n*${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}\\n*`);
3010
3181
  if (!re.test(existing)) return false;
3011
- fs10.writeFileSync(file, existing.replace(re, "\n"));
3182
+ fs11.writeFileSync(file, existing.replace(re, "\n"));
3012
3183
  return true;
3013
3184
  }
3014
3185
  function readJson(file) {
3015
- if (!fs10.existsSync(file)) return {};
3186
+ if (!fs11.existsSync(file)) return {};
3016
3187
  try {
3017
- const parsed = JSON.parse(fs10.readFileSync(file, "utf8"));
3188
+ const parsed = JSON.parse(fs11.readFileSync(file, "utf8"));
3018
3189
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
3019
3190
  return parsed;
3020
3191
  }
@@ -3033,6 +3204,6 @@ function escapeRe(s) {
3033
3204
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
3034
3205
  }
3035
3206
 
3036
- export { ASSISTANTS, CliError, ExitCode, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, UsageError, analyze, applyCoverage, assistantById, buildFacts, buildGraph, decodeScipIndex, detectAssistants, detectServeLaunch, discover, driftCount, epistemicBreakdown, groundGraph, hasDrift, installAssistant, isAssistantInstalled, isSkippedDirName, loadCoverage, loadSnapshot, probeFreshness, refreshInstalledInstructions, resolveLimits, scipEdges, uninstallAssistant, usageError, verifyDeterminism, writeNavigationConfig, writeSnapshot };
3037
- //# sourceMappingURL=chunk-5IA2TA57.js.map
3038
- //# sourceMappingURL=chunk-5IA2TA57.js.map
3207
+ export { ASSISTANTS, CliError, ExitCode, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, UsageError, analyze, applyCoverage, assistantById, buildFacts, buildGraph, decodeScipIndex, detectAssistants, detectServeLaunch, discover, driftCount, epistemicBreakdown, groundGraph, hasDrift, installAssistant, isAssistantInstalled, isSkippedDirName, loadCoverage, loadSnapshot, probeFreshness, refreshInstalledInstructions, resolveLimits, scipEdges, uninstallAssistant, usageError, verifyDeterminism, versionMarker, writeNavigationConfig, writeSnapshot };
3208
+ //# sourceMappingURL=chunk-FKFRASAB.js.map
3209
+ //# sourceMappingURL=chunk-FKFRASAB.js.map