@vibgrate/cli 2026.727.2 → 2026.727.3

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 (69) hide show
  1. package/DOCS.md +21 -1
  2. package/README.md +2 -1
  3. package/dist/baseline-ATM5MXBZ.js +8 -0
  4. package/dist/{baseline-TG4ATZGZ.js.map → baseline-ATM5MXBZ.js.map} +1 -1
  5. package/dist/{chunk-CY4WKXB2.js → chunk-2VFWXNS5.js} +3 -3
  6. package/dist/{chunk-CY4WKXB2.js.map → chunk-2VFWXNS5.js.map} +1 -1
  7. package/dist/{chunk-LKVMI67M.js → chunk-6JIKUDWM.js} +3 -3
  8. package/dist/{chunk-LKVMI67M.js.map → chunk-6JIKUDWM.js.map} +1 -1
  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-KCKYKDMS.js → chunk-AVQSHIJ5.js} +20 -17
  14. package/dist/chunk-AVQSHIJ5.js.map +1 -0
  15. package/dist/{chunk-2XQDMLKB.js → chunk-B3YUO3NW.js} +7 -3
  16. package/dist/chunk-B3YUO3NW.js.map +1 -0
  17. package/dist/{chunk-RNP3SMTV.js → chunk-C66GOHYB.js} +8 -8
  18. package/dist/{chunk-RNP3SMTV.js.map → chunk-C66GOHYB.js.map} +1 -1
  19. package/dist/{chunk-EX4PQT6W.js → chunk-FFWGT55D.js} +4 -4
  20. package/dist/{chunk-EX4PQT6W.js.map → chunk-FFWGT55D.js.map} +1 -1
  21. package/dist/{chunk-6AYDFFP5.js → chunk-HK3AWUXH.js} +3 -3
  22. package/dist/{chunk-6AYDFFP5.js.map → chunk-HK3AWUXH.js.map} +1 -1
  23. package/dist/{chunk-KNELIQJO.js → chunk-MAY5HLDH.js} +576 -189
  24. package/dist/chunk-MAY5HLDH.js.map +1 -0
  25. package/dist/{chunk-3Q7QBWFW.js → chunk-ON25BX6T.js} +9 -3
  26. package/dist/chunk-ON25BX6T.js.map +1 -0
  27. package/dist/{chunk-2MBL43EJ.js → chunk-XPJZTSY7.js} +3 -3
  28. package/dist/{chunk-2MBL43EJ.js.map → chunk-XPJZTSY7.js.map} +1 -1
  29. package/dist/{chunk-WGUL45AV.js → chunk-Y23HMSWU.js} +3 -3
  30. package/dist/{chunk-WGUL45AV.js.map → chunk-Y23HMSWU.js.map} +1 -1
  31. package/dist/{chunk-J4RFRKZH.js → chunk-Z7GP7XTJ.js} +7 -7
  32. package/dist/{chunk-J4RFRKZH.js.map → chunk-Z7GP7XTJ.js.map} +1 -1
  33. package/dist/{chunk-KSBHGWRV.js → chunk-ZBTY6VV4.js} +4 -4
  34. package/dist/{chunk-KSBHGWRV.js.map → chunk-ZBTY6VV4.js.map} +1 -1
  35. package/dist/{chunk-K3MZIVZW.js → chunk-ZKNB4YH4.js} +19 -5
  36. package/dist/chunk-ZKNB4YH4.js.map +1 -0
  37. package/dist/cli.js +424 -210
  38. package/dist/cli.js.map +1 -1
  39. package/dist/{graph-backend-73URGTFY.js → graph-backend-UTOL3SHE.js} +5 -5
  40. package/dist/{graph-backend-73URGTFY.js.map → graph-backend-UTOL3SHE.js.map} +1 -1
  41. package/dist/index.d.ts +12 -5
  42. package/dist/index.js +10 -10
  43. package/dist/{interactive-372NLI5C.js → interactive-INGJNSON.js} +19 -19
  44. package/dist/{interactive-372NLI5C.js.map → interactive-INGJNSON.js.map} +1 -1
  45. package/dist/load-QPOWQD7C.js +8 -0
  46. package/dist/{load-I333TGNI.js.map → load-QPOWQD7C.js.map} +1 -1
  47. package/dist/parse-worker.d.ts +1 -1
  48. package/dist/parse-worker.js +1 -1
  49. package/dist/{runtime-session-JRKCQUHY.js → runtime-session-4AMZIAAG.js} +7 -7
  50. package/dist/{runtime-session-JRKCQUHY.js.map → runtime-session-4AMZIAAG.js.map} +1 -1
  51. package/dist/{session-ITPYQ5XI.js → session-M72522AP.js} +6 -6
  52. package/dist/{session-ITPYQ5XI.js.map → session-M72522AP.js.map} +1 -1
  53. package/dist/sql-extract-JELDZA6W.js +81 -0
  54. package/dist/sql-extract-JELDZA6W.js.map +1 -0
  55. package/dist/{stream-json-SLMDKLXP.js → stream-json-6ZBUA2L3.js} +9 -9
  56. package/dist/{stream-json-SLMDKLXP.js.map → stream-json-6ZBUA2L3.js.map} +1 -1
  57. package/dist/{types-7AHBUbFm.d.ts → types-DLH-Ritr.d.ts} +18 -1
  58. package/dist/{vgd-7JV5KCNJ.js → vgd-CVLKBS7K.js} +6 -6
  59. package/dist/vgd-CVLKBS7K.js.map +1 -0
  60. package/package.json +1 -1
  61. package/dist/baseline-TG4ATZGZ.js +0 -8
  62. package/dist/chunk-2XQDMLKB.js.map +0 -1
  63. package/dist/chunk-3Q7QBWFW.js.map +0 -1
  64. package/dist/chunk-6ABXHZRN.js.map +0 -1
  65. package/dist/chunk-K3MZIVZW.js.map +0 -1
  66. package/dist/chunk-KCKYKDMS.js.map +0 -1
  67. package/dist/chunk-KNELIQJO.js.map +0 -1
  68. package/dist/load-I333TGNI.js +0 -8
  69. package/dist/vgd-7JV5KCNJ.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,46 +1,46 @@
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 { loadAdvancedScanHook, baselineCommand } from './chunk-FFWGT55D.js';
3
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-C66GOHYB.js';
4
+ export { runBuild } from './chunk-C66GOHYB.js';
5
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-Z7GP7XTJ.js';
6
+ import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
7
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-77LYGXBI.js';
6
8
  import './chunk-5I4VSBWQ.js';
7
9
  import './chunk-IS7VTH2Q.js';
8
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-J4RFRKZH.js';
9
10
  import { gatherSystemMemory } from './chunk-6UQMXIAG.js';
10
11
  import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-3V24O47U.js';
11
12
  import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
12
13
  import './chunk-IZDH67DX.js';
13
- import './chunk-6AYDFFP5.js';
14
+ import './chunk-HK3AWUXH.js';
14
15
  import { vgdIsRunning, vgdRequest, vgdSocketPath } from './chunk-PMYWZRRS.js';
15
16
  import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-PXHNTC6D.js';
16
17
  import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-K7REHDQS.js';
17
18
  import { buildIdentifierTrieFromGraph } from './chunk-JIBOJTGS.js';
18
19
  import './chunk-NDMDSPFX.js';
19
- import { runCodeSession } from './chunk-CY4WKXB2.js';
20
+ import { runCodeSession } from './chunk-2VFWXNS5.js';
20
21
  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';
22
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-AVQSHIJ5.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, 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-MAY5HLDH.js';
24
+ import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-6JIKUDWM.js';
25
+ 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-Y23HMSWU.js';
26
+ import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
26
27
  import { resolveOne } from './chunk-J7LKEB2R.js';
27
28
  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';
29
+ import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-ZBTY6VV4.js';
30
+ import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-6UK6QPTR.js';
31
+ import { resolvedGrammarFiles, grammarSetVersion } from './chunk-ON25BX6T.js';
31
32
  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';
33
+ import { resolveGraphPath, renderReport, loadGraph, writeArtifacts, vibgrateDir, SCHEMA_VERSION } from './chunk-B3YUO3NW.js';
34
+ import { cacheDir, stableStringify } from './chunk-ZKNB4YH4.js';
34
35
  import './chunk-BWPBB45M.js';
35
36
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
36
37
  import './chunk-BPF3YX2U.js';
37
38
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
38
- import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
39
39
  import './chunk-DGUM43GV.js';
40
40
  import * as fs8 from 'fs';
41
41
  import fs8__default, { realpathSync } from 'fs';
42
- import * as path36 from 'path';
43
- import path36__default from 'path';
42
+ import * as path37 from 'path';
43
+ import path37__default from 'path';
44
44
  import { fileURLToPath, pathToFileURL } from 'url';
45
45
  import { Command, CommanderError, Option } from 'commander';
46
46
  import * as os from 'os';
@@ -49,7 +49,7 @@ import { randomUUID } from 'crypto';
49
49
  import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
50
50
  import * as readline from 'readline';
51
51
  import chalk7 from 'chalk';
52
- import * as fs20 from 'fs/promises';
52
+ import * as fs21 from 'fs/promises';
53
53
  import semver2 from 'semver';
54
54
 
55
55
  function registerStatus(program) {
@@ -59,10 +59,10 @@ function registerStatus(program) {
59
59
  applyGlobalOptions(cmd);
60
60
  }
61
61
  async function runStatus(global) {
62
- const root2 = path36.resolve(global.cwd ?? ".");
62
+ const root2 = path37.resolve(global.cwd ?? ".");
63
63
  const graphPath = resolveGraphPath(root2, global.graph);
64
64
  const graph = loadGraph(root2, graphPath);
65
- const hasCache = fs8.existsSync(path36.join(cacheDir(root2), "parse-cache.json"));
65
+ const hasCache = fs8.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
66
66
  let stale = null;
67
67
  let staleExact = false;
68
68
  if (graph) {
@@ -82,8 +82,8 @@ async function runStatus(global) {
82
82
  }
83
83
  if (global.json) {
84
84
  json({
85
- root: path36.relative(process.cwd(), root2) || ".",
86
- graphPath: path36.relative(root2, graphPath),
85
+ root: path37.relative(process.cwd(), root2) || ".",
86
+ graphPath: path37.relative(root2, graphPath),
87
87
  built: graph !== null,
88
88
  generatedAt: graph?.generatedAt ?? null,
89
89
  counts: graph?.meta.counts ?? null,
@@ -98,11 +98,11 @@ async function runStatus(global) {
98
98
  return;
99
99
  }
100
100
  if (!graph) {
101
- info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path36.relative(root2, graphPath))}`);
101
+ info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
102
102
  info(` run ${c.bold("vg")} to build one`);
103
103
  return;
104
104
  }
105
- info(`${c.cyan("vg")} \xB7 ${path36.relative(root2, graphPath)}`);
105
+ info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
106
106
  info(` generated ${graph.generatedAt}`);
107
107
  info(
108
108
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -119,7 +119,7 @@ async function runStatus(global) {
119
119
  if (vibgrateDir(root2)) ;
120
120
  }
121
121
  function rootOf(global) {
122
- return path36.resolve(global.cwd ?? ".");
122
+ return path37.resolve(global.cwd ?? ".");
123
123
  }
124
124
  function requireGraph(global) {
125
125
  const root2 = rootOf(global);
@@ -402,6 +402,19 @@ function registerPath(program) {
402
402
  );
403
403
  }
404
404
  if (!result) {
405
+ const disc = pathDisconnect(graph, ra.node.id, rb.node.id);
406
+ if (global.json) {
407
+ json(disc);
408
+ throw new CliError(
409
+ `no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
410
+ ExitCode.NOT_FOUND
411
+ );
412
+ }
413
+ info(`${c.cyan("vg path")} \xB7 no path between ${c.bold(disc.from.name)} and ${c.bold(disc.to.name)}`);
414
+ printNeighborhood("from", disc.from);
415
+ printNeighborhood("to", disc.to);
416
+ info(c.dim(` ${disc.hint}`));
417
+ info(c.dim(` try: vg show ${disc.from.name} \xB7 vg impact ${disc.from.name} \xB7 vg show ${disc.to.name}`));
405
418
  throw new CliError(
406
419
  `no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
407
420
  ExitCode.NOT_FOUND
@@ -418,6 +431,14 @@ function registerPath(program) {
418
431
  });
419
432
  applyGlobalOptions(cmd);
420
433
  }
434
+ function printNeighborhood(label, n) {
435
+ const parts = [];
436
+ if (n.calls.length) parts.push(`calls ${n.calls.join(", ")}`);
437
+ if (n.calledBy.length) parts.push(`called by ${n.calledBy.join(", ")}`);
438
+ if (n.imports.length) parts.push(`imports ${n.imports.join(", ")}`);
439
+ if (n.importedBy.length) parts.push(`imported by ${n.importedBy.join(", ")}`);
440
+ info(` ${c.dim(label)} ${c.bold(n.name)}${parts.length ? c.dim(` \xB7 ${parts.join(" \xB7 ")}`) : c.dim(" \xB7 (no call/import neighbors)")}`);
441
+ }
421
442
 
422
443
  // src/commands/tree.ts
423
444
  function registerTree(program) {
@@ -531,12 +552,12 @@ function registerInsights(program) {
531
552
  }
532
553
  });
533
554
  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) {
555
+ 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
556
  const global = readGlobal(this);
536
557
  const { graph } = requireGraph(global);
537
558
  const limit = Number(opts.limit) || 20;
538
559
  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);
560
+ 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
561
  if (global.json) {
541
562
  json(
542
563
  list.map((e) => ({
@@ -549,7 +570,9 @@ function registerInsights(program) {
549
570
  return;
550
571
  }
551
572
  if (!list.length) {
552
- info(`${c.cyan("vg oddities")} \xB7 none found (no cross-area links, or only one area)`);
573
+ info(
574
+ `${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)")
575
+ );
553
576
  return;
554
577
  }
555
578
  info(`${c.cyan("vg oddities")} \xB7 top ${list.length} surprising links`);
@@ -561,6 +584,70 @@ function registerInsights(program) {
561
584
  });
562
585
  applyGlobalOptions(oddities);
563
586
  }
587
+ var FRAMEWORK_EXTERNALS = /* @__PURE__ */ new Set([
588
+ "react",
589
+ "react-dom",
590
+ "react-native",
591
+ "vue",
592
+ "vue-router",
593
+ "svelte",
594
+ "svelte/store",
595
+ "next",
596
+ "next/link",
597
+ "next/router",
598
+ "next/navigation",
599
+ "nuxt",
600
+ "angular",
601
+ "@angular/core",
602
+ "@angular/common",
603
+ "preact",
604
+ "solid-js",
605
+ "express",
606
+ "fastify",
607
+ "koa",
608
+ "hono",
609
+ "rxjs",
610
+ "lodash",
611
+ "lodash-es",
612
+ "underscore",
613
+ "jquery",
614
+ "axios",
615
+ "node:fs",
616
+ "node:path",
617
+ "node:url",
618
+ "node:http",
619
+ "node:https",
620
+ "fs",
621
+ "path",
622
+ "url",
623
+ "http",
624
+ "https",
625
+ "crypto",
626
+ "util",
627
+ "stream",
628
+ "events",
629
+ "assert",
630
+ "os",
631
+ "child_process"
632
+ ]);
633
+ function isFrameworkOddity(from, to, kind) {
634
+ if (kind !== "import") return false;
635
+ for (const n of [from, to]) {
636
+ if (n?.kind === "external" && isFrameworkName(n.qualifiedName || n.name)) return true;
637
+ }
638
+ return false;
639
+ }
640
+ function isFrameworkName(name) {
641
+ if (!name) return false;
642
+ if (FRAMEWORK_EXTERNALS.has(name)) return true;
643
+ const base = name.startsWith("@") ? name.split("/").slice(0, 2).join("/") : name.split("/")[0];
644
+ if (FRAMEWORK_EXTERNALS.has(base)) return true;
645
+ if (base.startsWith("react-") || base.startsWith("@types/react")) return true;
646
+ if (base.startsWith("@vue/") || base.startsWith("@angular/") || base.startsWith("@sveltejs/")) {
647
+ return true;
648
+ }
649
+ return false;
650
+ }
564
651
  function nodeSummary(n) {
565
652
  return {
566
653
  id: n.id,
@@ -743,8 +830,8 @@ function pad2(s, n) {
743
830
  }
744
831
  var SCHEMA_VERSION2 = "1";
745
832
  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");
833
+ var INSTALL_ID_DIR = path37.join(os.homedir(), ".vibgrate");
834
+ var INSTALL_ID_FILE = path37.join(INSTALL_ID_DIR, "install-id");
748
835
  var SEND_TIMEOUT_MS = 4e3;
749
836
  function telemetryOptOut(env = process.env) {
750
837
  const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
@@ -796,10 +883,10 @@ function statsEndpoint() {
796
883
  return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
797
884
  }
798
885
  function offsetPath(root2) {
799
- return path36.join(cacheDir(root2), OFFSET_FILE);
886
+ return path37.join(cacheDir(root2), OFFSET_FILE);
800
887
  }
801
888
  function ledgerFilePath(root2) {
802
- return path36.join(cacheDir(root2), "savings.jsonl");
889
+ return path37.join(cacheDir(root2), "savings.jsonl");
803
890
  }
804
891
  function readOffset(root2) {
805
892
  try {
@@ -970,7 +1057,7 @@ var PUBLISH_INTERVAL_MS = 2e3;
970
1057
  var KEEPALIVE_MS = 1e4;
971
1058
  var STALE_MS = 6e4;
972
1059
  function liveStatsDir(root2) {
973
- return path36.join(cacheDir(root2), "serve-live");
1060
+ return path37.join(cacheDir(root2), "serve-live");
974
1061
  }
975
1062
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
976
1063
  let entries;
@@ -984,7 +1071,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
984
1071
  if (!/^serve-\d+\.json$/.test(name)) continue;
985
1072
  let parsed;
986
1073
  try {
987
- parsed = JSON.parse(fs8.readFileSync(path36.join(dir, name), "utf8"));
1074
+ parsed = JSON.parse(fs8.readFileSync(path37.join(dir, name), "utf8"));
988
1075
  } catch {
989
1076
  continue;
990
1077
  }
@@ -1006,7 +1093,7 @@ var LiveStatsBus = class {
1006
1093
  this.dir = dir;
1007
1094
  this.stats = stats;
1008
1095
  this.pid = pid;
1009
- this.file = path36.join(dir, `serve-${this.pid}.json`);
1096
+ this.file = path37.join(dir, `serve-${this.pid}.json`);
1010
1097
  }
1011
1098
  dir;
1012
1099
  stats;
@@ -1059,7 +1146,7 @@ var LiveStatsBus = class {
1059
1146
  const out2 = [];
1060
1147
  for (const name of entries.sort()) {
1061
1148
  if (!/^serve-\d+\.json$/.test(name)) continue;
1062
- const file = path36.join(this.dir, name);
1149
+ const file = path37.join(this.dir, name);
1063
1150
  let parsed;
1064
1151
  try {
1065
1152
  parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
@@ -1487,8 +1574,8 @@ function registerServe(program) {
1487
1574
  await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
1488
1575
  } else {
1489
1576
  info(c.dim(`vg \xB7 MCP server on stdio (read-only, ${freshness}). Connect your assistant to this process.`));
1490
- await serveStdio(graphPath, serveOpts);
1491
1577
  display?.start();
1578
+ await serveStdio(graphPath, serveOpts);
1492
1579
  }
1493
1580
  });
1494
1581
  applyGlobalOptions(cmd);
@@ -1503,13 +1590,22 @@ async function ensureServableGraph(root2, graphPath, global, refresh, opts = {})
1503
1590
  { ...global, json: false }
1504
1591
  );
1505
1592
  } 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
- }
1593
+ const kick = refreshIfStale(root2, { inline: opts.inline, graphPath }).then((refreshed) => {
1594
+ if (refreshed.status === "refreshed") {
1595
+ const n = driftCount(refreshed.drift);
1596
+ info(
1597
+ c.dim(
1598
+ `vg \xB7 map refreshed in background \u2014 ${n} file(s) drifted (${(refreshed.ms / 1e3).toFixed(2)}s)`
1599
+ )
1600
+ );
1601
+ } else if (refreshed.status === "error") {
1602
+ info(c.yellow(`vg \xB7 map refresh failed (${refreshed.message}) \u2014 serving the last built map`));
1603
+ }
1604
+ }).catch((err) => {
1605
+ const msg = err instanceof Error ? err.message : String(err);
1606
+ info(c.yellow(`vg \xB7 map refresh failed (${msg}) \u2014 serving the last built map`));
1607
+ });
1608
+ if (opts.awaitStaleRefresh) await kick;
1513
1609
  }
1514
1610
  }
1515
1611
  if (!fs8.existsSync(graphPath)) {
@@ -1574,7 +1670,7 @@ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
1574
1670
  info(c.red(`vg serve: request error: ${err.message}`));
1575
1671
  }
1576
1672
  });
1577
- await new Promise((resolve19) => httpServer.listen(port, host, resolve19));
1673
+ await new Promise((resolve20) => httpServer.listen(port, host, resolve20));
1578
1674
  info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
1579
1675
  onReady?.();
1580
1676
  await new Promise(() => {
@@ -1788,7 +1884,7 @@ function endOfLine(text, line) {
1788
1884
  }
1789
1885
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1790
1886
  function cachePath(root2) {
1791
- return path36.join(cacheDir(root2), "lsp-scan.json");
1887
+ return path37.join(cacheDir(root2), "lsp-scan.json");
1792
1888
  }
1793
1889
  function manifestHash(root2) {
1794
1890
  const files = [];
@@ -1800,7 +1896,7 @@ function manifestHash(root2) {
1800
1896
  return;
1801
1897
  }
1802
1898
  for (const entry of entries) {
1803
- const abs = path36.join(dir, entry.name);
1899
+ const abs = path37.join(dir, entry.name);
1804
1900
  if (entry.isDirectory()) {
1805
1901
  if (SKIP_DIRS.has(entry.name)) continue;
1806
1902
  walk2(abs);
@@ -1810,7 +1906,7 @@ function manifestHash(root2) {
1810
1906
  const base = entry.name.toLowerCase();
1811
1907
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1812
1908
  try {
1813
- const rel = path36.relative(root2, abs).split(path36.sep).join("/");
1909
+ const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1814
1910
  files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
1815
1911
  } catch {
1816
1912
  }
@@ -2456,12 +2552,12 @@ function uriToPath(uri) {
2456
2552
  }
2457
2553
  }
2458
2554
  function projectForFile(root2, a, filePath) {
2459
- const dir = path36.dirname(path36.resolve(filePath));
2555
+ const dir = path37.dirname(path37.resolve(filePath));
2460
2556
  let best;
2461
2557
  let bestLen = -1;
2462
2558
  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) {
2559
+ const projDir = path37.resolve(root2, proj.path);
2560
+ if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2465
2561
  best = proj;
2466
2562
  bestLen = projDir.length;
2467
2563
  }
@@ -2469,7 +2565,7 @@ function projectForFile(root2, a, filePath) {
2469
2565
  return best;
2470
2566
  }
2471
2567
  function sameProject(location, projectPath) {
2472
- return path36.normalize(location) === path36.normalize(projectPath);
2568
+ return path37.normalize(location) === path37.normalize(projectPath);
2473
2569
  }
2474
2570
  function hasReleaseDates(a) {
2475
2571
  for (const proj of a.projects ?? []) {
@@ -2795,7 +2891,7 @@ function registerShare(program) {
2795
2891
  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
2892
  const global = readGlobal(this);
2797
2893
  const root2 = rootOf(global);
2798
- const gitDir = path36.join(root2, ".git");
2894
+ const gitDir = path37.join(root2, ".git");
2799
2895
  if (!fs8.existsSync(gitDir)) {
2800
2896
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
2801
2897
  }
@@ -2817,15 +2913,15 @@ function registerShare(program) {
2817
2913
  applyGlobalOptions(cmd);
2818
2914
  }
2819
2915
  function writeVibgrateGitignore(root2, reports) {
2820
- const dir = path36.join(root2, ".vibgrate");
2916
+ const dir = path37.join(root2, ".vibgrate");
2821
2917
  fs8.mkdirSync(dir, { recursive: true });
2822
2918
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl"];
2823
2919
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
2824
- fs8.writeFileSync(path36.join(dir, ".gitignore"), `${lines.join("\n")}
2920
+ fs8.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
2825
2921
  `);
2826
2922
  }
2827
2923
  function writeGitAttributes(root2) {
2828
- const file = path36.join(root2, ".gitattributes");
2924
+ const file = path37.join(root2, ".gitattributes");
2829
2925
  const line = ".vibgrate/graph.json merge=vg";
2830
2926
  let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
2831
2927
  if (!content.split("\n").some((l) => l.trim() === line)) {
@@ -2843,7 +2939,7 @@ function configureMergeDriver(root2) {
2843
2939
  function installPreCommitHook(root2) {
2844
2940
  const hooksDir = hookDir(root2);
2845
2941
  fs8.mkdirSync(hooksDir, { recursive: true });
2846
- const file = path36.join(hooksDir, "pre-commit");
2942
+ const file = path37.join(hooksDir, "pre-commit");
2847
2943
  const block = [
2848
2944
  HOOK_BEGIN,
2849
2945
  "if command -v vg >/dev/null 2>&1; then",
@@ -2865,14 +2961,14 @@ ${content}`;
2865
2961
  fs8.chmodSync(file, 493);
2866
2962
  }
2867
2963
  function undo(root2) {
2868
- const hookFile = path36.join(hookDir(root2), "pre-commit");
2964
+ const hookFile = path37.join(hookDir(root2), "pre-commit");
2869
2965
  if (fs8.existsSync(hookFile)) {
2870
2966
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
2871
2967
  const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
2872
2968
  if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
2873
2969
  else fs8.writeFileSync(hookFile, next2);
2874
2970
  }
2875
- const attr = path36.join(root2, ".gitattributes");
2971
+ const attr = path37.join(root2, ".gitattributes");
2876
2972
  if (fs8.existsSync(attr)) {
2877
2973
  const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
2878
2974
  fs8.writeFileSync(attr, next2);
@@ -2885,10 +2981,10 @@ function undo(root2) {
2885
2981
  function hookDir(root2) {
2886
2982
  try {
2887
2983
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
2888
- if (configured) return path36.resolve(root2, configured);
2984
+ if (configured) return path37.resolve(root2, configured);
2889
2985
  } catch {
2890
2986
  }
2891
- return path36.join(root2, ".git", "hooks");
2987
+ return path37.join(root2, ".git", "hooks");
2892
2988
  }
2893
2989
  function git(root2, args) {
2894
2990
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -2896,6 +2992,111 @@ function git(root2, args) {
2896
2992
  function escapeRe(s) {
2897
2993
  return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2898
2994
  }
2995
+ var DEFAULT_DEBOUNCE_MS = 400;
2996
+ var SKIP_NAME = /* @__PURE__ */ new Set([
2997
+ ".git",
2998
+ "node_modules",
2999
+ ".vibgrate",
3000
+ "dist",
3001
+ "build",
3002
+ "out",
3003
+ "coverage",
3004
+ ".next",
3005
+ "target",
3006
+ "__pycache__",
3007
+ ".venv",
3008
+ "venv"
3009
+ ]);
3010
+ function registerWatch(program) {
3011
+ 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) {
3012
+ const global = readGlobal(this);
3013
+ const root2 = rootOf(global);
3014
+ const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3015
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3016
+ for (const w of watchRoots) {
3017
+ if (!fs8.existsSync(w)) {
3018
+ throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3019
+ }
3020
+ }
3021
+ let building = false;
3022
+ let pending = false;
3023
+ let timer = null;
3024
+ const rebuild = async (reason) => {
3025
+ if (building) {
3026
+ pending = true;
3027
+ return;
3028
+ }
3029
+ building = true;
3030
+ try {
3031
+ info(c.dim(`vg watch \xB7 rebuild (${reason})`));
3032
+ const result = await buildGraph({
3033
+ root: root2,
3034
+ paths: paths.length ? paths : void 0,
3035
+ fast: opts.fast === true,
3036
+ noGround: false
3037
+ });
3038
+ writeArtifacts(result.graph, {
3039
+ root: root2,
3040
+ html: opts.html !== false,
3041
+ report: opts.report !== false,
3042
+ graphPath: global.graph
3043
+ });
3044
+ writeSnapshot(root2, result.graph.provenance.corpusHash, result.fileStats);
3045
+ const { counts } = result.graph.meta;
3046
+ info(
3047
+ `${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`) : "")
3048
+ );
3049
+ } catch (err) {
3050
+ info(c.yellow(`vg watch \xB7 rebuild failed: ${err.message}`));
3051
+ } finally {
3052
+ building = false;
3053
+ if (pending) {
3054
+ pending = false;
3055
+ void rebuild("queued changes");
3056
+ }
3057
+ }
3058
+ };
3059
+ const schedule = (label) => {
3060
+ if (timer) clearTimeout(timer);
3061
+ timer = setTimeout(() => {
3062
+ timer = null;
3063
+ void rebuild(label);
3064
+ }, debounceMs);
3065
+ };
3066
+ await rebuild("initial");
3067
+ const watchers = [];
3068
+ for (const w of watchRoots) {
3069
+ try {
3070
+ const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3071
+ if (!filename) {
3072
+ schedule("change");
3073
+ return;
3074
+ }
3075
+ const parts = filename.split(path37.sep);
3076
+ if (parts.some((p) => SKIP_NAME.has(p))) return;
3077
+ if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3078
+ return;
3079
+ }
3080
+ schedule(filename);
3081
+ });
3082
+ watchers.push(watcher);
3083
+ } catch (err) {
3084
+ throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3085
+ }
3086
+ }
3087
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3088
+ await new Promise((resolve20) => {
3089
+ const stop = () => {
3090
+ for (const w of watchers) w.close();
3091
+ if (timer) clearTimeout(timer);
3092
+ resolve20();
3093
+ };
3094
+ process.once("SIGINT", stop);
3095
+ process.once("SIGTERM", stop);
3096
+ });
3097
+ });
3098
+ applyGlobalOptions(cmd);
3099
+ }
2899
3100
  function registerTests(program) {
2900
3101
  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
3102
  const global = readGlobal(this);
@@ -2951,8 +3152,17 @@ function registerFacts(program) {
2951
3152
  const { node: node2, candidates } = resolveOne(graph, name, opts.pick ? Number(opts.pick) : void 0);
2952
3153
  if (!node2) throw ambiguityError(`"${name}" ${candidates.length ? "is ambiguous" : "not found"}`, candidates);
2953
3154
  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)`);
3155
+ if (global.json) {
3156
+ json({
3157
+ node: node2.qualifiedName,
3158
+ facts: [],
3159
+ note: "map has no facts \u2014 rebuild with a current vg (facts ship on every build)"
3160
+ });
3161
+ } else {
3162
+ info(
3163
+ `${c.cyan("vg facts")} \xB7 none in this map \u2014 rebuild with ${c.bold("vg")} (facts ship on every build)`
3164
+ );
3165
+ }
2956
3166
  return;
2957
3167
  }
2958
3168
  const facts = graph.facts.filter((f) => f.subjectIds.includes(node2.id));
@@ -3207,7 +3417,7 @@ function normalizeStandards(raw) {
3207
3417
  }
3208
3418
  function loadStandards(root2) {
3209
3419
  for (const rel of STANDARDS_FILES) {
3210
- const p = path36__default.join(root2, rel);
3420
+ const p = path37__default.join(root2, rel);
3211
3421
  let text;
3212
3422
  try {
3213
3423
  text = fs8__default.readFileSync(p, "utf8");
@@ -4083,8 +4293,8 @@ async function runHostBench(options = {}) {
4083
4293
  }
4084
4294
  async function runArmSimulate(input) {
4085
4295
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4086
- const path38 = `${modelPath}#${arm.id}`;
4087
- const session = await acquireHostSession(lib, path38);
4296
+ const path39 = `${modelPath}#${arm.id}`;
4297
+ const session = await acquireHostSession(lib, path39);
4088
4298
  const system = "You are a coding agent with a Task Capsule.";
4089
4299
  const capsule = "function readConfig(): Config { return load(); }";
4090
4300
  let last = null;
@@ -5026,7 +5236,7 @@ function registerModels(program) {
5026
5236
  );
5027
5237
  });
5028
5238
  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) {
5239
+ 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
5240
  const global = readGlobal(this);
5031
5241
  const root2 = rootOf(global);
5032
5242
  const sys = gatherSystemMemory();
@@ -5058,7 +5268,7 @@ function registerModels(program) {
5058
5268
  info(c.yellow(" will not fit \u2014 choose a lower mode or free memory before loading"));
5059
5269
  }
5060
5270
  });
5061
- applyGlobalOptions(resolve19);
5271
+ applyGlobalOptions(resolve20);
5062
5272
  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
5273
  const global = readGlobal(this);
5064
5274
  const root2 = rootOf(global);
@@ -5396,8 +5606,8 @@ function registerModels(program) {
5396
5606
  }
5397
5607
  });
5398
5608
  if (opts.out) {
5399
- const outPath = path36.resolve(opts.out);
5400
- fs8.mkdirSync(path36.dirname(outPath), { recursive: true });
5609
+ const outPath = path37.resolve(opts.out);
5610
+ fs8.mkdirSync(path37.dirname(outPath), { recursive: true });
5401
5611
  fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5402
5612
  `);
5403
5613
  if (!global.json) info(c.dim(` wrote ${outPath}`));
@@ -5508,11 +5718,11 @@ function fitColor(label) {
5508
5718
  return label;
5509
5719
  }
5510
5720
  function confirmYesNo(question) {
5511
- return new Promise((resolve19) => {
5721
+ return new Promise((resolve20) => {
5512
5722
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
5513
5723
  rl.question(`${question} [y/N] `, (answer) => {
5514
5724
  rl.close();
5515
- resolve19(/^y(es)?$/i.test(answer.trim()));
5725
+ resolve20(/^y(es)?$/i.test(answer.trim()));
5516
5726
  });
5517
5727
  });
5518
5728
  }
@@ -5538,7 +5748,7 @@ function printBackends(backends) {
5538
5748
  }
5539
5749
  }
5540
5750
  function codeConfigPath(root2) {
5541
- return path36.join(root2, ".vibgrate", "code.json");
5751
+ return path37.join(root2, ".vibgrate", "code.json");
5542
5752
  }
5543
5753
  function loadCodeConfig(root2) {
5544
5754
  try {
@@ -5620,7 +5830,7 @@ function discoverMcpServers(root2, ownServers) {
5620
5830
  const servers = {};
5621
5831
  const sources = [];
5622
5832
  for (const rel of MCP_CONFIG_FILES) {
5623
- const found = readMcpServersFile(path36.join(root2, rel));
5833
+ const found = readMcpServersFile(path37.join(root2, rel));
5624
5834
  const names = Object.keys(found);
5625
5835
  if (names.length) {
5626
5836
  sources.push(rel);
@@ -5647,7 +5857,7 @@ function registerCode(program) {
5647
5857
  try {
5648
5858
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2, providerForBackend: providerForBackend2 } = await import('./model-orchestrator-TVONAUPS.js');
5649
5859
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-5O2NN3GA.js');
5650
- const { loadGraph: loadGraph2 } = await import('./load-I333TGNI.js');
5860
+ const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
5651
5861
  const state = readOrchestratorState2();
5652
5862
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
5653
5863
  const pin = mode ? activePin2(mode, state) : null;
@@ -5731,7 +5941,7 @@ function registerCode(program) {
5731
5941
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
5732
5942
  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
5943
  }
5734
- const { runInteractive } = await import('./interactive-372NLI5C.js');
5944
+ const { runInteractive } = await import('./interactive-INGJNSON.js');
5735
5945
  await runInteractive(
5736
5946
  rootOf(global),
5737
5947
  global,
@@ -5785,18 +5995,18 @@ function registerCode(program) {
5785
5995
  }
5786
5996
  if (opts.streamJson && !opts.mock) {
5787
5997
  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');
5998
+ const { runCodeStreamJson } = await import('./stream-json-6ZBUA2L3.js');
5999
+ const { nodeCodeFs } = await import('./session-M72522AP.js');
5790
6000
  const readline5 = await import('readline');
5791
6001
  const child = await import('child_process');
5792
6002
  const { loadOrDiscoverFederation } = await import('./federation-SZWZIFZ7.js');
5793
6003
  const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
5794
6004
  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');
6005
+ const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
6006
+ const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
5797
6007
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
5798
6008
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
5799
- const { vgdRequest: vgdRequest2 } = await import('./vgd-7JV5KCNJ.js');
6009
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
5800
6010
  const federation = loadOrDiscoverFederation(root2);
5801
6011
  const modelProfile = mergeModelExecutionProfile(
5802
6012
  resolveModelExecutionProfile({
@@ -5885,8 +6095,8 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
5885
6095
  if (!autonomous && !tty) {
5886
6096
  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
6097
  }
5888
- const { agentTask } = await import('./interactive-372NLI5C.js');
5889
- const { nodeCodeFs } = await import('./session-ITPYQ5XI.js');
6098
+ const { agentTask } = await import('./interactive-INGJNSON.js');
6099
+ const { nodeCodeFs } = await import('./session-M72522AP.js');
5890
6100
  const { TtyPrompter } = await import('./ui-Q6DJ3GCU.js');
5891
6101
  let priorSummary;
5892
6102
  if (opts.continue) {
@@ -5908,11 +6118,11 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
5908
6118
  const { loadFederation } = await import('./federation-SZWZIFZ7.js');
5909
6119
  const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
5910
6120
  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');
6121
+ const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
6122
+ const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
5913
6123
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
5914
6124
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
5915
- const { vgdRequest: vgdRequest2 } = await import('./vgd-7JV5KCNJ.js');
6125
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
5916
6126
  const federation = loadFederation(root2);
5917
6127
  const modelProfile = mergeModelExecutionProfile(
5918
6128
  resolveModelExecutionProfile({
@@ -6056,11 +6266,11 @@ function resolveSecurityTierFlag(flag, fromConfig, auto) {
6056
6266
  return auto ? "L1" : "L0";
6057
6267
  }
6058
6268
  function confirm(question) {
6059
- return new Promise((resolve19) => {
6269
+ return new Promise((resolve20) => {
6060
6270
  const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
6061
6271
  rl.question(`${question} [y/N] `, (answer) => {
6062
6272
  rl.close();
6063
- resolve19(/^y(es)?$/i.test(answer.trim()));
6273
+ resolve20(/^y(es)?$/i.test(answer.trim()));
6064
6274
  });
6065
6275
  });
6066
6276
  }
@@ -6217,7 +6427,7 @@ async function addCmd(root2, rest, opts, asJson) {
6217
6427
  }
6218
6428
  function readPackageVersion(root2) {
6219
6429
  try {
6220
- const pkg = JSON.parse(fs8__default.readFileSync(path36__default.join(root2, "package.json"), "utf8"));
6430
+ const pkg = JSON.parse(fs8__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
6221
6431
  return typeof pkg.version === "string" ? pkg.version : void 0;
6222
6432
  } catch {
6223
6433
  return void 0;
@@ -6240,8 +6450,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
6240
6450
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
6241
6451
  const version = (opts.version || readPackageVersion(root2) || "").trim();
6242
6452
  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;
6453
+ const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6454
+ const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
6245
6455
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
6246
6456
  const result = await publishPrivateLibrary(
6247
6457
  { name, version, readme, dts, language: opts.language },
@@ -6354,7 +6564,7 @@ async function showCmd(root2, name, budget, asJson, opts = {}) {
6354
6564
  out(doc);
6355
6565
  }
6356
6566
  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) {
6567
+ 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
6568
  const global = readGlobal(this);
6359
6569
  const { graph } = requireGraph(global);
6360
6570
  const root2 = rootOf(global);
@@ -6365,13 +6575,15 @@ function registerExport(program) {
6365
6575
  graph,
6366
6576
  deps: needsDeps ? inventory(root2).records : void 0,
6367
6577
  models: needsDeps && !global.local ? discoverModels() : void 0,
6368
- generatedAt: graph.generatedAt
6578
+ generatedAt: graph.generatedAt,
6579
+ compact: opts.compact === true ? true : opts.compact === false ? false : void 0,
6580
+ slim: opts.slim === true
6369
6581
  });
6370
6582
  if (file === "-") {
6371
6583
  out(content.trimEnd());
6372
6584
  return;
6373
6585
  }
6374
- fs8.mkdirSync(path36.dirname(path36.resolve(file)), { recursive: true });
6586
+ fs8.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
6375
6587
  fs8.writeFileSync(file, content);
6376
6588
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
6377
6589
  });
@@ -6382,37 +6594,37 @@ function detectFormat(file) {
6382
6594
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
6383
6595
  if (lower.endsWith(".spdx.json")) return "spdx";
6384
6596
  if (file === "-") return "json";
6385
- return formatForExt(path36.extname(file));
6597
+ return formatForExt(path37.extname(file));
6386
6598
  }
6387
6599
  function registerBundle(program) {
6388
6600
  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
6601
  const global = readGlobal(this);
6390
6602
  const root2 = rootOf(global);
6391
- const outDir = path36.resolve(root2, opts.out ?? "vg-bundle");
6603
+ const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
6392
6604
  let grammarFiles;
6393
6605
  try {
6394
6606
  grammarFiles = resolvedGrammarFiles();
6395
6607
  } catch {
6396
6608
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
6397
6609
  }
6398
- fs8.mkdirSync(path36.join(outDir, "grammars"), { recursive: true });
6610
+ fs8.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
6399
6611
  let grammarCount = 0;
6400
6612
  for (const { fileName, absPath } of grammarFiles) {
6401
- fs8.copyFileSync(absPath, path36.join(outDir, "grammars", fileName));
6613
+ fs8.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
6402
6614
  grammarCount++;
6403
6615
  }
6404
6616
  const included = [`grammars/ (${grammarCount} .wasm)`];
6405
6617
  const graphSrc = resolveGraphPath(root2, global.graph);
6406
6618
  if (fs8.existsSync(graphSrc)) {
6407
- fs8.copyFileSync(graphSrc, path36.join(outDir, "graph.json"));
6619
+ fs8.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
6408
6620
  included.push("graph.json");
6409
6621
  }
6410
6622
  const cat = catalogPath(root2);
6411
6623
  if (fs8.existsSync(cat)) {
6412
- fs8.copyFileSync(cat, path36.join(outDir, "vibgrate.lib.json"));
6624
+ fs8.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
6413
6625
  included.push("vibgrate.lib.json");
6414
6626
  if (fs8.existsSync(libDir(root2))) {
6415
- fs8.cpSync(libDir(root2), path36.join(outDir, "lib"), { recursive: true });
6627
+ fs8.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
6416
6628
  included.push("lib/");
6417
6629
  }
6418
6630
  }
@@ -6424,15 +6636,15 @@ function registerBundle(program) {
6424
6636
  included,
6425
6637
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
6426
6638
  };
6427
- fs8.writeFileSync(path36.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
6639
+ fs8.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
6428
6640
  `);
6429
6641
  if (global.json) {
6430
- json({ out: path36.relative(root2, outDir), ...manifest });
6642
+ json({ out: path37.relative(root2, outDir), ...manifest });
6431
6643
  return;
6432
6644
  }
6433
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path36.relative(root2, outDir)}/`);
6645
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
6434
6646
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
6435
- info(c.dim(` offline: vg build --grammars "${path36.relative(root2, outDir)}/grammars"`));
6647
+ info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
6436
6648
  });
6437
6649
  applyGlobalOptions(cmd);
6438
6650
  }
@@ -6450,7 +6662,7 @@ async function runDoctor(global) {
6450
6662
  const root2 = rootOf(global);
6451
6663
  const local = global.local === true;
6452
6664
  const graphPath = resolveGraphPath(root2, global.graph);
6453
- const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path36.join(root2, f))) ?? null;
6665
+ const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path37.join(root2, f))) ?? null;
6454
6666
  const graph = loadGraph(root2, graphPath);
6455
6667
  let staleFiles = null;
6456
6668
  if (graph) {
@@ -6476,13 +6688,13 @@ async function runDoctor(global) {
6476
6688
  root: root2,
6477
6689
  configFile,
6478
6690
  map: {
6479
- path: path36.relative(root2, graphPath),
6691
+ path: path37.relative(root2, graphPath),
6480
6692
  built: graph !== null,
6481
6693
  generatedAt: graph?.generatedAt ?? null,
6482
6694
  staleFiles
6483
6695
  },
6484
6696
  libCatalog: {
6485
- path: path36.relative(root2, catalogPath(root2)),
6697
+ path: path37.relative(root2, catalogPath(root2)),
6486
6698
  present: fs8.existsSync(catalogPath(root2)),
6487
6699
  libraries: libCount
6488
6700
  },
@@ -6540,7 +6752,7 @@ async function runDoctor(global) {
6540
6752
  );
6541
6753
  info(
6542
6754
  ` 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}`
6755
+ ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
6544
6756
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
6545
6757
  );
6546
6758
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -6676,7 +6888,7 @@ function registerDaemon(program) {
6676
6888
  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
6889
  const global = readGlobal(this);
6678
6890
  const socketPath = socketOf(this);
6679
- const root2 = path36.resolve(rootArg ?? rootOf(global));
6891
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
6680
6892
  if (!await vgdIsRunning({ socketPath })) {
6681
6893
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
6682
6894
  }
@@ -6712,7 +6924,7 @@ function registerDaemon(program) {
6712
6924
  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
6925
  const global = readGlobal(this);
6714
6926
  const socketPath = socketOf(this);
6715
- const primary = path36.resolve(rootArg ?? rootOf(global));
6927
+ const primary = path37.resolve(rootArg ?? rootOf(global));
6716
6928
  if (!await vgdIsRunning({ socketPath })) {
6717
6929
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
6718
6930
  }
@@ -6740,11 +6952,11 @@ function registerDaemon(program) {
6740
6952
  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
6953
  const global = readGlobal(this);
6742
6954
  const socketPath = socketOf(this);
6743
- const root2 = path36.resolve(rootArg ?? rootOf(global));
6955
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
6744
6956
  if (!await vgdIsRunning({ socketPath })) {
6745
6957
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
6746
6958
  }
6747
- const { loadGraph: loadGraph2 } = await import('./load-I333TGNI.js');
6959
+ const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
6748
6960
  const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
6749
6961
  const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
6750
6962
  const opts = this.opts();
@@ -6860,7 +7072,7 @@ function socketOf(cmd) {
6860
7072
  let c2 = cmd;
6861
7073
  while (c2) {
6862
7074
  const opts = c2.opts();
6863
- if (opts.socket) return path36.resolve(opts.socket);
7075
+ if (opts.socket) return path37.resolve(opts.socket);
6864
7076
  c2 = c2.parent;
6865
7077
  }
6866
7078
  return vgdSocketPath();
@@ -7077,11 +7289,11 @@ function registerLlmHost(program) {
7077
7289
  applyGlobalOptions(cmd);
7078
7290
  }
7079
7291
  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");
7292
+ const rootDir = path37.resolve(targetPath);
7293
+ const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7082
7294
  await ensureDir(vibgrateDir2);
7083
7295
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7084
- const configPath = path36.join(rootDir, "vibgrate.config.ts");
7296
+ const configPath = path37.join(rootDir, "vibgrate.config.ts");
7085
7297
  if (await pathExists(configPath)) {
7086
7298
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7087
7299
  } else {
@@ -7089,7 +7301,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7089
7301
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7090
7302
  }
7091
7303
  if (opts.baseline) {
7092
- const { runBaseline } = await import('./baseline-TG4ATZGZ.js');
7304
+ const { runBaseline } = await import('./baseline-ATM5MXBZ.js');
7093
7305
  await runBaseline(rootDir);
7094
7306
  }
7095
7307
  console.log("");
@@ -7192,16 +7404,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
7192
7404
  };
7193
7405
  }
7194
7406
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
7195
- const content = await readFile3(path36.join(rootDir, relFile));
7407
+ const content = await readFile3(path37.join(rootDir, relFile));
7196
7408
  if (!content) return false;
7197
7409
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7198
7410
  return new RegExp(`\\b${escaped}\\b`).test(content);
7199
7411
  }
7200
7412
  async function defaultReadFile(absPath) {
7201
7413
  try {
7202
- const stat2 = await fs20.stat(absPath);
7414
+ const stat2 = await fs21.stat(absPath);
7203
7415
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
7204
- return await fs20.readFile(absPath, "utf8");
7416
+ return await fs21.readFile(absPath, "utf8");
7205
7417
  } catch {
7206
7418
  return null;
7207
7419
  }
@@ -7386,7 +7598,7 @@ var AI_ASSISTANT_DETECTORS = [
7386
7598
  async function detectAiAssistant(rootDir) {
7387
7599
  for (const detector of AI_ASSISTANT_DETECTORS) {
7388
7600
  for (const file of detector.files) {
7389
- if (await pathExists$1(path36.join(rootDir, file))) {
7601
+ if (await pathExists$1(path37.join(rootDir, file))) {
7390
7602
  return detector.name;
7391
7603
  }
7392
7604
  }
@@ -7579,7 +7791,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
7579
7791
  collectExcludes,
7580
7792
  []
7581
7793
  ).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);
7794
+ const rootDir = path37.resolve(targetPath);
7583
7795
  if (!await pathExists$1(rootDir)) {
7584
7796
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
7585
7797
  process.exit(1);
@@ -7587,7 +7799,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
7587
7799
  const hasDsn = !!resolveDsn(opts.dsn);
7588
7800
  const willPush = !opts.offline && (opts.push || hasDsn);
7589
7801
  const noLocalArtifacts = opts.localArtifacts === false;
7590
- const isFirstRun = !await pathExists$1(path36.join(rootDir, ".vibgrate", "scan_result.json"));
7802
+ const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
7591
7803
  let pinnedRegion;
7592
7804
  let planTier;
7593
7805
  let upgradeUrl;
@@ -7866,11 +8078,11 @@ function scanStaleness(rootDir, artifactPath) {
7866
8078
  scanned++;
7867
8079
  if (scanned > MAX_ENTRIES) break;
7868
8080
  if (e.isDirectory()) {
7869
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path36.join(dir, e.name), depth + 1);
8081
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
7870
8082
  continue;
7871
8083
  }
7872
8084
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
7873
- const abs = path36.join(dir, e.name);
8085
+ const abs = path37.join(dir, e.name);
7874
8086
  let mtimeMs;
7875
8087
  try {
7876
8088
  mtimeMs = fs8.statSync(abs).mtimeMs;
@@ -7879,7 +8091,7 @@ function scanStaleness(rootDir, artifactPath) {
7879
8091
  }
7880
8092
  if (mtimeMs > newest) {
7881
8093
  newest = mtimeMs;
7882
- newestChanged = path36.relative(rootDir, abs) || e.name;
8094
+ newestChanged = path37.relative(rootDir, abs) || e.name;
7883
8095
  }
7884
8096
  }
7885
8097
  };
@@ -8016,13 +8228,13 @@ function analyzeTree(root2, packages) {
8016
8228
  if (filesSeen >= MAX_FILES) return;
8017
8229
  if (entry.isDirectory()) {
8018
8230
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8019
- walk2(path36.join(dir, entry.name), depth + 1);
8231
+ walk2(path37.join(dir, entry.name), depth + 1);
8020
8232
  continue;
8021
8233
  }
8022
- const fileEco = EXT_ECOSYSTEM[path36.extname(entry.name)];
8234
+ const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8023
8235
  if (!fileEco || fileEco === "unknown") continue;
8024
8236
  filesSeen++;
8025
- const full = path36.join(dir, entry.name);
8237
+ const full = path37.join(dir, entry.name);
8026
8238
  let content;
8027
8239
  try {
8028
8240
  if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
@@ -8337,7 +8549,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8337
8549
  }
8338
8550
  const outcomes = effective.map((t) => {
8339
8551
  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)) };
8552
+ return { t, res: run(c2, path37.join(rootDir, t.dir)) };
8341
8553
  });
8342
8554
  const failures = outcomes.filter((o) => !o.res.ok);
8343
8555
  if (failures.length === 0) {
@@ -8366,8 +8578,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8366
8578
  return results;
8367
8579
  }
8368
8580
  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");
8581
+ var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
8582
+ var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
8371
8583
  async function fetchLatestVersion() {
8372
8584
  try {
8373
8585
  const controller = new AbortController();
@@ -8394,8 +8606,8 @@ async function fetchLatestVersion() {
8394
8606
  }
8395
8607
  async function writeCache(data) {
8396
8608
  try {
8397
- await fs20.mkdir(CACHE_DIR, { recursive: true });
8398
- await fs20.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
8609
+ await fs21.mkdir(CACHE_DIR, { recursive: true });
8610
+ await fs21.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
8399
8611
  } catch {
8400
8612
  }
8401
8613
  }
@@ -8436,14 +8648,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
8436
8648
  pm: "yarn",
8437
8649
  root: () => {
8438
8650
  const dir = tryRun("yarn global dir");
8439
- return dir ? path36.join(dir, "node_modules") : null;
8651
+ return dir ? path37.join(dir, "node_modules") : null;
8440
8652
  }
8441
8653
  },
8442
- { pm: "bun", root: () => path36.join(os.homedir(), ".bun", "install", "global", "node_modules") }
8654
+ { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
8443
8655
  ];
8444
8656
  for (const probe of probes) {
8445
8657
  const root2 = probe.root();
8446
- if (root2 && await pathExists(path36.join(root2, pkg))) return probe.pm;
8658
+ if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
8447
8659
  }
8448
8660
  return null;
8449
8661
  }
@@ -8462,15 +8674,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
8462
8674
  }
8463
8675
  }
8464
8676
  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";
8677
+ if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
8678
+ if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
8679
+ if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
8468
8680
  return "npm";
8469
8681
  }
8470
8682
  async function detectWorkspaceRoot(cwd) {
8471
- if (await pathExists(path36.join(cwd, "pnpm-workspace.yaml"))) return true;
8683
+ if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
8472
8684
  try {
8473
- const pkgPath = path36.join(cwd, "package.json");
8685
+ const pkgPath = path37.join(cwd, "package.json");
8474
8686
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
8475
8687
  const pkg = JSON.parse(raw);
8476
8688
  return pkg.workspaces != null;
@@ -8495,7 +8707,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
8495
8707
  }
8496
8708
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
8497
8709
  try {
8498
- const pkgPath = path36.join(cwd, "package.json");
8710
+ const pkgPath = path37.join(cwd, "package.json");
8499
8711
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
8500
8712
  const parsed = JSON.parse(raw);
8501
8713
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -8507,11 +8719,11 @@ async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
8507
8719
  async function confirmWorkspaceRoot(pm) {
8508
8720
  if (!(process.stdin.isTTY && process.stdout.isTTY)) return false;
8509
8721
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8510
- return new Promise((resolve19) => {
8722
+ return new Promise((resolve20) => {
8511
8723
  rl.question(chalk7.yellow(`Update the ${pm} workspace root with -w? [y/N]: `), (ans) => {
8512
8724
  rl.close();
8513
8725
  const t = ans.trim().toLowerCase();
8514
- resolve19(t === "y" || t === "yes");
8726
+ resolve20(t === "y" || t === "yes");
8515
8727
  });
8516
8728
  });
8517
8729
  }
@@ -8643,13 +8855,13 @@ function collectCandidates(artifact) {
8643
8855
  return out2;
8644
8856
  }
8645
8857
  var defaultFixScanner = async (rootDir) => {
8646
- const scratch = path36.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
8858
+ const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
8647
8859
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
8648
8860
  const advanced = await loadAdvancedScanHook();
8649
8861
  return runCoreScan(rootDir, scanOpts, advanced);
8650
8862
  };
8651
8863
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
8652
- const artifactPath = path36.isAbsolute(inFile) ? inFile : path36.join(rootDir, inFile);
8864
+ const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
8653
8865
  if (await pathExists(artifactPath)) {
8654
8866
  const staleness = scanStaleness(rootDir, artifactPath);
8655
8867
  if (!staleness.stale) {
@@ -8676,7 +8888,7 @@ async function repositoryIdentity(rootDir, override) {
8676
8888
  }
8677
8889
  }
8678
8890
  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);
8891
+ const rootDir = path37.resolve(targetPath);
8680
8892
  if (!await pathExists(rootDir)) {
8681
8893
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8682
8894
  process.exit(1);
@@ -8837,7 +9049,7 @@ function emit(report, format) {
8837
9049
  }
8838
9050
  }
8839
9051
  function relProjectDir(rootDir, projectPath) {
8840
- const rel = path36.isAbsolute(projectPath) ? path36.relative(rootDir, projectPath) : projectPath;
9052
+ const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
8841
9053
  return rel === "" ? "." : rel;
8842
9054
  }
8843
9055
  async function buildTargetResolver(rootDir, artifact) {
@@ -8878,14 +9090,14 @@ function promptPlanSelection(response) {
8878
9090
  const defaultIdx = plans.findIndex((p) => p.tier === response.recommended);
8879
9091
  const def = defaultIdx >= 0 ? defaultIdx + 1 : 1;
8880
9092
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
8881
- return new Promise((resolve19) => {
9093
+ return new Promise((resolve20) => {
8882
9094
  rl.question(`Plan [1-${plans.length}, default ${def}, q to cancel]: `, (ans) => {
8883
9095
  rl.close();
8884
9096
  const t = ans.trim().toLowerCase();
8885
- if (t === "q" || t === "quit") return resolve19(null);
9097
+ if (t === "q" || t === "quit") return resolve20(null);
8886
9098
  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);
9099
+ if (!Number.isInteger(n) || n < 1 || n > plans.length) return resolve20(null);
9100
+ resolve20(plans[n - 1].tier);
8889
9101
  });
8890
9102
  });
8891
9103
  }
@@ -9672,7 +9884,7 @@ function formatMarkdown(artifact) {
9672
9884
 
9673
9885
  // src/reporting/commands/report.ts
9674
9886
  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);
9887
+ const artifactPath = path37.resolve(opts.in);
9676
9888
  if (!await pathExists(artifactPath)) {
9677
9889
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
9678
9890
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -9718,10 +9930,10 @@ function openUrl(url) {
9718
9930
  }
9719
9931
 
9720
9932
  // src/reporting/commands/login.ts
9721
- var delay = (ms) => new Promise((resolve19) => setTimeout(resolve19, ms));
9933
+ var delay = (ms) => new Promise((resolve20) => setTimeout(resolve20, ms));
9722
9934
  function isInside(dir, file) {
9723
- const rel = path36.relative(dir, file);
9724
- return !!rel && !rel.startsWith("..") && !path36.isAbsolute(rel);
9935
+ const rel = path37.relative(dir, file);
9936
+ return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
9725
9937
  }
9726
9938
  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
9939
  "--local",
@@ -9976,7 +10188,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
9976
10188
  try {
9977
10189
  const statements = [];
9978
10190
  if (opts.from) {
9979
- const fromPath = path36.resolve(opts.from);
10191
+ const fromPath = path37.resolve(opts.from);
9980
10192
  if (!await pathExists(fromPath)) {
9981
10193
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
9982
10194
  `));
@@ -9994,9 +10206,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
9994
10206
  });
9995
10207
  const json2 = JSON.stringify(doc, null, 2);
9996
10208
  if (opts.out) {
9997
- await writeTextFile(path36.resolve(opts.out), json2 + "\n");
10209
+ await writeTextFile(path37.resolve(opts.out), json2 + "\n");
9998
10210
  process.stderr.write(
9999
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path36.resolve(opts.out)}
10211
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
10000
10212
  `
10001
10213
  );
10002
10214
  } else {
@@ -10179,7 +10391,7 @@ function formatDeltaText(base, current) {
10179
10391
  return lines.join("\n");
10180
10392
  }
10181
10393
  async function readArtifactOrExit(filePath) {
10182
- const absolutePath = path36.resolve(filePath);
10394
+ const absolutePath = path37.resolve(filePath);
10183
10395
  if (!await pathExists(absolutePath)) {
10184
10396
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
10185
10397
  process.exit(1);
@@ -10196,7 +10408,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
10196
10408
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
10197
10409
  const body = JSON.stringify(sbom, null, 2);
10198
10410
  if (opts.out) {
10199
- await writeTextFile(path36.resolve(opts.out), body);
10411
+ await writeTextFile(path37.resolve(opts.out), body);
10200
10412
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
10201
10413
  } else {
10202
10414
  console.log(body);
@@ -10207,7 +10419,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
10207
10419
  const current = await readArtifactOrExit(opts.to);
10208
10420
  const report = formatDeltaText(base, current);
10209
10421
  if (opts.out) {
10210
- await writeTextFile(path36.resolve(opts.out), report);
10422
+ await writeTextFile(path37.resolve(opts.out), report);
10211
10423
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
10212
10424
  } else {
10213
10425
  console.log(report);
@@ -10338,20 +10550,20 @@ function resolveRegime(id) {
10338
10550
  return regime;
10339
10551
  }
10340
10552
  function evidenceDir(root2) {
10341
- return path36.join(root2, ".vibgrate", "evidence");
10553
+ return path37.join(root2, ".vibgrate", "evidence");
10342
10554
  }
10343
10555
  function orgPath(root2) {
10344
- return path36.join(evidenceDir(root2), "org.json");
10556
+ return path37.join(evidenceDir(root2), "org.json");
10345
10557
  }
10346
10558
  function productsPath(root2) {
10347
- return path36.join(evidenceDir(root2), "products.json");
10559
+ return path37.join(evidenceDir(root2), "products.json");
10348
10560
  }
10349
10561
  function releasesDir(root2) {
10350
- return path36.join(evidenceDir(root2), "releases");
10562
+ return path37.join(evidenceDir(root2), "releases");
10351
10563
  }
10352
10564
  function releasePath(root2, productId, version) {
10353
10565
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
10354
- return path36.join(releasesDir(root2), `${safe}.json`);
10566
+ return path37.join(releasesDir(root2), `${safe}.json`);
10355
10567
  }
10356
10568
  var DEFAULT_ORG = {
10357
10569
  responsiblePersons: [],
@@ -10382,7 +10594,7 @@ async function freezeRelease(root2, release) {
10382
10594
  const p = releasePath(root2, release.productId, release.version);
10383
10595
  if (await pathExists(p)) {
10384
10596
  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`,
10597
+ `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
10598
  ExitCode.USAGE_ERROR
10387
10599
  );
10388
10600
  }
@@ -10396,7 +10608,7 @@ async function loadReleases(root2, productId) {
10396
10608
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
10397
10609
  const releases = [];
10398
10610
  for (const f of files) {
10399
- const rel = await readJsonFile(path36.join(dir, f));
10611
+ const rel = await readJsonFile(path37.join(dir, f));
10400
10612
  if (!productId || rel.productId === productId) releases.push(rel);
10401
10613
  }
10402
10614
  return releases;
@@ -11091,12 +11303,12 @@ function verifyEvidenceEnvelope(env, opts = {}) {
11091
11303
  var DEFAULT_KEY = "attest-key.pem";
11092
11304
  function resolveSigningKey(root2, explicit) {
11093
11305
  const chosen = process.env.VG_ATTEST_KEY;
11094
- const keyPath = chosen ? path36.resolve(chosen) : path36.join(root2, ".vibgrate", DEFAULT_KEY);
11306
+ const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
11095
11307
  let minted = false;
11096
11308
  if (!fs8.existsSync(keyPath)) {
11097
11309
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
11098
11310
  const kp = generateKeypair();
11099
- fs8.mkdirSync(path36.dirname(keyPath), { recursive: true });
11311
+ fs8.mkdirSync(path37.dirname(keyPath), { recursive: true });
11100
11312
  fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11101
11313
  fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
11102
11314
  minted = true;
@@ -11114,16 +11326,16 @@ function resolveSigningKey(root2, explicit) {
11114
11326
  }
11115
11327
  function writeBundle(input) {
11116
11328
  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)}
11329
+ fs8.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11330
+ const write = (rel, data) => fs8.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
11119
11331
  `);
11120
11332
  write("result.json", input.result);
11121
- write(path36.join("inputs", "advisory.json"), input.advisory);
11333
+ write(path37.join("inputs", "advisory.json"), input.advisory);
11122
11334
  for (const rel of input.releases) {
11123
11335
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11124
- write(path36.join("inputs", "releases", `${safe}.json`), rel);
11336
+ write(path37.join("inputs", "releases", `${safe}.json`), rel);
11125
11337
  }
11126
- write(path36.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11338
+ write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11127
11339
  write("provenance.json", {
11128
11340
  method: "deterministic",
11129
11341
  modelDrafted: [],
@@ -11139,13 +11351,13 @@ function writeBundle(input) {
11139
11351
  disclaimer: input.regime.disclaimer
11140
11352
  });
11141
11353
  if (input.envelope) {
11142
- fs8.writeFileSync(path36.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11354
+ fs8.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11143
11355
  `);
11144
11356
  }
11145
11357
  if (input.timestampToken) {
11146
- fs8.writeFileSync(path36.join(dir, "timestamp.tsr"), input.timestampToken);
11358
+ fs8.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
11147
11359
  }
11148
- fs8.writeFileSync(path36.join(dir, "VERIFY.md"), verifyDoc(input));
11360
+ fs8.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
11149
11361
  return dir;
11150
11362
  }
11151
11363
  function verifyDoc(input) {
@@ -11206,13 +11418,13 @@ function undeterminedFields(result, regime) {
11206
11418
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
11207
11419
  }
11208
11420
  async function recordDrill(root2, record) {
11209
- const dir = path36.join(evidenceDir(root2), "drills");
11210
- const p = path36.join(dir, `${record.drillId}.json`);
11421
+ const dir = path37.join(evidenceDir(root2), "drills");
11422
+ const p = path37.join(dir, `${record.drillId}.json`);
11211
11423
  await writeJsonFile(p, record);
11212
11424
  return p;
11213
11425
  }
11214
11426
  async function hasRecentDrill(root2, asOf) {
11215
- const dir = path36.join(evidenceDir(root2), "drills");
11427
+ const dir = path37.join(evidenceDir(root2), "drills");
11216
11428
  if (!await pathExists(dir)) return void 0;
11217
11429
  const { readdir } = await import('fs/promises');
11218
11430
  const { readJsonFile: readJsonFile2 } = await import('./fs-O5IQYXHO.js');
@@ -11220,7 +11432,7 @@ async function hasRecentDrill(root2, asOf) {
11220
11432
  if (files.length === 0) return void 0;
11221
11433
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
11222
11434
  for (const f of files) {
11223
- const rec = await readJsonFile2(path36.join(dir, f));
11435
+ const rec = await readJsonFile2(path37.join(dir, f));
11224
11436
  if (rec.ranAt >= cutoff) return true;
11225
11437
  }
11226
11438
  return false;
@@ -11300,7 +11512,7 @@ function formatRegimeList() {
11300
11512
 
11301
11513
  // src/reporting/commands/evidence/index.ts
11302
11514
  function root(opts) {
11303
- return path36.resolve(opts.cwd ?? process.cwd());
11515
+ return path37.resolve(opts.cwd ?? process.cwd());
11304
11516
  }
11305
11517
  function slug(name) {
11306
11518
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -11388,7 +11600,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11388
11600
  const release = await buildRelease({
11389
11601
  productId: product.id,
11390
11602
  version,
11391
- from: path36.resolve(rootDir, opts.from),
11603
+ from: path37.resolve(rootDir, opts.from),
11392
11604
  shipDate: opts.shipDate,
11393
11605
  buildId: opts.buildId,
11394
11606
  artefactDigest: opts.digest,
@@ -11396,7 +11608,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11396
11608
  frozenAt: nowIso()
11397
11609
  });
11398
11610
  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)}`);
11611
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
11400
11612
  });
11401
11613
  async function runExposure(rootDir, vuln, opts) {
11402
11614
  const org = await loadOrg(rootDir);
@@ -11448,7 +11660,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
11448
11660
  console.log("\n" + buildPack(result, regime, org, stage));
11449
11661
  }
11450
11662
  if (opts.bundle) {
11451
- const dir = path36.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
11663
+ const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
11452
11664
  let envelope;
11453
11665
  if (opts.sign !== false) {
11454
11666
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -11456,7 +11668,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
11456
11668
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
11457
11669
  }
11458
11670
  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" : ""}`);
11671
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
11460
11672
  }
11461
11673
  process.exitCode = exposureExit(result.overallStatus);
11462
11674
  });
@@ -11488,7 +11700,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
11488
11700
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
11489
11701
  const md = buildPack(result, regime, org, stage);
11490
11702
  if (opts.out) {
11491
- fs8.writeFileSync(path36.resolve(rootDir, opts.out), md);
11703
+ fs8.writeFileSync(path37.resolve(rootDir, opts.out), md);
11492
11704
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
11493
11705
  } else {
11494
11706
  console.log(md);
@@ -11530,18 +11742,18 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
11530
11742
  }
11531
11743
  });
11532
11744
  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;
11745
+ const abs = path37.resolve(bundlePath);
11746
+ const envPath = fs8.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
11535
11747
  if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
11536
11748
  const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
11537
- const resultPath = path36.join(path36.dirname(envPath), "result.json");
11749
+ const resultPath = path37.join(path37.dirname(envPath), "result.json");
11538
11750
  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;
11751
+ const publicKeyPem = opts.pub ? fs8.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
11540
11752
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
11541
11753
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
11542
11754
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
11543
11755
  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");
11756
+ const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
11545
11757
  if (fs8.existsSync(tsrPath) && result) {
11546
11758
  const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
11547
11759
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
@@ -11610,12 +11822,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
11610
11822
  const releases = [];
11611
11823
  for (const list of releasesByProduct.values()) releases.push(...list);
11612
11824
  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)`);
11825
+ const dir = path37.resolve(rootDir, opts.out);
11826
+ await writeJsonFile(path37.join(dir, "org.json"), org);
11827
+ await writeJsonFile(path37.join(dir, "products.json"), products);
11828
+ for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
11829
+ await writeJsonFile(path37.join(dir, "readiness.json"), report);
11830
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
11619
11831
  });
11620
11832
  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
11833
  const rootDir = root(opts);
@@ -11641,8 +11853,8 @@ var pushCmd = new Command("push").description("Push the product registry (and an
11641
11853
  }));
11642
11854
  let exposure;
11643
11855
  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;
11856
+ const raw = path37.resolve(rootDir, opts.result);
11857
+ const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
11646
11858
  if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
11647
11859
  exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
11648
11860
  }
@@ -11708,6 +11920,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
11708
11920
  "install",
11709
11921
  "uninstall",
11710
11922
  "share",
11923
+ "watch",
11711
11924
  "help",
11712
11925
  // Drift-reporting verbs (merged from the Vibgrate CLI).
11713
11926
  "init",
@@ -11748,6 +11961,7 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
11748
11961
  registerLsp(program);
11749
11962
  registerInstall(program);
11750
11963
  registerShare(program);
11964
+ registerWatch(program);
11751
11965
  registerTests(program);
11752
11966
  registerFacts(program);
11753
11967
  registerGuide(program);
@@ -11832,7 +12046,7 @@ function dispatch(argv, cwd) {
11832
12046
  }
11833
12047
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
11834
12048
  if (looksLikeQuestion) return ["ask", ...args];
11835
- if (fs8.existsSync(path36.resolve(cwd, first))) {
12049
+ if (fs8.existsSync(path37.resolve(cwd, first))) {
11836
12050
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
11837
12051
  }
11838
12052
  const moved = MOVED_COMMANDS[first];
@@ -11877,9 +12091,9 @@ async function main(argv = process.argv) {
11877
12091
  }
11878
12092
  function readCwd(raw) {
11879
12093
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
11880
- if (i >= 0 && raw[i + 1]) return path36.resolve(raw[i + 1]);
12094
+ if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
11881
12095
  const eq = raw.find((a) => a.startsWith("--cwd="));
11882
- if (eq) return path36.resolve(eq.slice("--cwd=".length));
12096
+ if (eq) return path37.resolve(eq.slice("--cwd=".length));
11883
12097
  return process.cwd();
11884
12098
  }
11885
12099
  function handleError(err) {