@vibgrate/cli 2026.727.3 → 2026.728.2

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 (81) hide show
  1. package/dist/baseline-MRUM2P6H.js +8 -0
  2. package/dist/{baseline-ATM5MXBZ.js.map → baseline-MRUM2P6H.js.map} +1 -1
  3. package/dist/chunk-3SDV6ADQ.js +78 -0
  4. package/dist/chunk-3SDV6ADQ.js.map +1 -0
  5. package/dist/{chunk-6JIKUDWM.js → chunk-6AXHLQBV.js} +219 -22
  6. package/dist/chunk-6AXHLQBV.js.map +1 -0
  7. package/dist/{chunk-K7REHDQS.js → chunk-6HX47EBL.js} +25 -19
  8. package/dist/chunk-6HX47EBL.js.map +1 -0
  9. package/dist/{chunk-Z7GP7XTJ.js → chunk-A2IYFNCQ.js} +26 -64
  10. package/dist/chunk-A2IYFNCQ.js.map +1 -0
  11. package/dist/{chunk-MAY5HLDH.js → chunk-GQTWDKMJ.js} +158 -161
  12. package/dist/chunk-GQTWDKMJ.js.map +1 -0
  13. package/dist/{chunk-OOIG3RUM.js → chunk-GYSOQH5C.js} +18 -79
  14. package/dist/chunk-GYSOQH5C.js.map +1 -0
  15. package/dist/{chunk-C66GOHYB.js → chunk-IWP7MYIA.js} +61 -23
  16. package/dist/chunk-IWP7MYIA.js.map +1 -0
  17. package/dist/{chunk-77LYGXBI.js → chunk-JRAGO6OB.js} +3 -3
  18. package/dist/{chunk-77LYGXBI.js.map → chunk-JRAGO6OB.js.map} +1 -1
  19. package/dist/{chunk-NDMDSPFX.js → chunk-KKRSQQ3A.js} +4 -3
  20. package/dist/chunk-KKRSQQ3A.js.map +1 -0
  21. package/dist/{chunk-FFWGT55D.js → chunk-NTW5UEKT.js} +3 -3
  22. package/dist/{chunk-FFWGT55D.js.map → chunk-NTW5UEKT.js.map} +1 -1
  23. package/dist/chunk-OSD546W7.js +167 -0
  24. package/dist/chunk-OSD546W7.js.map +1 -0
  25. package/dist/{chunk-3V24O47U.js → chunk-PVZBYZZR.js} +19 -9
  26. package/dist/chunk-PVZBYZZR.js.map +1 -0
  27. package/dist/{chunk-XPJZTSY7.js → chunk-R2QNFXE5.js} +3 -3
  28. package/dist/{chunk-XPJZTSY7.js.map → chunk-R2QNFXE5.js.map} +1 -1
  29. package/dist/{chunk-PXHNTC6D.js → chunk-SIPGDJT4.js} +3 -3
  30. package/dist/{chunk-PXHNTC6D.js.map → chunk-SIPGDJT4.js.map} +1 -1
  31. package/dist/chunk-UIOBFLE6.js +356 -0
  32. package/dist/chunk-UIOBFLE6.js.map +1 -0
  33. package/dist/chunk-UZJS7GMK.js +57 -0
  34. package/dist/chunk-UZJS7GMK.js.map +1 -0
  35. package/dist/{chunk-2VFWXNS5.js → chunk-WH2N22S3.js} +3 -3
  36. package/dist/{chunk-2VFWXNS5.js.map → chunk-WH2N22S3.js.map} +1 -1
  37. package/dist/{chunk-AVQSHIJ5.js → chunk-WY6DGTBP.js} +4 -4
  38. package/dist/{chunk-AVQSHIJ5.js.map → chunk-WY6DGTBP.js.map} +1 -1
  39. package/dist/{chunk-OFUC6RYN.js → chunk-YF43FOPP.js} +8 -101
  40. package/dist/chunk-YF43FOPP.js.map +1 -0
  41. package/dist/{chunk-Y23HMSWU.js → chunk-ZFTFCM7B.js} +14 -7
  42. package/dist/chunk-ZFTFCM7B.js.map +1 -0
  43. package/dist/cli.js +179 -213
  44. package/dist/cli.js.map +1 -1
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.js +8 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/{interactive-INGJNSON.js → interactive-36ZZ64WL.js} +48 -17
  49. package/dist/interactive-36ZZ64WL.js.map +1 -0
  50. package/dist/{llm-host-7GWDO6IX.js → llm-host-XYBT4267.js} +4 -4
  51. package/dist/{llm-host-7GWDO6IX.js.map → llm-host-XYBT4267.js.map} +1 -1
  52. package/dist/model-manager-OEPY4I7W.js +10 -0
  53. package/dist/{model-orchestrator-TVONAUPS.js.map → model-manager-OEPY4I7W.js.map} +1 -1
  54. package/dist/{model-orchestrator-TVONAUPS.js → model-orchestrator-4VSYP4J4.js} +3 -3
  55. package/dist/model-orchestrator-4VSYP4J4.js.map +1 -0
  56. package/dist/resolve-gguf-Y6FH3CNB.js +9 -0
  57. package/dist/{resolve-gguf-VPL4YQ6J.js.map → resolve-gguf-Y6FH3CNB.js.map} +1 -1
  58. package/dist/{runtime-session-4AMZIAAG.js → runtime-session-EJQZXANB.js} +5 -5
  59. package/dist/{runtime-session-4AMZIAAG.js.map → runtime-session-EJQZXANB.js.map} +1 -1
  60. package/dist/{session-M72522AP.js → session-ZJGENHKX.js} +6 -4
  61. package/dist/{session-M72522AP.js.map → session-ZJGENHKX.js.map} +1 -1
  62. package/dist/{stream-json-6ZBUA2L3.js → stream-json-Z5KC2DM3.js} +8 -6
  63. package/dist/stream-json-Z5KC2DM3.js.map +1 -0
  64. package/dist/{vgd-CVLKBS7K.js → vgd-3MHSB4KA.js} +4 -4
  65. package/dist/vgd-3MHSB4KA.js.map +1 -0
  66. package/package.json +1 -1
  67. package/dist/baseline-ATM5MXBZ.js +0 -8
  68. package/dist/chunk-3V24O47U.js.map +0 -1
  69. package/dist/chunk-6JIKUDWM.js.map +0 -1
  70. package/dist/chunk-C66GOHYB.js.map +0 -1
  71. package/dist/chunk-K7REHDQS.js.map +0 -1
  72. package/dist/chunk-MAY5HLDH.js.map +0 -1
  73. package/dist/chunk-NDMDSPFX.js.map +0 -1
  74. package/dist/chunk-OFUC6RYN.js.map +0 -1
  75. package/dist/chunk-OOIG3RUM.js.map +0 -1
  76. package/dist/chunk-Y23HMSWU.js.map +0 -1
  77. package/dist/chunk-Z7GP7XTJ.js.map +0 -1
  78. package/dist/interactive-INGJNSON.js.map +0 -1
  79. package/dist/resolve-gguf-VPL4YQ6J.js +0 -8
  80. package/dist/stream-json-6ZBUA2L3.js.map +0 -1
  81. package/dist/vgd-CVLKBS7K.js.map +0 -1
@@ -1,16 +1,16 @@
1
- import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-6JIKUDWM.js';
2
- import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-Y23HMSWU.js';
1
+ import { resolveVersion, resolveLib, loadCatalog, driftFor, localPackageDocs, readDoc, inventory, localApiSurface, edgeId, buildModuleResolver, resolve, applyStaticTestLinkage, nodeId } from './chunk-6AXHLQBV.js';
2
+ import { loadConfig, computeUpgradeImpact, getChangelogSignals, gitHistoryAvailable, buildVersionTimelines, findPackageTimeline, severityRank, projectTypeToVulnEcosystem, VERSION } from './chunk-ZFTFCM7B.js';
3
3
  import { writeTextFile, pathExists, readJsonFile } from './chunk-CRAMOEBE.js';
4
4
  import { resolveOne, findNodes } from './chunk-J7LKEB2R.js';
5
- import { discoverModels } from './chunk-OOIG3RUM.js';
6
5
  import { impactOf, indexFor, withTimeout, getNodeEmbeddings, queryGraphSemantic, queryGraph, loadEmbedder, isModelReady, acquireLock, releaseLock } from './chunk-6UK6QPTR.js';
6
+ import { discoverModels } from './chunk-3SDV6ADQ.js';
7
+ import { whichOnPath, isInstalledOwnBinary } from './chunk-UZJS7GMK.js';
7
8
  import { langById, grammarSetVersion, langForExtension, setGrammarsOverride, parseSource } from './chunk-ON25BX6T.js';
8
9
  import { redactSecrets } from './chunk-RXP66R2E.js';
9
10
  import { writeGraphIndex, SCHEMA_VERSION, loadGraph, ensureVibgrateGitignore, vibgrateDir, writeArtifacts } from './chunk-B3YUO3NW.js';
10
11
  import { cacheDir, loadCache, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
11
12
  import { shortId, canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
12
- import * as fs18 from 'fs';
13
- import { spawnSync, execFileSync } from 'child_process';
13
+ import * as fs17 from 'fs';
14
14
  import * as path19 from 'path';
15
15
  import ignore from 'ignore';
16
16
  import * as v8 from 'v8';
@@ -22,7 +22,7 @@ import louvain from 'graphology-communities-louvain';
22
22
  import * as os from 'os';
23
23
  import { fileURLToPath } from 'url';
24
24
  import ts from 'typescript';
25
- import * as fs8 from 'fs/promises';
25
+ import * as fs7 from 'fs/promises';
26
26
  import { bidirectional } from 'graphology-shortest-path/unweighted.js';
27
27
  import * as crypto from 'crypto';
28
28
  import { createHash } from 'crypto';
@@ -30,58 +30,10 @@ import { Command } from 'commander';
30
30
  import chalk from 'chalk';
31
31
  import * as zlib from 'zlib';
32
32
  import { promisify } from 'util';
33
+ import { spawnSync } from 'child_process';
33
34
  import { Worker } from 'worker_threads';
34
35
  import { encode, decode } from 'gpt-tokenizer/encoding/cl100k_base';
35
36
 
36
- var NPX_INVOCATION = "npx @vibgrate/cli";
37
- function whichOnPath(cmd) {
38
- try {
39
- const out = execFileSync(process.platform === "win32" ? "where" : "which", [cmd], {
40
- encoding: "utf8",
41
- stdio: ["ignore", "pipe", "ignore"]
42
- }).trim().split(/\r?\n/)[0];
43
- return out || null;
44
- } catch {
45
- return null;
46
- }
47
- }
48
- function isOwnBinary(binPath) {
49
- try {
50
- const real = fs18.realpathSync(binPath);
51
- if (/[\\/]@vibgrate[\\/]cli[\\/]/.test(real)) return true;
52
- const head = fs18.readFileSync(real, { encoding: "utf8" }).slice(0, 2048);
53
- return head.includes("@vibgrate/cli") || head.includes("vibgrate");
54
- } catch {
55
- return false;
56
- }
57
- }
58
- function isEphemeralNpxBinary(binPath) {
59
- const NPX_SEGMENT = /[\\/]_npx[\\/]/;
60
- if (NPX_SEGMENT.test(binPath)) return true;
61
- try {
62
- return NPX_SEGMENT.test(fs18.realpathSync(binPath));
63
- } catch {
64
- return false;
65
- }
66
- }
67
- function isInstalledOwnBinary(binPath) {
68
- return isOwnBinary(binPath) && !isEphemeralNpxBinary(binPath);
69
- }
70
- var cached;
71
- function resolveCliInvocation(which) {
72
- if (!which && cached !== void 0) return cached;
73
- const lookup = which ?? whichOnPath;
74
- const vg = lookup("vg");
75
- let result;
76
- if (vg && isInstalledOwnBinary(vg)) {
77
- result = "vg";
78
- } else {
79
- const vibgrate = lookup("vibgrate");
80
- result = vibgrate && isInstalledOwnBinary(vibgrate) ? "vibgrate" : NPX_INVOCATION;
81
- }
82
- if (!which) cached = result;
83
- return result;
84
- }
85
37
  var SKIP_DIRS = /* @__PURE__ */ new Set([
86
38
  // Version control, IDE & tool metadata
87
39
  ".git",
@@ -241,8 +193,8 @@ function toPosix(p) {
241
193
  function buildRootIgnore(root, exclude) {
242
194
  const ig = ignore();
243
195
  const gitignorePath = path19.join(root, ".gitignore");
244
- if (fs18.existsSync(gitignorePath)) {
245
- ig.add(fs18.readFileSync(gitignorePath, "utf8"));
196
+ if (fs17.existsSync(gitignorePath)) {
197
+ ig.add(fs17.readFileSync(gitignorePath, "utf8"));
246
198
  }
247
199
  if (exclude.length) ig.add(exclude);
248
200
  return ig;
@@ -257,7 +209,7 @@ function discover(options) {
257
209
  }
258
210
  }
259
211
  const rootIg = buildRootIgnore(root, options.exclude ?? []);
260
- const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path19.resolve(root, p)) : [root]).filter((p) => fs18.existsSync(p));
212
+ const scopeAbs = (options.paths && options.paths.length ? options.paths.map((p) => path19.resolve(root, p)) : [root]).filter((p) => fs17.existsSync(p));
261
213
  const found = /* @__PURE__ */ new Map();
262
214
  const considerFile = (abs) => {
263
215
  const rel2 = toPosix(path19.relative(root, abs));
@@ -271,7 +223,7 @@ function discover(options) {
271
223
  const walk = (dir) => {
272
224
  let entries;
273
225
  try {
274
- entries = fs18.readdirSync(dir, { withFileTypes: true });
226
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
275
227
  } catch {
276
228
  return;
277
229
  }
@@ -288,7 +240,7 @@ function discover(options) {
288
240
  }
289
241
  };
290
242
  for (const scope of scopeAbs) {
291
- const stat = fs18.statSync(scope);
243
+ const stat = fs17.statSync(scope);
292
244
  if (stat.isDirectory()) walk(scope);
293
245
  else if (stat.isFile()) considerFile(scope);
294
246
  }
@@ -772,12 +724,12 @@ function loadCoverage(root, explicit) {
772
724
  const candidates = (explicit && explicit.length ? explicit : DEFAULT_PATHS).map(
773
725
  (p) => path19.resolve(root, p)
774
726
  );
775
- const found = candidates.filter((p) => fs18.existsSync(p));
727
+ const found = candidates.filter((p) => fs17.existsSync(p));
776
728
  if (found.length === 0) return null;
777
729
  const map = /* @__PURE__ */ new Map();
778
730
  for (const file of found) {
779
731
  try {
780
- const text = fs18.readFileSync(file, "utf8");
732
+ const text = fs17.readFileSync(file, "utf8");
781
733
  if (file.endsWith(".json")) mergeIstanbul(map, text, root);
782
734
  else mergeLcov(map, text, root);
783
735
  } catch {
@@ -1094,7 +1046,7 @@ async function parseInline(files, options) {
1094
1046
  onProgress?.(0, files.length);
1095
1047
  for (const file of files) {
1096
1048
  try {
1097
- const source = fs18.readFileSync(file.abs, "utf8");
1049
+ const source = fs17.readFileSync(file.abs, "utf8");
1098
1050
  out.push(await parseSource(file.rel, file.lang.id, source));
1099
1051
  } catch (err) {
1100
1052
  out.push(emptyParse(file, `parse failed: ${err.message}`));
@@ -1151,7 +1103,7 @@ function isWorkerOom(err) {
1151
1103
  function resolveWorkerFile() {
1152
1104
  const here = path19.dirname(fileURLToPath(import.meta.url));
1153
1105
  const candidate = path19.join(here, "parse-worker.js");
1154
- return fs18.existsSync(candidate) ? candidate : null;
1106
+ return fs17.existsSync(candidate) ? candidate : null;
1155
1107
  }
1156
1108
  function chunk(items, buckets) {
1157
1109
  const out = Array.from({ length: Math.min(buckets, items.length || 1) }, () => []);
@@ -1648,9 +1600,9 @@ function toPosix2(p) {
1648
1600
  function buildRootIgnore2(root, exclude) {
1649
1601
  const ig = ignore();
1650
1602
  const gitignorePath = path19.join(root, ".gitignore");
1651
- if (fs18.existsSync(gitignorePath)) {
1603
+ if (fs17.existsSync(gitignorePath)) {
1652
1604
  try {
1653
- ig.add(fs18.readFileSync(gitignorePath, "utf8"));
1605
+ ig.add(fs17.readFileSync(gitignorePath, "utf8"));
1654
1606
  } catch {
1655
1607
  }
1656
1608
  }
@@ -1694,7 +1646,7 @@ function discoverDocs(options) {
1694
1646
  const maxFiles = options.maxFiles ?? DOC_MAX_FILES;
1695
1647
  const rootIg = buildRootIgnore2(root, options.exclude ?? []);
1696
1648
  const scopeAbs = (options.paths?.length ? options.paths.map((p) => path19.resolve(root, p)) : [root]).filter(
1697
- (p) => fs18.existsSync(p)
1649
+ (p) => fs17.existsSync(p)
1698
1650
  );
1699
1651
  const found = /* @__PURE__ */ new Map();
1700
1652
  const consider = (abs) => {
@@ -1707,7 +1659,7 @@ function discoverDocs(options) {
1707
1659
  const category = classifyProjectContext(rel2);
1708
1660
  if (!category) return;
1709
1661
  try {
1710
- const st = fs18.statSync(abs);
1662
+ const st = fs17.statSync(abs);
1711
1663
  if (!st.isFile() || st.size > DOC_FILE_MAX_BYTES) return;
1712
1664
  if (st.size === 0) return;
1713
1665
  } catch {
@@ -1719,7 +1671,7 @@ function discoverDocs(options) {
1719
1671
  if (found.size >= maxFiles || depth > 12) return;
1720
1672
  let entries;
1721
1673
  try {
1722
- entries = fs18.readdirSync(dir, { withFileTypes: true });
1674
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
1723
1675
  } catch {
1724
1676
  return;
1725
1677
  }
@@ -1738,7 +1690,7 @@ function discoverDocs(options) {
1738
1690
  };
1739
1691
  for (const scope of scopeAbs) {
1740
1692
  try {
1741
- const st = fs18.statSync(scope);
1693
+ const st = fs17.statSync(scope);
1742
1694
  if (st.isDirectory()) walk(scope, 0);
1743
1695
  else if (st.isFile()) consider(scope);
1744
1696
  } catch {
@@ -1795,7 +1747,7 @@ function documentNodesFromDocs(docs) {
1795
1747
  for (const d of docs) {
1796
1748
  let raw = "";
1797
1749
  try {
1798
- raw = fs18.readFileSync(d.abs, "utf8");
1750
+ raw = fs17.readFileSync(d.abs, "utf8");
1799
1751
  } catch {
1800
1752
  continue;
1801
1753
  }
@@ -1853,7 +1805,7 @@ function nearestProjectKey(root, startDir, cache) {
1853
1805
  let dir = startDir;
1854
1806
  const rootAbs = path19.resolve(root);
1855
1807
  while (true) {
1856
- if (fs18.existsSync(path19.join(dir, "tsconfig.json")) || fs18.existsSync(path19.join(dir, "tsconfig.base.json")) || fs18.existsSync(path19.join(dir, "package.json"))) {
1808
+ if (fs17.existsSync(path19.join(dir, "tsconfig.json")) || fs17.existsSync(path19.join(dir, "tsconfig.base.json")) || fs17.existsSync(path19.join(dir, "package.json"))) {
1857
1809
  const key = toPosix3(path19.relative(rootAbs, dir)) || ".";
1858
1810
  cache.set(startDir, key);
1859
1811
  return key;
@@ -1960,7 +1912,7 @@ var emptyNode = (partial) => ({
1960
1912
  function extractManifests(root, opts = {}) {
1961
1913
  const absRoot = path19.resolve(root);
1962
1914
  const ig = buildRootIgnore3(absRoot, opts.exclude ?? []);
1963
- const scopes = (opts.paths?.length ? opts.paths : ["."]).map((p) => path19.resolve(absRoot, p)).filter((p) => fs18.existsSync(p));
1915
+ const scopes = (opts.paths?.length ? opts.paths : ["."]).map((p) => path19.resolve(absRoot, p)).filter((p) => fs17.existsSync(p));
1964
1916
  const found = /* @__PURE__ */ new Map();
1965
1917
  for (const scope of scopes) {
1966
1918
  walkManifests(absRoot, scope, ig, found);
@@ -1990,7 +1942,7 @@ function extractManifests(root, opts = {}) {
1990
1942
  };
1991
1943
  }
1992
1944
  function ingestPackageJson(rel2, abs, nodes, edges) {
1993
- const raw = JSON.parse(fs18.readFileSync(abs, "utf8"));
1945
+ const raw = JSON.parse(fs17.readFileSync(abs, "utf8"));
1994
1946
  const pkgName = raw.name && String(raw.name).trim() || path19.posix.dirname(rel2) || ".";
1995
1947
  const localId = nodeId({ kind: "package", qualifiedName: pkgName, file: rel2 });
1996
1948
  nodes.set(
@@ -2034,7 +1986,7 @@ function ingestPackageJson(rel2, abs, nodes, edges) {
2034
1986
  return n;
2035
1987
  }
2036
1988
  function ingestGoMod(rel2, abs, nodes, edges) {
2037
- const text = fs18.readFileSync(abs, "utf8");
1989
+ const text = fs17.readFileSync(abs, "utf8");
2038
1990
  let moduleName = path19.posix.dirname(rel2) || ".";
2039
1991
  const moduleMatch = /^\s*module\s+(\S+)/m.exec(text);
2040
1992
  if (moduleMatch) moduleName = moduleMatch[1];
@@ -2118,9 +2070,9 @@ function addEdge(edges, kind, src, dst, confidence) {
2118
2070
  function buildRootIgnore3(root, exclude) {
2119
2071
  const ig = ignore();
2120
2072
  const gitignorePath = path19.join(root, ".gitignore");
2121
- if (fs18.existsSync(gitignorePath)) {
2073
+ if (fs17.existsSync(gitignorePath)) {
2122
2074
  try {
2123
- ig.add(fs18.readFileSync(gitignorePath, "utf8"));
2075
+ ig.add(fs17.readFileSync(gitignorePath, "utf8"));
2124
2076
  } catch {
2125
2077
  }
2126
2078
  }
@@ -2130,7 +2082,7 @@ function buildRootIgnore3(root, exclude) {
2130
2082
  function walkManifests(root, dir, ig, found) {
2131
2083
  let entries;
2132
2084
  try {
2133
- entries = fs18.readdirSync(dir, { withFileTypes: true });
2085
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
2134
2086
  } catch {
2135
2087
  return;
2136
2088
  }
@@ -2163,7 +2115,7 @@ async function hashFilesParallel(jobs, concurrency) {
2163
2115
  if (i >= jobs.length) return;
2164
2116
  const job = jobs[i];
2165
2117
  try {
2166
- const buf = await fs8.readFile(job.abs);
2118
+ const buf = await fs7.readFile(job.abs);
2167
2119
  out[i] = { rel: job.rel, hash: hashBytes(buf), ok: true };
2168
2120
  } catch {
2169
2121
  out[i] = { rel: job.rel, hash: "", ok: false };
@@ -2211,7 +2163,7 @@ async function buildGraph(options) {
2211
2163
  for (const file of files) {
2212
2164
  let stat;
2213
2165
  try {
2214
- stat = fs18.statSync(file.abs);
2166
+ stat = fs17.statSync(file.abs);
2215
2167
  } catch {
2216
2168
  continue;
2217
2169
  }
@@ -2257,10 +2209,10 @@ async function buildGraph(options) {
2257
2209
  mtimeMs: p.mtimeMs,
2258
2210
  hash: r.hash
2259
2211
  });
2260
- const cached2 = cache.get(p.file.rel, r.hash);
2261
- if (cached2) {
2262
- reused.push(cached2);
2263
- cache.set(p.file.rel, cached2, { mtimeMs: p.mtimeMs, size: p.size });
2212
+ const cached = cache.get(p.file.rel, r.hash);
2213
+ if (cached) {
2214
+ reused.push(cached);
2215
+ cache.set(p.file.rel, cached, { mtimeMs: p.mtimeMs, size: p.size });
2264
2216
  } else {
2265
2217
  toParse.push(p.file);
2266
2218
  }
@@ -2387,8 +2339,8 @@ async function buildGraph(options) {
2387
2339
  });
2388
2340
  for (const d of docs) {
2389
2341
  try {
2390
- const st = fs18.statSync(d.abs);
2391
- const hash = hashBytes(fs18.readFileSync(d.abs));
2342
+ const st = fs17.statSync(d.abs);
2343
+ const hash = hashBytes(fs17.readFileSync(d.abs));
2392
2344
  hashes.set(d.rel, hash);
2393
2345
  fileStats.push({ rel: d.rel, size: st.size, mtimeMs: st.mtimeMs, hash });
2394
2346
  } catch {
@@ -2493,9 +2445,9 @@ function loadScipIndex(root, explicit) {
2493
2445
  ].filter((p) => Boolean(p));
2494
2446
  for (const file of candidates) {
2495
2447
  const abs = path19.isAbsolute(file) ? file : path19.resolve(root, file);
2496
- if (!fs18.existsSync(abs)) continue;
2448
+ if (!fs17.existsSync(abs)) continue;
2497
2449
  try {
2498
- const index = decodeScipIndex(new Uint8Array(fs18.readFileSync(abs)));
2450
+ const index = decodeScipIndex(new Uint8Array(fs17.readFileSync(abs)));
2499
2451
  if (index.documents.length) {
2500
2452
  return { index, tool: index.toolVersion ? `${index.toolName} ${index.toolVersion}` : index.toolName };
2501
2453
  }
@@ -2552,10 +2504,10 @@ async function verifyDeterminism(opts) {
2552
2504
  const buildA = await buildGraph({ ...base, noCache: true, jobs: opts.jobs });
2553
2505
  const a = serializeGraph(buildA.graph);
2554
2506
  const b = serializeGraph((await buildGraph({ ...base, noCache: true, jobs: 1 })).graph);
2555
- const cached2 = serializeGraph((await buildGraph({ ...base, noCache: false })).graph);
2507
+ const cached = serializeGraph((await buildGraph({ ...base, noCache: false })).graph);
2556
2508
  const checks = [
2557
2509
  { name: "run-to-run determinism", ok: a === b, detail: diffHint(a, b) },
2558
- { name: "cache safety (incremental == full)", ok: a === cached2, detail: diffHint(a, cached2) }
2510
+ { name: "cache safety (incremental == full)", ok: a === cached, detail: diffHint(a, cached) }
2559
2511
  ];
2560
2512
  const scoped = Boolean(opts.only?.length || opts.exclude?.length);
2561
2513
  const committed = scoped ? null : loadGraph(opts.root);
@@ -2617,14 +2569,14 @@ function writeSnapshot(root, corpusHash, fileStats, scope = {}) {
2617
2569
  for (const f of fileStats) files[f.rel] = { size: f.size, mtimeMs: f.mtimeMs, hash: f.hash };
2618
2570
  const snapshot = { version: SNAPSHOT_VERSION, corpusHash, scope: pruneScope(scope), files };
2619
2571
  try {
2620
- fs18.mkdirSync(cacheDir(root), { recursive: true });
2621
- fs18.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2572
+ fs17.mkdirSync(cacheDir(root), { recursive: true });
2573
+ fs17.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2622
2574
  } catch {
2623
2575
  }
2624
2576
  }
2625
2577
  function loadSnapshot(root) {
2626
2578
  try {
2627
- const loaded = JSON.parse(fs18.readFileSync(snapshotPath(root), "utf8"));
2579
+ const loaded = JSON.parse(fs17.readFileSync(snapshotPath(root), "utf8"));
2628
2580
  if (loaded.version === SNAPSHOT_VERSION && loaded.files && typeof loaded.corpusHash === "string") {
2629
2581
  return { ...loaded, scope: loaded.scope ?? {} };
2630
2582
  }
@@ -2667,7 +2619,7 @@ function probeFreshness(root) {
2667
2619
  }
2668
2620
  let stat;
2669
2621
  try {
2670
- stat = fs18.statSync(file.abs);
2622
+ stat = fs17.statSync(file.abs);
2671
2623
  } catch {
2672
2624
  drift.removed.push(file.rel);
2673
2625
  continue;
@@ -2685,7 +2637,7 @@ function probeFreshness(root) {
2685
2637
  }
2686
2638
  let hash = "";
2687
2639
  try {
2688
- hash = hashBytes(fs18.readFileSync(file.abs));
2640
+ hash = hashBytes(fs17.readFileSync(file.abs));
2689
2641
  } catch {
2690
2642
  drift.removed.push(file.rel);
2691
2643
  continue;
@@ -2702,7 +2654,7 @@ function probeFreshness(root) {
2702
2654
  }
2703
2655
  if (absorbed && !hasDrift(drift)) {
2704
2656
  try {
2705
- fs18.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2657
+ fs17.writeFileSync(snapshotPath(root), stableStringify(snapshot, 0));
2706
2658
  } catch {
2707
2659
  }
2708
2660
  }
@@ -2808,9 +2760,9 @@ function testsToRun(graph, rootId, depth = 4) {
2808
2760
  }
2809
2761
  function detectRunner(root, lang) {
2810
2762
  const pkgPath = path19.join(root, "package.json");
2811
- if (fs18.existsSync(pkgPath)) {
2763
+ if (fs17.existsSync(pkgPath)) {
2812
2764
  try {
2813
- const pkg = JSON.parse(fs18.readFileSync(pkgPath, "utf8"));
2765
+ const pkg = JSON.parse(fs17.readFileSync(pkgPath, "utf8"));
2814
2766
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
2815
2767
  if (deps.vitest) return { name: "vitest", command: (f) => `npx vitest run ${f.join(" ")}`.trim() };
2816
2768
  if (deps.jest) return { name: "jest", command: (f) => `npx jest ${f.join(" ")}`.trim() };
@@ -2818,10 +2770,10 @@ function detectRunner(root, lang) {
2818
2770
  } catch {
2819
2771
  }
2820
2772
  }
2821
- if (lang === "py" || fs18.existsSync(path19.join(root, "pyproject.toml")) || fs18.existsSync(path19.join(root, "pytest.ini"))) {
2773
+ if (lang === "py" || fs17.existsSync(path19.join(root, "pyproject.toml")) || fs17.existsSync(path19.join(root, "pytest.ini"))) {
2822
2774
  return { name: "pytest", command: (f) => `pytest ${f.join(" ")}`.trim() };
2823
2775
  }
2824
- if (lang === "go" || fs18.existsSync(path19.join(root, "go.mod"))) {
2776
+ if (lang === "go" || fs17.existsSync(path19.join(root, "go.mod"))) {
2825
2777
  return { name: "go test", command: () => "go test ./..." };
2826
2778
  }
2827
2779
  if (lang === "cs" || hasFile(root, /\.csproj$/) || hasFile(root, /\.sln$/)) {
@@ -2832,7 +2784,7 @@ function detectRunner(root, lang) {
2832
2784
  }
2833
2785
  function hasFile(root, re) {
2834
2786
  try {
2835
- return fs18.readdirSync(root).some((f) => re.test(f));
2787
+ return fs17.readdirSync(root).some((f) => re.test(f));
2836
2788
  } catch {
2837
2789
  return false;
2838
2790
  }
@@ -2840,7 +2792,7 @@ function hasFile(root, re) {
2840
2792
  function findGitRoot(startDir = process.cwd()) {
2841
2793
  let dir = path19.resolve(startDir);
2842
2794
  for (; ; ) {
2843
- if (fs18.existsSync(path19.join(dir, ".git"))) return dir;
2795
+ if (fs17.existsSync(path19.join(dir, ".git"))) return dir;
2844
2796
  const parent = path19.dirname(dir);
2845
2797
  if (parent === dir) return null;
2846
2798
  dir = parent;
@@ -2857,14 +2809,14 @@ function ensureGitignored(entry, startDir = process.cwd()) {
2857
2809
  let existing = "";
2858
2810
  let fileExisted = true;
2859
2811
  try {
2860
- existing = fs18.readFileSync(gitignorePath, "utf8");
2812
+ existing = fs17.readFileSync(gitignorePath, "utf8");
2861
2813
  } catch {
2862
2814
  fileExisted = false;
2863
2815
  }
2864
2816
  const alreadyPresent = existing.split(/\r?\n/).some((line) => normalizeEntry(line) === target);
2865
2817
  if (alreadyPresent) return { status: "present", entry, gitignorePath };
2866
2818
  const needsLeadingNewline = existing.length > 0 && !existing.endsWith("\n");
2867
- fs18.appendFileSync(gitignorePath, `${needsLeadingNewline ? "\n" : ""}${entry}
2819
+ fs17.appendFileSync(gitignorePath, `${needsLeadingNewline ? "\n" : ""}${entry}
2868
2820
  `, "utf8");
2869
2821
  return { status: fileExisted ? "added" : "created", entry, gitignorePath };
2870
2822
  }
@@ -3054,7 +3006,7 @@ function credentialsPath(opts = {}) {
3054
3006
  if (override) return path19.resolve(override);
3055
3007
  const local = projectCredentialsPath(opts.cwd);
3056
3008
  if (opts.local) return local;
3057
- if (fs18.existsSync(local)) return local;
3009
+ if (fs17.existsSync(local)) return local;
3058
3010
  return homeCredentialsPath();
3059
3011
  }
3060
3012
  function gitignoreEntryForCredentials(repoRoot, credsFile = credentialsPath()) {
@@ -3066,7 +3018,7 @@ function gitignoreEntryForCredentials(repoRoot, credsFile = credentialsPath()) {
3066
3018
  }
3067
3019
  function readStoredCredentials(opts = {}) {
3068
3020
  try {
3069
- const raw = fs18.readFileSync(credentialsPath(opts), "utf8");
3021
+ const raw = fs17.readFileSync(credentialsPath(opts), "utf8");
3070
3022
  const parsed = JSON.parse(raw);
3071
3023
  return parsed && typeof parsed.dsn === "string" && parsed.dsn ? parsed : null;
3072
3024
  } catch {
@@ -3075,16 +3027,16 @@ function readStoredCredentials(opts = {}) {
3075
3027
  }
3076
3028
  function writeStoredCredentials(creds, opts = {}) {
3077
3029
  const file = credentialsPath(opts);
3078
- fs18.mkdirSync(path19.dirname(file), { recursive: true });
3079
- fs18.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf8", mode: 384 });
3030
+ fs17.mkdirSync(path19.dirname(file), { recursive: true });
3031
+ fs17.writeFileSync(file, JSON.stringify(creds, null, 2) + "\n", { encoding: "utf8", mode: 384 });
3080
3032
  try {
3081
- fs18.chmodSync(file, 384);
3033
+ fs17.chmodSync(file, 384);
3082
3034
  } catch {
3083
3035
  }
3084
3036
  }
3085
3037
  function clearStoredCredentials(opts = {}) {
3086
3038
  try {
3087
- fs18.rmSync(credentialsPath(opts));
3039
+ fs17.rmSync(credentialsPath(opts));
3088
3040
  return true;
3089
3041
  } catch {
3090
3042
  return false;
@@ -3550,7 +3502,7 @@ function measure(root, files) {
3550
3502
  for (const rel2 of files) {
3551
3503
  let size;
3552
3504
  try {
3553
- size = fs18.statSync(path19.join(root, rel2)).size;
3505
+ size = fs17.statSync(path19.join(root, rel2)).size;
3554
3506
  } catch {
3555
3507
  continue;
3556
3508
  }
@@ -3573,9 +3525,9 @@ function matchLines(text, needleLower) {
3573
3525
  }
3574
3526
  function readCandidate(abs, knownSize) {
3575
3527
  try {
3576
- const size = knownSize ?? fs18.statSync(abs).size;
3528
+ const size = knownSize ?? fs17.statSync(abs).size;
3577
3529
  if (size > MAX_FILE_BYTES) return null;
3578
- const text = fs18.readFileSync(abs, "utf8");
3530
+ const text = fs17.readFileSync(abs, "utf8");
3579
3531
  return text.includes(NUL) ? null : text;
3580
3532
  } catch {
3581
3533
  return null;
@@ -3869,7 +3821,7 @@ function walkCandidates(root) {
3869
3821
  const dir = stack.pop();
3870
3822
  let entries;
3871
3823
  try {
3872
- entries = fs18.readdirSync(dir, { withFileTypes: true });
3824
+ entries = fs17.readdirSync(dir, { withFileTypes: true });
3873
3825
  } catch {
3874
3826
  continue;
3875
3827
  }
@@ -3933,7 +3885,7 @@ function parseRgFileList(stdout, sep10 = path19.sep) {
3933
3885
  function readScanArtifact(root) {
3934
3886
  try {
3935
3887
  const file = path19.join(root, ".vibgrate", "scan_result.json");
3936
- return JSON.parse(fs18.readFileSync(file, "utf8"));
3888
+ return JSON.parse(fs17.readFileSync(file, "utf8"));
3937
3889
  } catch {
3938
3890
  return null;
3939
3891
  }
@@ -4189,6 +4141,12 @@ ${chunk2}`);
4189
4141
  }
4190
4142
 
4191
4143
  // src/engine/quality.ts
4144
+ var IDENT_RE = /^(?:[A-Za-z][a-z0-9]*[A-Z][A-Za-z0-9]*|[a-z][a-z0-9]*(?:_[a-z0-9]+)+|[a-z][a-z0-9]*(?:-[a-z0-9]+)+)$/;
4145
+ function identifierTerms(query) {
4146
+ if (!query) return [];
4147
+ const raw = [...new Set(query.split(/[^A-Za-z0-9_-]+/).filter((w) => w.length > 2))];
4148
+ return raw.filter((t) => IDENT_RE.test(t) || t.length >= 6 && /[A-Z]/.test(t) && /[a-z]/.test(t));
4149
+ }
4192
4150
  function assessDocQuality(content, opts = {}) {
4193
4151
  const minTokens = opts.minTokens ?? 60;
4194
4152
  const lc = content.toLowerCase();
@@ -4206,20 +4164,36 @@ function assessDocQuality(content, opts = {}) {
4206
4164
  else reasons.push("library name absent");
4207
4165
  }
4208
4166
  const qt = tokenizeQuery(opts.query);
4167
+ const idents = identifierTerms(opts.query);
4209
4168
  let onTopic = qt.length === 0;
4210
4169
  if (qt.length) {
4211
- const hits = qt.filter((t) => lc.includes(t)).length;
4212
- if (hits) {
4213
- score += Math.min(hits, 2);
4214
- onTopic = true;
4170
+ const missingIdents = idents.filter((id) => !lc.includes(id.toLowerCase()));
4171
+ if (missingIdents.length) {
4172
+ reasons.push(`API symbol(s) absent: ${missingIdents.join(", ")}`);
4173
+ onTopic = false;
4215
4174
  } else {
4216
- reasons.push("query terms absent");
4175
+ const hits = qt.filter((t) => lc.includes(t)).length;
4176
+ const need = Math.max(1, Math.floor(qt.length / 2) + 1);
4177
+ if (hits >= need) {
4178
+ score += Math.min(hits, 2);
4179
+ onTopic = true;
4180
+ } else {
4181
+ reasons.push(hits === 0 ? "query terms absent" : `query terms weak (${hits}/${qt.length})`);
4182
+ onTopic = false;
4183
+ }
4217
4184
  }
4218
4185
  }
4219
4186
  if (opts.symbols?.length) {
4220
4187
  if (opts.symbols.some((s) => s.length > 2 && lc.includes(s.toLowerCase()))) score += 1;
4221
4188
  else reasons.push("no API symbols present");
4222
4189
  }
4190
+ if (opts.readmeOnly && (idents.length > 0 || qt.length >= 2)) {
4191
+ onTopic = false;
4192
+ if (!reasons.includes("README-only source cannot answer a focused API query")) {
4193
+ reasons.push("README-only source cannot answer a focused API query");
4194
+ }
4195
+ score = Math.min(score, 4);
4196
+ }
4223
4197
  const sufficient = hasCode && tokens >= minTokens && onTopic;
4224
4198
  return { score, sufficient, reasons };
4225
4199
  }
@@ -4339,7 +4313,7 @@ function hostedDocsCacheKey(req, opts = {}) {
4339
4313
  }
4340
4314
  function loadFile(root) {
4341
4315
  try {
4342
- const parsed = JSON.parse(fs18.readFileSync(cachePath(root), "utf8"));
4316
+ const parsed = JSON.parse(fs17.readFileSync(cachePath(root), "utf8"));
4343
4317
  if (parsed && parsed.version === CACHE_VERSION && parsed.entries && typeof parsed.entries === "object") return parsed;
4344
4318
  } catch {
4345
4319
  }
@@ -4353,8 +4327,8 @@ function saveFile(root, file) {
4353
4327
  delete file.entries[k];
4354
4328
  }
4355
4329
  }
4356
- fs18.mkdirSync(cacheDir(root), { recursive: true });
4357
- fs18.writeFileSync(cachePath(root), JSON.stringify(file));
4330
+ fs17.mkdirSync(cacheDir(root), { recursive: true });
4331
+ fs17.writeFileSync(cachePath(root), JSON.stringify(file));
4358
4332
  } catch {
4359
4333
  }
4360
4334
  }
@@ -4798,9 +4772,15 @@ var TOOLS = [
4798
4772
  {
4799
4773
  name: "get_facts",
4800
4774
  description: "Deterministic facts for a node (contract / invariant / characterization).",
4801
- inputSchema: obj({ name: { type: "string" } }, ["name"]),
4775
+ inputSchema: obj(
4776
+ {
4777
+ name: { type: "string" },
4778
+ pick: { type: "number", description: "nth candidate if ambiguous" }
4779
+ },
4780
+ ["name"]
4781
+ ),
4802
4782
  handler: (graph, args) => {
4803
- const { node, candidates } = resolveOne(graph, String(args.name ?? ""));
4783
+ const { node, candidates } = resolveOne(graph, String(args.name ?? ""), numOrU(args.pick));
4804
4784
  if (!node) return unresolved(candidates);
4805
4785
  if (!graph.facts) {
4806
4786
  return {
@@ -4815,9 +4795,15 @@ var TOOLS = [
4815
4795
  {
4816
4796
  name: "guide_node",
4817
4797
  description: "Cited standards/practices for a node (OWASP/CWE).",
4818
- inputSchema: obj({ name: { type: "string" } }, ["name"]),
4798
+ inputSchema: obj(
4799
+ {
4800
+ name: { type: "string" },
4801
+ pick: { type: "number", description: "nth candidate if ambiguous" }
4802
+ },
4803
+ ["name"]
4804
+ ),
4819
4805
  handler: (graph, args) => {
4820
- const { node, candidates } = resolveOne(graph, String(args.name ?? ""));
4806
+ const { node, candidates } = resolveOne(graph, String(args.name ?? ""), numOrU(args.pick));
4821
4807
  if (!node) return unresolved(candidates);
4822
4808
  const entries = new Map(FREE_PACK.entries.map((e) => [e.id, e]));
4823
4809
  return {
@@ -5011,13 +4997,24 @@ var TOOLS = [
5011
4997
  const verbosity = ["concise", "balanced", "exhaustive"].includes(String(args.verbosity)) ? String(args.verbosity) : query ? "concise" : "balanced";
5012
4998
  const budget = numOrU(args.max_tokens) ?? numOrU(args.tokens) ?? VERBOSITY_BUDGET[verbosity];
5013
4999
  const ver = resolveVersion(ctx.root, id);
5014
- const render = (readme, libName) => {
5015
- const apiSurface = localApiSurface(ctx.root, libName);
5016
- const sel = selectForBudget({ readme, query, apiSurface, budget });
5017
- const quality = assessDocQuality([readme, apiSurface].filter(Boolean).join("\n\n"), {
5000
+ const focusQuery = (() => {
5001
+ const q = query.trim();
5002
+ if (!q) return q;
5003
+ const bare = id.replace(/^@[^/]+\//, "").toLowerCase();
5004
+ const parts = q.split(/\s+/);
5005
+ if (parts.length > 1 && parts[0].toLowerCase().replace(/^@[^/]+\//, "") === bare) {
5006
+ return parts.slice(1).join(" ");
5007
+ }
5008
+ return q;
5009
+ })();
5010
+ const render = (readme, libName, readmeOnly) => {
5011
+ const apiSurface = localApiSurface(ctx.root, libName, focusQuery || void 0);
5012
+ const sel = selectForBudget({ readme, query: focusQuery || query, apiSurface, budget });
5013
+ const quality = assessDocQuality(sel.text, {
5018
5014
  name: libName,
5019
- query,
5020
- symbols: symbolsFromApi(apiSurface)
5015
+ query: focusQuery || query || void 0,
5016
+ symbols: symbolsFromApi(apiSurface),
5017
+ readmeOnly: readmeOnly === true && !apiSurface
5021
5018
  });
5022
5019
  return {
5023
5020
  content: sel.text,
@@ -5034,7 +5031,7 @@ var TOOLS = [
5034
5031
  let answer = null;
5035
5032
  let sufficient = false;
5036
5033
  if (entry) {
5037
- const r = render(readDoc(ctx.root, entry), entry.name);
5034
+ const r = render(readDoc(ctx.root, entry), entry.name, false);
5038
5035
  sufficient = r.metadata.quality.sufficient;
5039
5036
  answer = {
5040
5037
  targetId: entry.id,
@@ -5049,9 +5046,9 @@ var TOOLS = [
5049
5046
  metadata: r.metadata
5050
5047
  };
5051
5048
  } else {
5052
- const local = localPackageDocs(ctx.root, id);
5049
+ const local = localPackageDocs(ctx.root, id, { query: focusQuery || query || void 0 });
5053
5050
  if (local) {
5054
- const r = render(local.docs, id);
5051
+ const r = render(local.docs, id, local.readmeOnly);
5055
5052
  sufficient = r.metadata.quality.sufficient;
5056
5053
  answer = {
5057
5054
  targetId: id,
@@ -5366,12 +5363,12 @@ function detectAssistants(root, opts = {}) {
5366
5363
  const which = opts.which ?? whichOnPath;
5367
5364
  const found = [];
5368
5365
  for (const assistant of ASSISTANTS) {
5369
- const repoHit = (assistant.markers ?? []).find((m) => fs18.existsSync(path19.join(root, m)));
5366
+ const repoHit = (assistant.markers ?? []).find((m) => fs17.existsSync(path19.join(root, m)));
5370
5367
  if (repoHit) {
5371
5368
  found.push({ assistant, via: "repo", marker: repoHit });
5372
5369
  continue;
5373
5370
  }
5374
- const homeHit = (assistant.homeMarkers ?? []).find((m) => fs18.existsSync(path19.join(home, m)));
5371
+ const homeHit = (assistant.homeMarkers ?? []).find((m) => fs17.existsSync(path19.join(home, m)));
5375
5372
  if (homeHit) {
5376
5373
  found.push({ assistant, via: "home", marker: homeHit });
5377
5374
  continue;
@@ -5432,23 +5429,23 @@ function uninstallAssistant(a, root, purge) {
5432
5429
  const file = path19.join(root, a.nudge.file);
5433
5430
  if (a.nudge.kind === "block") {
5434
5431
  if (removeBlock(file)) removed.push(a.nudge.file);
5435
- } else if (fs18.existsSync(file)) {
5436
- fs18.rmSync(file);
5432
+ } else if (fs17.existsSync(file)) {
5433
+ fs17.rmSync(file);
5437
5434
  removed.push(a.nudge.file);
5438
5435
  }
5439
5436
  }
5440
5437
  if (purge && a.skill) {
5441
5438
  const file = path19.join(root, a.skill);
5442
- if (fs18.existsSync(file)) {
5443
- fs18.rmSync(file);
5439
+ if (fs17.existsSync(file)) {
5440
+ fs17.rmSync(file);
5444
5441
  removed.push(a.skill);
5445
5442
  }
5446
5443
  }
5447
5444
  return removed;
5448
5445
  }
5449
5446
  function writeFileEnsured(file, content) {
5450
- fs18.mkdirSync(path19.dirname(file), { recursive: true });
5451
- fs18.writeFileSync(file, content);
5447
+ fs17.mkdirSync(path19.dirname(file), { recursive: true });
5448
+ fs17.writeFileSync(file, content);
5452
5449
  }
5453
5450
  function writeNavigationConfig(root) {
5454
5451
  ensureVibgrateGitignore(root);
@@ -5474,7 +5471,7 @@ function upsertMcp(file, target, launch) {
5474
5471
  `);
5475
5472
  }
5476
5473
  function removeMcp(file, target) {
5477
- if (!fs18.existsSync(file)) return false;
5474
+ if (!fs17.existsSync(file)) return false;
5478
5475
  const config = readJson(file);
5479
5476
  const bag = config[target.key];
5480
5477
  if (!bag || !(bag.vg !== void 0)) return false;
@@ -5494,7 +5491,7 @@ function refreshInstalledInstructions(root, smallRepo) {
5494
5491
  for (const a of ASSISTANTS) {
5495
5492
  if (a.skill) {
5496
5493
  const file = path19.join(root, a.skill);
5497
- if (fs18.existsSync(file)) {
5494
+ if (fs17.existsSync(file)) {
5498
5495
  const text = readTextSafe(file);
5499
5496
  const from = text === null ? null : staleVersion(text, "# vg \u2014 the code map");
5500
5497
  if (from !== null) {
@@ -5505,7 +5502,7 @@ function refreshInstalledInstructions(root, smallRepo) {
5505
5502
  }
5506
5503
  if (a.nudge) {
5507
5504
  const file = path19.join(root, a.nudge.file);
5508
- if (!fs18.existsSync(file)) continue;
5505
+ if (!fs17.existsSync(file)) continue;
5509
5506
  const text = readTextSafe(file);
5510
5507
  if (text === null) continue;
5511
5508
  if (a.nudge.kind === "block") {
@@ -5529,7 +5526,7 @@ function refreshInstalledInstructions(root, smallRepo) {
5529
5526
  }
5530
5527
  function readTextSafe(file) {
5531
5528
  try {
5532
- return fs18.readFileSync(file, "utf8");
5529
+ return fs17.readFileSync(file, "utf8");
5533
5530
  } catch {
5534
5531
  return null;
5535
5532
  }
@@ -5548,8 +5545,8 @@ ${stripMarkers(nudgeMarkdown(smallRepo, client))}` : stripMarkers(nudgeMarkdown(
5548
5545
  upsertBlock(file, nudgeMarkdown(smallRepo, client));
5549
5546
  }
5550
5547
  function upsertBlock(file, block) {
5551
- fs18.mkdirSync(path19.dirname(file), { recursive: true });
5552
- let existing = fs18.existsSync(file) ? fs18.readFileSync(file, "utf8") : "";
5548
+ fs17.mkdirSync(path19.dirname(file), { recursive: true });
5549
+ let existing = fs17.existsSync(file) ? fs17.readFileSync(file, "utf8") : "";
5553
5550
  const re = new RegExp(`${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}`);
5554
5551
  if (re.test(existing)) existing = existing.replace(re, block);
5555
5552
  else existing = existing.length ? `${existing.replace(/\s*$/, "")}
@@ -5557,20 +5554,20 @@ function upsertBlock(file, block) {
5557
5554
  ${block}
5558
5555
  ` : `${block}
5559
5556
  `;
5560
- fs18.writeFileSync(file, existing);
5557
+ fs17.writeFileSync(file, existing);
5561
5558
  }
5562
5559
  function removeBlock(file) {
5563
- if (!fs18.existsSync(file)) return false;
5564
- const existing = fs18.readFileSync(file, "utf8");
5560
+ if (!fs17.existsSync(file)) return false;
5561
+ const existing = fs17.readFileSync(file, "utf8");
5565
5562
  const re = new RegExp(`\\n*${escapeRe(NUDGE_BEGIN)}[\\s\\S]*?${escapeRe(NUDGE_END)}\\n*`);
5566
5563
  if (!re.test(existing)) return false;
5567
- fs18.writeFileSync(file, existing.replace(re, "\n"));
5564
+ fs17.writeFileSync(file, existing.replace(re, "\n"));
5568
5565
  return true;
5569
5566
  }
5570
5567
  function readJson(file) {
5571
- if (!fs18.existsSync(file)) return {};
5568
+ if (!fs17.existsSync(file)) return {};
5572
5569
  try {
5573
- const parsed = JSON.parse(fs18.readFileSync(file, "utf8"));
5570
+ const parsed = JSON.parse(fs17.readFileSync(file, "utf8"));
5574
5571
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
5575
5572
  return parsed;
5576
5573
  }
@@ -5622,8 +5619,8 @@ async function refreshIfStale(root, opts = {}) {
5622
5619
  writeArtifacts(result.graph, {
5623
5620
  root,
5624
5621
  graphPath: opts.graphPath,
5625
- report: fs18.existsSync(path19.join(dir, "GRAPH_REPORT.md")),
5626
- html: fs18.existsSync(path19.join(dir, "graph.html"))
5622
+ report: fs17.existsSync(path19.join(dir, "GRAPH_REPORT.md")),
5623
+ html: fs17.existsSync(path19.join(dir, "graph.html"))
5627
5624
  });
5628
5625
  }
5629
5626
  writeSnapshot(root, result.graph.provenance.corpusHash, result.fileStats, scope);
@@ -5643,6 +5640,6 @@ async function refreshIfStale(root, opts = {}) {
5643
5640
  }
5644
5641
  }
5645
5642
 
5646
- export { ASSISTANTS, CliError, ExitCode, FREE_PACK, NPX_INVOCATION, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, TOOLS, UsageError, analyze, applyCoverage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, clearStoredCredentials, countTokens, coveringTests, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, detectAssistants, detectRunner, detectServeLaunch, discover, driftCount, dsnCommand, ensureGitignored, epistemicBreakdown, fetchHostedDocsCached, findGitRoot, gitignoreEntryForCredentials, groundGraph, hasDrift, homeCredentialsPath, hostedBase, ingestHostForRegionId, installAssistant, loadCoverage, loadSnapshot, parseDsn, pathDisconnect, probeFreshness, projectCredentialsPath, publishPrivateLibrary, pushCommand, readScanArtifact, readStoredCredentials, refreshIfStale, refreshInstalledInstructions, renderToolResult, resolveCliInvocation, resolveDsn, resolveIngestHost, resolveLimits, scipEdges, searchSymbols, selectForBudget, shortestPath, symbolsFromApi, testsToRun, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, warmEmbedderInBackground, writeNavigationConfig, writeSnapshot, writeStoredCredentials };
5647
- //# sourceMappingURL=chunk-MAY5HLDH.js.map
5648
- //# sourceMappingURL=chunk-MAY5HLDH.js.map
5643
+ export { ASSISTANTS, CliError, ExitCode, FREE_PACK, ResourceLimitError, SKIP_DIRS, SKIP_FILES, SMALL_REPO_FILES, TOOLS, UsageError, analyze, applyCoverage, assessDocQuality, assistantById, availableRegionIds, buildFacts, buildGraph, clearStoredCredentials, countTokens, coveringTests, createWorkspaceDsn, credentialsPath, dashHostForIngestHost, decodeScipIndex, detectAssistants, detectRunner, detectServeLaunch, discover, driftCount, dsnCommand, ensureGitignored, epistemicBreakdown, fetchHostedDocsCached, findGitRoot, gitignoreEntryForCredentials, groundGraph, hasDrift, homeCredentialsPath, hostedBase, ingestHostForRegionId, installAssistant, loadCoverage, loadSnapshot, parseDsn, pathDisconnect, probeFreshness, projectCredentialsPath, publishPrivateLibrary, pushCommand, readScanArtifact, readStoredCredentials, refreshIfStale, refreshInstalledInstructions, renderToolResult, resolveDsn, resolveIngestHost, resolveLimits, scipEdges, searchSymbols, selectForBudget, shortestPath, symbolsFromApi, testsToRun, uninstallAssistant, uploadScanArtifact, usageError, verifyDeterminism, warmEmbedderInBackground, writeNavigationConfig, writeSnapshot, writeStoredCredentials };
5644
+ //# sourceMappingURL=chunk-GQTWDKMJ.js.map
5645
+ //# sourceMappingURL=chunk-GQTWDKMJ.js.map