@vibgrate/cli 2026.703.5 → 2026.703.7

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.
@@ -1,6 +1,7 @@
1
1
  import { langById, shortId, canonicalize, grammarSetVersion, hashBytes, hashString, langForExtension, setGrammarsOverride, parseSource } from './chunk-X5YT263H.js';
2
- import { writeTextFile, pathExists, readJsonFile, VERSION, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem } from './chunk-L7YBNIBF.js';
3
- import * as fs17 from 'fs';
2
+ import { writeTextFile, pathExists, readJsonFile, VERSION, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem } from './chunk-QWS7M7DG.js';
3
+ import * as fs18 from 'fs';
4
+ import { execFileSync } from 'child_process';
4
5
  import * as path18 from 'path';
5
6
  import ignore from 'ignore';
6
7
  import Graph from 'graphology';
@@ -12,7 +13,6 @@ import * as os from 'os';
12
13
  import { fileURLToPath } from 'url';
13
14
  import ts from 'typescript';
14
15
  import { bidirectional } from 'graphology-shortest-path/unweighted.js';
15
- import { execFileSync } from 'child_process';
16
16
  import * as crypto from 'crypto';
17
17
  import { Command } from 'commander';
18
18
  import chalk from 'chalk';
@@ -23,6 +23,43 @@ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
23
23
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
24
24
  import { ListToolsRequestSchema, CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
25
25
 
26
+ var NPX_INVOCATION = "npx @vibgrate/cli";
27
+ function whichOnPath(cmd) {
28
+ try {
29
+ const out = execFileSync(process.platform === "win32" ? "where" : "which", [cmd], {
30
+ encoding: "utf8",
31
+ stdio: ["ignore", "pipe", "ignore"]
32
+ }).trim().split(/\r?\n/)[0];
33
+ return out || null;
34
+ } catch {
35
+ return null;
36
+ }
37
+ }
38
+ function isOwnBinary(binPath) {
39
+ try {
40
+ const real = fs18.realpathSync(binPath);
41
+ if (/[\\/]@vibgrate[\\/]cli[\\/]/.test(real)) return true;
42
+ const head = fs18.readFileSync(real, { encoding: "utf8" }).slice(0, 2048);
43
+ return head.includes("@vibgrate/cli") || head.includes("vibgrate");
44
+ } catch {
45
+ return false;
46
+ }
47
+ }
48
+ var cached;
49
+ function resolveCliInvocation(which) {
50
+ if (!which && cached !== void 0) return cached;
51
+ const lookup = which ?? whichOnPath;
52
+ const vg = lookup("vg");
53
+ let result;
54
+ if (vg && isOwnBinary(vg)) {
55
+ result = "vg";
56
+ } else {
57
+ const vibgrate = lookup("vibgrate");
58
+ result = vibgrate && isOwnBinary(vibgrate) ? "vibgrate" : NPX_INVOCATION;
59
+ }
60
+ if (!which) cached = result;
61
+ return result;
62
+ }
26
63
  var SKIP_DIRS = /* @__PURE__ */ new Set([
27
64
  ".git",
28
65
  "node_modules",
@@ -56,8 +93,8 @@ function toPosix(p) {
56
93
  function buildRootIgnore(root, exclude) {
57
94
  const ig = ignore();
58
95
  const gitignorePath = path18.join(root, ".gitignore");
59
- if (fs17.existsSync(gitignorePath)) {
60
- ig.add(fs17.readFileSync(gitignorePath, "utf8"));
96
+ if (fs18.existsSync(gitignorePath)) {
97
+ ig.add(fs18.readFileSync(gitignorePath, "utf8"));
61
98
  }
62
99
  if (exclude.length) ig.add(exclude);
63
100
  return ig;
@@ -72,7 +109,7 @@ function discover(options) {
72
109
  }
73
110
  }
74
111
  const rootIg = buildRootIgnore(root, options.exclude ?? []);
75
- const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path18.resolve(root, p)) : [root]).filter((p) => fs17.existsSync(p));
112
+ const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path18.resolve(root, p)) : [root]).filter((p) => fs18.existsSync(p));
76
113
  const found = /* @__PURE__ */ new Map();
77
114
  const considerFile = (abs) => {
78
115
  const rel2 = toPosix(path18.relative(root, abs));
@@ -85,7 +122,7 @@ function discover(options) {
85
122
  const walk2 = (dir) => {
86
123
  let entries;
87
124
  try {
88
- entries = fs17.readdirSync(dir, { withFileTypes: true });
125
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
89
126
  } catch {
90
127
  return;
91
128
  }
@@ -102,7 +139,7 @@ function discover(options) {
102
139
  }
103
140
  };
104
141
  for (const scope of scopeAbs) {
105
- const stat = fs17.statSync(scope);
142
+ const stat = fs18.statSync(scope);
106
143
  if (stat.isDirectory()) walk2(scope);
107
144
  else if (stat.isFile()) considerFile(scope);
108
145
  }
@@ -336,7 +373,7 @@ function matchPattern(pattern, source) {
336
373
  function loadTsconfigPaths(root) {
337
374
  for (const name of ["tsconfig.base.json", "tsconfig.json"]) {
338
375
  const file = path18.join(root, name);
339
- if (fs17.existsSync(file)) {
376
+ if (fs18.existsSync(file)) {
340
377
  const merged = readTsconfigChain(root, file, /* @__PURE__ */ new Set());
341
378
  if (merged && merged.paths.length) return merged;
342
379
  }
@@ -348,7 +385,7 @@ function readTsconfigChain(root, file, seen) {
348
385
  seen.add(file);
349
386
  let cfg;
350
387
  try {
351
- cfg = parseJsonc(fs17.readFileSync(file, "utf8"));
388
+ cfg = parseJsonc(fs18.readFileSync(file, "utf8"));
352
389
  } catch {
353
390
  return null;
354
391
  }
@@ -356,7 +393,7 @@ function readTsconfigChain(root, file, seen) {
356
393
  let base = { baseUrlRel: "", paths: [] };
357
394
  if (cfg.extends && cfg.extends.startsWith(".")) {
358
395
  const extPath = path18.resolve(dir, cfg.extends.endsWith(".json") ? cfg.extends : `${cfg.extends}.json`);
359
- if (fs17.existsSync(extPath)) {
396
+ if (fs18.existsSync(extPath)) {
360
397
  const inherited = readTsconfigChain(root, extPath, seen);
361
398
  if (inherited) base = inherited;
362
399
  }
@@ -371,17 +408,17 @@ function loadWorkspacePackages(root) {
371
408
  const map = /* @__PURE__ */ new Map();
372
409
  const globs = [];
373
410
  const rootPkg = path18.join(root, "package.json");
374
- if (fs17.existsSync(rootPkg)) {
411
+ if (fs18.existsSync(rootPkg)) {
375
412
  try {
376
- const pkg = JSON.parse(fs17.readFileSync(rootPkg, "utf8"));
413
+ const pkg = JSON.parse(fs18.readFileSync(rootPkg, "utf8"));
377
414
  const ws = Array.isArray(pkg.workspaces) ? pkg.workspaces : pkg.workspaces?.packages;
378
415
  if (ws) globs.push(...ws);
379
416
  } catch {
380
417
  }
381
418
  }
382
419
  const pnpmWs = path18.join(root, "pnpm-workspace.yaml");
383
- if (fs17.existsSync(pnpmWs)) {
384
- for (const line of fs17.readFileSync(pnpmWs, "utf8").split("\n")) {
420
+ if (fs18.existsSync(pnpmWs)) {
421
+ for (const line of fs18.readFileSync(pnpmWs, "utf8").split("\n")) {
385
422
  const m = /^\s*-\s*['"]?([^'"\n]+)['"]?\s*$/.exec(line);
386
423
  if (m) globs.push(m[1].trim());
387
424
  }
@@ -389,7 +426,7 @@ function loadWorkspacePackages(root) {
389
426
  for (const dir of expandWorkspaceGlobs(root, globs)) {
390
427
  const pj = path18.join(dir, "package.json");
391
428
  try {
392
- const name = JSON.parse(fs17.readFileSync(pj, "utf8")).name;
429
+ const name = JSON.parse(fs18.readFileSync(pj, "utf8")).name;
393
430
  if (name) map.set(name, path18.relative(root, dir).split(path18.sep).join("/"));
394
431
  } catch {
395
432
  }
@@ -403,7 +440,7 @@ function expandWorkspaceGlobs(root, globs) {
403
440
  const baseDir = path18.join(root, clean);
404
441
  const recurse = glob.endsWith("**");
405
442
  if (glob === clean) {
406
- if (fs17.existsSync(path18.join(baseDir, "package.json"))) out.add(baseDir);
443
+ if (fs18.existsSync(path18.join(baseDir, "package.json"))) out.add(baseDir);
407
444
  continue;
408
445
  }
409
446
  collectPackageDirs(baseDir, recurse ? 4 : 1, out);
@@ -414,14 +451,14 @@ function collectPackageDirs(dir, depth, out) {
414
451
  if (depth < 0) return;
415
452
  let entries;
416
453
  try {
417
- entries = fs17.readdirSync(dir, { withFileTypes: true });
454
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
418
455
  } catch {
419
456
  return;
420
457
  }
421
458
  for (const e of entries) {
422
459
  if (!e.isDirectory() || e.name === "node_modules" || e.name.startsWith(".")) continue;
423
460
  const child = path18.join(dir, e.name);
424
- if (fs17.existsSync(path18.join(child, "package.json"))) out.add(child);
461
+ if (fs18.existsSync(path18.join(child, "package.json"))) out.add(child);
425
462
  else collectPackageDirs(child, depth - 1, out);
426
463
  }
427
464
  }
@@ -921,12 +958,12 @@ function loadCoverage(root, explicit) {
921
958
  const candidates = (explicit && explicit.length ? explicit : DEFAULT_PATHS).map(
922
959
  (p) => path18.resolve(root, p)
923
960
  );
924
- const found = candidates.filter((p) => fs17.existsSync(p));
961
+ const found = candidates.filter((p) => fs18.existsSync(p));
925
962
  if (found.length === 0) return null;
926
963
  const map = /* @__PURE__ */ new Map();
927
964
  for (const file of found) {
928
965
  try {
929
- const text = fs17.readFileSync(file, "utf8");
966
+ const text = fs18.readFileSync(file, "utf8");
930
967
  if (file.endsWith(".json")) mergeIstanbul(map, text, root);
931
968
  else mergeLcov(map, text, root);
932
969
  } catch {
@@ -1272,7 +1309,7 @@ async function parseInline(files, onProgress) {
1272
1309
  onProgress?.(0, files.length);
1273
1310
  for (const file of files) {
1274
1311
  try {
1275
- const source = fs17.readFileSync(file.abs, "utf8");
1312
+ const source = fs18.readFileSync(file.abs, "utf8");
1276
1313
  out.push(await parseSource(file.rel, file.lang.id, source));
1277
1314
  } catch (err) {
1278
1315
  out.push(emptyParse(file, `parse failed: ${err.message}`));
@@ -1309,7 +1346,7 @@ async function parsePooled(files, jobs, workerFile, onProgress, grammarsDir) {
1309
1346
  function resolveWorkerFile() {
1310
1347
  const here = path18.dirname(fileURLToPath(import.meta.url));
1311
1348
  const candidate = path18.join(here, "parse-worker.js");
1312
- return fs17.existsSync(candidate) ? candidate : null;
1349
+ return fs18.existsSync(candidate) ? candidate : null;
1313
1350
  }
1314
1351
  function chunk(items, buckets) {
1315
1352
  const out = Array.from({ length: Math.min(buckets, items.length || 1) }, () => []);
@@ -1769,9 +1806,9 @@ function loadCache(root, opts) {
1769
1806
  grammars: opts.grammars,
1770
1807
  entries: {}
1771
1808
  };
1772
- if (!opts.disabled && fs17.existsSync(file)) {
1809
+ if (!opts.disabled && fs18.existsSync(file)) {
1773
1810
  try {
1774
- const loaded = JSON.parse(fs17.readFileSync(file, "utf8"));
1811
+ const loaded = JSON.parse(fs18.readFileSync(file, "utf8"));
1775
1812
  if (loaded.version === CACHE_VERSION && loaded.toolVersion === opts.toolVersion && loaded.grammars === opts.grammars && loaded.entries) {
1776
1813
  data = loaded;
1777
1814
  }
@@ -1792,8 +1829,8 @@ function loadCache(root, opts) {
1792
1829
  }
1793
1830
  },
1794
1831
  save() {
1795
- fs17.mkdirSync(cacheDir(root), { recursive: true });
1796
- fs17.writeFileSync(file, stableStringify(data, 0));
1832
+ fs18.mkdirSync(cacheDir(root), { recursive: true });
1833
+ fs18.writeFileSync(file, stableStringify(data, 0));
1797
1834
  }
1798
1835
  };
1799
1836
  }
@@ -1822,15 +1859,15 @@ async function buildGraph(options) {
1822
1859
  let hash = "";
1823
1860
  let stat;
1824
1861
  try {
1825
- stat = fs17.statSync(file.abs);
1826
- hash = hashBytes(fs17.readFileSync(file.abs));
1862
+ stat = fs18.statSync(file.abs);
1863
+ hash = hashBytes(fs18.readFileSync(file.abs));
1827
1864
  } catch {
1828
1865
  continue;
1829
1866
  }
1830
1867
  hashes.set(file.rel, hash);
1831
1868
  fileStats.push({ rel: file.rel, size: stat.size, mtimeMs: stat.mtimeMs, hash });
1832
- const cached = cache.get(file.rel, hash);
1833
- if (cached) reused.push(cached);
1869
+ const cached2 = cache.get(file.rel, hash);
1870
+ if (cached2) reused.push(cached2);
1834
1871
  else toParse.push(file);
1835
1872
  }
1836
1873
  const parsedNew = await parseFiles(toParse, {
@@ -1943,9 +1980,9 @@ function loadScipIndex(root, explicit) {
1943
1980
  ].filter((p) => Boolean(p));
1944
1981
  for (const file of candidates) {
1945
1982
  const abs = path18.isAbsolute(file) ? file : path18.resolve(root, file);
1946
- if (!fs17.existsSync(abs)) continue;
1983
+ if (!fs18.existsSync(abs)) continue;
1947
1984
  try {
1948
- const index = decodeScipIndex(new Uint8Array(fs17.readFileSync(abs)));
1985
+ const index = decodeScipIndex(new Uint8Array(fs18.readFileSync(abs)));
1949
1986
  if (index.documents.length) {
1950
1987
  return { index, tool: index.toolVersion ? `${index.toolName} ${index.toolVersion}` : index.toolName };
1951
1988
  }
@@ -1987,7 +2024,7 @@ function isProcessAlive(pid) {
1987
2024
  }
1988
2025
  function lockIsStale(file, staleMs) {
1989
2026
  try {
1990
- const { pid, at } = JSON.parse(fs17.readFileSync(file, "utf8"));
2027
+ const { pid, at } = JSON.parse(fs18.readFileSync(file, "utf8"));
1991
2028
  if (typeof at === "number" && Date.now() - at > staleMs) return true;
1992
2029
  if (typeof pid === "number" && !isProcessAlive(pid)) return true;
1993
2030
  return false;
@@ -1998,10 +2035,10 @@ function lockIsStale(file, staleMs) {
1998
2035
  function acquireLock(file, staleMs = DEFAULT_LOCK_STALE_MS) {
1999
2036
  const write = () => {
2000
2037
  try {
2001
- fs17.mkdirSync(path18.dirname(file), { recursive: true });
2002
- const fd = fs17.openSync(file, "wx");
2003
- fs17.writeFileSync(fd, JSON.stringify({ pid: process.pid, at: Date.now() }));
2004
- fs17.closeSync(fd);
2038
+ fs18.mkdirSync(path18.dirname(file), { recursive: true });
2039
+ const fd = fs18.openSync(file, "wx");
2040
+ fs18.writeFileSync(fd, JSON.stringify({ pid: process.pid, at: Date.now() }));
2041
+ fs18.closeSync(fd);
2005
2042
  return true;
2006
2043
  } catch {
2007
2044
  return false;
@@ -2010,7 +2047,7 @@ function acquireLock(file, staleMs = DEFAULT_LOCK_STALE_MS) {
2010
2047
  if (write()) return true;
2011
2048
  if (lockIsStale(file, staleMs)) {
2012
2049
  try {
2013
- fs17.rmSync(file, { force: true });
2050
+ fs18.rmSync(file, { force: true });
2014
2051
  } catch {
2015
2052
  }
2016
2053
  return write();
@@ -2019,7 +2056,7 @@ function acquireLock(file, staleMs = DEFAULT_LOCK_STALE_MS) {
2019
2056
  }
2020
2057
  function releaseLock(file) {
2021
2058
  try {
2022
- fs17.rmSync(file, { force: true });
2059
+ fs18.rmSync(file, { force: true });
2023
2060
  } catch {
2024
2061
  }
2025
2062
  }
@@ -2036,7 +2073,7 @@ function modelReadyMarker(modelId) {
2036
2073
  return path18.join(modelCacheDir(), `.ready-${safe(modelId)}`);
2037
2074
  }
2038
2075
  function isModelReady(modelId = resolveEmbedModel()) {
2039
- return fs17.existsSync(modelReadyMarker(modelId));
2076
+ return fs18.existsSync(modelReadyMarker(modelId));
2040
2077
  }
2041
2078
  function unavailableMessage(reason) {
2042
2079
  switch (reason) {
@@ -2053,13 +2090,13 @@ function unavailableMessage(reason) {
2053
2090
  }
2054
2091
  function modelCacheInfo(modelId = resolveEmbedModel()) {
2055
2092
  const dir = modelCacheDir();
2056
- return { dir, present: isModelReady(modelId) || fs17.existsSync(dir), bytes: dirSize(dir) };
2093
+ return { dir, present: isModelReady(modelId) || fs18.existsSync(dir), bytes: dirSize(dir) };
2057
2094
  }
2058
2095
  function clearModelCache() {
2059
2096
  const dir = modelCacheDir();
2060
2097
  const bytes = dirSize(dir);
2061
2098
  try {
2062
- fs17.rmSync(dir, { recursive: true, force: true });
2099
+ fs18.rmSync(dir, { recursive: true, force: true });
2063
2100
  } catch {
2064
2101
  }
2065
2102
  return bytes;
@@ -2068,7 +2105,7 @@ function dirSize(dir) {
2068
2105
  let total = 0;
2069
2106
  let entries;
2070
2107
  try {
2071
- entries = fs17.readdirSync(dir, { withFileTypes: true });
2108
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
2072
2109
  } catch {
2073
2110
  return 0;
2074
2111
  }
@@ -2077,7 +2114,7 @@ function dirSize(dir) {
2077
2114
  if (e.isDirectory()) total += dirSize(p);
2078
2115
  else {
2079
2116
  try {
2080
- total += fs17.statSync(p).size;
2117
+ total += fs18.statSync(p).size;
2081
2118
  } catch {
2082
2119
  }
2083
2120
  }
@@ -2089,7 +2126,7 @@ function isPermissionError(e) {
2089
2126
  return code === "EACCES" || code === "EPERM" || code === "EROFS";
2090
2127
  }
2091
2128
  function embeddingsCached(root, modelId) {
2092
- return fs17.existsSync(path18.join(cacheDir(root), `embeddings-${safe(modelId)}.json`));
2129
+ return fs18.existsSync(path18.join(cacheDir(root), `embeddings-${safe(modelId)}.json`));
2093
2130
  }
2094
2131
  async function loadEmbedder(options = {}) {
2095
2132
  if (options.local) return null;
@@ -2103,7 +2140,7 @@ async function loadEmbedder(options = {}) {
2103
2140
  if (!mod?.FlagEmbedding) return fail("not-installed");
2104
2141
  const cache = modelCacheDir();
2105
2142
  try {
2106
- fs17.mkdirSync(cache, { recursive: true });
2143
+ fs18.mkdirSync(cache, { recursive: true });
2107
2144
  } catch (e) {
2108
2145
  return fail(isPermissionError(e) ? "no-permission" : "init-failed");
2109
2146
  }
@@ -2118,7 +2155,7 @@ async function loadEmbedder(options = {}) {
2118
2155
  "embedding model init timed out"
2119
2156
  );
2120
2157
  try {
2121
- fs17.writeFileSync(modelReadyMarker(modelId), (/* @__PURE__ */ new Date(0)).toISOString());
2158
+ fs18.writeFileSync(modelReadyMarker(modelId), (/* @__PURE__ */ new Date(0)).toISOString());
2122
2159
  } catch {
2123
2160
  }
2124
2161
  return {
@@ -2225,15 +2262,15 @@ function countPending(graph, root, modelId) {
2225
2262
  for (const n of graph.nodes) {
2226
2263
  if (n.kind === "file" || n.kind === "external") continue;
2227
2264
  const h = hashString(nodeEmbedText(n, areaLabel.get(n.area)));
2228
- const cached = entries[n.id];
2229
- if (!cached || cached.hash !== h) pending++;
2265
+ const cached2 = entries[n.id];
2266
+ if (!cached2 || cached2.hash !== h) pending++;
2230
2267
  }
2231
2268
  return pending;
2232
2269
  }
2233
2270
  function readCacheEntries(file, modelId) {
2234
- if (!fs17.existsSync(file)) return {};
2271
+ if (!fs18.existsSync(file)) return {};
2235
2272
  try {
2236
- const loaded = JSON.parse(fs17.readFileSync(file, "utf8"));
2273
+ const loaded = JSON.parse(fs18.readFileSync(file, "utf8"));
2237
2274
  if (loaded.model === modelId && loaded.entries) return loaded.entries;
2238
2275
  } catch {
2239
2276
  }
@@ -2242,9 +2279,9 @@ function readCacheEntries(file, modelId) {
2242
2279
  async function getNodeEmbeddings(graph, embedder, root, onProgress) {
2243
2280
  const file = vectorCachePath(root, embedder.id);
2244
2281
  let cache = { model: embedder.id, entries: {} };
2245
- if (fs17.existsSync(file)) {
2282
+ if (fs18.existsSync(file)) {
2246
2283
  try {
2247
- const loaded = JSON.parse(fs17.readFileSync(file, "utf8"));
2284
+ const loaded = JSON.parse(fs18.readFileSync(file, "utf8"));
2248
2285
  if (loaded.model === embedder.id && loaded.entries) cache = loaded;
2249
2286
  } catch {
2250
2287
  }
@@ -2256,16 +2293,16 @@ async function getNodeEmbeddings(graph, embedder, root, onProgress) {
2256
2293
  for (const n of targets) {
2257
2294
  const text = nodeEmbedText(n, areaLabel.get(n.area));
2258
2295
  const h = hashString(text);
2259
- const cached = cache.entries[n.id];
2260
- if (cached && cached.hash === h) vectors.set(n.id, cached.vec);
2296
+ const cached2 = cache.entries[n.id];
2297
+ if (cached2 && cached2.hash === h) vectors.set(n.id, cached2.vec);
2261
2298
  else toEmbed.push({ id: n.id, text, hash: h });
2262
2299
  }
2263
2300
  const persist = () => {
2264
2301
  try {
2265
- fs17.mkdirSync(cacheDir(root), { recursive: true });
2302
+ fs18.mkdirSync(cacheDir(root), { recursive: true });
2266
2303
  const tmp = `${file}.tmp.${process.pid}`;
2267
- fs17.writeFileSync(tmp, JSON.stringify(cache));
2268
- fs17.renameSync(tmp, file);
2304
+ fs18.writeFileSync(tmp, JSON.stringify(cache));
2305
+ fs18.renameSync(tmp, file);
2269
2306
  } catch {
2270
2307
  }
2271
2308
  };
@@ -2421,31 +2458,31 @@ function defaultGraphPath(root) {
2421
2458
  }
2422
2459
  function writeArtifacts(graph, options) {
2423
2460
  const dir = vibgrateDir(options.root);
2424
- fs17.mkdirSync(dir, { recursive: true });
2461
+ fs18.mkdirSync(dir, { recursive: true });
2425
2462
  const graphPath = options.graphPath ?? defaultGraphPath(options.root);
2426
- fs17.mkdirSync(path18.dirname(graphPath), { recursive: true });
2463
+ fs18.mkdirSync(path18.dirname(graphPath), { recursive: true });
2427
2464
  const tmp = `${graphPath}.${process.pid}.tmp`;
2428
2465
  try {
2429
- fs17.writeFileSync(tmp, serializeGraph(graph));
2430
- fs17.renameSync(tmp, graphPath);
2466
+ fs18.writeFileSync(tmp, serializeGraph(graph));
2467
+ fs18.renameSync(tmp, graphPath);
2431
2468
  } catch (err) {
2432
- fs17.rmSync(tmp, { force: true });
2469
+ fs18.rmSync(tmp, { force: true });
2433
2470
  throw err;
2434
2471
  }
2435
2472
  const written = { graphPath };
2436
2473
  if (options.report !== false) {
2437
2474
  const reportPath = path18.join(dir, "GRAPH_REPORT.md");
2438
- fs17.writeFileSync(reportPath, renderReport(graph));
2475
+ fs18.writeFileSync(reportPath, renderReport(graph));
2439
2476
  written.reportPath = reportPath;
2440
2477
  }
2441
2478
  if (options.html !== false) {
2442
2479
  const htmlPath = path18.join(dir, "graph.html");
2443
- fs17.writeFileSync(htmlPath, renderHtml(graph));
2480
+ fs18.writeFileSync(htmlPath, renderHtml(graph));
2444
2481
  written.htmlPath = htmlPath;
2445
2482
  }
2446
2483
  if (graph.facts && graph.facts.length) {
2447
2484
  const factsPath = path18.join(dir, "facts.jsonl");
2448
- fs17.writeFileSync(factsPath, graph.facts.map((f) => JSON.stringify(f)).join("\n") + "\n");
2485
+ fs18.writeFileSync(factsPath, graph.facts.map((f) => JSON.stringify(f)).join("\n") + "\n");
2449
2486
  written.factsPath = factsPath;
2450
2487
  }
2451
2488
  return written;
@@ -2459,14 +2496,14 @@ function writeSnapshot(root, corpusHash, fileStats, scope = {}) {
2459
2496
  for (const f of fileStats) files[f.rel] = { size: f.size, mtimeMs: f.mtimeMs, hash: f.hash };
2460
2497
  const snapshot = { version: SNAPSHOT_VERSION, corpusHash, scope: pruneScope(scope), files };
2461
2498
  try {
2462
- fs17.mkdirSync(cacheDir(root), { recursive: true });
2463
- fs17.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2499
+ fs18.mkdirSync(cacheDir(root), { recursive: true });
2500
+ fs18.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2464
2501
  } catch {
2465
2502
  }
2466
2503
  }
2467
2504
  function loadSnapshot(root) {
2468
2505
  try {
2469
- const loaded = JSON.parse(fs17.readFileSync(snapshotPath(root), "utf8"));
2506
+ const loaded = JSON.parse(fs18.readFileSync(snapshotPath(root), "utf8"));
2470
2507
  if (loaded.version === SNAPSHOT_VERSION && loaded.files && typeof loaded.corpusHash === "string") {
2471
2508
  return { ...loaded, scope: loaded.scope ?? {} };
2472
2509
  }
@@ -2502,7 +2539,7 @@ function probeFreshness(root) {
2502
2539
  }
2503
2540
  let stat;
2504
2541
  try {
2505
- stat = fs17.statSync(file.abs);
2542
+ stat = fs18.statSync(file.abs);
2506
2543
  } catch {
2507
2544
  drift.removed.push(file.rel);
2508
2545
  continue;
@@ -2510,7 +2547,7 @@ function probeFreshness(root) {
2510
2547
  if (stat.size === entry.size && stat.mtimeMs === entry.mtimeMs) continue;
2511
2548
  let hash = "";
2512
2549
  try {
2513
- hash = hashBytes(fs17.readFileSync(file.abs));
2550
+ hash = hashBytes(fs18.readFileSync(file.abs));
2514
2551
  } catch {
2515
2552
  drift.removed.push(file.rel);
2516
2553
  continue;
@@ -2527,7 +2564,7 @@ function probeFreshness(root) {
2527
2564
  }
2528
2565
  if (absorbed && !hasDrift(drift)) {
2529
2566
  try {
2530
- fs17.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2567
+ fs18.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2531
2568
  } catch {
2532
2569
  }
2533
2570
  }
@@ -2573,8 +2610,8 @@ function usageError(message) {
2573
2610
  }
2574
2611
  function loadGraph(root, graphPath) {
2575
2612
  const file = graphPath ?? defaultGraphPath(root);
2576
- if (!fs17.existsSync(file)) return null;
2577
- return parseGraph(fs17.readFileSync(file, "utf8"));
2613
+ if (!fs18.existsSync(file)) return null;
2614
+ return parseGraph(fs18.readFileSync(file, "utf8"));
2578
2615
  }
2579
2616
 
2580
2617
  // src/engine/verify.ts
@@ -2583,10 +2620,10 @@ async function verifyDeterminism(opts) {
2583
2620
  const base = { root: opts.root, only: opts.only, exclude: opts.exclude, generatedAt: PINNED };
2584
2621
  const a = serializeGraph((await buildGraph({ ...base, noCache: true, jobs: opts.jobs })).graph);
2585
2622
  const b = serializeGraph((await buildGraph({ ...base, noCache: true, jobs: 1 })).graph);
2586
- const cached = serializeGraph((await buildGraph({ ...base, noCache: false })).graph);
2623
+ const cached2 = serializeGraph((await buildGraph({ ...base, noCache: false })).graph);
2587
2624
  const checks = [
2588
2625
  { name: "run-to-run determinism", ok: a === b, detail: diffHint(a, b) },
2589
- { name: "cache safety (incremental == full)", ok: a === cached, detail: diffHint(a, cached) }
2626
+ { name: "cache safety (incremental == full)", ok: a === cached2, detail: diffHint(a, cached2) }
2590
2627
  ];
2591
2628
  return {
2592
2629
  ok: checks.every((c) => c.ok),
@@ -2871,8 +2908,8 @@ async function refreshIfStale(root, opts = {}) {
2871
2908
  const dir = vibgrateDir(root);
2872
2909
  writeArtifacts(result.graph, {
2873
2910
  root,
2874
- report: fs17.existsSync(path18.join(dir, "GRAPH_REPORT.md")),
2875
- html: fs17.existsSync(path18.join(dir, "graph.html"))
2911
+ report: fs18.existsSync(path18.join(dir, "GRAPH_REPORT.md")),
2912
+ html: fs18.existsSync(path18.join(dir, "graph.html"))
2876
2913
  });
2877
2914
  }
2878
2915
  writeSnapshot(root, result.graph.provenance.corpusHash, result.fileStats, scope);
@@ -3049,9 +3086,9 @@ function testsToRun(graph, rootId, depth = 4) {
3049
3086
  }
3050
3087
  function detectRunner(root, lang) {
3051
3088
  const pkgPath = path18.join(root, "package.json");
3052
- if (fs17.existsSync(pkgPath)) {
3089
+ if (fs18.existsSync(pkgPath)) {
3053
3090
  try {
3054
- const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf8"));
3091
+ const pkg = JSON.parse(fs18.readFileSync(pkgPath, "utf8"));
3055
3092
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
3056
3093
  if (deps.vitest) return { name: "vitest", command: (f) => `npx vitest run ${f.join(" ")}`.trim() };
3057
3094
  if (deps.jest) return { name: "jest", command: (f) => `npx jest ${f.join(" ")}`.trim() };
@@ -3059,10 +3096,10 @@ function detectRunner(root, lang) {
3059
3096
  } catch {
3060
3097
  }
3061
3098
  }
3062
- if (lang === "py" || fs17.existsSync(path18.join(root, "pyproject.toml")) || fs17.existsSync(path18.join(root, "pytest.ini"))) {
3099
+ if (lang === "py" || fs18.existsSync(path18.join(root, "pyproject.toml")) || fs18.existsSync(path18.join(root, "pytest.ini"))) {
3063
3100
  return { name: "pytest", command: (f) => `pytest ${f.join(" ")}`.trim() };
3064
3101
  }
3065
- if (lang === "go" || fs17.existsSync(path18.join(root, "go.mod"))) {
3102
+ if (lang === "go" || fs18.existsSync(path18.join(root, "go.mod"))) {
3066
3103
  return { name: "go test", command: () => "go test ./..." };
3067
3104
  }
3068
3105
  if (lang === "cs" || hasFile(root, /\.csproj$/) || hasFile(root, /\.sln$/)) {
@@ -3073,7 +3110,7 @@ function detectRunner(root, lang) {
3073
3110
  }
3074
3111
  function hasFile(root, re) {
3075
3112
  try {
3076
- return fs17.readdirSync(root).some((f) => re.test(f));
3113
+ return fs18.readdirSync(root).some((f) => re.test(f));
3077
3114
  } catch {
3078
3115
  return false;
3079
3116
  }
@@ -3145,7 +3182,7 @@ function findManifests(root) {
3145
3182
  if (depth > 8 || scanned > MAX_ENTRIES) return;
3146
3183
  let entries;
3147
3184
  try {
3148
- entries = fs17.readdirSync(dir, { withFileTypes: true });
3185
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
3149
3186
  } catch {
3150
3187
  return;
3151
3188
  }
@@ -3169,7 +3206,7 @@ function npmDeps(files) {
3169
3206
  for (const file of files) {
3170
3207
  let pkg;
3171
3208
  try {
3172
- pkg = JSON.parse(fs17.readFileSync(file, "utf8"));
3209
+ pkg = JSON.parse(fs18.readFileSync(file, "utf8"));
3173
3210
  } catch {
3174
3211
  continue;
3175
3212
  }
@@ -3186,7 +3223,7 @@ function installedNpmVersion(dir, name) {
3186
3223
  for (let i = 0; i < 12; i++) {
3187
3224
  const p = path18.join(cur, "node_modules", name, "package.json");
3188
3225
  try {
3189
- return JSON.parse(fs17.readFileSync(p, "utf8")).version;
3226
+ return JSON.parse(fs18.readFileSync(p, "utf8")).version;
3190
3227
  } catch {
3191
3228
  }
3192
3229
  const parent = path18.dirname(cur);
@@ -3206,7 +3243,7 @@ function normalizePep503(name) {
3206
3243
  function sitePackagesDirs(base) {
3207
3244
  const out = [];
3208
3245
  try {
3209
- for (const d of fs17.readdirSync(path18.join(base, "lib"))) {
3246
+ for (const d of fs18.readdirSync(path18.join(base, "lib"))) {
3210
3247
  if (d.startsWith("python")) out.push(path18.join(base, "lib", d, "site-packages"));
3211
3248
  }
3212
3249
  } catch {
@@ -3220,7 +3257,7 @@ function installedPypiVersion(root, name) {
3220
3257
  for (const sp of sitePackagesDirs(path18.join(root, venv))) {
3221
3258
  let entries;
3222
3259
  try {
3223
- entries = fs17.readdirSync(sp);
3260
+ entries = fs18.readdirSync(sp);
3224
3261
  } catch {
3225
3262
  continue;
3226
3263
  }
@@ -3235,7 +3272,7 @@ function installedPypiVersion(root, name) {
3235
3272
  function installedPhpVersion(root, name) {
3236
3273
  let data;
3237
3274
  try {
3238
- data = JSON.parse(fs17.readFileSync(path18.join(root, "vendor", "composer", "installed.json"), "utf8"));
3275
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "vendor", "composer", "installed.json"), "utf8"));
3239
3276
  } catch {
3240
3277
  return void 0;
3241
3278
  }
@@ -3254,7 +3291,7 @@ function pypiDeps(files) {
3254
3291
  for (const file of files) {
3255
3292
  let text;
3256
3293
  try {
3257
- text = fs17.readFileSync(file, "utf8");
3294
+ text = fs18.readFileSync(file, "utf8");
3258
3295
  } catch {
3259
3296
  continue;
3260
3297
  }
@@ -3342,7 +3379,7 @@ function goDeps(files) {
3342
3379
  for (const mod of files) {
3343
3380
  let text;
3344
3381
  try {
3345
- text = fs17.readFileSync(mod, "utf8");
3382
+ text = fs18.readFileSync(mod, "utf8");
3346
3383
  } catch {
3347
3384
  continue;
3348
3385
  }
@@ -3360,7 +3397,7 @@ function cargoDeps(files) {
3360
3397
  for (const file of files) {
3361
3398
  let text;
3362
3399
  try {
3363
- text = fs17.readFileSync(file, "utf8");
3400
+ text = fs18.readFileSync(file, "utf8");
3364
3401
  } catch {
3365
3402
  continue;
3366
3403
  }
@@ -3392,7 +3429,7 @@ function rubyDeps(files) {
3392
3429
  for (const file of files) {
3393
3430
  let text;
3394
3431
  try {
3395
- text = fs17.readFileSync(file, "utf8");
3432
+ text = fs18.readFileSync(file, "utf8");
3396
3433
  } catch {
3397
3434
  continue;
3398
3435
  }
@@ -3407,7 +3444,7 @@ function phpDeps(files) {
3407
3444
  for (const file of files) {
3408
3445
  let pkg;
3409
3446
  try {
3410
- pkg = JSON.parse(fs17.readFileSync(file, "utf8"));
3447
+ pkg = JSON.parse(fs18.readFileSync(file, "utf8"));
3411
3448
  } catch {
3412
3449
  continue;
3413
3450
  }
@@ -3424,7 +3461,7 @@ function dotnetDeps(files) {
3424
3461
  for (const file of files) {
3425
3462
  let text;
3426
3463
  try {
3427
- text = fs17.readFileSync(file, "utf8");
3464
+ text = fs18.readFileSync(file, "utf8");
3428
3465
  } catch {
3429
3466
  continue;
3430
3467
  }
@@ -3444,7 +3481,7 @@ function swiftDeps(files) {
3444
3481
  for (const file of files) {
3445
3482
  let text;
3446
3483
  try {
3447
- text = fs17.readFileSync(file, "utf8");
3484
+ text = fs18.readFileSync(file, "utf8");
3448
3485
  } catch {
3449
3486
  continue;
3450
3487
  }
@@ -3466,7 +3503,7 @@ function dartDeps(files) {
3466
3503
  for (const file of files) {
3467
3504
  let text;
3468
3505
  try {
3469
- text = fs17.readFileSync(file, "utf8");
3506
+ text = fs18.readFileSync(file, "utf8");
3470
3507
  } catch {
3471
3508
  continue;
3472
3509
  }
@@ -3491,7 +3528,7 @@ function javaDeps(files) {
3491
3528
  for (const file of files) {
3492
3529
  let text;
3493
3530
  try {
3494
- text = fs17.readFileSync(file, "utf8");
3531
+ text = fs18.readFileSync(file, "utf8");
3495
3532
  } catch {
3496
3533
  continue;
3497
3534
  }
@@ -3580,7 +3617,7 @@ function walk(dir, depth, onFile) {
3580
3617
  if (depth < 0) return;
3581
3618
  let entries;
3582
3619
  try {
3583
- entries = fs17.readdirSync(dir, { withFileTypes: true });
3620
+ entries = fs18.readdirSync(dir, { withFileTypes: true });
3584
3621
  } catch {
3585
3622
  return;
3586
3623
  }
@@ -3616,7 +3653,7 @@ function lockfileVersion(root, ecosystem, name) {
3616
3653
  function gradleLock(root, name) {
3617
3654
  let text;
3618
3655
  try {
3619
- text = fs17.readFileSync(path18.join(root, "gradle.lockfile"), "utf8");
3656
+ text = fs18.readFileSync(path18.join(root, "gradle.lockfile"), "utf8");
3620
3657
  } catch {
3621
3658
  return void 0;
3622
3659
  }
@@ -3626,7 +3663,7 @@ function gradleLock(root, name) {
3626
3663
  function packageResolved(root, name) {
3627
3664
  let data;
3628
3665
  try {
3629
- data = JSON.parse(fs17.readFileSync(path18.join(root, "Package.resolved"), "utf8"));
3666
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "Package.resolved"), "utf8"));
3630
3667
  } catch {
3631
3668
  return void 0;
3632
3669
  }
@@ -3642,7 +3679,7 @@ function packageResolved(root, name) {
3642
3679
  function pubspecLock(root, name) {
3643
3680
  let text;
3644
3681
  try {
3645
- text = fs17.readFileSync(path18.join(root, "pubspec.lock"), "utf8");
3682
+ text = fs18.readFileSync(path18.join(root, "pubspec.lock"), "utf8");
3646
3683
  } catch {
3647
3684
  return void 0;
3648
3685
  }
@@ -3666,7 +3703,7 @@ function escapeRegExp(s) {
3666
3703
  function gemfileLock(root, name) {
3667
3704
  let text;
3668
3705
  try {
3669
- text = fs17.readFileSync(path18.join(root, "Gemfile.lock"), "utf8");
3706
+ text = fs18.readFileSync(path18.join(root, "Gemfile.lock"), "utf8");
3670
3707
  } catch {
3671
3708
  return void 0;
3672
3709
  }
@@ -3676,7 +3713,7 @@ function gemfileLock(root, name) {
3676
3713
  function composerLock(root, name) {
3677
3714
  let data;
3678
3715
  try {
3679
- data = JSON.parse(fs17.readFileSync(path18.join(root, "composer.lock"), "utf8"));
3716
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "composer.lock"), "utf8"));
3680
3717
  } catch {
3681
3718
  return void 0;
3682
3719
  }
@@ -3691,7 +3728,7 @@ function composerLock(root, name) {
3691
3728
  function packagesLock(root, name) {
3692
3729
  let data;
3693
3730
  try {
3694
- data = JSON.parse(fs17.readFileSync(path18.join(root, "packages.lock.json"), "utf8"));
3731
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "packages.lock.json"), "utf8"));
3695
3732
  } catch {
3696
3733
  return void 0;
3697
3734
  }
@@ -3716,7 +3753,7 @@ function pypiLockVersion(root, name) {
3716
3753
  function tomlPackageLock(root, file, name, normalize3) {
3717
3754
  let text;
3718
3755
  try {
3719
- text = fs17.readFileSync(path18.join(root, file), "utf8");
3756
+ text = fs18.readFileSync(path18.join(root, file), "utf8");
3720
3757
  } catch {
3721
3758
  return void 0;
3722
3759
  }
@@ -3733,7 +3770,7 @@ function tomlPackageLock(root, file, name, normalize3) {
3733
3770
  function pipfileLock(root, name) {
3734
3771
  let data;
3735
3772
  try {
3736
- data = JSON.parse(fs17.readFileSync(path18.join(root, "Pipfile.lock"), "utf8"));
3773
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "Pipfile.lock"), "utf8"));
3737
3774
  } catch {
3738
3775
  return void 0;
3739
3776
  }
@@ -3752,7 +3789,7 @@ function pipfileLock(root, name) {
3752
3789
  function packageLockVersion(root, name) {
3753
3790
  let data;
3754
3791
  try {
3755
- data = JSON.parse(fs17.readFileSync(path18.join(root, "package-lock.json"), "utf8"));
3792
+ data = JSON.parse(fs18.readFileSync(path18.join(root, "package-lock.json"), "utf8"));
3756
3793
  } catch {
3757
3794
  return void 0;
3758
3795
  }
@@ -3764,7 +3801,7 @@ function packageLockVersion(root, name) {
3764
3801
  function yarnLockVersion(root, name) {
3765
3802
  let text;
3766
3803
  try {
3767
- text = fs17.readFileSync(path18.join(root, "yarn.lock"), "utf8");
3804
+ text = fs18.readFileSync(path18.join(root, "yarn.lock"), "utf8");
3768
3805
  } catch {
3769
3806
  return void 0;
3770
3807
  }
@@ -3802,9 +3839,9 @@ function libId(name) {
3802
3839
  }
3803
3840
  function loadCatalog(root) {
3804
3841
  const file = catalogPath(root);
3805
- if (fs17.existsSync(file)) {
3842
+ if (fs18.existsSync(file)) {
3806
3843
  try {
3807
- const data = JSON.parse(fs17.readFileSync(file, "utf8"));
3844
+ const data = JSON.parse(fs18.readFileSync(file, "utf8"));
3808
3845
  if (data.schemaVersion === LIB_SCHEMA && data.libraries) return data;
3809
3846
  } catch {
3810
3847
  }
@@ -3812,7 +3849,7 @@ function loadCatalog(root) {
3812
3849
  return { schemaVersion: LIB_SCHEMA, libraries: {} };
3813
3850
  }
3814
3851
  function saveCatalog(root, catalog) {
3815
- fs17.writeFileSync(catalogPath(root), `${stableStringify(catalog, 2)}
3852
+ fs18.writeFileSync(catalogPath(root), `${stableStringify(catalog, 2)}
3816
3853
  `);
3817
3854
  }
3818
3855
  function resolveLib(catalog, name) {
@@ -3889,16 +3926,16 @@ async function addLibrary(source, opts) {
3889
3926
  type = source.endsWith("llms.txt") ? "llms.txt" : source.endsWith(".json") ? "openapi" : "website";
3890
3927
  } else {
3891
3928
  const abs = path18.resolve(root, source);
3892
- if (!fs17.existsSync(abs)) throw new Error(`source not found: ${source}`);
3929
+ if (!fs18.existsSync(abs)) throw new Error(`source not found: ${source}`);
3893
3930
  content = readLocal(abs);
3894
3931
  type = "local";
3895
3932
  }
3896
3933
  const name = opts.name ?? inferName(source);
3897
3934
  const id = libId(name);
3898
3935
  const version = opts.version ?? installedVersion(root, name) ?? "*";
3899
- fs17.mkdirSync(libDir(root), { recursive: true });
3936
+ fs18.mkdirSync(libDir(root), { recursive: true });
3900
3937
  const docFileAbs = path18.join(libDir(root), `${id}.md`);
3901
- fs17.writeFileSync(docFileAbs, content);
3938
+ fs18.writeFileSync(docFileAbs, content);
3902
3939
  const entry = {
3903
3940
  id,
3904
3941
  name,
@@ -3915,13 +3952,13 @@ async function addLibrary(source, opts) {
3915
3952
  }
3916
3953
  function readDoc(root, entry) {
3917
3954
  const abs = path18.resolve(root, entry.docFile);
3918
- return fs17.existsSync(abs) ? fs17.readFileSync(abs, "utf8") : "";
3955
+ return fs18.existsSync(abs) ? fs18.readFileSync(abs, "utf8") : "";
3919
3956
  }
3920
3957
  function npmPackageDir(root, name) {
3921
3958
  let cur = root;
3922
3959
  for (let i = 0; i < 12; i++) {
3923
3960
  const dir = path18.join(cur, "node_modules", name);
3924
- if (fs17.existsSync(path18.join(dir, "package.json"))) return dir;
3961
+ if (fs18.existsSync(path18.join(dir, "package.json"))) return dir;
3925
3962
  const parent = path18.dirname(cur);
3926
3963
  if (parent === cur) break;
3927
3964
  cur = parent;
@@ -3935,7 +3972,7 @@ function localPackageDocs(root, name) {
3935
3972
  for (const f of ["llms.txt", "README.md", "README.mdx", "README", "readme.md"]) {
3936
3973
  const p = path18.join(dir, f);
3937
3974
  try {
3938
- const docs = fs17.readFileSync(p, "utf8");
3975
+ const docs = fs18.readFileSync(p, "utf8");
3939
3976
  if (docs.trim()) {
3940
3977
  return { docs, version, source: path18.relative(root, p).split(path18.sep).join("/") };
3941
3978
  }
@@ -3943,7 +3980,7 @@ function localPackageDocs(root, name) {
3943
3980
  }
3944
3981
  }
3945
3982
  try {
3946
- const pkg = JSON.parse(fs17.readFileSync(path18.join(dir, "package.json"), "utf8"));
3983
+ const pkg = JSON.parse(fs18.readFileSync(path18.join(dir, "package.json"), "utf8"));
3947
3984
  if (pkg.description?.trim()) {
3948
3985
  return {
3949
3986
  docs: `# ${name}
@@ -3959,17 +3996,17 @@ ${pkg.description}`,
3959
3996
  }
3960
3997
  function dtsEntry(dir) {
3961
3998
  try {
3962
- const pkg = JSON.parse(fs17.readFileSync(path18.join(dir, "package.json"), "utf8"));
3999
+ const pkg = JSON.parse(fs18.readFileSync(path18.join(dir, "package.json"), "utf8"));
3963
4000
  const rel2 = pkg.types ?? pkg.typings;
3964
4001
  if (typeof rel2 === "string") {
3965
4002
  const p = path18.join(dir, rel2);
3966
- if (fs17.existsSync(p)) return p;
4003
+ if (fs18.existsSync(p)) return p;
3967
4004
  }
3968
4005
  } catch {
3969
4006
  }
3970
4007
  for (const c of ["index.d.ts", "dist/index.d.ts", "lib/index.d.ts", "types/index.d.ts"]) {
3971
4008
  const p = path18.join(dir, c);
3972
- if (fs17.existsSync(p)) return p;
4009
+ if (fs18.existsSync(p)) return p;
3973
4010
  }
3974
4011
  return void 0;
3975
4012
  }
@@ -4002,7 +4039,7 @@ function localApiSurface(root, name) {
4002
4039
  if (!dts) return void 0;
4003
4040
  let src;
4004
4041
  try {
4005
- src = fs17.readFileSync(dts, "utf8");
4042
+ src = fs18.readFileSync(dts, "utf8");
4006
4043
  } catch {
4007
4044
  return void 0;
4008
4045
  }
@@ -4010,36 +4047,36 @@ function localApiSurface(root, name) {
4010
4047
  return decls.length ? decls.join("\n\n") : void 0;
4011
4048
  }
4012
4049
  function cloneAndReadGit(url) {
4013
- const dir = fs17.mkdtempSync(path18.join(os.tmpdir(), "vg-lib-git-"));
4050
+ const dir = fs18.mkdtempSync(path18.join(os.tmpdir(), "vg-lib-git-"));
4014
4051
  try {
4015
4052
  execFileSync("git", ["clone", "--depth", "1", "--quiet", url, dir], {
4016
4053
  stdio: ["ignore", "ignore", "pipe"]
4017
4054
  });
4018
4055
  } catch (err) {
4019
- fs17.rmSync(dir, { recursive: true, force: true });
4056
+ fs18.rmSync(dir, { recursive: true, force: true });
4020
4057
  const detail = err instanceof Error && err.message ? `: ${err.message.split("\n")[0]}` : "";
4021
4058
  throw new Error(`git clone failed for ${url}${detail}`);
4022
4059
  }
4023
4060
  try {
4024
4061
  return readGitDocs(dir);
4025
4062
  } finally {
4026
- fs17.rmSync(dir, { recursive: true, force: true });
4063
+ fs18.rmSync(dir, { recursive: true, force: true });
4027
4064
  }
4028
4065
  }
4029
4066
  function readGitDocs(dir) {
4030
4067
  const docsDir = path18.join(dir, "docs");
4031
- if (fs17.existsSync(docsDir) && fs17.statSync(docsDir).isDirectory()) return readLocal(docsDir);
4032
- const readme = ["README.md", "README.mdx", "README.txt", "README.rst", "readme.md"].map((f) => path18.join(dir, f)).find((p) => fs17.existsSync(p));
4033
- if (readme) return fs17.readFileSync(readme, "utf8");
4068
+ if (fs18.existsSync(docsDir) && fs18.statSync(docsDir).isDirectory()) return readLocal(docsDir);
4069
+ const readme = ["README.md", "README.mdx", "README.txt", "README.rst", "readme.md"].map((f) => path18.join(dir, f)).find((p) => fs18.existsSync(p));
4070
+ if (readme) return fs18.readFileSync(readme, "utf8");
4034
4071
  return readLocal(dir);
4035
4072
  }
4036
4073
  function readLocal(abs) {
4037
- const stat = fs17.statSync(abs);
4038
- if (stat.isFile()) return fs17.readFileSync(abs, "utf8");
4074
+ const stat = fs18.statSync(abs);
4075
+ if (stat.isFile()) return fs18.readFileSync(abs, "utf8");
4039
4076
  const parts = [];
4040
- const files = fs17.readdirSync(abs, { withFileTypes: true }).filter((e) => e.isFile() && /\.(md|mdx|txt|rst)$/i.test(e.name)).map((e) => e.name).sort();
4077
+ const files = fs18.readdirSync(abs, { withFileTypes: true }).filter((e) => e.isFile() && /\.(md|mdx|txt|rst)$/i.test(e.name)).map((e) => e.name).sort();
4041
4078
  for (const f of files) parts.push(`<!-- ${f} -->
4042
- ${fs17.readFileSync(path18.join(abs, f), "utf8")}`);
4079
+ ${fs18.readFileSync(path18.join(abs, f), "utf8")}`);
4043
4080
  return parts.join("\n\n");
4044
4081
  }
4045
4082
  function inferName(source) {
@@ -4050,7 +4087,7 @@ function inferName(source) {
4050
4087
  function findGitRoot(startDir = process.cwd()) {
4051
4088
  let dir = path18.resolve(startDir);
4052
4089
  for (; ; ) {
4053
- if (fs17.existsSync(path18.join(dir, ".git"))) return dir;
4090
+ if (fs18.existsSync(path18.join(dir, ".git"))) return dir;
4054
4091
  const parent = path18.dirname(dir);
4055
4092
  if (parent === dir) return null;
4056
4093
  dir = parent;
@@ -4067,14 +4104,14 @@ function ensureGitignored(entry, startDir = process.cwd()) {
4067
4104
  let existing = "";
4068
4105
  let fileExisted = true;
4069
4106
  try {
4070
- existing = fs17.readFileSync(gitignorePath, "utf8");
4107
+ existing = fs18.readFileSync(gitignorePath, "utf8");
4071
4108
  } catch {
4072
4109
  fileExisted = false;
4073
4110
  }
4074
4111
  const alreadyPresent = existing.split(/\r?\n/).some((line) => normalizeEntry(line) === target);
4075
4112
  if (alreadyPresent) return { status: "present", entry, gitignorePath };
4076
4113
  const needsLeadingNewline = existing.length > 0 && !existing.endsWith("\n");
4077
- fs17.appendFileSync(gitignorePath, `${needsLeadingNewline ? "\n" : ""}${entry}
4114
+ fs18.appendFileSync(gitignorePath, `${needsLeadingNewline ? "\n" : ""}${entry}
4078
4115
  `, "utf8");
4079
4116
  return { status: fileExisted ? "added" : "created", entry, gitignorePath };
4080
4117
  }
@@ -4250,41 +4287,51 @@ dsnCommand.command("create").description("Create a new DSN token").option("--ing
4250
4287
  }
4251
4288
  }
4252
4289
  });
4253
- function credentialsDir() {
4254
- return path18.join(os.homedir(), ".vibgrate");
4255
- }
4256
- function credentialsPath() {
4257
- return path18.join(credentialsDir(), "credentials.json");
4258
- }
4259
- function gitignoreEntryForCredentials(repoRoot) {
4260
- const rel2 = path18.relative(repoRoot, credentialsPath());
4290
+ var STORE_DIRNAME = ".vibgrate";
4291
+ var STORE_FILENAME = "credentials.json";
4292
+ function homeCredentialsPath() {
4293
+ return path18.join(os.homedir(), STORE_DIRNAME, STORE_FILENAME);
4294
+ }
4295
+ function projectCredentialsPath(cwd = process.cwd()) {
4296
+ const root = findGitRoot(cwd) ?? cwd;
4297
+ return path18.join(root, STORE_DIRNAME, STORE_FILENAME);
4298
+ }
4299
+ function credentialsPath(opts = {}) {
4300
+ const override = process.env.VIBGRATE_CREDENTIALS?.trim();
4301
+ if (override) return path18.resolve(override);
4302
+ const local = projectCredentialsPath(opts.cwd);
4303
+ if (opts.local) return local;
4304
+ if (fs18.existsSync(local)) return local;
4305
+ return homeCredentialsPath();
4306
+ }
4307
+ function gitignoreEntryForCredentials(repoRoot, credsFile = credentialsPath()) {
4308
+ const rel2 = path18.relative(repoRoot, credsFile);
4261
4309
  if (rel2 && !rel2.startsWith("..") && !path18.isAbsolute(rel2)) {
4262
4310
  return rel2.split(path18.sep).join("/");
4263
4311
  }
4264
- return ".vibgrate/credentials.json";
4312
+ return `${STORE_DIRNAME}/${STORE_FILENAME}`;
4265
4313
  }
4266
- function readStoredCredentials() {
4314
+ function readStoredCredentials(opts = {}) {
4267
4315
  try {
4268
- const raw = fs17.readFileSync(credentialsPath(), "utf8");
4316
+ const raw = fs18.readFileSync(credentialsPath(opts), "utf8");
4269
4317
  const parsed = JSON.parse(raw);
4270
4318
  return parsed && typeof parsed.dsn === "string" && parsed.dsn ? parsed : null;
4271
4319
  } catch {
4272
4320
  return null;
4273
4321
  }
4274
4322
  }
4275
- function writeStoredCredentials(creds) {
4276
- const dir = credentialsDir();
4277
- fs17.mkdirSync(dir, { recursive: true });
4278
- const file = credentialsPath();
4279
- fs17.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf8", mode: 384 });
4323
+ function writeStoredCredentials(creds, opts = {}) {
4324
+ const file = credentialsPath(opts);
4325
+ fs18.mkdirSync(path18.dirname(file), { recursive: true });
4326
+ fs18.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf8", mode: 384 });
4280
4327
  try {
4281
- fs17.chmodSync(file, 384);
4328
+ fs18.chmodSync(file, 384);
4282
4329
  } catch {
4283
4330
  }
4284
4331
  }
4285
- function clearStoredCredentials() {
4332
+ function clearStoredCredentials(opts = {}) {
4286
4333
  try {
4287
- fs17.rmSync(credentialsPath());
4334
+ fs18.rmSync(credentialsPath(opts));
4288
4335
  return true;
4289
4336
  } catch {
4290
4337
  return false;
@@ -4673,7 +4720,7 @@ var pushCommand = new Command("push").description("Push scan results to Vibgrate
4673
4720
  function readScanArtifact(root) {
4674
4721
  try {
4675
4722
  const file = path18.join(root, ".vibgrate", "scan_result.json");
4676
- return JSON.parse(fs17.readFileSync(file, "utf8"));
4723
+ return JSON.parse(fs18.readFileSync(file, "utf8"));
4677
4724
  } catch {
4678
4725
  return null;
4679
4726
  }
@@ -5648,13 +5695,13 @@ function ledgerPath(root) {
5648
5695
  return path18.join(cacheDir(root), LEDGER);
5649
5696
  }
5650
5697
  function savingsRecorded(root) {
5651
- return fs17.existsSync(ledgerPath(root));
5698
+ return fs18.existsSync(ledgerPath(root));
5652
5699
  }
5653
5700
  function recordSaving(root, entry, now) {
5654
5701
  try {
5655
- fs17.mkdirSync(cacheDir(root), { recursive: true });
5702
+ fs18.mkdirSync(cacheDir(root), { recursive: true });
5656
5703
  const line = JSON.stringify({ ts: now, ...entry });
5657
- fs17.appendFileSync(ledgerPath(root), line + "\n");
5704
+ fs18.appendFileSync(ledgerPath(root), line + "\n");
5658
5705
  } catch {
5659
5706
  }
5660
5707
  }
@@ -5666,8 +5713,8 @@ function readSavings(root, days, now, ratePerM = DEFAULT_RATE_PER_M) {
5666
5713
  let queries = 0;
5667
5714
  let vgTokens = 0;
5668
5715
  let baselineTokens = 0;
5669
- if (fs17.existsSync(file)) {
5670
- for (const line of fs17.readFileSync(file, "utf8").split("\n")) {
5716
+ if (fs18.existsSync(file)) {
5717
+ for (const line of fs18.readFileSync(file, "utf8").split("\n")) {
5671
5718
  if (!line.trim()) continue;
5672
5719
  try {
5673
5720
  const e = JSON.parse(line);
@@ -5723,9 +5770,9 @@ var GraphSource = class {
5723
5770
  /** Current graph: auto-refreshed if the tree drifted, reloaded if the file changed. */
5724
5771
  async get() {
5725
5772
  if (this.refresh) await this.maybeRefresh();
5726
- const stat = fs17.statSync(this.graphPath);
5773
+ const stat = fs18.statSync(this.graphPath);
5727
5774
  if (stat.mtimeMs !== this.cachedMtimeMs || !this.cached) {
5728
- this.cached = parseGraph(fs17.readFileSync(this.graphPath, "utf8"));
5775
+ this.cached = parseGraph(fs18.readFileSync(this.graphPath, "utf8"));
5729
5776
  this.cachedMtimeMs = stat.mtimeMs;
5730
5777
  }
5731
5778
  return this.cached;
@@ -5806,8 +5853,8 @@ async function serveStdio(graphPath, opts = {}) {
5806
5853
  await server.connect(new StdioServerTransport());
5807
5854
  }
5808
5855
  function sleep(ms) {
5809
- return new Promise((resolve11) => {
5810
- const timer = setTimeout(resolve11, ms);
5856
+ return new Promise((resolve12) => {
5857
+ const timer = setTimeout(resolve12, ms);
5811
5858
  timer.unref?.();
5812
5859
  });
5813
5860
  }
@@ -5975,27 +6022,6 @@ function detectServeLaunch(which = whichOnPath) {
5975
6022
  note: "vg is not installed on PATH \u2014 registered an npx launcher. Install globally (`npm i -g @vibgrate/cli`) and rerun `vg install` for a faster startup."
5976
6023
  };
5977
6024
  }
5978
- function whichOnPath(cmd) {
5979
- try {
5980
- const out = execFileSync(process.platform === "win32" ? "where" : "which", [cmd], {
5981
- encoding: "utf8",
5982
- stdio: ["ignore", "pipe", "ignore"]
5983
- }).trim().split(/\r?\n/)[0];
5984
- return out || null;
5985
- } catch {
5986
- return null;
5987
- }
5988
- }
5989
- function isOwnBinary(binPath) {
5990
- try {
5991
- const real = fs17.realpathSync(binPath);
5992
- if (/[\\/]@vibgrate[\\/]cli[\\/]/.test(real)) return true;
5993
- const head = fs17.readFileSync(real, { encoding: "utf8" }).slice(0, 2048);
5994
- return head.includes("@vibgrate/cli") || head.includes("vibgrate");
5995
- } catch {
5996
- return false;
5997
- }
5998
- }
5999
6025
  function installAssistant(a, opts) {
6000
6026
  const wrote = [];
6001
6027
  const skipped = [];
@@ -6030,23 +6056,23 @@ function uninstallAssistant(a, root, purge) {
6030
6056
  const file = path18.join(root, a.nudge.file);
6031
6057
  if (a.nudge.kind === "block") {
6032
6058
  if (removeBlock(file)) removed.push(a.nudge.file);
6033
- } else if (fs17.existsSync(file)) {
6034
- fs17.rmSync(file);
6059
+ } else if (fs18.existsSync(file)) {
6060
+ fs18.rmSync(file);
6035
6061
  removed.push(a.nudge.file);
6036
6062
  }
6037
6063
  }
6038
6064
  if (purge && a.skill) {
6039
6065
  const file = path18.join(root, a.skill);
6040
- if (fs17.existsSync(file)) {
6041
- fs17.rmSync(file);
6066
+ if (fs18.existsSync(file)) {
6067
+ fs18.rmSync(file);
6042
6068
  removed.push(a.skill);
6043
6069
  }
6044
6070
  }
6045
6071
  return removed;
6046
6072
  }
6047
6073
  function writeFileEnsured(file, content) {
6048
- fs17.mkdirSync(path18.dirname(file), { recursive: true });
6049
- fs17.writeFileSync(file, content);
6074
+ fs18.mkdirSync(path18.dirname(file), { recursive: true });
6075
+ fs18.writeFileSync(file, content);
6050
6076
  }
6051
6077
  function upsertMcp(file, target, launch) {
6052
6078
  const config = readJson(file);
@@ -6059,7 +6085,7 @@ function upsertMcp(file, target, launch) {
6059
6085
  `);
6060
6086
  }
6061
6087
  function removeMcp(file, target) {
6062
- if (!fs17.existsSync(file)) return false;
6088
+ if (!fs18.existsSync(file)) return false;
6063
6089
  const config = readJson(file);
6064
6090
  const bag = config[target.key];
6065
6091
  if (!bag || !(bag.vg !== void 0)) return false;
@@ -6082,8 +6108,8 @@ ${stripMarkers(nudgeMarkdown(smallRepo))}` : stripMarkers(nudgeMarkdown(smallRep
6082
6108
  upsertBlock(file, nudgeMarkdown(smallRepo));
6083
6109
  }
6084
6110
  function upsertBlock(file, block) {
6085
- fs17.mkdirSync(path18.dirname(file), { recursive: true });
6086
- let existing = fs17.existsSync(file) ? fs17.readFileSync(file, "utf8") : "";
6111
+ fs18.mkdirSync(path18.dirname(file), { recursive: true });
6112
+ let existing = fs18.existsSync(file) ? fs18.readFileSync(file, "utf8") : "";
6087
6113
  const re = new RegExp(`${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}`);
6088
6114
  if (re.test(existing)) existing = existing.replace(re, block);
6089
6115
  else existing = existing.length ? `${existing.replace(/\s*$/, "")}
@@ -6091,20 +6117,20 @@ function upsertBlock(file, block) {
6091
6117
  ${block}
6092
6118
  ` : `${block}
6093
6119
  `;
6094
- fs17.writeFileSync(file, existing);
6120
+ fs18.writeFileSync(file, existing);
6095
6121
  }
6096
6122
  function removeBlock(file) {
6097
- if (!fs17.existsSync(file)) return false;
6098
- const existing = fs17.readFileSync(file, "utf8");
6123
+ if (!fs18.existsSync(file)) return false;
6124
+ const existing = fs18.readFileSync(file, "utf8");
6099
6125
  const re = new RegExp(`\\n*${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}\\n*`);
6100
6126
  if (!re.test(existing)) return false;
6101
- fs17.writeFileSync(file, existing.replace(re, "\n"));
6127
+ fs18.writeFileSync(file, existing.replace(re, "\n"));
6102
6128
  return true;
6103
6129
  }
6104
6130
  function readJson(file) {
6105
- if (!fs17.existsSync(file)) return {};
6131
+ if (!fs18.existsSync(file)) return {};
6106
6132
  try {
6107
- const parsed = JSON.parse(fs17.readFileSync(file, "utf8"));
6133
+ const parsed = JSON.parse(fs18.readFileSync(file, "utf8"));
6108
6134
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
6109
6135
  return parsed;
6110
6136
  }
@@ -6262,6 +6288,6 @@ function spdx(ctx) {
6262
6288
  return JSON.stringify(doc, null, 2) + "\n";
6263
6289
  }
6264
6290
 
6265
- export { ASSISTANTS, CliError, ECOSYSTEMS, ExitCode, FREE_PACK, GraphIndex, GraphSource, SCHEMA_VERSION, SKIP_DIRS, TOOLS, UsageError, addLibrary, analyze, applyCoverage, applyStaticTestLinkage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, buildModuleResolver, cacheDir, catalogPath, clearModelCache, clearStoredCredentials, cosine, countPending, coveringTests, createServer, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, defaultGraphPath, detectRunner, detectServeLaunch, discover, discoverModels, driftCount, driftFor, dsnCommand, embeddingsCached, enrichOnline, ensureGitignored, exportGraph, fetchHostedDocs, findGitRoot, findNodes, formatForExt, getNodeEmbeddings, gitignoreEntryForCredentials, groundGraph, hasDrift, identifierParts, impactOf, installAssistant, inventory, isModelReady, isTestFile, libDir, libId, loadCatalog, loadCoverage, loadEmbedder, loadGraph, loadSnapshot, localApiSurface, localPackageDocs, modelCacheInfo, nodeById, nodeEmbedText, parseDsn, parseGraph, parseJsonc, probeFreshness, publishPrivateLibrary, pushCommand, queryGraph, queryGraphSemantic, readDoc, readSavings, readScanArtifact, recordSaving, refreshIfStale, relativeResolver, renderHtml, renderReport, resolveDsn, resolveEmbedModel, resolveIngestHost, resolveLib, resolveOne, resolveVersion, saveCatalog, savingsRecorded, scipEdges, selectForBudget, serializeGraph, serveStdio, shortestPath, stableStringify, symbolsFromApi, testsToRun, unavailableMessage, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, vibgrateDir, writeArtifacts, writeSnapshot, writeStoredCredentials };
6266
- //# sourceMappingURL=chunk-W2QP2YH6.js.map
6267
- //# sourceMappingURL=chunk-W2QP2YH6.js.map
6291
+ export { ASSISTANTS, CliError, ECOSYSTEMS, ExitCode, FREE_PACK, GraphIndex, GraphSource, NPX_INVOCATION, SCHEMA_VERSION, SKIP_DIRS, TOOLS, UsageError, addLibrary, analyze, applyCoverage, applyStaticTestLinkage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, buildModuleResolver, cacheDir, catalogPath, clearModelCache, clearStoredCredentials, cosine, countPending, coveringTests, createServer, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, defaultGraphPath, detectRunner, detectServeLaunch, discover, discoverModels, driftCount, driftFor, dsnCommand, embeddingsCached, enrichOnline, ensureGitignored, exportGraph, fetchHostedDocs, findGitRoot, findNodes, formatForExt, getNodeEmbeddings, gitignoreEntryForCredentials, groundGraph, hasDrift, identifierParts, impactOf, installAssistant, inventory, isModelReady, isTestFile, libDir, libId, loadCatalog, loadCoverage, loadEmbedder, loadGraph, loadSnapshot, localApiSurface, localPackageDocs, modelCacheInfo, nodeById, nodeEmbedText, parseDsn, parseGraph, parseJsonc, probeFreshness, publishPrivateLibrary, pushCommand, queryGraph, queryGraphSemantic, readDoc, readSavings, readScanArtifact, recordSaving, refreshIfStale, relativeResolver, renderHtml, renderReport, resolveCliInvocation, resolveDsn, resolveEmbedModel, resolveIngestHost, resolveLib, resolveOne, resolveVersion, saveCatalog, savingsRecorded, scipEdges, selectForBudget, serializeGraph, serveStdio, shortestPath, stableStringify, symbolsFromApi, testsToRun, unavailableMessage, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, vibgrateDir, writeArtifacts, writeSnapshot, writeStoredCredentials };
6292
+ //# sourceMappingURL=chunk-WGXDYBAN.js.map
6293
+ //# sourceMappingURL=chunk-WGXDYBAN.js.map