@vibgrate/cli 2026.727.2 → 2026.727.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/DOCS.md +21 -1
  2. package/README.md +2 -1
  3. package/dist/baseline-ENCOSJYQ.js +8 -0
  4. package/dist/{baseline-TG4ATZGZ.js.map → baseline-ENCOSJYQ.js.map} +1 -1
  5. package/dist/chunk-3SDV6ADQ.js +78 -0
  6. package/dist/chunk-3SDV6ADQ.js.map +1 -0
  7. package/dist/{chunk-LKVMI67M.js → chunk-6AXHLQBV.js} +220 -23
  8. package/dist/chunk-6AXHLQBV.js.map +1 -0
  9. package/dist/{chunk-6ABXHZRN.js → chunk-6UK6QPTR.js} +69 -70
  10. package/dist/chunk-6UK6QPTR.js.map +1 -0
  11. package/dist/{chunk-TCDAZZNP.js → chunk-77LYGXBI.js} +5 -5
  12. package/dist/{chunk-TCDAZZNP.js.map → chunk-77LYGXBI.js.map} +1 -1
  13. package/dist/{chunk-2XQDMLKB.js → chunk-B3YUO3NW.js} +7 -3
  14. package/dist/chunk-B3YUO3NW.js.map +1 -0
  15. package/dist/{chunk-RNP3SMTV.js → chunk-FPEOIS7K.js} +61 -26
  16. package/dist/chunk-FPEOIS7K.js.map +1 -0
  17. package/dist/{chunk-OOIG3RUM.js → chunk-GYSOQH5C.js} +18 -79
  18. package/dist/chunk-GYSOQH5C.js.map +1 -0
  19. package/dist/{chunk-6AYDFFP5.js → chunk-HK3AWUXH.js} +3 -3
  20. package/dist/{chunk-6AYDFFP5.js.map → chunk-HK3AWUXH.js.map} +1 -1
  21. package/dist/{chunk-EX4PQT6W.js → chunk-HYRAILGM.js} +4 -4
  22. package/dist/{chunk-EX4PQT6W.js.map → chunk-HYRAILGM.js.map} +1 -1
  23. package/dist/{chunk-NDMDSPFX.js → chunk-KKRSQQ3A.js} +4 -3
  24. package/dist/chunk-KKRSQQ3A.js.map +1 -0
  25. package/dist/chunk-KUIBP3LU.js +101 -0
  26. package/dist/chunk-KUIBP3LU.js.map +1 -0
  27. package/dist/{chunk-OFUC6RYN.js → chunk-KXSKFQMI.js} +6 -99
  28. package/dist/chunk-KXSKFQMI.js.map +1 -0
  29. package/dist/{chunk-KCKYKDMS.js → chunk-LJP2EPKM.js} +20 -17
  30. package/dist/chunk-LJP2EPKM.js.map +1 -0
  31. package/dist/{chunk-J4RFRKZH.js → chunk-MAUJTPQW.js} +8 -8
  32. package/dist/{chunk-J4RFRKZH.js.map → chunk-MAUJTPQW.js.map} +1 -1
  33. package/dist/{chunk-3Q7QBWFW.js → chunk-ON25BX6T.js} +9 -3
  34. package/dist/chunk-ON25BX6T.js.map +1 -0
  35. package/dist/{chunk-3V24O47U.js → chunk-PVZBYZZR.js} +19 -9
  36. package/dist/chunk-PVZBYZZR.js.map +1 -0
  37. package/dist/{chunk-CY4WKXB2.js → chunk-R6ZRVVZT.js} +4 -4
  38. package/dist/{chunk-CY4WKXB2.js.map → chunk-R6ZRVVZT.js.map} +1 -1
  39. package/dist/{chunk-WGUL45AV.js → chunk-T3AYRS7J.js} +14 -7
  40. package/dist/chunk-T3AYRS7J.js.map +1 -0
  41. package/dist/{chunk-2MBL43EJ.js → chunk-XPJZTSY7.js} +3 -3
  42. package/dist/{chunk-2MBL43EJ.js.map → chunk-XPJZTSY7.js.map} +1 -1
  43. package/dist/chunk-YCJIIGLP.js +356 -0
  44. package/dist/chunk-YCJIIGLP.js.map +1 -0
  45. package/dist/{chunk-KNELIQJO.js → chunk-YKVH2PGF.js} +640 -208
  46. package/dist/chunk-YKVH2PGF.js.map +1 -0
  47. package/dist/{chunk-KSBHGWRV.js → chunk-ZBTY6VV4.js} +4 -4
  48. package/dist/{chunk-KSBHGWRV.js.map → chunk-ZBTY6VV4.js.map} +1 -1
  49. package/dist/{chunk-K3MZIVZW.js → chunk-ZKNB4YH4.js} +19 -5
  50. package/dist/chunk-ZKNB4YH4.js.map +1 -0
  51. package/dist/cli.js +476 -393
  52. package/dist/cli.js.map +1 -1
  53. package/dist/{graph-backend-73URGTFY.js → graph-backend-UTOL3SHE.js} +5 -5
  54. package/dist/{graph-backend-73URGTFY.js.map → graph-backend-UTOL3SHE.js.map} +1 -1
  55. package/dist/index.d.ts +12 -5
  56. package/dist/index.js +12 -11
  57. package/dist/index.js.map +1 -1
  58. package/dist/{interactive-372NLI5C.js → interactive-SMHVURYK.js} +54 -24
  59. package/dist/interactive-SMHVURYK.js.map +1 -0
  60. package/dist/load-QPOWQD7C.js +8 -0
  61. package/dist/{load-I333TGNI.js.map → load-QPOWQD7C.js.map} +1 -1
  62. package/dist/model-manager-PN7HEDXD.js +9 -0
  63. package/dist/{model-orchestrator-TVONAUPS.js.map → model-manager-PN7HEDXD.js.map} +1 -1
  64. package/dist/{model-orchestrator-TVONAUPS.js → model-orchestrator-4VSYP4J4.js} +3 -3
  65. package/dist/model-orchestrator-4VSYP4J4.js.map +1 -0
  66. package/dist/parse-worker.d.ts +1 -1
  67. package/dist/parse-worker.js +1 -1
  68. package/dist/resolve-gguf-Y6FH3CNB.js +9 -0
  69. package/dist/{resolve-gguf-VPL4YQ6J.js.map → resolve-gguf-Y6FH3CNB.js.map} +1 -1
  70. package/dist/{runtime-session-JRKCQUHY.js → runtime-session-4AMZIAAG.js} +7 -7
  71. package/dist/{runtime-session-JRKCQUHY.js.map → runtime-session-4AMZIAAG.js.map} +1 -1
  72. package/dist/session-W3646AOV.js +12 -0
  73. package/dist/{session-ITPYQ5XI.js.map → session-W3646AOV.js.map} +1 -1
  74. package/dist/sql-extract-JELDZA6W.js +81 -0
  75. package/dist/sql-extract-JELDZA6W.js.map +1 -0
  76. package/dist/{stream-json-SLMDKLXP.js → stream-json-X7UQFB4T.js} +11 -10
  77. package/dist/stream-json-X7UQFB4T.js.map +1 -0
  78. package/dist/{types-7AHBUbFm.d.ts → types-DLH-Ritr.d.ts} +18 -1
  79. package/dist/{vgd-7JV5KCNJ.js → vgd-CVLKBS7K.js} +6 -6
  80. package/dist/vgd-CVLKBS7K.js.map +1 -0
  81. package/package.json +1 -1
  82. package/dist/baseline-TG4ATZGZ.js +0 -8
  83. package/dist/chunk-2XQDMLKB.js.map +0 -1
  84. package/dist/chunk-3Q7QBWFW.js.map +0 -1
  85. package/dist/chunk-3V24O47U.js.map +0 -1
  86. package/dist/chunk-6ABXHZRN.js.map +0 -1
  87. package/dist/chunk-K3MZIVZW.js.map +0 -1
  88. package/dist/chunk-KCKYKDMS.js.map +0 -1
  89. package/dist/chunk-KNELIQJO.js.map +0 -1
  90. package/dist/chunk-LKVMI67M.js.map +0 -1
  91. package/dist/chunk-NDMDSPFX.js.map +0 -1
  92. package/dist/chunk-OFUC6RYN.js.map +0 -1
  93. package/dist/chunk-OOIG3RUM.js.map +0 -1
  94. package/dist/chunk-RNP3SMTV.js.map +0 -1
  95. package/dist/chunk-WGUL45AV.js.map +0 -1
  96. package/dist/interactive-372NLI5C.js.map +0 -1
  97. package/dist/load-I333TGNI.js +0 -8
  98. package/dist/resolve-gguf-VPL4YQ6J.js +0 -8
  99. package/dist/session-ITPYQ5XI.js +0 -11
  100. package/dist/stream-json-SLMDKLXP.js.map +0 -1
  101. package/dist/vgd-7JV5KCNJ.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,46 +1,49 @@
1
1
  #!/usr/bin/env node
2
- import { loadAdvancedScanHook, baselineCommand } from './chunk-EX4PQT6W.js';
3
- import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-RNP3SMTV.js';
4
- export { runBuild } from './chunk-RNP3SMTV.js';
5
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-TCDAZZNP.js';
2
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-FPEOIS7K.js';
3
+ export { runBuild } from './chunk-FPEOIS7K.js';
4
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-MAUJTPQW.js';
5
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-HYRAILGM.js';
6
+ import { runCodeSession } from './chunk-R6ZRVVZT.js';
7
+ import { summarizeDiffs, ScriptedProvider } from './chunk-KXSKFQMI.js';
8
+ import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
9
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-77LYGXBI.js';
6
10
  import './chunk-5I4VSBWQ.js';
7
11
  import './chunk-IS7VTH2Q.js';
8
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-J4RFRKZH.js';
9
12
  import { gatherSystemMemory } from './chunk-6UQMXIAG.js';
10
- import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-3V24O47U.js';
13
+ import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-PVZBYZZR.js';
11
14
  import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
12
15
  import './chunk-IZDH67DX.js';
13
- import './chunk-6AYDFFP5.js';
16
+ import './chunk-HK3AWUXH.js';
14
17
  import { vgdIsRunning, vgdRequest, vgdSocketPath } from './chunk-PMYWZRRS.js';
15
18
  import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-PXHNTC6D.js';
16
19
  import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-K7REHDQS.js';
17
20
  import { buildIdentifierTrieFromGraph } from './chunk-JIBOJTGS.js';
18
- import './chunk-NDMDSPFX.js';
19
- import { runCodeSession } from './chunk-CY4WKXB2.js';
20
- import { ensurePackage, ensureUnavailableMessage, isPackageInstalled, summarizeDiffs, ScriptedProvider } from './chunk-OFUC6RYN.js';
21
- import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
22
- import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-KCKYKDMS.js';
23
- import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, CliError, ExitCode, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, NPX_INVOCATION, refreshIfStale, driftCount, countTokens, shortestPath, testsToRun, detectRunner, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-KNELIQJO.js';
24
- import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-WGUL45AV.js';
25
- import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-LKVMI67M.js';
21
+ import './chunk-KKRSQQ3A.js';
22
+ import { buildModelInstallPlan } from './chunk-YCJIIGLP.js';
23
+ import { ensurePackage, ensureUnavailableMessage } from './chunk-KUIBP3LU.js';
24
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-LJP2EPKM.js';
25
+ import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, CliError, ExitCode, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, NPX_INVOCATION, refreshIfStale, driftCount, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-YKVH2PGF.js';
26
+ import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-6AXHLQBV.js';
27
+ import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-T3AYRS7J.js';
28
+ import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-ZBTY6VV4.js';
29
+ import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
26
30
  import { resolveOne } from './chunk-J7LKEB2R.js';
27
- import { discoverModels, listCachedWeights, isWeightCached, lookupCatalog, ensureWeightCached, catalogIntegrityReport, weightStoreDir } from './chunk-OOIG3RUM.js';
28
- import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-KSBHGWRV.js';
29
- import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-6ABXHZRN.js';
30
- import { resolvedGrammarFiles, grammarSetVersion } from './chunk-3Q7QBWFW.js';
31
+ import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-6UK6QPTR.js';
32
+ import { discoverModels } from './chunk-3SDV6ADQ.js';
33
+ import { listCachedWeights, ensureWeightCached, catalogIntegrityReport, weightStoreDir } from './chunk-GYSOQH5C.js';
34
+ import { resolvedGrammarFiles, grammarSetVersion } from './chunk-ON25BX6T.js';
31
35
  import './chunk-RXP66R2E.js';
32
- import { resolveGraphPath, renderReport, loadGraph, writeArtifacts, vibgrateDir, SCHEMA_VERSION } from './chunk-2XQDMLKB.js';
33
- import { cacheDir, stableStringify } from './chunk-K3MZIVZW.js';
36
+ import { resolveGraphPath, renderReport, loadGraph, writeArtifacts, vibgrateDir, SCHEMA_VERSION } from './chunk-B3YUO3NW.js';
37
+ import { cacheDir, stableStringify } from './chunk-ZKNB4YH4.js';
34
38
  import './chunk-BWPBB45M.js';
35
39
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
36
40
  import './chunk-BPF3YX2U.js';
37
41
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
38
- import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
39
42
  import './chunk-DGUM43GV.js';
40
43
  import * as fs8 from 'fs';
41
44
  import fs8__default, { realpathSync } from 'fs';
42
- import * as path36 from 'path';
43
- import path36__default from 'path';
45
+ import * as path37 from 'path';
46
+ import path37__default from 'path';
44
47
  import { fileURLToPath, pathToFileURL } from 'url';
45
48
  import { Command, CommanderError, Option } from 'commander';
46
49
  import * as os from 'os';
@@ -49,7 +52,7 @@ import { randomUUID } from 'crypto';
49
52
  import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
50
53
  import * as readline from 'readline';
51
54
  import chalk7 from 'chalk';
52
- import * as fs20 from 'fs/promises';
55
+ import * as fs21 from 'fs/promises';
53
56
  import semver2 from 'semver';
54
57
 
55
58
  function registerStatus(program) {
@@ -59,10 +62,10 @@ function registerStatus(program) {
59
62
  applyGlobalOptions(cmd);
60
63
  }
61
64
  async function runStatus(global) {
62
- const root2 = path36.resolve(global.cwd ?? ".");
65
+ const root2 = path37.resolve(global.cwd ?? ".");
63
66
  const graphPath = resolveGraphPath(root2, global.graph);
64
67
  const graph = loadGraph(root2, graphPath);
65
- const hasCache = fs8.existsSync(path36.join(cacheDir(root2), "parse-cache.json"));
68
+ const hasCache = fs8.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
66
69
  let stale = null;
67
70
  let staleExact = false;
68
71
  if (graph) {
@@ -82,8 +85,8 @@ async function runStatus(global) {
82
85
  }
83
86
  if (global.json) {
84
87
  json({
85
- root: path36.relative(process.cwd(), root2) || ".",
86
- graphPath: path36.relative(root2, graphPath),
88
+ root: path37.relative(process.cwd(), root2) || ".",
89
+ graphPath: path37.relative(root2, graphPath),
87
90
  built: graph !== null,
88
91
  generatedAt: graph?.generatedAt ?? null,
89
92
  counts: graph?.meta.counts ?? null,
@@ -98,11 +101,11 @@ async function runStatus(global) {
98
101
  return;
99
102
  }
100
103
  if (!graph) {
101
- info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path36.relative(root2, graphPath))}`);
104
+ info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
102
105
  info(` run ${c.bold("vg")} to build one`);
103
106
  return;
104
107
  }
105
- info(`${c.cyan("vg")} \xB7 ${path36.relative(root2, graphPath)}`);
108
+ info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
106
109
  info(` generated ${graph.generatedAt}`);
107
110
  info(
108
111
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -119,7 +122,7 @@ async function runStatus(global) {
119
122
  if (vibgrateDir(root2)) ;
120
123
  }
121
124
  function rootOf(global) {
122
- return path36.resolve(global.cwd ?? ".");
125
+ return path37.resolve(global.cwd ?? ".");
123
126
  }
124
127
  function requireGraph(global) {
125
128
  const root2 = rootOf(global);
@@ -402,6 +405,19 @@ function registerPath(program) {
402
405
  );
403
406
  }
404
407
  if (!result) {
408
+ const disc = pathDisconnect(graph, ra.node.id, rb.node.id);
409
+ if (global.json) {
410
+ json(disc);
411
+ throw new CliError(
412
+ `no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
413
+ ExitCode.NOT_FOUND
414
+ );
415
+ }
416
+ info(`${c.cyan("vg path")} \xB7 no path between ${c.bold(disc.from.name)} and ${c.bold(disc.to.name)}`);
417
+ printNeighborhood("from", disc.from);
418
+ printNeighborhood("to", disc.to);
419
+ info(c.dim(` ${disc.hint}`));
420
+ info(c.dim(` try: vg show ${disc.from.name} \xB7 vg impact ${disc.from.name} \xB7 vg show ${disc.to.name}`));
405
421
  throw new CliError(
406
422
  `no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
407
423
  ExitCode.NOT_FOUND
@@ -418,6 +434,14 @@ function registerPath(program) {
418
434
  });
419
435
  applyGlobalOptions(cmd);
420
436
  }
437
+ function printNeighborhood(label, n) {
438
+ const parts = [];
439
+ if (n.calls.length) parts.push(`calls ${n.calls.join(", ")}`);
440
+ if (n.calledBy.length) parts.push(`called by ${n.calledBy.join(", ")}`);
441
+ if (n.imports.length) parts.push(`imports ${n.imports.join(", ")}`);
442
+ if (n.importedBy.length) parts.push(`imported by ${n.importedBy.join(", ")}`);
443
+ info(` ${c.dim(label)} ${c.bold(n.name)}${parts.length ? c.dim(` \xB7 ${parts.join(" \xB7 ")}`) : c.dim(" \xB7 (no call/import neighbors)")}`);
444
+ }
421
445
 
422
446
  // src/commands/tree.ts
423
447
  function registerTree(program) {
@@ -531,12 +555,12 @@ function registerInsights(program) {
531
555
  }
532
556
  });
533
557
  applyGlobalOptions(areas);
534
- const oddities = program.command("oddities").description("surprising cross-area links (architectural smells)").option("-n, --limit <n>", "how many to show", "20").action(function(opts) {
558
+ const oddities = program.command("oddities").description("surprising cross-area links (architectural smells)").option("-n, --limit <n>", "how many to show", "20").option("--all", "include framework/runtime externals (default: filter them out)").action(function(opts) {
535
559
  const global = readGlobal(this);
536
560
  const { graph } = requireGraph(global);
537
561
  const limit = Number(opts.limit) || 20;
538
562
  const byId = new Map(graph.nodes.map((n) => [n.id, n]));
539
- const list = graph.edges.filter((e) => typeof e.surprise === "number" && e.surprise > 0).sort((a, b) => (b.surprise ?? 0) - (a.surprise ?? 0) || a.id.localeCompare(b.id)).slice(0, limit);
563
+ const list = graph.edges.filter((e) => typeof e.surprise === "number" && e.surprise > 0).filter((e) => opts.all || !isFrameworkOddity(byId.get(e.src), byId.get(e.dst), e.kind)).sort((a, b) => (b.surprise ?? 0) - (a.surprise ?? 0) || a.id.localeCompare(b.id)).slice(0, limit);
540
564
  if (global.json) {
541
565
  json(
542
566
  list.map((e) => ({
@@ -549,7 +573,9 @@ function registerInsights(program) {
549
573
  return;
550
574
  }
551
575
  if (!list.length) {
552
- info(`${c.cyan("vg oddities")} \xB7 none found (no cross-area links, or only one area)`);
576
+ info(
577
+ `${c.cyan("vg oddities")} \xB7 none found` + (opts.all ? " (no cross-area links, or only one area)" : " (no app-level surprises; try --all for framework links)")
578
+ );
553
579
  return;
554
580
  }
555
581
  info(`${c.cyan("vg oddities")} \xB7 top ${list.length} surprising links`);
@@ -561,6 +587,70 @@ function registerInsights(program) {
561
587
  });
562
588
  applyGlobalOptions(oddities);
563
589
  }
590
+ var FRAMEWORK_EXTERNALS = /* @__PURE__ */ new Set([
591
+ "react",
592
+ "react-dom",
593
+ "react-native",
594
+ "vue",
595
+ "vue-router",
596
+ "svelte",
597
+ "svelte/store",
598
+ "next",
599
+ "next/link",
600
+ "next/router",
601
+ "next/navigation",
602
+ "nuxt",
603
+ "angular",
604
+ "@angular/core",
605
+ "@angular/common",
606
+ "preact",
607
+ "solid-js",
608
+ "express",
609
+ "fastify",
610
+ "koa",
611
+ "hono",
612
+ "rxjs",
613
+ "lodash",
614
+ "lodash-es",
615
+ "underscore",
616
+ "jquery",
617
+ "axios",
618
+ "node:fs",
619
+ "node:path",
620
+ "node:url",
621
+ "node:http",
622
+ "node:https",
623
+ "fs",
624
+ "path",
625
+ "url",
626
+ "http",
627
+ "https",
628
+ "crypto",
629
+ "util",
630
+ "stream",
631
+ "events",
632
+ "assert",
633
+ "os",
634
+ "child_process"
635
+ ]);
636
+ function isFrameworkOddity(from, to, kind) {
637
+ if (kind !== "import") return false;
638
+ for (const n of [from, to]) {
639
+ if (n?.kind === "external" && isFrameworkName(n.qualifiedName || n.name)) return true;
640
+ }
641
+ return false;
642
+ }
643
+ function isFrameworkName(name) {
644
+ if (!name) return false;
645
+ if (FRAMEWORK_EXTERNALS.has(name)) return true;
646
+ const base = name.startsWith("@") ? name.split("/").slice(0, 2).join("/") : name.split("/")[0];
647
+ if (FRAMEWORK_EXTERNALS.has(base)) return true;
648
+ if (base.startsWith("react-") || base.startsWith("@types/react")) return true;
649
+ if (base.startsWith("@vue/") || base.startsWith("@angular/") || base.startsWith("@sveltejs/")) {
650
+ return true;
651
+ }
652
+ return false;
653
+ }
564
654
  function nodeSummary(n) {
565
655
  return {
566
656
  id: n.id,
@@ -743,8 +833,8 @@ function pad2(s, n) {
743
833
  }
744
834
  var SCHEMA_VERSION2 = "1";
745
835
  var OFFSET_FILE = "stats-share.json";
746
- var INSTALL_ID_DIR = path36.join(os.homedir(), ".vibgrate");
747
- var INSTALL_ID_FILE = path36.join(INSTALL_ID_DIR, "install-id");
836
+ var INSTALL_ID_DIR = path37.join(os.homedir(), ".vibgrate");
837
+ var INSTALL_ID_FILE = path37.join(INSTALL_ID_DIR, "install-id");
748
838
  var SEND_TIMEOUT_MS = 4e3;
749
839
  function telemetryOptOut(env = process.env) {
750
840
  const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
@@ -796,10 +886,10 @@ function statsEndpoint() {
796
886
  return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
797
887
  }
798
888
  function offsetPath(root2) {
799
- return path36.join(cacheDir(root2), OFFSET_FILE);
889
+ return path37.join(cacheDir(root2), OFFSET_FILE);
800
890
  }
801
891
  function ledgerFilePath(root2) {
802
- return path36.join(cacheDir(root2), "savings.jsonl");
892
+ return path37.join(cacheDir(root2), "savings.jsonl");
803
893
  }
804
894
  function readOffset(root2) {
805
895
  try {
@@ -970,7 +1060,7 @@ var PUBLISH_INTERVAL_MS = 2e3;
970
1060
  var KEEPALIVE_MS = 1e4;
971
1061
  var STALE_MS = 6e4;
972
1062
  function liveStatsDir(root2) {
973
- return path36.join(cacheDir(root2), "serve-live");
1063
+ return path37.join(cacheDir(root2), "serve-live");
974
1064
  }
975
1065
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
976
1066
  let entries;
@@ -984,7 +1074,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
984
1074
  if (!/^serve-\d+\.json$/.test(name)) continue;
985
1075
  let parsed;
986
1076
  try {
987
- parsed = JSON.parse(fs8.readFileSync(path36.join(dir, name), "utf8"));
1077
+ parsed = JSON.parse(fs8.readFileSync(path37.join(dir, name), "utf8"));
988
1078
  } catch {
989
1079
  continue;
990
1080
  }
@@ -1006,7 +1096,7 @@ var LiveStatsBus = class {
1006
1096
  this.dir = dir;
1007
1097
  this.stats = stats;
1008
1098
  this.pid = pid;
1009
- this.file = path36.join(dir, `serve-${this.pid}.json`);
1099
+ this.file = path37.join(dir, `serve-${this.pid}.json`);
1010
1100
  }
1011
1101
  dir;
1012
1102
  stats;
@@ -1059,7 +1149,7 @@ var LiveStatsBus = class {
1059
1149
  const out2 = [];
1060
1150
  for (const name of entries.sort()) {
1061
1151
  if (!/^serve-\d+\.json$/.test(name)) continue;
1062
- const file = path36.join(this.dir, name);
1152
+ const file = path37.join(this.dir, name);
1063
1153
  let parsed;
1064
1154
  try {
1065
1155
  parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
@@ -1487,8 +1577,8 @@ function registerServe(program) {
1487
1577
  await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
1488
1578
  } else {
1489
1579
  info(c.dim(`vg \xB7 MCP server on stdio (read-only, ${freshness}). Connect your assistant to this process.`));
1490
- await serveStdio(graphPath, serveOpts);
1491
1580
  display?.start();
1581
+ await serveStdio(graphPath, serveOpts);
1492
1582
  }
1493
1583
  });
1494
1584
  applyGlobalOptions(cmd);
@@ -1503,13 +1593,22 @@ async function ensureServableGraph(root2, graphPath, global, refresh, opts = {})
1503
1593
  { ...global, json: false }
1504
1594
  );
1505
1595
  } else {
1506
- const refreshed = await refreshIfStale(root2, { inline: opts.inline, graphPath });
1507
- if (refreshed.status === "refreshed") {
1508
- const n = driftCount(refreshed.drift);
1509
- info(c.dim(`vg \xB7 map refreshed before serving \u2014 ${n} file(s) drifted (${(refreshed.ms / 1e3).toFixed(2)}s)`));
1510
- } else if (refreshed.status === "error") {
1511
- info(c.yellow(`vg \xB7 map refresh failed (${refreshed.message}) \u2014 serving the last built map`));
1512
- }
1596
+ const kick = refreshIfStale(root2, { inline: opts.inline, graphPath }).then((refreshed) => {
1597
+ if (refreshed.status === "refreshed") {
1598
+ const n = driftCount(refreshed.drift);
1599
+ info(
1600
+ c.dim(
1601
+ `vg \xB7 map refreshed in background \u2014 ${n} file(s) drifted (${(refreshed.ms / 1e3).toFixed(2)}s)`
1602
+ )
1603
+ );
1604
+ } else if (refreshed.status === "error") {
1605
+ info(c.yellow(`vg \xB7 map refresh failed (${refreshed.message}) \u2014 serving the last built map`));
1606
+ }
1607
+ }).catch((err) => {
1608
+ const msg = err instanceof Error ? err.message : String(err);
1609
+ info(c.yellow(`vg \xB7 map refresh failed (${msg}) \u2014 serving the last built map`));
1610
+ });
1611
+ if (opts.awaitStaleRefresh) await kick;
1513
1612
  }
1514
1613
  }
1515
1614
  if (!fs8.existsSync(graphPath)) {
@@ -1574,7 +1673,7 @@ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
1574
1673
  info(c.red(`vg serve: request error: ${err.message}`));
1575
1674
  }
1576
1675
  });
1577
- await new Promise((resolve19) => httpServer.listen(port, host, resolve19));
1676
+ await new Promise((resolve20) => httpServer.listen(port, host, resolve20));
1578
1677
  info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
1579
1678
  onReady?.();
1580
1679
  await new Promise(() => {
@@ -1788,7 +1887,7 @@ function endOfLine(text, line) {
1788
1887
  }
1789
1888
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1790
1889
  function cachePath(root2) {
1791
- return path36.join(cacheDir(root2), "lsp-scan.json");
1890
+ return path37.join(cacheDir(root2), "lsp-scan.json");
1792
1891
  }
1793
1892
  function manifestHash(root2) {
1794
1893
  const files = [];
@@ -1800,7 +1899,7 @@ function manifestHash(root2) {
1800
1899
  return;
1801
1900
  }
1802
1901
  for (const entry of entries) {
1803
- const abs = path36.join(dir, entry.name);
1902
+ const abs = path37.join(dir, entry.name);
1804
1903
  if (entry.isDirectory()) {
1805
1904
  if (SKIP_DIRS.has(entry.name)) continue;
1806
1905
  walk2(abs);
@@ -1810,7 +1909,7 @@ function manifestHash(root2) {
1810
1909
  const base = entry.name.toLowerCase();
1811
1910
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1812
1911
  try {
1813
- const rel = path36.relative(root2, abs).split(path36.sep).join("/");
1912
+ const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1814
1913
  files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
1815
1914
  } catch {
1816
1915
  }
@@ -2456,12 +2555,12 @@ function uriToPath(uri) {
2456
2555
  }
2457
2556
  }
2458
2557
  function projectForFile(root2, a, filePath) {
2459
- const dir = path36.dirname(path36.resolve(filePath));
2558
+ const dir = path37.dirname(path37.resolve(filePath));
2460
2559
  let best;
2461
2560
  let bestLen = -1;
2462
2561
  for (const proj of a.projects ?? []) {
2463
- const projDir = path36.resolve(root2, proj.path);
2464
- if ((dir === projDir || dir.startsWith(projDir + path36.sep)) && projDir.length > bestLen) {
2562
+ const projDir = path37.resolve(root2, proj.path);
2563
+ if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2465
2564
  best = proj;
2466
2565
  bestLen = projDir.length;
2467
2566
  }
@@ -2469,7 +2568,7 @@ function projectForFile(root2, a, filePath) {
2469
2568
  return best;
2470
2569
  }
2471
2570
  function sameProject(location, projectPath) {
2472
- return path36.normalize(location) === path36.normalize(projectPath);
2571
+ return path37.normalize(location) === path37.normalize(projectPath);
2473
2572
  }
2474
2573
  function hasReleaseDates(a) {
2475
2574
  for (const proj of a.projects ?? []) {
@@ -2795,7 +2894,7 @@ function registerShare(program) {
2795
2894
  const cmd = program.command("share").description("make the map committable + auto-updating for your team (git)").option("--undo", "reverse what `vg share` installed").option("--reports", "also commit graph.html / GRAPH_REPORT.md (default: gitignored)").action(function(opts) {
2796
2895
  const global = readGlobal(this);
2797
2896
  const root2 = rootOf(global);
2798
- const gitDir = path36.join(root2, ".git");
2897
+ const gitDir = path37.join(root2, ".git");
2799
2898
  if (!fs8.existsSync(gitDir)) {
2800
2899
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
2801
2900
  }
@@ -2817,15 +2916,15 @@ function registerShare(program) {
2817
2916
  applyGlobalOptions(cmd);
2818
2917
  }
2819
2918
  function writeVibgrateGitignore(root2, reports) {
2820
- const dir = path36.join(root2, ".vibgrate");
2919
+ const dir = path37.join(root2, ".vibgrate");
2821
2920
  fs8.mkdirSync(dir, { recursive: true });
2822
2921
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl"];
2823
2922
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
2824
- fs8.writeFileSync(path36.join(dir, ".gitignore"), `${lines.join("\n")}
2923
+ fs8.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
2825
2924
  `);
2826
2925
  }
2827
2926
  function writeGitAttributes(root2) {
2828
- const file = path36.join(root2, ".gitattributes");
2927
+ const file = path37.join(root2, ".gitattributes");
2829
2928
  const line = ".vibgrate/graph.json merge=vg";
2830
2929
  let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
2831
2930
  if (!content.split("\n").some((l) => l.trim() === line)) {
@@ -2843,7 +2942,7 @@ function configureMergeDriver(root2) {
2843
2942
  function installPreCommitHook(root2) {
2844
2943
  const hooksDir = hookDir(root2);
2845
2944
  fs8.mkdirSync(hooksDir, { recursive: true });
2846
- const file = path36.join(hooksDir, "pre-commit");
2945
+ const file = path37.join(hooksDir, "pre-commit");
2847
2946
  const block = [
2848
2947
  HOOK_BEGIN,
2849
2948
  "if command -v vg >/dev/null 2>&1; then",
@@ -2865,14 +2964,14 @@ ${content}`;
2865
2964
  fs8.chmodSync(file, 493);
2866
2965
  }
2867
2966
  function undo(root2) {
2868
- const hookFile = path36.join(hookDir(root2), "pre-commit");
2967
+ const hookFile = path37.join(hookDir(root2), "pre-commit");
2869
2968
  if (fs8.existsSync(hookFile)) {
2870
2969
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
2871
2970
  const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
2872
2971
  if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
2873
2972
  else fs8.writeFileSync(hookFile, next2);
2874
2973
  }
2875
- const attr = path36.join(root2, ".gitattributes");
2974
+ const attr = path37.join(root2, ".gitattributes");
2876
2975
  if (fs8.existsSync(attr)) {
2877
2976
  const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
2878
2977
  fs8.writeFileSync(attr, next2);
@@ -2885,10 +2984,10 @@ function undo(root2) {
2885
2984
  function hookDir(root2) {
2886
2985
  try {
2887
2986
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
2888
- if (configured) return path36.resolve(root2, configured);
2987
+ if (configured) return path37.resolve(root2, configured);
2889
2988
  } catch {
2890
2989
  }
2891
- return path36.join(root2, ".git", "hooks");
2990
+ return path37.join(root2, ".git", "hooks");
2892
2991
  }
2893
2992
  function git(root2, args) {
2894
2993
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -2896,6 +2995,111 @@ function git(root2, args) {
2896
2995
  function escapeRe(s) {
2897
2996
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2898
2997
  }
2998
+ var DEFAULT_DEBOUNCE_MS = 400;
2999
+ var SKIP_NAME = /* @__PURE__ */ new Set([
3000
+ ".git",
3001
+ "node_modules",
3002
+ ".vibgrate",
3003
+ "dist",
3004
+ "build",
3005
+ "out",
3006
+ "coverage",
3007
+ ".next",
3008
+ "target",
3009
+ "__pycache__",
3010
+ ".venv",
3011
+ "venv"
3012
+ ]);
3013
+ function registerWatch(program) {
3014
+ const cmd = program.command("watch").description("rebuild the code map when files change (debounced)").argument("[paths...]", "folders to watch (default: current folder)").option("--debounce <ms>", "settle time after a change before rebuild", String(DEFAULT_DEBOUNCE_MS)).option("--no-html", "do not write graph.html on each rebuild").option("--no-report", "do not write GRAPH_REPORT.md on each rebuild").option("--fast", "skip precise tsc resolve on rebuilds (heuristic only)").action(async function(paths, opts) {
3015
+ const global = readGlobal(this);
3016
+ const root2 = rootOf(global);
3017
+ const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3018
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3019
+ for (const w of watchRoots) {
3020
+ if (!fs8.existsSync(w)) {
3021
+ throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3022
+ }
3023
+ }
3024
+ let building = false;
3025
+ let pending = false;
3026
+ let timer = null;
3027
+ const rebuild = async (reason) => {
3028
+ if (building) {
3029
+ pending = true;
3030
+ return;
3031
+ }
3032
+ building = true;
3033
+ try {
3034
+ info(c.dim(`vg watch \xB7 rebuild (${reason})`));
3035
+ const result = await buildGraph({
3036
+ root: root2,
3037
+ paths: paths.length ? paths : void 0,
3038
+ fast: opts.fast === true,
3039
+ noGround: false
3040
+ });
3041
+ writeArtifacts(result.graph, {
3042
+ root: root2,
3043
+ html: opts.html !== false,
3044
+ report: opts.report !== false,
3045
+ graphPath: global.graph
3046
+ });
3047
+ writeSnapshot(root2, result.graph.provenance.corpusHash, result.fileStats);
3048
+ const { counts } = result.graph.meta;
3049
+ info(
3050
+ `${c.cyan("vg watch")} \xB7 ${counts.nodes} nodes \xB7 ${counts.edges} edges \xB7 ${(result.timing.totalMs / 1e3).toFixed(2)}s` + (result.statHits ? c.dim(` \xB7 ${result.statHits} mtime hits`) : "")
3051
+ );
3052
+ } catch (err) {
3053
+ info(c.yellow(`vg watch \xB7 rebuild failed: ${err.message}`));
3054
+ } finally {
3055
+ building = false;
3056
+ if (pending) {
3057
+ pending = false;
3058
+ void rebuild("queued changes");
3059
+ }
3060
+ }
3061
+ };
3062
+ const schedule = (label) => {
3063
+ if (timer) clearTimeout(timer);
3064
+ timer = setTimeout(() => {
3065
+ timer = null;
3066
+ void rebuild(label);
3067
+ }, debounceMs);
3068
+ };
3069
+ await rebuild("initial");
3070
+ const watchers = [];
3071
+ for (const w of watchRoots) {
3072
+ try {
3073
+ const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3074
+ if (!filename) {
3075
+ schedule("change");
3076
+ return;
3077
+ }
3078
+ const parts = filename.split(path37.sep);
3079
+ if (parts.some((p) => SKIP_NAME.has(p))) return;
3080
+ if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3081
+ return;
3082
+ }
3083
+ schedule(filename);
3084
+ });
3085
+ watchers.push(watcher);
3086
+ } catch (err) {
3087
+ throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3088
+ }
3089
+ }
3090
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3091
+ await new Promise((resolve20) => {
3092
+ const stop = () => {
3093
+ for (const w of watchers) w.close();
3094
+ if (timer) clearTimeout(timer);
3095
+ resolve20();
3096
+ };
3097
+ process.once("SIGINT", stop);
3098
+ process.once("SIGTERM", stop);
3099
+ });
3100
+ });
3101
+ applyGlobalOptions(cmd);
3102
+ }
2899
3103
  function registerTests(program) {
2900
3104
  const cmd = program.command("tests").description("which tests cover a node (call/coverage linkage)").argument("<name>", "node to inspect").option("--missing", "show untested nodes nearby instead").option("--run", "print the command to run exactly these tests").option("--exec", "run that command").option("--pick <n>", "pick the nth candidate when ambiguous").action(function(name, opts) {
2901
3105
  const global = readGlobal(this);
@@ -2951,8 +3155,17 @@ function registerFacts(program) {
2951
3155
  const { node: node2, candidates } = resolveOne(graph, name, opts.pick ? Number(opts.pick) : void 0);
2952
3156
  if (!node2) throw ambiguityError(`"${name}" ${candidates.length ? "is ambiguous" : "not found"}`, candidates);
2953
3157
  if (!graph.facts) {
2954
- if (global.json) json({ node: node2.qualifiedName, facts: [], note: "facts require a --deep build" });
2955
- else info(`${c.cyan("vg facts")} \xB7 run ${c.bold("vg --deep")} to derive facts (none in this map)`);
3158
+ if (global.json) {
3159
+ json({
3160
+ node: node2.qualifiedName,
3161
+ facts: [],
3162
+ note: "map has no facts \u2014 rebuild with a current vg (facts ship on every build)"
3163
+ });
3164
+ } else {
3165
+ info(
3166
+ `${c.cyan("vg facts")} \xB7 none in this map \u2014 rebuild with ${c.bold("vg")} (facts ship on every build)`
3167
+ );
3168
+ }
2956
3169
  return;
2957
3170
  }
2958
3171
  const facts = graph.facts.filter((f) => f.subjectIds.includes(node2.id));
@@ -3207,7 +3420,7 @@ function normalizeStandards(raw) {
3207
3420
  }
3208
3421
  function loadStandards(root2) {
3209
3422
  for (const rel of STANDARDS_FILES) {
3210
- const p = path36__default.join(root2, rel);
3423
+ const p = path37__default.join(root2, rel);
3211
3424
  let text;
3212
3425
  try {
3213
3426
  text = fs8__default.readFileSync(p, "utf8");
@@ -3330,166 +3543,6 @@ function toEstimateJson(e) {
3330
3543
  guessed: e.guessed
3331
3544
  };
3332
3545
  }
3333
-
3334
- // src/runtime/model-install-plan.ts
3335
- var MODEL_INSTALL_PLAN_SCHEMA_VERSION = "model-install-plan/0";
3336
- function runtimeDepsForBackend(backend) {
3337
- const b = backend.toLowerCase();
3338
- if (b === "llama.cpp" || b === "llama-cpp" || b === "vibgrate") {
3339
- return [
3340
- {
3341
- id: "node-llama-cpp",
3342
- kind: "npm-runtime",
3343
- spec: "node-llama-cpp@^3",
3344
- reason: "in-process llama.cpp binding for the first-party / llama-cpp provider"
3345
- }
3346
- ];
3347
- }
3348
- if (b === "ollama") {
3349
- return [
3350
- {
3351
- id: "ollama",
3352
- kind: "native-binary",
3353
- binary: "ollama",
3354
- reason: "Ollama on PATH (install from https://ollama.com \u2014 third-party apps are not auto-installed)"
3355
- }
3356
- ];
3357
- }
3358
- return [];
3359
- }
3360
- function weightsChannelForBackend(backend, opts) {
3361
- const b = backend.toLowerCase();
3362
- if (b === "ollama") return "ollama";
3363
- if (b === "llama.cpp" || b === "llama-cpp" || b === "vibgrate") {
3364
- if (opts?.downloadUrl || opts?.weightsRef && lookupCatalog(opts.weightsRef)) return "vibgrate";
3365
- return "local-path";
3366
- }
3367
- if (b === "lm-studio" || b === "lmstudio" || b === "foundry-local") return "manual";
3368
- return "manual";
3369
- }
3370
- function weightsInstalled(ref, installedNames) {
3371
- const want = ref.toLowerCase();
3372
- return installedNames.some((n) => {
3373
- const have = n.toLowerCase();
3374
- return have === want || have.includes(want) || want.includes(have);
3375
- });
3376
- }
3377
- function buildModelInstallPlan(input) {
3378
- const hasBinary2 = input.hasBinary ?? (() => false);
3379
- const pkgInstalled = input.isPackageInstalled ?? isPackageInstalled;
3380
- const installedNames = input.installedNames ?? [];
3381
- const offline = !!input.offline;
3382
- const backend = input.backend;
3383
- const provider = providerLabel(backend);
3384
- const runtimeDeps = runtimeDepsForBackend(backend).map((dep) => {
3385
- if (dep.kind === "npm-runtime" && dep.spec) {
3386
- return { ...dep, status: pkgInstalled(dep.spec) ? "satisfied" : "missing" };
3387
- }
3388
- if (dep.kind === "native-binary" && dep.binary) {
3389
- return { ...dep, status: hasBinary2(dep.binary) ? "satisfied" : "unmanaged" };
3390
- }
3391
- return { ...dep, status: "unmanaged" };
3392
- });
3393
- const channel = weightsChannelForBackend(backend, {
3394
- downloadUrl: input.downloadUrl,
3395
- weightsRef: input.weightsRef
3396
- });
3397
- const weightCached = (input.isWeightCached ?? isWeightCached)(input.weightsRef);
3398
- const catalog = lookupCatalog(input.weightsRef);
3399
- const downloadUrl = input.downloadUrl ?? catalog?.url;
3400
- let weightsStatus = "missing";
3401
- if (channel === "ollama") {
3402
- weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? "satisfied" : "missing";
3403
- } else if (channel === "vibgrate") {
3404
- weightsStatus = weightCached || weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath ? "satisfied" : "missing";
3405
- } else if (channel === "local-path") {
3406
- weightsStatus = weightsInstalled(input.weightsRef, installedNames) || !!input.modelPath || weightCached ? "satisfied" : "manual";
3407
- } else {
3408
- weightsStatus = weightsInstalled(input.weightsRef, installedNames) ? "satisfied" : "manual";
3409
- }
3410
- const alreadySatisfied = [];
3411
- const willInstall = [];
3412
- const willDownload = [];
3413
- const blocked = [];
3414
- for (const dep of runtimeDeps) {
3415
- if (dep.status === "satisfied") {
3416
- alreadySatisfied.push(dep.id);
3417
- continue;
3418
- }
3419
- if (dep.kind === "npm-runtime" && dep.spec && dep.status === "missing") {
3420
- if (offline) {
3421
- blocked.push({ id: dep.id, reason: `${dep.spec} needed but --local/offline forbids install` });
3422
- } else {
3423
- willInstall.push(dep.spec);
3424
- }
3425
- continue;
3426
- }
3427
- if (dep.kind === "native-binary" && dep.status === "unmanaged") {
3428
- blocked.push({
3429
- id: dep.id,
3430
- reason: dep.reason
3431
- });
3432
- }
3433
- }
3434
- if (weightsStatus === "satisfied") {
3435
- alreadySatisfied.push(`weights:${input.weightsRef}`);
3436
- } else if (weightsStatus === "missing" && (channel === "ollama" || channel === "vibgrate")) {
3437
- if (offline) {
3438
- blocked.push({ id: `weights:${input.weightsRef}`, reason: "weights missing and --local/offline forbids download" });
3439
- } else if (channel === "ollama" && runtimeDeps.some((d) => d.id === "ollama" && d.status === "unmanaged")) {
3440
- willDownload.push(input.weightsRef);
3441
- } else if (channel === "vibgrate" && !downloadUrl) {
3442
- blocked.push({
3443
- id: `weights:${input.weightsRef}`,
3444
- reason: `no first-party download URL for ${input.weightsRef} \u2014 place a gguf in the weight store or pass --model-path`
3445
- });
3446
- } else {
3447
- willDownload.push(input.weightsRef);
3448
- }
3449
- } else if (weightsStatus === "manual" || weightsStatus === "missing") {
3450
- blocked.push({
3451
- id: `weights:${input.weightsRef}`,
3452
- reason: channel === "local-path" ? `point --model-path at a local gguf for ${input.weightsRef}, or run install when a first-party URL is catalogued` : `install or link weights for ${input.weightsRef} via the backend app`
3453
- });
3454
- }
3455
- const effectiveWillInstall = offline ? [] : willInstall;
3456
- const effectiveWillDownload = offline ? [] : willDownload;
3457
- const offlineBlocked = offline && blocked.some((b) => /offline|forbids/i.test(b.reason));
3458
- const allRuntimeOk = runtimeDeps.every((d) => d.status === "satisfied");
3459
- const fullyReady = allRuntimeOk && weightsStatus === "satisfied" && blocked.length === 0;
3460
- return {
3461
- schemaVersion: MODEL_INSTALL_PLAN_SCHEMA_VERSION,
3462
- provider,
3463
- backend,
3464
- model: input.weightsRef,
3465
- mode: input.mode,
3466
- packId: input.packId,
3467
- license: input.license,
3468
- promise: input.promise,
3469
- fit: input.fit,
3470
- runtimeDeps,
3471
- weights: {
3472
- channel,
3473
- ref: input.weightsRef,
3474
- status: weightsStatus,
3475
- downloadUrl: channel === "vibgrate" ? downloadUrl : void 0
3476
- },
3477
- alreadySatisfied,
3478
- willInstall: effectiveWillInstall,
3479
- willDownload: effectiveWillDownload,
3480
- blocked,
3481
- offlineBlocked,
3482
- ready: fullyReady
3483
- };
3484
- }
3485
- function providerLabel(backend) {
3486
- const b = backend.toLowerCase();
3487
- if (b === "llama.cpp" || b === "llama-cpp") return "llama-cpp";
3488
- if (b === "vibgrate") return "vibgrate";
3489
- if (b === "lm-studio" || b === "lmstudio") return "lmstudio";
3490
- if (b === "foundry-local") return "foundry-local";
3491
- return b === "ollama" ? "ollama" : backend;
3492
- }
3493
3546
  async function executeModelInstallPlan(plan, options = {}) {
3494
3547
  const installedDeps = [];
3495
3548
  const pulledWeights = [];
@@ -4083,8 +4136,8 @@ async function runHostBench(options = {}) {
4083
4136
  }
4084
4137
  async function runArmSimulate(input) {
4085
4138
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4086
- const path38 = `${modelPath}#${arm.id}`;
4087
- const session = await acquireHostSession(lib, path38);
4139
+ const path39 = `${modelPath}#${arm.id}`;
4140
+ const session = await acquireHostSession(lib, path39);
4088
4141
  const system = "You are a coding agent with a Task Capsule.";
4089
4142
  const capsule = "function readConfig(): Config { return load(); }";
4090
4143
  let last = null;
@@ -5026,7 +5079,7 @@ function registerModels(program) {
5026
5079
  );
5027
5080
  });
5028
5081
  applyGlobalOptions(modeCmd);
5029
- const resolve19 = cmd.command("resolve").description("resolve a Code Mode to pack + underlying model + fit (no download)").argument("[mode]", "spark | flow | forge (default: auto-fit or configured default)").action(function(modeArg) {
5082
+ const resolve20 = cmd.command("resolve").description("resolve a Code Mode to pack + underlying model + fit (no download)").argument("[mode]", "spark | flow | forge (default: auto-fit or configured default)").action(function(modeArg) {
5030
5083
  const global = readGlobal(this);
5031
5084
  const root2 = rootOf(global);
5032
5085
  const sys = gatherSystemMemory();
@@ -5058,7 +5111,7 @@ function registerModels(program) {
5058
5111
  info(c.yellow(" will not fit \u2014 choose a lower mode or free memory before loading"));
5059
5112
  }
5060
5113
  });
5061
- applyGlobalOptions(resolve19);
5114
+ applyGlobalOptions(resolve20);
5062
5115
  const installCmd = cmd.command("install").description("resolve the best Code Mode for this machine and install the pack").argument("[mode]", "spark | flow | forge (default: auto-fit)").option("--dry-run", "print the install plan only \u2014 do not download").option("--yes", "skip prompts (install already runs by default)").action(async function(modeArg, opts) {
5063
5116
  const global = readGlobal(this);
5064
5117
  const root2 = rootOf(global);
@@ -5396,8 +5449,8 @@ function registerModels(program) {
5396
5449
  }
5397
5450
  });
5398
5451
  if (opts.out) {
5399
- const outPath = path36.resolve(opts.out);
5400
- fs8.mkdirSync(path36.dirname(outPath), { recursive: true });
5452
+ const outPath = path37.resolve(opts.out);
5453
+ fs8.mkdirSync(path37.dirname(outPath), { recursive: true });
5401
5454
  fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5402
5455
  `);
5403
5456
  if (!global.json) info(c.dim(` wrote ${outPath}`));
@@ -5508,11 +5561,11 @@ function fitColor(label) {
5508
5561
  return label;
5509
5562
  }
5510
5563
  function confirmYesNo(question) {
5511
- return new Promise((resolve19) => {
5564
+ return new Promise((resolve20) => {
5512
5565
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
5513
5566
  rl.question(`${question} [y/N] `, (answer) => {
5514
5567
  rl.close();
5515
- resolve19(/^y(es)?$/i.test(answer.trim()));
5568
+ resolve20(/^y(es)?$/i.test(answer.trim()));
5516
5569
  });
5517
5570
  });
5518
5571
  }
@@ -5538,7 +5591,7 @@ function printBackends(backends) {
5538
5591
  }
5539
5592
  }
5540
5593
  function codeConfigPath(root2) {
5541
- return path36.join(root2, ".vibgrate", "code.json");
5594
+ return path37.join(root2, ".vibgrate", "code.json");
5542
5595
  }
5543
5596
  function loadCodeConfig(root2) {
5544
5597
  try {
@@ -5620,7 +5673,7 @@ function discoverMcpServers(root2, ownServers) {
5620
5673
  const servers = {};
5621
5674
  const sources = [];
5622
5675
  for (const rel of MCP_CONFIG_FILES) {
5623
- const found = readMcpServersFile(path36.join(root2, rel));
5676
+ const found = readMcpServersFile(path37.join(root2, rel));
5624
5677
  const names = Object.keys(found);
5625
5678
  if (names.length) {
5626
5679
  sources.push(rel);
@@ -5643,11 +5696,13 @@ function registerCode(program) {
5643
5696
  let provider = opts.provider ?? config.provider;
5644
5697
  let model = opts.model ?? config.model;
5645
5698
  const modeFlag = opts.mode ?? config.modelProfile?.mode;
5646
- if (!opts.model && !opts.modelPath && (modeFlag || !provider && !model)) {
5699
+ let codeModeActive = false;
5700
+ const customSelection = !!(opts.provider || opts.model || opts.modelPath || config.provider || config.model);
5701
+ if (!customSelection && (modeFlag || !provider && !model)) {
5647
5702
  try {
5648
- const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2, providerForBackend: providerForBackend2 } = await import('./model-orchestrator-TVONAUPS.js');
5703
+ const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-4VSYP4J4.js');
5649
5704
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-5O2NN3GA.js');
5650
- const { loadGraph: loadGraph2 } = await import('./load-I333TGNI.js');
5705
+ const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
5651
5706
  const state = readOrchestratorState2();
5652
5707
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
5653
5708
  const pin = mode ? activePin2(mode, state) : null;
@@ -5676,26 +5731,31 @@ function registerCode(program) {
5676
5731
  ExitCode.ERROR
5677
5732
  );
5678
5733
  }
5679
- const { resolveGgufPath } = await import('./resolve-gguf-VPL4YQ6J.js');
5734
+ const { resolveGgufPath } = await import('./resolve-gguf-Y6FH3CNB.js');
5735
+ const primaryRef = resolved.pack.primary.backend === "llama.cpp" ? resolved.pack.primary.weightsRef : resolved.underlying.weightsRef;
5680
5736
  const gguf = resolveGgufPath({
5681
- modelRef: resolved.underlying.weightsRef,
5737
+ modelRef: primaryRef,
5682
5738
  modelPath: opts.modelPath
5683
5739
  }) ?? resolveGgufPath({
5684
- modelRef: resolved.pack.primary.backend === "llama.cpp" ? resolved.pack.primary.weightsRef : void 0
5740
+ modelRef: resolved.underlying.weightsRef,
5741
+ modelPath: opts.modelPath
5685
5742
  });
5686
- if (gguf && !opts.provider) {
5743
+ if (!gguf && !opts.mock) {
5744
+ throw new CliError(
5745
+ `Code Mode ${resolved.mode} uses the Vibgrate model manager \u2014 weights not installed. Run \`vg models install ${resolved.mode}\` then retry. (Custom Ollama/LM Studio: pass --provider explicitly.)`,
5746
+ ExitCode.NOT_FOUND
5747
+ );
5748
+ }
5749
+ if (gguf) {
5750
+ codeModeActive = true;
5687
5751
  provider = "llama-cpp";
5688
- model = model ?? gguf.ref ?? resolved.underlying.weightsRef;
5752
+ model = model ?? gguf.ref ?? primaryRef;
5689
5753
  opts.modelPath = gguf.path;
5690
5754
  if (!global.json && !global.quiet && !opts.streamJson) {
5691
5755
  info(
5692
- `${c.cyan("vg code")} \xB7 Code Mode ${c.bold(resolved.mode)} \u2192 embedded llama.cpp ${c.dim(gguf.path)} ${c.dim(`(${resolved.fit.label})`)}`
5756
+ `${c.cyan("vg code")} \xB7 Code Mode ${c.bold(resolved.mode)} \u2192 Vibgrate manager ${c.dim(gguf.path)} ${c.dim(`(${resolved.fit.label})`)}`
5693
5757
  );
5694
5758
  }
5695
- } else {
5696
- const ollamaFb = resolved.underlying.backend === "ollama" ? resolved.underlying : resolved.pack.fallback?.find((f) => f.backend === "ollama") ?? resolved.underlying;
5697
- provider = provider ?? providerForBackend2(ollamaFb.backend);
5698
- model = model ?? ollamaFb.weightsRef;
5699
5759
  }
5700
5760
  if (!config.modelProfile?.capsuleBudgetTokens) {
5701
5761
  config.modelProfile = {
@@ -5709,11 +5769,6 @@ function registerCode(program) {
5709
5769
  } else if (!config.modelProfile?.mode) {
5710
5770
  config.modelProfile = { ...config.modelProfile, mode: resolved.mode };
5711
5771
  }
5712
- if (!global.json && !global.quiet && !opts.streamJson && provider !== "llama-cpp") {
5713
- info(
5714
- `${c.cyan("vg code")} \xB7 Code Mode ${c.bold(resolved.mode)} \u2192 ${resolved.underlying.weightsRef} ${c.dim(`(${resolved.fit.label})`)}`
5715
- );
5716
- }
5717
5772
  } catch (e) {
5718
5773
  if (e instanceof CliError) throw e;
5719
5774
  if (!provider && !model && !opts.mock) throw e;
@@ -5731,7 +5786,7 @@ function registerCode(program) {
5731
5786
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
5732
5787
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
5733
5788
  }
5734
- const { runInteractive } = await import('./interactive-372NLI5C.js');
5789
+ const { runInteractive } = await import('./interactive-SMHVURYK.js');
5735
5790
  await runInteractive(
5736
5791
  rootOf(global),
5737
5792
  global,
@@ -5775,28 +5830,52 @@ function registerCode(program) {
5775
5830
  model,
5776
5831
  modelPath: opts.modelPath,
5777
5832
  local: global.local,
5778
- consent: opts.yes,
5779
- mockReply
5833
+ consent: opts.yes || codeModeActive || customSelection,
5834
+ mockReply,
5835
+ codeMode: codeModeActive,
5836
+ preferEmbedded: codeModeActive || void 0
5780
5837
  },
5781
5838
  {}
5782
5839
  );
5840
+ if (!opts.mock && route.providers[0]) {
5841
+ const { ensureManagerRuntime } = await import('./model-manager-PN7HEDXD.js');
5842
+ const ensure = await ensureManagerRuntime({
5843
+ providerId: route.providers[0].id,
5844
+ model: route.providers[0].model,
5845
+ offline: !!global.local,
5846
+ // Code Mode / explicit custom selection / --yes count as consent for
5847
+ // npm runtime deps (and ollama pull when the binary is already present).
5848
+ consent: !!(opts.yes || codeModeActive || customSelection || process.stdin.isTTY),
5849
+ onProgress: (line) => {
5850
+ if (!global.json && !global.quiet && !opts.streamJson) info(c.dim(` ${line}`));
5851
+ }
5852
+ });
5853
+ if (!ensure.ok) {
5854
+ throw new CliError(ensure.error ?? "model manager runtime not ready", ExitCode.ERROR);
5855
+ }
5856
+ if (!global.json && !global.quiet && !opts.streamJson && (ensure.installed.length || ensure.pulled.length)) {
5857
+ for (const s of ensure.installed) info(c.dim(` installed ${s}`));
5858
+ for (const s of ensure.pulled) info(c.dim(` pulled ${s}`));
5859
+ }
5860
+ }
5783
5861
  if (!global.json && !global.quiet) {
5784
5862
  info(`${c.cyan("vg code")} \xB7 ${c.dim(route.reason)}`);
5863
+ info(`${c.cyan("vg code")} \xB7 manager ${c.bold(route.managerLine)}`);
5785
5864
  }
5786
5865
  if (opts.streamJson && !opts.mock) {
5787
5866
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
5788
- const { runCodeStreamJson } = await import('./stream-json-SLMDKLXP.js');
5789
- const { nodeCodeFs } = await import('./session-ITPYQ5XI.js');
5867
+ const { runCodeStreamJson } = await import('./stream-json-X7UQFB4T.js');
5868
+ const { nodeCodeFs } = await import('./session-W3646AOV.js');
5790
5869
  const readline5 = await import('readline');
5791
5870
  const child = await import('child_process');
5792
5871
  const { loadOrDiscoverFederation } = await import('./federation-SZWZIFZ7.js');
5793
5872
  const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
5794
5873
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-TFBKCNJG.js');
5795
- const { startCodeRuntimeSession } = await import('./runtime-session-JRKCQUHY.js');
5796
- const { resolveGraphBackend } = await import('./graph-backend-73URGTFY.js');
5874
+ const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
5875
+ const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
5797
5876
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
5798
5877
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
5799
- const { vgdRequest: vgdRequest2 } = await import('./vgd-7JV5KCNJ.js');
5878
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
5800
5879
  const federation = loadOrDiscoverFederation(root2);
5801
5880
  const modelProfile = mergeModelExecutionProfile(
5802
5881
  resolveModelExecutionProfile({
@@ -5885,8 +5964,8 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
5885
5964
  if (!autonomous && !tty) {
5886
5965
  throw usageError("the agent approves each edit/command \u2014 run in a terminal to approve interactively, or pass --auto to run autonomously (or --single for a one-shot diff).");
5887
5966
  }
5888
- const { agentTask } = await import('./interactive-372NLI5C.js');
5889
- const { nodeCodeFs } = await import('./session-ITPYQ5XI.js');
5967
+ const { agentTask } = await import('./interactive-SMHVURYK.js');
5968
+ const { nodeCodeFs } = await import('./session-W3646AOV.js');
5890
5969
  const { TtyPrompter } = await import('./ui-Q6DJ3GCU.js');
5891
5970
  let priorSummary;
5892
5971
  if (opts.continue) {
@@ -5908,11 +5987,11 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
5908
5987
  const { loadFederation } = await import('./federation-SZWZIFZ7.js');
5909
5988
  const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
5910
5989
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-TFBKCNJG.js');
5911
- const { startCodeRuntimeSession } = await import('./runtime-session-JRKCQUHY.js');
5912
- const { resolveGraphBackend } = await import('./graph-backend-73URGTFY.js');
5990
+ const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
5991
+ const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
5913
5992
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
5914
5993
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
5915
- const { vgdRequest: vgdRequest2 } = await import('./vgd-7JV5KCNJ.js');
5994
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
5916
5995
  const federation = loadFederation(root2);
5917
5996
  const modelProfile = mergeModelExecutionProfile(
5918
5997
  resolveModelExecutionProfile({
@@ -6056,11 +6135,11 @@ function resolveSecurityTierFlag(flag, fromConfig, auto) {
6056
6135
  return auto ? "L1" : "L0";
6057
6136
  }
6058
6137
  function confirm(question) {
6059
- return new Promise((resolve19) => {
6138
+ return new Promise((resolve20) => {
6060
6139
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
6061
6140
  rl.question(`${question} [y/N] `, (answer) => {
6062
6141
  rl.close();
6063
- resolve19(/^y(es)?$/i.test(answer.trim()));
6142
+ resolve20(/^y(es)?$/i.test(answer.trim()));
6064
6143
  });
6065
6144
  });
6066
6145
  }
@@ -6217,7 +6296,7 @@ async function addCmd(root2, rest, opts, asJson) {
6217
6296
  }
6218
6297
  function readPackageVersion(root2) {
6219
6298
  try {
6220
- const pkg = JSON.parse(fs8__default.readFileSync(path36__default.join(root2, "package.json"), "utf8"));
6299
+ const pkg = JSON.parse(fs8__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
6221
6300
  return typeof pkg.version === "string" ? pkg.version : void 0;
6222
6301
  } catch {
6223
6302
  return void 0;
@@ -6240,8 +6319,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
6240
6319
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
6241
6320
  const version = (opts.version || readPackageVersion(root2) || "").trim();
6242
6321
  if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
6243
- const readme = readOptionalFile(opts.readme ? path36__default.resolve(opts.readme) : path36__default.join(root2, "README.md"));
6244
- const dts = opts.dts ? readOptionalFile(path36__default.resolve(opts.dts)) : void 0;
6322
+ const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6323
+ const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
6245
6324
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
6246
6325
  const result = await publishPrivateLibrary(
6247
6326
  { name, version, readme, dts, language: opts.language },
@@ -6354,7 +6433,7 @@ async function showCmd(root2, name, budget, asJson, opts = {}) {
6354
6433
  out(doc);
6355
6434
  }
6356
6435
  function registerExport(program) {
6357
- const cmd = program.command("export").description("export the map (format inferred: json|ndjson|graphml|dot|cypher|sql|md|html|cdx.json|spdx.json)").argument("[file]", "target file (or - for stdout)", "map.json").action(function(file) {
6436
+ const cmd = program.command("export").description("export the map (format inferred: json|ndjson|graphml|dot|cypher|sql|md|html|cdx.json|spdx.json)").argument("[file]", "target file (or - for stdout)", "map.json").option("--compact", "compact JSON (no pretty-print; auto for large maps)").option("--slim", "drop heavy fields (area member lists, grounding) for smaller exports").action(function(file, opts) {
6358
6437
  const global = readGlobal(this);
6359
6438
  const { graph } = requireGraph(global);
6360
6439
  const root2 = rootOf(global);
@@ -6365,13 +6444,15 @@ function registerExport(program) {
6365
6444
  graph,
6366
6445
  deps: needsDeps ? inventory(root2).records : void 0,
6367
6446
  models: needsDeps && !global.local ? discoverModels() : void 0,
6368
- generatedAt: graph.generatedAt
6447
+ generatedAt: graph.generatedAt,
6448
+ compact: opts.compact === true ? true : opts.compact === false ? false : void 0,
6449
+ slim: opts.slim === true
6369
6450
  });
6370
6451
  if (file === "-") {
6371
6452
  out(content.trimEnd());
6372
6453
  return;
6373
6454
  }
6374
- fs8.mkdirSync(path36.dirname(path36.resolve(file)), { recursive: true });
6455
+ fs8.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
6375
6456
  fs8.writeFileSync(file, content);
6376
6457
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
6377
6458
  });
@@ -6382,37 +6463,37 @@ function detectFormat(file) {
6382
6463
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
6383
6464
  if (lower.endsWith(".spdx.json")) return "spdx";
6384
6465
  if (file === "-") return "json";
6385
- return formatForExt(path36.extname(file));
6466
+ return formatForExt(path37.extname(file));
6386
6467
  }
6387
6468
  function registerBundle(program) {
6388
6469
  const cmd = program.command("bundle").description("build an air-gapped bundle (grammars + graph + library catalog)").option("--offline", "offline bundle (default; present for clarity)").option("-o, --out <dir>", "output directory", "vg-bundle").action(function(opts) {
6389
6470
  const global = readGlobal(this);
6390
6471
  const root2 = rootOf(global);
6391
- const outDir = path36.resolve(root2, opts.out ?? "vg-bundle");
6472
+ const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
6392
6473
  let grammarFiles;
6393
6474
  try {
6394
6475
  grammarFiles = resolvedGrammarFiles();
6395
6476
  } catch {
6396
6477
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
6397
6478
  }
6398
- fs8.mkdirSync(path36.join(outDir, "grammars"), { recursive: true });
6479
+ fs8.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
6399
6480
  let grammarCount = 0;
6400
6481
  for (const { fileName, absPath } of grammarFiles) {
6401
- fs8.copyFileSync(absPath, path36.join(outDir, "grammars", fileName));
6482
+ fs8.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
6402
6483
  grammarCount++;
6403
6484
  }
6404
6485
  const included = [`grammars/ (${grammarCount} .wasm)`];
6405
6486
  const graphSrc = resolveGraphPath(root2, global.graph);
6406
6487
  if (fs8.existsSync(graphSrc)) {
6407
- fs8.copyFileSync(graphSrc, path36.join(outDir, "graph.json"));
6488
+ fs8.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
6408
6489
  included.push("graph.json");
6409
6490
  }
6410
6491
  const cat = catalogPath(root2);
6411
6492
  if (fs8.existsSync(cat)) {
6412
- fs8.copyFileSync(cat, path36.join(outDir, "vibgrate.lib.json"));
6493
+ fs8.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
6413
6494
  included.push("vibgrate.lib.json");
6414
6495
  if (fs8.existsSync(libDir(root2))) {
6415
- fs8.cpSync(libDir(root2), path36.join(outDir, "lib"), { recursive: true });
6496
+ fs8.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
6416
6497
  included.push("lib/");
6417
6498
  }
6418
6499
  }
@@ -6424,15 +6505,15 @@ function registerBundle(program) {
6424
6505
  included,
6425
6506
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
6426
6507
  };
6427
- fs8.writeFileSync(path36.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
6508
+ fs8.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
6428
6509
  `);
6429
6510
  if (global.json) {
6430
- json({ out: path36.relative(root2, outDir), ...manifest });
6511
+ json({ out: path37.relative(root2, outDir), ...manifest });
6431
6512
  return;
6432
6513
  }
6433
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path36.relative(root2, outDir)}/`);
6514
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
6434
6515
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
6435
- info(c.dim(` offline: vg build --grammars "${path36.relative(root2, outDir)}/grammars"`));
6516
+ info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
6436
6517
  });
6437
6518
  applyGlobalOptions(cmd);
6438
6519
  }
@@ -6450,7 +6531,7 @@ async function runDoctor(global) {
6450
6531
  const root2 = rootOf(global);
6451
6532
  const local = global.local === true;
6452
6533
  const graphPath = resolveGraphPath(root2, global.graph);
6453
- const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path36.join(root2, f))) ?? null;
6534
+ const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path37.join(root2, f))) ?? null;
6454
6535
  const graph = loadGraph(root2, graphPath);
6455
6536
  let staleFiles = null;
6456
6537
  if (graph) {
@@ -6476,13 +6557,13 @@ async function runDoctor(global) {
6476
6557
  root: root2,
6477
6558
  configFile,
6478
6559
  map: {
6479
- path: path36.relative(root2, graphPath),
6560
+ path: path37.relative(root2, graphPath),
6480
6561
  built: graph !== null,
6481
6562
  generatedAt: graph?.generatedAt ?? null,
6482
6563
  staleFiles
6483
6564
  },
6484
6565
  libCatalog: {
6485
- path: path36.relative(root2, catalogPath(root2)),
6566
+ path: path37.relative(root2, catalogPath(root2)),
6486
6567
  present: fs8.existsSync(catalogPath(root2)),
6487
6568
  libraries: libCount
6488
6569
  },
@@ -6540,7 +6621,7 @@ async function runDoctor(global) {
6540
6621
  );
6541
6622
  info(
6542
6623
  ` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
6543
- ` \xB7 last ${path36.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
6624
+ ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
6544
6625
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
6545
6626
  );
6546
6627
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -6676,7 +6757,7 @@ function registerDaemon(program) {
6676
6757
  const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
6677
6758
  const global = readGlobal(this);
6678
6759
  const socketPath = socketOf(this);
6679
- const root2 = path36.resolve(rootArg ?? rootOf(global));
6760
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
6680
6761
  if (!await vgdIsRunning({ socketPath })) {
6681
6762
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
6682
6763
  }
@@ -6712,7 +6793,7 @@ function registerDaemon(program) {
6712
6793
  const federation = cmd.command("federation").description("register a multi-root federation from .vibgrate/federation.json (or primary cwd)").argument("[root]", "primary repository root (default: cwd)").action(async function(rootArg) {
6713
6794
  const global = readGlobal(this);
6714
6795
  const socketPath = socketOf(this);
6715
- const primary = path36.resolve(rootArg ?? rootOf(global));
6796
+ const primary = path37.resolve(rootArg ?? rootOf(global));
6716
6797
  if (!await vgdIsRunning({ socketPath })) {
6717
6798
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
6718
6799
  }
@@ -6740,11 +6821,11 @@ function registerDaemon(program) {
6740
6821
  const publish = cmd.command("publish").description("load the workspace code map into vgd ActiveGraph (from global/legacy store)").argument("[root]", "repository root (default: cwd)").option("--git-ref <ref>", "branch or SHA (default: detect HEAD)").action(async function(rootArg) {
6741
6822
  const global = readGlobal(this);
6742
6823
  const socketPath = socketOf(this);
6743
- const root2 = path36.resolve(rootArg ?? rootOf(global));
6824
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
6744
6825
  if (!await vgdIsRunning({ socketPath })) {
6745
6826
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
6746
6827
  }
6747
- const { loadGraph: loadGraph2 } = await import('./load-I333TGNI.js');
6828
+ const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
6748
6829
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
6749
6830
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
6750
6831
  const opts = this.opts();
@@ -6860,7 +6941,7 @@ function socketOf(cmd) {
6860
6941
  let c2 = cmd;
6861
6942
  while (c2) {
6862
6943
  const opts = c2.opts();
6863
- if (opts.socket) return path36.resolve(opts.socket);
6944
+ if (opts.socket) return path37.resolve(opts.socket);
6864
6945
  c2 = c2.parent;
6865
6946
  }
6866
6947
  return vgdSocketPath();
@@ -7077,11 +7158,11 @@ function registerLlmHost(program) {
7077
7158
  applyGlobalOptions(cmd);
7078
7159
  }
7079
7160
  var initCommand = new Command("init").description("Initialize vibgrate in a project").argument("[path]", "Path to initialize", ".").option("--baseline", "Create initial baseline after init").option("--yes", "Skip confirmation prompts").action(async (targetPath, opts) => {
7080
- const rootDir = path36.resolve(targetPath);
7081
- const vibgrateDir2 = path36.join(rootDir, ".vibgrate");
7161
+ const rootDir = path37.resolve(targetPath);
7162
+ const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7082
7163
  await ensureDir(vibgrateDir2);
7083
7164
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7084
- const configPath = path36.join(rootDir, "vibgrate.config.ts");
7165
+ const configPath = path37.join(rootDir, "vibgrate.config.ts");
7085
7166
  if (await pathExists(configPath)) {
7086
7167
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7087
7168
  } else {
@@ -7089,7 +7170,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7089
7170
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7090
7171
  }
7091
7172
  if (opts.baseline) {
7092
- const { runBaseline } = await import('./baseline-TG4ATZGZ.js');
7173
+ const { runBaseline } = await import('./baseline-ENCOSJYQ.js');
7093
7174
  await runBaseline(rootDir);
7094
7175
  }
7095
7176
  console.log("");
@@ -7192,16 +7273,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
7192
7273
  };
7193
7274
  }
7194
7275
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
7195
- const content = await readFile3(path36.join(rootDir, relFile));
7276
+ const content = await readFile3(path37.join(rootDir, relFile));
7196
7277
  if (!content) return false;
7197
7278
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7198
7279
  return new RegExp(`\\b${escaped}\\b`).test(content);
7199
7280
  }
7200
7281
  async function defaultReadFile(absPath) {
7201
7282
  try {
7202
- const stat2 = await fs20.stat(absPath);
7283
+ const stat2 = await fs21.stat(absPath);
7203
7284
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
7204
- return await fs20.readFile(absPath, "utf8");
7285
+ return await fs21.readFile(absPath, "utf8");
7205
7286
  } catch {
7206
7287
  return null;
7207
7288
  }
@@ -7386,7 +7467,7 @@ var AI_ASSISTANT_DETECTORS = [
7386
7467
  async function detectAiAssistant(rootDir) {
7387
7468
  for (const detector of AI_ASSISTANT_DETECTORS) {
7388
7469
  for (const file of detector.files) {
7389
- if (await pathExists$1(path36.join(rootDir, file))) {
7470
+ if (await pathExists$1(path37.join(rootDir, file))) {
7390
7471
  return detector.name;
7391
7472
  }
7392
7473
  }
@@ -7579,7 +7660,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
7579
7660
  collectExcludes,
7580
7661
  []
7581
7662
  ).option("--concurrency <n>", "Max concurrent npm calls", "8").option("--push", "Auto-push results to Vibgrate API after scan").option("--dsn <dsn>", "DSN token for push (or use VIBGRATE_DSN env)").option("--region <region>", "Override data residency region for push (us, eu)").option("--strict", "Fail on push errors").option("--ui-purpose", "Enable optional UI purpose evidence extraction (slower)").option("--no-local-artifacts", "Do not write .vibgrate JSON artifacts to disk").option("--max-privacy", "Enable strongest privacy mode (minimal scanners, no local artifacts)").option("--offline", "Run without network calls; do not upload results").option("--full", "Comprehensive scan: turns on known-vulnerability detection (= --vulns) and, when a standards policy exists, a banned-dependency report \u2014 on top of drift scoring and the code map").option("--vulns", "Also scan installed dependencies for known vulnerabilities (OSV online, or advisories from --package-manifest when offline)").option("--package-manifest <file>", "Use local package-version manifest JSON/ZIP (for offline mode)").option("--project-scan-timeout <seconds>", "Per-project scan timeout in seconds (default: 180)").option("--drift-budget <score>", "Fail if DriftScore is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").option("--repository-name <name>", "Override the repository name recorded for this scan (defaults to the directory or package.json name)").option("--force", "Always create a fresh scan ingest, even if the repository is unchanged since the last scan (skips the unchanged/reuse optimization). Used by scheduled and dashboard-triggered scans.").option("--no-graph", "Skip building the local code map (the AI/docs index) that scan produces after scoring drift").option("--quiet", "Suppress promotional output (the free-plan tracking panel and the AI Context install prompt); scan results are unaffected").action(async (targetPath, opts) => {
7582
- const rootDir = path36.resolve(targetPath);
7663
+ const rootDir = path37.resolve(targetPath);
7583
7664
  if (!await pathExists$1(rootDir)) {
7584
7665
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
7585
7666
  process.exit(1);
@@ -7587,7 +7668,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
7587
7668
  const hasDsn = !!resolveDsn(opts.dsn);
7588
7669
  const willPush = !opts.offline && (opts.push || hasDsn);
7589
7670
  const noLocalArtifacts = opts.localArtifacts === false;
7590
- const isFirstRun = !await pathExists$1(path36.join(rootDir, ".vibgrate", "scan_result.json"));
7671
+ const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
7591
7672
  let pinnedRegion;
7592
7673
  let planTier;
7593
7674
  let upgradeUrl;
@@ -7866,11 +7947,11 @@ function scanStaleness(rootDir, artifactPath) {
7866
7947
  scanned++;
7867
7948
  if (scanned > MAX_ENTRIES) break;
7868
7949
  if (e.isDirectory()) {
7869
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path36.join(dir, e.name), depth + 1);
7950
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
7870
7951
  continue;
7871
7952
  }
7872
7953
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
7873
- const abs = path36.join(dir, e.name);
7954
+ const abs = path37.join(dir, e.name);
7874
7955
  let mtimeMs;
7875
7956
  try {
7876
7957
  mtimeMs = fs8.statSync(abs).mtimeMs;
@@ -7879,7 +7960,7 @@ function scanStaleness(rootDir, artifactPath) {
7879
7960
  }
7880
7961
  if (mtimeMs > newest) {
7881
7962
  newest = mtimeMs;
7882
- newestChanged = path36.relative(rootDir, abs) || e.name;
7963
+ newestChanged = path37.relative(rootDir, abs) || e.name;
7883
7964
  }
7884
7965
  }
7885
7966
  };
@@ -8016,13 +8097,13 @@ function analyzeTree(root2, packages) {
8016
8097
  if (filesSeen >= MAX_FILES) return;
8017
8098
  if (entry.isDirectory()) {
8018
8099
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8019
- walk2(path36.join(dir, entry.name), depth + 1);
8100
+ walk2(path37.join(dir, entry.name), depth + 1);
8020
8101
  continue;
8021
8102
  }
8022
- const fileEco = EXT_ECOSYSTEM[path36.extname(entry.name)];
8103
+ const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8023
8104
  if (!fileEco || fileEco === "unknown") continue;
8024
8105
  filesSeen++;
8025
- const full = path36.join(dir, entry.name);
8106
+ const full = path37.join(dir, entry.name);
8026
8107
  let content;
8027
8108
  try {
8028
8109
  if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
@@ -8337,7 +8418,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8337
8418
  }
8338
8419
  const outcomes = effective.map((t) => {
8339
8420
  const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
8340
- return { t, res: run(c2, path36.join(rootDir, t.dir)) };
8421
+ return { t, res: run(c2, path37.join(rootDir, t.dir)) };
8341
8422
  });
8342
8423
  const failures = outcomes.filter((o) => !o.res.ok);
8343
8424
  if (failures.length === 0) {
@@ -8366,8 +8447,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8366
8447
  return results;
8367
8448
  }
8368
8449
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
8369
- var CACHE_DIR = path36.join(os.homedir(), ".vibgrate");
8370
- var CACHE_FILE = path36.join(CACHE_DIR, "update-check.json");
8450
+ var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
8451
+ var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
8371
8452
  async function fetchLatestVersion() {
8372
8453
  try {
8373
8454
  const controller = new AbortController();
@@ -8394,8 +8475,8 @@ async function fetchLatestVersion() {
8394
8475
  }
8395
8476
  async function writeCache(data) {
8396
8477
  try {
8397
- await fs20.mkdir(CACHE_DIR, { recursive: true });
8398
- await fs20.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
8478
+ await fs21.mkdir(CACHE_DIR, { recursive: true });
8479
+ await fs21.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
8399
8480
  } catch {
8400
8481
  }
8401
8482
  }
@@ -8436,14 +8517,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
8436
8517
  pm: "yarn",
8437
8518
  root: () => {
8438
8519
  const dir = tryRun("yarn global dir");
8439
- return dir ? path36.join(dir, "node_modules") : null;
8520
+ return dir ? path37.join(dir, "node_modules") : null;
8440
8521
  }
8441
8522
  },
8442
- { pm: "bun", root: () => path36.join(os.homedir(), ".bun", "install", "global", "node_modules") }
8523
+ { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
8443
8524
  ];
8444
8525
  for (const probe of probes) {
8445
8526
  const root2 = probe.root();
8446
- if (root2 && await pathExists(path36.join(root2, pkg))) return probe.pm;
8527
+ if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
8447
8528
  }
8448
8529
  return null;
8449
8530
  }
@@ -8462,15 +8543,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
8462
8543
  }
8463
8544
  }
8464
8545
  async function detectPackageManager(cwd) {
8465
- if (await pathExists(path36.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
8466
- if (await pathExists(path36.join(cwd, "bun.lockb"))) return "bun";
8467
- if (await pathExists(path36.join(cwd, "yarn.lock"))) return "yarn";
8546
+ if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
8547
+ if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
8548
+ if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
8468
8549
  return "npm";
8469
8550
  }
8470
8551
  async function detectWorkspaceRoot(cwd) {
8471
- if (await pathExists(path36.join(cwd, "pnpm-workspace.yaml"))) return true;
8552
+ if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
8472
8553
  try {
8473
- const pkgPath = path36.join(cwd, "package.json");
8554
+ const pkgPath = path37.join(cwd, "package.json");
8474
8555
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
8475
8556
  const pkg = JSON.parse(raw);
8476
8557
  return pkg.workspaces != null;
@@ -8495,7 +8576,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
8495
8576
  }
8496
8577
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
8497
8578
  try {
8498
- const pkgPath = path36.join(cwd, "package.json");
8579
+ const pkgPath = path37.join(cwd, "package.json");
8499
8580
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
8500
8581
  const parsed = JSON.parse(raw);
8501
8582
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -8507,11 +8588,11 @@ async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
8507
8588
  async function confirmWorkspaceRoot(pm) {
8508
8589
  if (!(process.stdin.isTTY && process.stdout.isTTY)) return false;
8509
8590
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8510
- return new Promise((resolve19) => {
8591
+ return new Promise((resolve20) => {
8511
8592
  rl.question(chalk7.yellow(`Update the ${pm} workspace root with -w? [y/N]: `), (ans) => {
8512
8593
  rl.close();
8513
8594
  const t = ans.trim().toLowerCase();
8514
- resolve19(t === "y" || t === "yes");
8595
+ resolve20(t === "y" || t === "yes");
8515
8596
  });
8516
8597
  });
8517
8598
  }
@@ -8643,13 +8724,13 @@ function collectCandidates(artifact) {
8643
8724
  return out2;
8644
8725
  }
8645
8726
  var defaultFixScanner = async (rootDir) => {
8646
- const scratch = path36.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
8727
+ const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
8647
8728
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
8648
8729
  const advanced = await loadAdvancedScanHook();
8649
8730
  return runCoreScan(rootDir, scanOpts, advanced);
8650
8731
  };
8651
8732
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
8652
- const artifactPath = path36.isAbsolute(inFile) ? inFile : path36.join(rootDir, inFile);
8733
+ const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
8653
8734
  if (await pathExists(artifactPath)) {
8654
8735
  const staleness = scanStaleness(rootDir, artifactPath);
8655
8736
  if (!staleness.stale) {
@@ -8676,7 +8757,7 @@ async function repositoryIdentity(rootDir, override) {
8676
8757
  }
8677
8758
  }
8678
8759
  var fixCommand = new Command("fix").description("Get ranked, risk-tiered upgrade plans from the hosted planner and optionally apply them (prompts before changing files; --yes applies non-interactively, --dry-run previews, --no-apply only prints). Requires login/DSN.").argument("[path]", "Path to analyse", ".").option("--in <file>", "Scan artifact to read", ".vibgrate/scan_result.json").option("--format <format>", "Output format (text|json|md)", "text").option("--dsn <dsn>", 'DSN token (or use VIBGRATE_DSN env / "vg login")').option("--region <region>", "Override data residency region (us, eu)").option("--repository-name <name>", "Override the repository name recorded for this plan").option("--plan <tier>", "Apply a specific plan non-interactively (safe|balanced|aggressive)").option("--yes", "Apply the recommended plan without prompting").option("--dry-run", "Show what would change without applying").option("--no-apply", "Only print the plans; never modify the project").option("--fail-on-vulns <severity>", "Exit non-zero if the recommended plan leaves an advisory at/above this severity unresolved (low|moderate|high|critical)").action(async (targetPath, opts) => {
8679
- const rootDir = path36.resolve(targetPath);
8760
+ const rootDir = path37.resolve(targetPath);
8680
8761
  if (!await pathExists(rootDir)) {
8681
8762
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8682
8763
  process.exit(1);
@@ -8837,7 +8918,7 @@ function emit(report, format) {
8837
8918
  }
8838
8919
  }
8839
8920
  function relProjectDir(rootDir, projectPath) {
8840
- const rel = path36.isAbsolute(projectPath) ? path36.relative(rootDir, projectPath) : projectPath;
8921
+ const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
8841
8922
  return rel === "" ? "." : rel;
8842
8923
  }
8843
8924
  async function buildTargetResolver(rootDir, artifact) {
@@ -8878,14 +8959,14 @@ function promptPlanSelection(response) {
8878
8959
  const defaultIdx = plans.findIndex((p) => p.tier === response.recommended);
8879
8960
  const def = defaultIdx >= 0 ? defaultIdx + 1 : 1;
8880
8961
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8881
- return new Promise((resolve19) => {
8962
+ return new Promise((resolve20) => {
8882
8963
  rl.question(`Plan [1-${plans.length}, default ${def}, q to cancel]: `, (ans) => {
8883
8964
  rl.close();
8884
8965
  const t = ans.trim().toLowerCase();
8885
- if (t === "q" || t === "quit") return resolve19(null);
8966
+ if (t === "q" || t === "quit") return resolve20(null);
8886
8967
  const n = t === "" ? def : Number.parseInt(t, 10);
8887
- if (!Number.isInteger(n) || n < 1 || n > plans.length) return resolve19(null);
8888
- resolve19(plans[n - 1].tier);
8968
+ if (!Number.isInteger(n) || n < 1 || n > plans.length) return resolve20(null);
8969
+ resolve20(plans[n - 1].tier);
8889
8970
  });
8890
8971
  });
8891
8972
  }
@@ -9672,7 +9753,7 @@ function formatMarkdown(artifact) {
9672
9753
 
9673
9754
  // src/reporting/commands/report.ts
9674
9755
  var reportCommand = new Command("report").description("Generate a drift report from a scan artifact").option("--in <file>", "Input artifact file", ".vibgrate/scan_result.json").option("--format <format>", "Output format (md|text|json)", "text").action(async (opts) => {
9675
- const artifactPath = path36.resolve(opts.in);
9756
+ const artifactPath = path37.resolve(opts.in);
9676
9757
  if (!await pathExists(artifactPath)) {
9677
9758
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
9678
9759
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -9718,10 +9799,10 @@ function openUrl(url) {
9718
9799
  }
9719
9800
 
9720
9801
  // src/reporting/commands/login.ts
9721
- var delay = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms));
9802
+ var delay = (ms) => new Promise((resolve20) => setTimeout(resolve20, ms));
9722
9803
  function isInside(dir, file) {
9723
- const rel = path36.relative(dir, file);
9724
- return !!rel && !rel.startsWith("..") && !path36.isAbsolute(rel);
9804
+ const rel = path37.relative(dir, file);
9805
+ return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
9725
9806
  }
9726
9807
  var loginCommand = new Command("login").description("Authenticate the CLI with your Vibgrate workspace via the browser").option("--ingest <url>", "Ingest API URL (overrides --region)").option("--region <region>", `Data residency region (${availableRegionIds().join(", ")})`, "us").option("--no-browser", "Do not attempt to open a browser automatically").option(
9727
9808
  "--local",
@@ -9976,7 +10057,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
9976
10057
  try {
9977
10058
  const statements = [];
9978
10059
  if (opts.from) {
9979
- const fromPath = path36.resolve(opts.from);
10060
+ const fromPath = path37.resolve(opts.from);
9980
10061
  if (!await pathExists(fromPath)) {
9981
10062
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
9982
10063
  `));
@@ -9994,9 +10075,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
9994
10075
  });
9995
10076
  const json2 = JSON.stringify(doc, null, 2);
9996
10077
  if (opts.out) {
9997
- await writeTextFile(path36.resolve(opts.out), json2 + "\n");
10078
+ await writeTextFile(path37.resolve(opts.out), json2 + "\n");
9998
10079
  process.stderr.write(
9999
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path36.resolve(opts.out)}
10080
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
10000
10081
  `
10001
10082
  );
10002
10083
  } else {
@@ -10179,7 +10260,7 @@ function formatDeltaText(base, current) {
10179
10260
  return lines.join("\n");
10180
10261
  }
10181
10262
  async function readArtifactOrExit(filePath) {
10182
- const absolutePath = path36.resolve(filePath);
10263
+ const absolutePath = path37.resolve(filePath);
10183
10264
  if (!await pathExists(absolutePath)) {
10184
10265
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
10185
10266
  process.exit(1);
@@ -10196,7 +10277,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
10196
10277
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
10197
10278
  const body = JSON.stringify(sbom, null, 2);
10198
10279
  if (opts.out) {
10199
- await writeTextFile(path36.resolve(opts.out), body);
10280
+ await writeTextFile(path37.resolve(opts.out), body);
10200
10281
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
10201
10282
  } else {
10202
10283
  console.log(body);
@@ -10207,7 +10288,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
10207
10288
  const current = await readArtifactOrExit(opts.to);
10208
10289
  const report = formatDeltaText(base, current);
10209
10290
  if (opts.out) {
10210
- await writeTextFile(path36.resolve(opts.out), report);
10291
+ await writeTextFile(path37.resolve(opts.out), report);
10211
10292
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
10212
10293
  } else {
10213
10294
  console.log(report);
@@ -10338,20 +10419,20 @@ function resolveRegime(id) {
10338
10419
  return regime;
10339
10420
  }
10340
10421
  function evidenceDir(root2) {
10341
- return path36.join(root2, ".vibgrate", "evidence");
10422
+ return path37.join(root2, ".vibgrate", "evidence");
10342
10423
  }
10343
10424
  function orgPath(root2) {
10344
- return path36.join(evidenceDir(root2), "org.json");
10425
+ return path37.join(evidenceDir(root2), "org.json");
10345
10426
  }
10346
10427
  function productsPath(root2) {
10347
- return path36.join(evidenceDir(root2), "products.json");
10428
+ return path37.join(evidenceDir(root2), "products.json");
10348
10429
  }
10349
10430
  function releasesDir(root2) {
10350
- return path36.join(evidenceDir(root2), "releases");
10431
+ return path37.join(evidenceDir(root2), "releases");
10351
10432
  }
10352
10433
  function releasePath(root2, productId, version) {
10353
10434
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
10354
- return path36.join(releasesDir(root2), `${safe}.json`);
10435
+ return path37.join(releasesDir(root2), `${safe}.json`);
10355
10436
  }
10356
10437
  var DEFAULT_ORG = {
10357
10438
  responsiblePersons: [],
@@ -10382,7 +10463,7 @@ async function freezeRelease(root2, release) {
10382
10463
  const p = releasePath(root2, release.productId, release.version);
10383
10464
  if (await pathExists(p)) {
10384
10465
  throw new CliError(
10385
- `release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path36.relative(root2, p)} only if it was frozen in error`,
10466
+ `release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path37.relative(root2, p)} only if it was frozen in error`,
10386
10467
  ExitCode.USAGE_ERROR
10387
10468
  );
10388
10469
  }
@@ -10396,7 +10477,7 @@ async function loadReleases(root2, productId) {
10396
10477
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
10397
10478
  const releases = [];
10398
10479
  for (const f of files) {
10399
- const rel = await readJsonFile(path36.join(dir, f));
10480
+ const rel = await readJsonFile(path37.join(dir, f));
10400
10481
  if (!productId || rel.productId === productId) releases.push(rel);
10401
10482
  }
10402
10483
  return releases;
@@ -11091,12 +11172,12 @@ function verifyEvidenceEnvelope(env, opts = {}) {
11091
11172
  var DEFAULT_KEY = "attest-key.pem";
11092
11173
  function resolveSigningKey(root2, explicit) {
11093
11174
  const chosen = process.env.VG_ATTEST_KEY;
11094
- const keyPath = chosen ? path36.resolve(chosen) : path36.join(root2, ".vibgrate", DEFAULT_KEY);
11175
+ const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
11095
11176
  let minted = false;
11096
11177
  if (!fs8.existsSync(keyPath)) {
11097
11178
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
11098
11179
  const kp = generateKeypair();
11099
- fs8.mkdirSync(path36.dirname(keyPath), { recursive: true });
11180
+ fs8.mkdirSync(path37.dirname(keyPath), { recursive: true });
11100
11181
  fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11101
11182
  fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
11102
11183
  minted = true;
@@ -11114,16 +11195,16 @@ function resolveSigningKey(root2, explicit) {
11114
11195
  }
11115
11196
  function writeBundle(input) {
11116
11197
  const dir = input.outDir;
11117
- fs8.mkdirSync(path36.join(dir, "inputs", "releases"), { recursive: true });
11118
- const write = (rel, data) => fs8.writeFileSync(path36.join(dir, rel), `${JSON.stringify(data, null, 2)}
11198
+ fs8.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11199
+ const write = (rel, data) => fs8.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
11119
11200
  `);
11120
11201
  write("result.json", input.result);
11121
- write(path36.join("inputs", "advisory.json"), input.advisory);
11202
+ write(path37.join("inputs", "advisory.json"), input.advisory);
11122
11203
  for (const rel of input.releases) {
11123
11204
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11124
- write(path36.join("inputs", "releases", `${safe}.json`), rel);
11205
+ write(path37.join("inputs", "releases", `${safe}.json`), rel);
11125
11206
  }
11126
- write(path36.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11207
+ write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11127
11208
  write("provenance.json", {
11128
11209
  method: "deterministic",
11129
11210
  modelDrafted: [],
@@ -11139,13 +11220,13 @@ function writeBundle(input) {
11139
11220
  disclaimer: input.regime.disclaimer
11140
11221
  });
11141
11222
  if (input.envelope) {
11142
- fs8.writeFileSync(path36.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11223
+ fs8.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11143
11224
  `);
11144
11225
  }
11145
11226
  if (input.timestampToken) {
11146
- fs8.writeFileSync(path36.join(dir, "timestamp.tsr"), input.timestampToken);
11227
+ fs8.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
11147
11228
  }
11148
- fs8.writeFileSync(path36.join(dir, "VERIFY.md"), verifyDoc(input));
11229
+ fs8.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
11149
11230
  return dir;
11150
11231
  }
11151
11232
  function verifyDoc(input) {
@@ -11206,13 +11287,13 @@ function undeterminedFields(result, regime) {
11206
11287
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
11207
11288
  }
11208
11289
  async function recordDrill(root2, record) {
11209
- const dir = path36.join(evidenceDir(root2), "drills");
11210
- const p = path36.join(dir, `${record.drillId}.json`);
11290
+ const dir = path37.join(evidenceDir(root2), "drills");
11291
+ const p = path37.join(dir, `${record.drillId}.json`);
11211
11292
  await writeJsonFile(p, record);
11212
11293
  return p;
11213
11294
  }
11214
11295
  async function hasRecentDrill(root2, asOf) {
11215
- const dir = path36.join(evidenceDir(root2), "drills");
11296
+ const dir = path37.join(evidenceDir(root2), "drills");
11216
11297
  if (!await pathExists(dir)) return void 0;
11217
11298
  const { readdir } = await import('fs/promises');
11218
11299
  const { readJsonFile: readJsonFile2 } = await import('./fs-O5IQYXHO.js');
@@ -11220,7 +11301,7 @@ async function hasRecentDrill(root2, asOf) {
11220
11301
  if (files.length === 0) return void 0;
11221
11302
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
11222
11303
  for (const f of files) {
11223
- const rec = await readJsonFile2(path36.join(dir, f));
11304
+ const rec = await readJsonFile2(path37.join(dir, f));
11224
11305
  if (rec.ranAt >= cutoff) return true;
11225
11306
  }
11226
11307
  return false;
@@ -11300,7 +11381,7 @@ function formatRegimeList() {
11300
11381
 
11301
11382
  // src/reporting/commands/evidence/index.ts
11302
11383
  function root(opts) {
11303
- return path36.resolve(opts.cwd ?? process.cwd());
11384
+ return path37.resolve(opts.cwd ?? process.cwd());
11304
11385
  }
11305
11386
  function slug(name) {
11306
11387
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -11388,7 +11469,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11388
11469
  const release = await buildRelease({
11389
11470
  productId: product.id,
11390
11471
  version,
11391
- from: path36.resolve(rootDir, opts.from),
11472
+ from: path37.resolve(rootDir, opts.from),
11392
11473
  shipDate: opts.shipDate,
11393
11474
  buildId: opts.buildId,
11394
11475
  artefactDigest: opts.digest,
@@ -11396,7 +11477,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11396
11477
  frozenAt: nowIso()
11397
11478
  });
11398
11479
  const p = await freezeRelease(rootDir, release);
11399
- console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path36.relative(rootDir, p)}`);
11480
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
11400
11481
  });
11401
11482
  async function runExposure(rootDir, vuln, opts) {
11402
11483
  const org = await loadOrg(rootDir);
@@ -11448,7 +11529,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
11448
11529
  console.log("\n" + buildPack(result, regime, org, stage));
11449
11530
  }
11450
11531
  if (opts.bundle) {
11451
- const dir = path36.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
11532
+ const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
11452
11533
  let envelope;
11453
11534
  if (opts.sign !== false) {
11454
11535
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -11456,7 +11537,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
11456
11537
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
11457
11538
  }
11458
11539
  writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
11459
- console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path36.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
11540
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
11460
11541
  }
11461
11542
  process.exitCode = exposureExit(result.overallStatus);
11462
11543
  });
@@ -11488,7 +11569,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
11488
11569
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
11489
11570
  const md = buildPack(result, regime, org, stage);
11490
11571
  if (opts.out) {
11491
- fs8.writeFileSync(path36.resolve(rootDir, opts.out), md);
11572
+ fs8.writeFileSync(path37.resolve(rootDir, opts.out), md);
11492
11573
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
11493
11574
  } else {
11494
11575
  console.log(md);
@@ -11530,18 +11611,18 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
11530
11611
  }
11531
11612
  });
11532
11613
  var verifyCmd = new Command("verify").description("Verify an evidence bundle offline (no Vibgrate needed)").argument("<bundle>", "Path to an evidence bundle directory or evidence.intoto.jsonl").option("--pub <file>", "Public key PEM to pin the signer (establish trust)").action((bundlePath, opts) => {
11533
- const abs = path36.resolve(bundlePath);
11534
- const envPath = fs8.statSync(abs).isDirectory() ? path36.join(abs, "evidence.intoto.jsonl") : abs;
11614
+ const abs = path37.resolve(bundlePath);
11615
+ const envPath = fs8.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
11535
11616
  if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
11536
11617
  const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
11537
- const resultPath = path36.join(path36.dirname(envPath), "result.json");
11618
+ const resultPath = path37.join(path37.dirname(envPath), "result.json");
11538
11619
  const result = fs8.existsSync(resultPath) ? JSON.parse(fs8.readFileSync(resultPath, "utf8")) : void 0;
11539
- const publicKeyPem = opts.pub ? fs8.readFileSync(path36.resolve(opts.pub), "utf8") : void 0;
11620
+ const publicKeyPem = opts.pub ? fs8.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
11540
11621
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
11541
11622
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
11542
11623
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
11543
11624
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
11544
- const tsrPath = path36.join(path36.dirname(envPath), "timestamp.tsr");
11625
+ const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
11545
11626
  if (fs8.existsSync(tsrPath) && result) {
11546
11627
  const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
11547
11628
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
@@ -11610,12 +11691,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
11610
11691
  const releases = [];
11611
11692
  for (const list of releasesByProduct.values()) releases.push(...list);
11612
11693
  const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
11613
- const dir = path36.resolve(rootDir, opts.out);
11614
- await writeJsonFile(path36.join(dir, "org.json"), org);
11615
- await writeJsonFile(path36.join(dir, "products.json"), products);
11616
- for (const r of releases) await writeJsonFile(path36.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
11617
- await writeJsonFile(path36.join(dir, "readiness.json"), report);
11618
- console.error(chalk7.green("\u2714") + ` exported evidence state to ${path36.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
11694
+ const dir = path37.resolve(rootDir, opts.out);
11695
+ await writeJsonFile(path37.join(dir, "org.json"), org);
11696
+ await writeJsonFile(path37.join(dir, "products.json"), products);
11697
+ for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
11698
+ await writeJsonFile(path37.join(dir, "readiness.json"), report);
11699
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
11619
11700
  });
11620
11701
  var pushCmd = new Command("push").description("Push the product registry (and an optional exposure result) to Vibgrate Cloud").option(...cwdOption).option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env / `vg login`)").option("--regime <id>", "Reporting regime").option("--result <file>", "An exposure result.json (or a bundle dir) to include").option("--signed", "Mark the included exposure result as signed").option("--strict", "Fail on push errors").action(async (opts) => {
11621
11702
  const rootDir = root(opts);
@@ -11641,8 +11722,8 @@ var pushCmd = new Command("push").description("Push the product registry (and an
11641
11722
  }));
11642
11723
  let exposure;
11643
11724
  if (opts.result) {
11644
- const raw = path36.resolve(rootDir, opts.result);
11645
- const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path36.join(raw, "result.json") : raw;
11725
+ const raw = path37.resolve(rootDir, opts.result);
11726
+ const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
11646
11727
  if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
11647
11728
  exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
11648
11729
  }
@@ -11708,6 +11789,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
11708
11789
  "install",
11709
11790
  "uninstall",
11710
11791
  "share",
11792
+ "watch",
11711
11793
  "help",
11712
11794
  // Drift-reporting verbs (merged from the Vibgrate CLI).
11713
11795
  "init",
@@ -11748,6 +11830,7 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
11748
11830
  registerLsp(program);
11749
11831
  registerInstall(program);
11750
11832
  registerShare(program);
11833
+ registerWatch(program);
11751
11834
  registerTests(program);
11752
11835
  registerFacts(program);
11753
11836
  registerGuide(program);
@@ -11832,7 +11915,7 @@ function dispatch(argv, cwd) {
11832
11915
  }
11833
11916
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
11834
11917
  if (looksLikeQuestion) return ["ask", ...args];
11835
- if (fs8.existsSync(path36.resolve(cwd, first))) {
11918
+ if (fs8.existsSync(path37.resolve(cwd, first))) {
11836
11919
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
11837
11920
  }
11838
11921
  const moved = MOVED_COMMANDS[first];
@@ -11877,9 +11960,9 @@ async function main(argv = process.argv) {
11877
11960
  }
11878
11961
  function readCwd(raw) {
11879
11962
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
11880
- if (i >= 0 && raw[i + 1]) return path36.resolve(raw[i + 1]);
11963
+ if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
11881
11964
  const eq = raw.find((a) => a.startsWith("--cwd="));
11882
- if (eq) return path36.resolve(eq.slice("--cwd=".length));
11965
+ if (eq) return path37.resolve(eq.slice("--cwd=".length));
11883
11966
  return process.cwd();
11884
11967
  }
11885
11968
  function handleError(err) {