@vibgrate/cli 2026.729.1 → 2026.729.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 (84) hide show
  1. package/DOCS.md +5 -1
  2. package/dist/agent-Z4Z66IGM.js +22 -0
  3. package/dist/agent-Z4Z66IGM.js.map +1 -0
  4. package/dist/baseline-Q3QQF5QF.js +9 -0
  5. package/dist/{baseline-MROWBNK7.js.map → baseline-Q3QQF5QF.js.map} +1 -1
  6. package/dist/checkpoint-4WFZMKEO.js +56 -0
  7. package/dist/checkpoint-4WFZMKEO.js.map +1 -0
  8. package/dist/{chunk-YMHQZ24Q.js → chunk-3FQSBVQD.js} +6 -6
  9. package/dist/{chunk-YMHQZ24Q.js.map → chunk-3FQSBVQD.js.map} +1 -1
  10. package/dist/{chunk-2ZHWF7C6.js → chunk-42RDYQFF.js} +42 -67
  11. package/dist/chunk-42RDYQFF.js.map +1 -0
  12. package/dist/{chunk-OIWHR57Q.js → chunk-4BOWWYSE.js} +37 -19
  13. package/dist/chunk-4BOWWYSE.js.map +1 -0
  14. package/dist/chunk-543E6WDJ.js +61 -0
  15. package/dist/chunk-543E6WDJ.js.map +1 -0
  16. package/dist/{chunk-JIBOJTGS.js → chunk-5HYCB55P.js} +101 -101
  17. package/dist/chunk-5HYCB55P.js.map +1 -0
  18. package/dist/{chunk-EEVZVXT2.js → chunk-5MNX3OLS.js} +19 -11
  19. package/dist/chunk-5MNX3OLS.js.map +1 -0
  20. package/dist/{chunk-2JV3J5NF.js → chunk-EQ3IOFIG.js} +55 -9
  21. package/dist/chunk-EQ3IOFIG.js.map +1 -0
  22. package/dist/{chunk-SIPGDJT4.js → chunk-EVLS2M5G.js} +4 -4
  23. package/dist/{chunk-SIPGDJT4.js.map → chunk-EVLS2M5G.js.map} +1 -1
  24. package/dist/{chunk-TQFY6OSV.js → chunk-HWFVBYX4.js} +6 -6
  25. package/dist/{chunk-TQFY6OSV.js.map → chunk-HWFVBYX4.js.map} +1 -1
  26. package/dist/{chunk-YKVNMNEM.js → chunk-JXMZCTVZ.js} +3 -3
  27. package/dist/{chunk-YKVNMNEM.js.map → chunk-JXMZCTVZ.js.map} +1 -1
  28. package/dist/{chunk-3IJB5UJI.js → chunk-KBPNH67Q.js} +4 -4
  29. package/dist/{chunk-3IJB5UJI.js.map → chunk-KBPNH67Q.js.map} +1 -1
  30. package/dist/{chunk-RZEXHDCF.js → chunk-MYM5VIJ4.js} +14 -3
  31. package/dist/chunk-MYM5VIJ4.js.map +1 -0
  32. package/dist/chunk-N3HCPBFY.js +6 -0
  33. package/dist/{chunk-NQ4FSRXL.js.map → chunk-N3HCPBFY.js.map} +1 -1
  34. package/dist/{chunk-PMYWZRRS.js → chunk-RBIRXQR6.js} +21 -3
  35. package/dist/chunk-RBIRXQR6.js.map +1 -0
  36. package/dist/{chunk-TCJTQGAO.js → chunk-RGEVBSLK.js} +3 -3
  37. package/dist/{chunk-TCJTQGAO.js.map → chunk-RGEVBSLK.js.map} +1 -1
  38. package/dist/{chunk-QS5BTBRX.js → chunk-RIEUPFXO.js} +4 -4
  39. package/dist/{chunk-QS5BTBRX.js.map → chunk-RIEUPFXO.js.map} +1 -1
  40. package/dist/{chunk-PRGCCW7D.js → chunk-WBMMRERH.js} +3 -3
  41. package/dist/{chunk-PRGCCW7D.js.map → chunk-WBMMRERH.js.map} +1 -1
  42. package/dist/{chunk-6HX47EBL.js → chunk-X634FZVG.js} +3 -3
  43. package/dist/{chunk-6HX47EBL.js.map → chunk-X634FZVG.js.map} +1 -1
  44. package/dist/{chunk-CF2MLSOV.js → chunk-YMSXP6AO.js} +3 -3
  45. package/dist/{chunk-CF2MLSOV.js.map → chunk-YMSXP6AO.js.map} +1 -1
  46. package/dist/cli.js +738 -383
  47. package/dist/cli.js.map +1 -1
  48. package/dist/{graph-backend-GBL33GMW.js → graph-backend-G5Y6QQV4.js} +4 -4
  49. package/dist/{graph-backend-GBL33GMW.js.map → graph-backend-G5Y6QQV4.js.map} +1 -1
  50. package/dist/index.d.ts +1 -1
  51. package/dist/index.js +8 -8
  52. package/dist/{interactive-R5VQGDWP.js → interactive-MJVMY5JP.js} +23 -22
  53. package/dist/interactive-MJVMY5JP.js.map +1 -0
  54. package/dist/{llm-host-5RE34322.js → llm-host-DZBD5D36.js} +5 -5
  55. package/dist/{llm-host-5RE34322.js.map → llm-host-DZBD5D36.js.map} +1 -1
  56. package/dist/load-4PARCNMD.js +9 -0
  57. package/dist/{load-WKIZF2AK.js.map → load-4PARCNMD.js.map} +1 -1
  58. package/dist/rules-ASYEUNB5.js +74 -0
  59. package/dist/rules-ASYEUNB5.js.map +1 -0
  60. package/dist/runtime-session-AILFASQV.js +19 -0
  61. package/dist/{runtime-session-5NRB6BTR.js.map → runtime-session-AILFASQV.js.map} +1 -1
  62. package/dist/{session-2JT4AUZT.js → session-3OBIQLE4.js} +5 -5
  63. package/dist/{session-2JT4AUZT.js.map → session-3OBIQLE4.js.map} +1 -1
  64. package/dist/{stream-json-Y45JBNYP.js → stream-json-MTPWWVRR.js} +81 -9
  65. package/dist/stream-json-MTPWWVRR.js.map +1 -0
  66. package/dist/{vg-mcp-bridge-YXQS6HTO.js → vg-mcp-bridge-BLHEIWMT.js} +6 -6
  67. package/dist/{vg-mcp-bridge-YXQS6HTO.js.map → vg-mcp-bridge-BLHEIWMT.js.map} +1 -1
  68. package/dist/{vgd-KC5RCOP6.js → vgd-S7D2SITC.js} +8 -8
  69. package/dist/vgd-S7D2SITC.js.map +1 -0
  70. package/package.json +1 -1
  71. package/dist/baseline-MROWBNK7.js +0 -9
  72. package/dist/chunk-2JV3J5NF.js.map +0 -1
  73. package/dist/chunk-2ZHWF7C6.js.map +0 -1
  74. package/dist/chunk-EEVZVXT2.js.map +0 -1
  75. package/dist/chunk-JIBOJTGS.js.map +0 -1
  76. package/dist/chunk-NQ4FSRXL.js +0 -6
  77. package/dist/chunk-OIWHR57Q.js.map +0 -1
  78. package/dist/chunk-PMYWZRRS.js.map +0 -1
  79. package/dist/chunk-RZEXHDCF.js.map +0 -1
  80. package/dist/interactive-R5VQGDWP.js.map +0 -1
  81. package/dist/load-WKIZF2AK.js +0 -9
  82. package/dist/runtime-session-5NRB6BTR.js +0 -19
  83. package/dist/stream-json-Y45JBNYP.js.map +0 -1
  84. package/dist/vgd-KC5RCOP6.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,63 +1,65 @@
1
1
  #!/usr/bin/env node
2
- import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-EEVZVXT2.js';
3
- export { runBuild } from './chunk-EEVZVXT2.js';
4
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-2ZHWF7C6.js';
5
- import { loadAdvancedScanHook, baselineCommand } from './chunk-CF2MLSOV.js';
6
- import { runCodeSession } from './chunk-PRGCCW7D.js';
7
- import { summarizeDiffs, ScriptedProvider } from './chunk-RZEXHDCF.js';
2
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-5MNX3OLS.js';
3
+ export { runBuild } from './chunk-5MNX3OLS.js';
4
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-YMSXP6AO.js';
5
+ import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
6
+ import { runCodeSession } from './chunk-WBMMRERH.js';
8
7
  import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
9
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-2JV3J5NF.js';
8
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-EQ3IOFIG.js';
10
9
  import './chunk-5I4VSBWQ.js';
11
10
  import './chunk-IS7VTH2Q.js';
12
11
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
13
12
  import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-NZELMYT4.js';
14
13
  import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
15
14
  import './chunk-IZDH67DX.js';
16
- import './chunk-TCJTQGAO.js';
17
- import { vgdIsRunning, vgdRequest, vgdSocketPath } from './chunk-PMYWZRRS.js';
18
- import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-SIPGDJT4.js';
19
- import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-6HX47EBL.js';
20
- import { buildIdentifierTrieFromGraph } from './chunk-JIBOJTGS.js';
21
- import './chunk-7AVYKZEM.js';
22
- import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
15
+ import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
16
+ import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-X634FZVG.js';
17
+ import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-42RDYQFF.js';
18
+ import './chunk-543E6WDJ.js';
19
+ import { summarizeDiffs, ScriptedProvider } from './chunk-MYM5VIJ4.js';
23
20
  import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
24
- import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-TQFY6OSV.js';
25
- import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-YMHQZ24Q.js';
26
- import { resolveDsn, resolveIngestHost, dashHostForIngestHost, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-QS5BTBRX.js';
21
+ import './chunk-RGEVBSLK.js';
22
+ import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
23
+ import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
24
+ import './chunk-7AVYKZEM.js';
25
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-HWFVBYX4.js';
26
+ import { CliError, ExitCode, refreshIfStale, driftCount, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, SKIP_DIRS, SKIP_FILES } from './chunk-3FQSBVQD.js';
27
+ import { resolveDsn, resolveIngestHost, dashHostForIngestHost, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-RIEUPFXO.js';
28
+ import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-4BOWWYSE.js';
29
+ import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
27
30
  import './chunk-IPICO2RV.js';
28
31
  import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-G4HTI4ZM.js';
29
- import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-OIWHR57Q.js';
30
32
  import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
31
- import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
33
+ import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
32
34
  import { resolveOne } from './chunk-J7LKEB2R.js';
33
35
  import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-EETK7S43.js';
34
36
  import { discoverModels } from './chunk-CQDUBAQY.js';
35
- import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
36
37
  import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
37
38
  import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
38
39
  import './chunk-RXP66R2E.js';
39
- import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-YKVNMNEM.js';
40
- import { VERSION } from './chunk-NQ4FSRXL.js';
40
+ import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-JXMZCTVZ.js';
41
+ import { VERSION } from './chunk-N3HCPBFY.js';
41
42
  import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
42
43
  import './chunk-BWPBB45M.js';
43
44
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
44
45
  import './chunk-BPF3YX2U.js';
45
46
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
46
47
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
47
- import * as fs7 from 'fs';
48
- import fs7__default, { realpathSync } from 'fs';
49
- import * as path37 from 'path';
50
- import path37__default from 'path';
48
+ import * as fs8 from 'fs';
49
+ import fs8__default, { realpathSync } from 'fs';
50
+ import * as path38 from 'path';
51
+ import path38__default from 'path';
51
52
  import { fileURLToPath, pathToFileURL } from 'url';
52
53
  import { Command, CommanderError, Option } from 'commander';
53
54
  import * as os from 'os';
54
55
  import * as crypto3 from 'crypto';
55
56
  import { randomUUID } from 'crypto';
57
+ import * as semver3 from 'semver';
58
+ import semver3__default from 'semver';
56
59
  import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
57
60
  import * as readline from 'readline';
58
61
  import chalk7 from 'chalk';
59
- import * as fs20 from 'fs/promises';
60
- import semver2 from 'semver';
62
+ import * as fs22 from 'fs/promises';
61
63
 
62
64
  init_cli_invocation();
63
65
  function registerStatus(program) {
@@ -67,10 +69,10 @@ function registerStatus(program) {
67
69
  applyGlobalOptions(cmd);
68
70
  }
69
71
  async function runStatus(global) {
70
- const root2 = path37.resolve(global.cwd ?? ".");
72
+ const root2 = path38.resolve(global.cwd ?? ".");
71
73
  const graphPath = resolveGraphPath(root2, global.graph);
72
74
  const graph = loadGraph(root2, graphPath);
73
- const hasCache = fs7.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
75
+ const hasCache = fs8.existsSync(path38.join(cacheDir(root2), "parse-cache.json"));
74
76
  let stale = null;
75
77
  let staleExact = false;
76
78
  if (graph) {
@@ -90,8 +92,8 @@ async function runStatus(global) {
90
92
  }
91
93
  if (global.json) {
92
94
  json({
93
- root: path37.relative(process.cwd(), root2) || ".",
94
- graphPath: path37.relative(root2, graphPath),
95
+ root: path38.relative(process.cwd(), root2) || ".",
96
+ graphPath: path38.relative(root2, graphPath),
95
97
  built: graph !== null,
96
98
  generatedAt: graph?.generatedAt ?? null,
97
99
  counts: graph?.meta.counts ?? null,
@@ -106,11 +108,11 @@ async function runStatus(global) {
106
108
  return;
107
109
  }
108
110
  if (!graph) {
109
- info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
111
+ info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path38.relative(root2, graphPath))}`);
110
112
  info(` run ${c.bold("vg")} to build one`);
111
113
  return;
112
114
  }
113
- info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
115
+ info(`${c.cyan("vg")} \xB7 ${path38.relative(root2, graphPath)}`);
114
116
  info(` generated ${graph.generatedAt}`);
115
117
  info(
116
118
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -127,7 +129,7 @@ async function runStatus(global) {
127
129
  if (vibgrateDir(root2)) ;
128
130
  }
129
131
  function rootOf(global) {
130
- return path37.resolve(global.cwd ?? ".");
132
+ return path38.resolve(global.cwd ?? ".");
131
133
  }
132
134
  function requireGraph(global) {
133
135
  const root2 = rootOf(global);
@@ -838,8 +840,8 @@ function pad2(s, n) {
838
840
  }
839
841
  var SCHEMA_VERSION2 = "1";
840
842
  var OFFSET_FILE = "stats-share.json";
841
- var INSTALL_ID_DIR = path37.join(os.homedir(), ".vibgrate");
842
- var INSTALL_ID_FILE = path37.join(INSTALL_ID_DIR, "install-id");
843
+ var INSTALL_ID_DIR = path38.join(os.homedir(), ".vibgrate");
844
+ var INSTALL_ID_FILE = path38.join(INSTALL_ID_DIR, "install-id");
843
845
  var SEND_TIMEOUT_MS = 4e3;
844
846
  function telemetryOptOut(env = process.env) {
845
847
  const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
@@ -867,14 +869,14 @@ function isCI(env = process.env) {
867
869
  function installId(env = process.env) {
868
870
  if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
869
871
  try {
870
- const existing = fs7.readFileSync(INSTALL_ID_FILE, "utf8").trim();
872
+ const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
871
873
  if (isUuid(existing)) return existing;
872
874
  } catch {
873
875
  }
874
876
  const id = randomUuid();
875
877
  try {
876
- fs7.mkdirSync(INSTALL_ID_DIR, { recursive: true });
877
- fs7.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
878
+ fs8.mkdirSync(INSTALL_ID_DIR, { recursive: true });
879
+ fs8.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
878
880
  } catch {
879
881
  }
880
882
  return id;
@@ -891,14 +893,14 @@ function statsEndpoint() {
891
893
  return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
892
894
  }
893
895
  function offsetPath(root2) {
894
- return path37.join(cacheDir(root2), OFFSET_FILE);
896
+ return path38.join(cacheDir(root2), OFFSET_FILE);
895
897
  }
896
898
  function ledgerFilePath(root2) {
897
- return path37.join(cacheDir(root2), "savings.jsonl");
899
+ return path38.join(cacheDir(root2), "savings.jsonl");
898
900
  }
899
901
  function readOffset(root2) {
900
902
  try {
901
- const raw = JSON.parse(fs7.readFileSync(offsetPath(root2), "utf8"));
903
+ const raw = JSON.parse(fs8.readFileSync(offsetPath(root2), "utf8"));
902
904
  return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
903
905
  } catch {
904
906
  return 0;
@@ -906,8 +908,8 @@ function readOffset(root2) {
906
908
  }
907
909
  function writeOffset(root2, offset) {
908
910
  try {
909
- fs7.mkdirSync(cacheDir(root2), { recursive: true });
910
- fs7.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
911
+ fs8.mkdirSync(cacheDir(root2), { recursive: true });
912
+ fs8.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
911
913
  } catch {
912
914
  }
913
915
  }
@@ -915,7 +917,7 @@ function buildBatch(root2, fromOffset, id = installId()) {
915
917
  const file = ledgerFilePath(root2);
916
918
  let size = 0;
917
919
  try {
918
- size = fs7.statSync(file).size;
920
+ size = fs8.statSync(file).size;
919
921
  } catch {
920
922
  return { batch: null, newOffset: 0 };
921
923
  }
@@ -923,13 +925,13 @@ function buildBatch(root2, fromOffset, id = installId()) {
923
925
  if (start >= size) return { batch: null, newOffset: size };
924
926
  let text = "";
925
927
  try {
926
- const fd = fs7.openSync(file, "r");
928
+ const fd = fs8.openSync(file, "r");
927
929
  try {
928
930
  const buf = Buffer.alloc(size - start);
929
- fs7.readSync(fd, buf, 0, buf.length, start);
931
+ fs8.readSync(fd, buf, 0, buf.length, start);
930
932
  text = buf.toString("utf8");
931
933
  } finally {
932
- fs7.closeSync(fd);
934
+ fs8.closeSync(fd);
933
935
  }
934
936
  } catch {
935
937
  return { batch: null, newOffset: fromOffset };
@@ -1065,12 +1067,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
1065
1067
  var KEEPALIVE_MS = 1e4;
1066
1068
  var STALE_MS = 6e4;
1067
1069
  function liveStatsDir(root2) {
1068
- return path37.join(cacheDir(root2), "serve-live");
1070
+ return path38.join(cacheDir(root2), "serve-live");
1069
1071
  }
1070
1072
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
1071
1073
  let entries;
1072
1074
  try {
1073
- entries = fs7.readdirSync(dir);
1075
+ entries = fs8.readdirSync(dir);
1074
1076
  } catch {
1075
1077
  return [];
1076
1078
  }
@@ -1079,7 +1081,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
1079
1081
  if (!/^serve-\d+\.json$/.test(name)) continue;
1080
1082
  let parsed;
1081
1083
  try {
1082
- parsed = JSON.parse(fs7.readFileSync(path37.join(dir, name), "utf8"));
1084
+ parsed = JSON.parse(fs8.readFileSync(path38.join(dir, name), "utf8"));
1083
1085
  } catch {
1084
1086
  continue;
1085
1087
  }
@@ -1101,7 +1103,7 @@ var LiveStatsBus = class {
1101
1103
  this.dir = dir;
1102
1104
  this.stats = stats;
1103
1105
  this.pid = pid;
1104
- this.file = path37.join(dir, `serve-${this.pid}.json`);
1106
+ this.file = path38.join(dir, `serve-${this.pid}.json`);
1105
1107
  }
1106
1108
  dir;
1107
1109
  stats;
@@ -1133,10 +1135,10 @@ var LiveStatsBus = class {
1133
1135
  this.lastWriteAt = now;
1134
1136
  const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
1135
1137
  try {
1136
- fs7.mkdirSync(this.dir, { recursive: true });
1138
+ fs8.mkdirSync(this.dir, { recursive: true });
1137
1139
  const tmp = `${this.file}.tmp`;
1138
- fs7.writeFileSync(tmp, JSON.stringify(body));
1139
- fs7.renameSync(tmp, this.file);
1140
+ fs8.writeFileSync(tmp, JSON.stringify(body));
1141
+ fs8.renameSync(tmp, this.file);
1140
1142
  } catch {
1141
1143
  }
1142
1144
  }
@@ -1147,24 +1149,24 @@ var LiveStatsBus = class {
1147
1149
  siblings(now = Date.now()) {
1148
1150
  let entries;
1149
1151
  try {
1150
- entries = fs7.readdirSync(this.dir);
1152
+ entries = fs8.readdirSync(this.dir);
1151
1153
  } catch {
1152
1154
  return [];
1153
1155
  }
1154
1156
  const out2 = [];
1155
1157
  for (const name of entries.sort()) {
1156
1158
  if (!/^serve-\d+\.json$/.test(name)) continue;
1157
- const file = path37.join(this.dir, name);
1159
+ const file = path38.join(this.dir, name);
1158
1160
  let parsed;
1159
1161
  try {
1160
- parsed = JSON.parse(fs7.readFileSync(file, "utf8"));
1162
+ parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
1161
1163
  } catch {
1162
1164
  continue;
1163
1165
  }
1164
1166
  if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
1165
1167
  if (now - parsed.updatedAt > STALE_MS) {
1166
1168
  try {
1167
- fs7.unlinkSync(file);
1169
+ fs8.unlinkSync(file);
1168
1170
  } catch {
1169
1171
  }
1170
1172
  continue;
@@ -1176,7 +1178,7 @@ var LiveStatsBus = class {
1176
1178
  }
1177
1179
  unlinkOwn = () => {
1178
1180
  try {
1179
- fs7.unlinkSync(this.file);
1181
+ fs8.unlinkSync(this.file);
1180
1182
  } catch {
1181
1183
  }
1182
1184
  };
@@ -1489,12 +1491,12 @@ var LedgerTail = class {
1489
1491
  if (size === this.offset) return;
1490
1492
  let chunk;
1491
1493
  try {
1492
- const fd = fs7.openSync(this.file, "r");
1494
+ const fd = fs8.openSync(this.file, "r");
1493
1495
  try {
1494
1496
  chunk = Buffer.alloc(size - this.offset);
1495
- fs7.readSync(fd, chunk, 0, chunk.length, this.offset);
1497
+ fs8.readSync(fd, chunk, 0, chunk.length, this.offset);
1496
1498
  } finally {
1497
- fs7.closeSync(fd);
1499
+ fs8.closeSync(fd);
1498
1500
  }
1499
1501
  } catch {
1500
1502
  return;
@@ -1507,7 +1509,7 @@ var LedgerTail = class {
1507
1509
  }
1508
1510
  sizeOf() {
1509
1511
  try {
1510
- return fs7.statSync(this.file).size;
1512
+ return fs8.statSync(this.file).size;
1511
1513
  } catch {
1512
1514
  return 0;
1513
1515
  }
@@ -1892,19 +1894,19 @@ function endOfLine(text, line) {
1892
1894
  }
1893
1895
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1894
1896
  function cachePath(root2) {
1895
- return path37.join(cacheDir(root2), "lsp-scan.json");
1897
+ return path38.join(cacheDir(root2), "lsp-scan.json");
1896
1898
  }
1897
1899
  function manifestHash(root2) {
1898
1900
  const files = [];
1899
1901
  const walk2 = (dir) => {
1900
1902
  let entries;
1901
1903
  try {
1902
- entries = fs7.readdirSync(dir, { withFileTypes: true });
1904
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
1903
1905
  } catch {
1904
1906
  return;
1905
1907
  }
1906
1908
  for (const entry of entries) {
1907
- const abs = path37.join(dir, entry.name);
1909
+ const abs = path38.join(dir, entry.name);
1908
1910
  if (entry.isDirectory()) {
1909
1911
  if (SKIP_DIRS.has(entry.name)) continue;
1910
1912
  walk2(abs);
@@ -1914,8 +1916,8 @@ function manifestHash(root2) {
1914
1916
  const base = entry.name.toLowerCase();
1915
1917
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1916
1918
  try {
1917
- const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1918
- files.push({ rel, hash: hashBytes(fs7.readFileSync(abs)) });
1919
+ const rel = path38.relative(root2, abs).split(path38.sep).join("/");
1920
+ files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
1919
1921
  } catch {
1920
1922
  }
1921
1923
  }
@@ -1925,16 +1927,16 @@ function manifestHash(root2) {
1925
1927
  return hashString(canonicalize(files));
1926
1928
  }
1927
1929
  function isDependencyFile(root2, filePath) {
1928
- const rel = path37.relative(path37.resolve(root2), path37.resolve(filePath));
1929
- if (rel === "" || rel.startsWith("..") || path37.isAbsolute(rel)) return false;
1930
- const parts = rel.split(path37.sep);
1930
+ const rel = path38.relative(path38.resolve(root2), path38.resolve(filePath));
1931
+ if (rel === "" || rel.startsWith("..") || path38.isAbsolute(rel)) return false;
1932
+ const parts = rel.split(path38.sep);
1931
1933
  if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
1932
1934
  const base = parts[parts.length - 1].toLowerCase();
1933
1935
  return isManifest(filePath) || SKIP_FILES.has(base);
1934
1936
  }
1935
1937
  function loadScanCache(root2, key2) {
1936
1938
  try {
1937
- const raw = JSON.parse(fs7.readFileSync(cachePath(root2), "utf8"));
1939
+ const raw = JSON.parse(fs8.readFileSync(cachePath(root2), "utf8"));
1938
1940
  if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
1939
1941
  return { manifestHash: raw.manifestHash, artifact: raw.artifact };
1940
1942
  }
@@ -1944,8 +1946,8 @@ function loadScanCache(root2, key2) {
1944
1946
  }
1945
1947
  function writeScanCache(root2, key2, artifact) {
1946
1948
  try {
1947
- fs7.mkdirSync(cacheDir(root2), { recursive: true });
1948
- fs7.writeFileSync(
1949
+ fs8.mkdirSync(cacheDir(root2), { recursive: true });
1950
+ fs8.writeFileSync(
1949
1951
  cachePath(root2),
1950
1952
  stableStringify(
1951
1953
  { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
@@ -1955,6 +1957,66 @@ function writeScanCache(root2, key2, artifact) {
1955
1957
  } catch {
1956
1958
  }
1957
1959
  }
1960
+ var MAX_ENTRIES = 1e3;
1961
+ var KEEP_ENTRIES = 500;
1962
+ function historyPath(root2) {
1963
+ return path38.join(root2, ".vibgrate", "score-history.jsonl");
1964
+ }
1965
+ function parseLine(line) {
1966
+ try {
1967
+ const e = JSON.parse(line);
1968
+ if (typeof e.ts === "string" && typeof e.score === "number" && typeof e.band === "string" && (e.mode === "verified" || e.mode === "estimated") && typeof e.methodology === "string") {
1969
+ return e;
1970
+ }
1971
+ } catch {
1972
+ }
1973
+ return null;
1974
+ }
1975
+ function readHistory(root2) {
1976
+ try {
1977
+ return fs8.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1978
+ } catch {
1979
+ return [];
1980
+ }
1981
+ }
1982
+ function lastEntry(root2) {
1983
+ const all = readHistory(root2);
1984
+ return all.length ? all[all.length - 1] : null;
1985
+ }
1986
+ function recentHistory(root2, days, now = Date.now()) {
1987
+ const cutoff = now - days * 24 * 60 * 60 * 1e3;
1988
+ return readHistory(root2).filter((e) => {
1989
+ const t = Date.parse(e.ts);
1990
+ return Number.isFinite(t) && t >= cutoff;
1991
+ });
1992
+ }
1993
+ function recordScore(root2, entry) {
1994
+ try {
1995
+ const prev = lastEntry(root2);
1996
+ if (prev && prev.score === entry.score && prev.band === entry.band && prev.mode === entry.mode && prev.methodology === entry.methodology) {
1997
+ const prevT = Date.parse(prev.ts);
1998
+ const nextT = Date.parse(entry.ts);
1999
+ if (Number.isFinite(prevT) && Number.isFinite(nextT) && nextT - prevT < 24 * 60 * 60 * 1e3) {
2000
+ return;
2001
+ }
2002
+ }
2003
+ const file = historyPath(root2);
2004
+ fs8.mkdirSync(path38.dirname(file), { recursive: true });
2005
+ fs8.appendFileSync(file, `${JSON.stringify(entry)}
2006
+ `);
2007
+ const all = readHistory(root2);
2008
+ if (all.length > MAX_ENTRIES) {
2009
+ const kept = all.slice(-KEEP_ENTRIES);
2010
+ fs8.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
2011
+ }
2012
+ } catch {
2013
+ }
2014
+ }
2015
+ function deltaFrom(prev, current) {
2016
+ if (!prev) return void 0;
2017
+ if (prev.methodology !== current.methodology) return void 0;
2018
+ return current.score - prev.score;
2019
+ }
1958
2020
 
1959
2021
  // src/lsp/graph-query.ts
1960
2022
  async function runGraphQuery(graph, params, ctx) {
@@ -2466,6 +2528,11 @@ var VibgrateLanguageServer = class {
2466
2528
  this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
2467
2529
  this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
2468
2530
  this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
2531
+ this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2532
+ const p = params;
2533
+ const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
2534
+ return { days, entries: recentHistory(this.opts.root, days) };
2535
+ });
2469
2536
  this.conn.onRequest("vibgrate/enrich", (_m, params) => this.onEnrich(params));
2470
2537
  this.conn.onRequest("vibgrate/vulns", (_m, _params) => this.onVulns());
2471
2538
  this.conn.onRequest("workspace/executeCommand", (_m, params) => {
@@ -2554,6 +2621,15 @@ var VibgrateLanguageServer = class {
2554
2621
  (f) => f.ruleId === "vibgrate/unmaintained" || f.ruleId === "vibgrate/abandoned"
2555
2622
  ).length;
2556
2623
  const band = a.drift.riskLevel ?? "low";
2624
+ const historyEntry = {
2625
+ ts: a.timestamp,
2626
+ score: a.drift.score,
2627
+ band,
2628
+ mode: a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated"),
2629
+ methodology: a.drift.methodologyVersion ?? "unknown"
2630
+ };
2631
+ const delta = deltaFrom(lastEntry(this.opts.root), historyEntry);
2632
+ recordScore(this.opts.root, historyEntry);
2557
2633
  const payload = {
2558
2634
  score: a.drift.score,
2559
2635
  band,
@@ -2561,12 +2637,13 @@ var VibgrateLanguageServer = class {
2561
2637
  // offline marker. An air-gapped scan against a dated snapshot is Verified.
2562
2638
  // The score now carries the authoritative provenance (driftscore-3.0
2563
2639
  // envelope); fall back to the artifact heuristic for pre-v3 engines.
2564
- mode: a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated"),
2565
- methodology: a.drift.methodologyVersion ?? "unknown",
2640
+ mode: historyEntry.mode,
2641
+ methodology: historyEntry.methodology,
2566
2642
  scale: "0 best, 100 worst",
2567
2643
  counts: { behind, eol, unmaintained, total },
2568
2644
  rootPath: a.rootPath,
2569
2645
  scannedAt: a.timestamp,
2646
+ ...delta !== void 0 ? { delta } : {},
2570
2647
  ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
2571
2648
  };
2572
2649
  this.conn.notify("vibgrate/score", payload);
@@ -2756,10 +2833,10 @@ var VibgrateLanguageServer = class {
2756
2833
  const ecosystem = osvEcosystem(proj.type);
2757
2834
  if (!ecosystem) continue;
2758
2835
  const relManifest = manifestRelativePath(proj);
2759
- const absManifest = path37.resolve(this.opts.root, relManifest);
2836
+ const absManifest = path38.resolve(this.opts.root, relManifest);
2760
2837
  let text = null;
2761
2838
  try {
2762
- if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2839
+ if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
2763
2840
  } catch {
2764
2841
  text = null;
2765
2842
  }
@@ -2805,12 +2882,12 @@ function uriToPath(uri) {
2805
2882
  }
2806
2883
  }
2807
2884
  function projectForFile(root2, a, filePath) {
2808
- const dir = path37.dirname(path37.resolve(filePath));
2885
+ const dir = path38.dirname(path38.resolve(filePath));
2809
2886
  let best;
2810
2887
  let bestLen = -1;
2811
2888
  for (const proj of a.projects ?? []) {
2812
- const projDir = path37.resolve(root2, proj.path);
2813
- if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2889
+ const projDir = path38.resolve(root2, proj.path);
2890
+ if ((dir === projDir || dir.startsWith(projDir + path38.sep)) && projDir.length > bestLen) {
2814
2891
  best = proj;
2815
2892
  bestLen = projDir.length;
2816
2893
  }
@@ -2818,7 +2895,7 @@ function projectForFile(root2, a, filePath) {
2818
2895
  return best;
2819
2896
  }
2820
2897
  function sameProject(location, projectPath) {
2821
- return path37.normalize(location) === path37.normalize(projectPath);
2898
+ return path38.normalize(location) === path38.normalize(projectPath);
2822
2899
  }
2823
2900
  function hasReleaseDates(a) {
2824
2901
  for (const proj of a.projects ?? []) {
@@ -2891,34 +2968,34 @@ function buildBreakdown(drift, projects) {
2891
2968
  }
2892
2969
  function manifestRelativePath(proj) {
2893
2970
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2894
- const join27 = (name) => base ? path37.join(base, name) : name;
2971
+ const join28 = (name) => base ? path38.join(base, name) : name;
2895
2972
  switch (proj.type) {
2896
2973
  case "node":
2897
2974
  case "typescript":
2898
- return join27("package.json");
2975
+ return join28("package.json");
2899
2976
  case "python":
2900
- return join27("pyproject.toml");
2977
+ return join28("pyproject.toml");
2901
2978
  case "go":
2902
- return join27("go.mod");
2979
+ return join28("go.mod");
2903
2980
  case "rust":
2904
- return join27("Cargo.toml");
2981
+ return join28("Cargo.toml");
2905
2982
  case "ruby":
2906
- return join27("Gemfile");
2983
+ return join28("Gemfile");
2907
2984
  case "php":
2908
- return join27("composer.json");
2985
+ return join28("composer.json");
2909
2986
  case "java":
2910
2987
  case "kotlin":
2911
2988
  case "scala":
2912
2989
  case "groovy":
2913
- return join27("pom.xml");
2990
+ return join28("pom.xml");
2914
2991
  case "dotnet":
2915
- return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2992
+ return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2916
2993
  case "dart":
2917
- return join27("pubspec.yaml");
2994
+ return join28("pubspec.yaml");
2918
2995
  case "elixir":
2919
- return join27("mix.exs");
2996
+ return join28("mix.exs");
2920
2997
  default:
2921
- return join27("package.json");
2998
+ return join28("package.json");
2922
2999
  }
2923
3000
  }
2924
3001
  function packageReachSet(graph) {
@@ -2978,9 +3055,19 @@ function osvEcosystem(type) {
2978
3055
  return null;
2979
3056
  }
2980
3057
  }
3058
+ function inRangeStep(dep) {
3059
+ const target = dep.latestSatisfying;
3060
+ if (!target || !dep.resolvedVersion) return null;
3061
+ if (!semver3.valid(target) || !semver3.valid(dep.resolvedVersion)) return null;
3062
+ if (!semver3.gt(target, dep.resolvedVersion)) return null;
3063
+ const diff2 = semver3.diff(dep.resolvedVersion, target);
3064
+ return { version: target, size: diff2 === "patch" || diff2 === "prepatch" ? "patch" : "minor" };
3065
+ }
2981
3066
  function inlineLabel(dep) {
2982
3067
  const bits = [];
2983
3068
  if (dep.drift === "major-behind") {
3069
+ const step2 = inRangeStep(dep);
3070
+ if (step2) bits.push(`${step2.size} behind`, step2.version);
2984
3071
  const n = dep.majorsBehind ?? 1;
2985
3072
  bits.push(`${n} major behind`);
2986
3073
  } else if (dep.drift === "minor-behind") {
@@ -3025,6 +3112,10 @@ function hoverMarkdown(dep, contribution) {
3025
3112
  lines.push(`| | |`);
3026
3113
  lines.push(`|---|---|`);
3027
3114
  lines.push(`| yours | \`${yours}\` |`);
3115
+ const step2 = inRangeStep(dep);
3116
+ if (step2 && step2.version !== dep.latestStable) {
3117
+ lines.push(`| latest in range | \`${step2.version}\` |`);
3118
+ }
3028
3119
  lines.push(`| latest | \`${dep.latestStable}\` |`);
3029
3120
  const journey = versionJourney(yours, dep.latestStable);
3030
3121
  if (journey) lines.push(`| journey | ${journey} |`);
@@ -3064,7 +3155,7 @@ function hoverMarkdown(dep, contribution) {
3064
3155
  return lines.join("\n");
3065
3156
  }
3066
3157
  function startLanguageServer(opts) {
3067
- if (!fs7.existsSync(opts.root)) {
3158
+ if (!fs8.existsSync(opts.root)) {
3068
3159
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3069
3160
  `);
3070
3161
  process.exit(1);
@@ -3201,8 +3292,8 @@ function registerShare(program) {
3201
3292
  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) {
3202
3293
  const global = readGlobal(this);
3203
3294
  const root2 = rootOf(global);
3204
- const gitDir = path37.join(root2, ".git");
3205
- if (!fs7.existsSync(gitDir)) {
3295
+ const gitDir = path38.join(root2, ".git");
3296
+ if (!fs8.existsSync(gitDir)) {
3206
3297
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3207
3298
  }
3208
3299
  if (opts.undo) {
@@ -3223,23 +3314,23 @@ function registerShare(program) {
3223
3314
  applyGlobalOptions(cmd);
3224
3315
  }
3225
3316
  function writeVibgrateGitignore(root2, reports) {
3226
- const dir = path37.join(root2, ".vibgrate");
3227
- fs7.mkdirSync(dir, { recursive: true });
3317
+ const dir = path38.join(root2, ".vibgrate");
3318
+ fs8.mkdirSync(dir, { recursive: true });
3228
3319
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
3229
3320
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3230
- fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
3321
+ fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
3231
3322
  `);
3232
3323
  }
3233
3324
  function writeGitAttributes(root2) {
3234
- const file = path37.join(root2, ".gitattributes");
3325
+ const file = path38.join(root2, ".gitattributes");
3235
3326
  const line = ".vibgrate/graph.json merge=vg";
3236
- let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "";
3327
+ let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
3237
3328
  if (!content.split("\n").some((l) => l.trim() === line)) {
3238
3329
  content = content.length ? `${content.replace(/\s*$/, "")}
3239
3330
  ${line}
3240
3331
  ` : `${line}
3241
3332
  `;
3242
- fs7.writeFileSync(file, content);
3333
+ fs8.writeFileSync(file, content);
3243
3334
  }
3244
3335
  }
3245
3336
  function configureMergeDriver(root2) {
@@ -3248,8 +3339,8 @@ function configureMergeDriver(root2) {
3248
3339
  }
3249
3340
  function installPreCommitHook(root2) {
3250
3341
  const hooksDir = hookDir(root2);
3251
- fs7.mkdirSync(hooksDir, { recursive: true });
3252
- const file = path37.join(hooksDir, "pre-commit");
3342
+ fs8.mkdirSync(hooksDir, { recursive: true });
3343
+ const file = path38.join(hooksDir, "pre-commit");
3253
3344
  const block = [
3254
3345
  HOOK_BEGIN,
3255
3346
  "if command -v vg >/dev/null 2>&1; then",
@@ -3258,7 +3349,7 @@ function installPreCommitHook(root2) {
3258
3349
  "fi",
3259
3350
  HOOK_END
3260
3351
  ].join("\n");
3261
- let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "#!/bin/sh\n";
3352
+ let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "#!/bin/sh\n";
3262
3353
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3263
3354
  if (re.test(content)) content = content.replace(re, block);
3264
3355
  else content = `${content.replace(/\s*$/, "")}
@@ -3267,21 +3358,21 @@ ${block}
3267
3358
  `;
3268
3359
  if (!content.startsWith("#!")) content = `#!/bin/sh
3269
3360
  ${content}`;
3270
- fs7.writeFileSync(file, content);
3271
- fs7.chmodSync(file, 493);
3361
+ fs8.writeFileSync(file, content);
3362
+ fs8.chmodSync(file, 493);
3272
3363
  }
3273
3364
  function undo(root2) {
3274
- const hookFile = path37.join(hookDir(root2), "pre-commit");
3275
- if (fs7.existsSync(hookFile)) {
3365
+ const hookFile = path38.join(hookDir(root2), "pre-commit");
3366
+ if (fs8.existsSync(hookFile)) {
3276
3367
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
3277
- const next2 = fs7.readFileSync(hookFile, "utf8").replace(re, "\n");
3278
- if (next2.trim() === "#!/bin/sh") fs7.rmSync(hookFile);
3279
- else fs7.writeFileSync(hookFile, next2);
3368
+ const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
3369
+ if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
3370
+ else fs8.writeFileSync(hookFile, next2);
3280
3371
  }
3281
- const attr = path37.join(root2, ".gitattributes");
3282
- if (fs7.existsSync(attr)) {
3283
- const next2 = fs7.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3284
- fs7.writeFileSync(attr, next2);
3372
+ const attr = path38.join(root2, ".gitattributes");
3373
+ if (fs8.existsSync(attr)) {
3374
+ const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3375
+ fs8.writeFileSync(attr, next2);
3285
3376
  }
3286
3377
  try {
3287
3378
  git(root2, ["config", "--remove-section", "merge.vg"]);
@@ -3291,10 +3382,10 @@ function undo(root2) {
3291
3382
  function hookDir(root2) {
3292
3383
  try {
3293
3384
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
3294
- if (configured) return path37.resolve(root2, configured);
3385
+ if (configured) return path38.resolve(root2, configured);
3295
3386
  } catch {
3296
3387
  }
3297
- return path37.join(root2, ".git", "hooks");
3388
+ return path38.join(root2, ".git", "hooks");
3298
3389
  }
3299
3390
  function git(root2, args) {
3300
3391
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -3322,9 +3413,9 @@ function registerWatch(program) {
3322
3413
  const global = readGlobal(this);
3323
3414
  const root2 = rootOf(global);
3324
3415
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3325
- const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3416
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
3326
3417
  for (const w of watchRoots) {
3327
- if (!fs7.existsSync(w)) {
3418
+ if (!fs8.existsSync(w)) {
3328
3419
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3329
3420
  }
3330
3421
  }
@@ -3377,14 +3468,14 @@ function registerWatch(program) {
3377
3468
  const watchers = [];
3378
3469
  for (const w of watchRoots) {
3379
3470
  try {
3380
- const watcher = fs7.watch(w, { recursive: true }, (_event, filename) => {
3471
+ const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3381
3472
  if (!filename) {
3382
3473
  schedule("change");
3383
3474
  return;
3384
3475
  }
3385
- const parts = filename.split(path37.sep);
3476
+ const parts = filename.split(path38.sep);
3386
3477
  if (parts.some((p) => SKIP_NAME.has(p))) return;
3387
- if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3478
+ if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
3388
3479
  return;
3389
3480
  }
3390
3481
  schedule(filename);
@@ -3394,7 +3485,7 @@ function registerWatch(program) {
3394
3485
  throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3395
3486
  }
3396
3487
  }
3397
- info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3488
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path38.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3398
3489
  await new Promise((resolve21) => {
3399
3490
  const stop = () => {
3400
3491
  for (const w of watchers) w.close();
@@ -3727,10 +3818,10 @@ function normalizeStandards(raw) {
3727
3818
  }
3728
3819
  function loadStandards(root2) {
3729
3820
  for (const rel of STANDARDS_FILES) {
3730
- const p = path37__default.join(root2, rel);
3821
+ const p = path38__default.join(root2, rel);
3731
3822
  let text;
3732
3823
  try {
3733
- text = fs7__default.readFileSync(p, "utf8");
3824
+ text = fs8__default.readFileSync(p, "utf8");
3734
3825
  } catch {
3735
3826
  continue;
3736
3827
  }
@@ -4448,8 +4539,8 @@ async function runHostBench(options = {}) {
4448
4539
  }
4449
4540
  async function runArmSimulate(input) {
4450
4541
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4451
- const path39 = `${modelPath}#${arm.id}`;
4452
- const session = await acquireHostSession(lib, path39);
4542
+ const path40 = `${modelPath}#${arm.id}`;
4543
+ const session = await acquireHostSession(lib, path40);
4453
4544
  const system = "You are a coding agent with a Task Capsule.";
4454
4545
  const capsule = "function readConfig(): Config { return load(); }";
4455
4546
  let last = null;
@@ -5661,7 +5752,7 @@ function registerModels(program) {
5661
5752
  );
5662
5753
  }
5663
5754
  } else {
5664
- if (!target.path || !fs7.existsSync(target.path)) {
5755
+ if (!target.path || !fs8.existsSync(target.path)) {
5665
5756
  throw new CliError(
5666
5757
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
5667
5758
  ExitCode.NOT_FOUND
@@ -5675,7 +5766,7 @@ function registerModels(program) {
5675
5766
  }
5676
5767
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
5677
5768
  try {
5678
- fs7.unlinkSync(target.path);
5769
+ fs8.unlinkSync(target.path);
5679
5770
  } catch (e) {
5680
5771
  const msg = e instanceof Error ? e.message : String(e);
5681
5772
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -5813,9 +5904,9 @@ function registerModels(program) {
5813
5904
  }
5814
5905
  });
5815
5906
  if (opts.out) {
5816
- const outPath = path37.resolve(opts.out);
5817
- fs7.mkdirSync(path37.dirname(outPath), { recursive: true });
5818
- fs7.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5907
+ const outPath = path38.resolve(opts.out);
5908
+ fs8.mkdirSync(path38.dirname(outPath), { recursive: true });
5909
+ fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5819
5910
  `);
5820
5911
  if (!global.json) info(c.dim(` wrote ${outPath}`));
5821
5912
  }
@@ -5964,14 +6055,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
5964
6055
  }
5965
6056
  return exact[0];
5966
6057
  }
5967
- const base = path37.basename(wantLc);
6058
+ const base = path38.basename(wantLc);
5968
6059
  const soft = fleet.filter((m) => {
5969
6060
  const n = m.name.toLowerCase();
5970
- return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path37.basename(n) === base;
6061
+ return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path38.basename(n) === base;
5971
6062
  });
5972
6063
  if (soft.length === 1) return soft[0];
5973
6064
  if (soft.length > 1) {
5974
- const baseHits = soft.filter((m) => path37.basename(m.name).toLowerCase() === base);
6065
+ const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
5975
6066
  const pool = baseHits.length ? baseHits : soft;
5976
6067
  const order = ["ollama", "gguf", "lm-studio"];
5977
6068
  for (const rt of order) {
@@ -6009,11 +6100,11 @@ function printBackends(backends) {
6009
6100
  }
6010
6101
  }
6011
6102
  function codeConfigPath(root2) {
6012
- return path37.join(root2, ".vibgrate", "code.json");
6103
+ return path38.join(root2, ".vibgrate", "code.json");
6013
6104
  }
6014
6105
  function loadCodeConfig(root2) {
6015
6106
  try {
6016
- const raw = JSON.parse(fs7.readFileSync(codeConfigPath(root2), "utf8"));
6107
+ const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
6017
6108
  return sanitize(raw);
6018
6109
  } catch {
6019
6110
  return {};
@@ -6080,7 +6171,7 @@ function contextBudgetFor(config, modelContextWindow) {
6080
6171
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
6081
6172
  function readMcpServersFile(file) {
6082
6173
  try {
6083
- const raw = JSON.parse(fs7.readFileSync(file, "utf8"));
6174
+ const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
6084
6175
  const map = raw.mcpServers ?? raw.servers;
6085
6176
  return map && typeof map === "object" ? parseMcpServers(map) : {};
6086
6177
  } catch {
@@ -6091,7 +6182,7 @@ function discoverMcpServers(root2, ownServers) {
6091
6182
  const servers = {};
6092
6183
  const sources = [];
6093
6184
  for (const rel of MCP_CONFIG_FILES) {
6094
- const found = readMcpServersFile(path37.join(root2, rel));
6185
+ const found = readMcpServersFile(path38.join(root2, rel));
6095
6186
  const names = Object.keys(found);
6096
6187
  if (names.length) {
6097
6188
  sources.push(rel);
@@ -6107,7 +6198,7 @@ function discoverMcpServers(root2, ownServers) {
6107
6198
 
6108
6199
  // src/commands/code.ts
6109
6200
  function registerCode(program) {
6110
- const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
6201
+ const cmd = program.command("code").description("propose a graph-grounded code edit (guided mode with no instruction; dry-run by default)").argument("[instruction...]", "what to change, in plain language (omit for guided interactive mode)").option("--provider <id>", "backend: vibgrate-relay (Vibgrate Relay), ollama, lmstudio, foundry-local, openrouter, litellm, openai, together, llama-cpp").option("--model <id>", "model id (or set VG_CODE_MODEL). No model is hard-coded \u2014 pick the current best.").option("--mode <mode>", "Code Mode: spark | flow | forge (preferred over raw model names; auto-fits when omitted and no --model)").option("--model-path <gguf>", "gguf path for --provider llama-cpp (weights are never auto-downloaded)").option("-f, --file <path>", "restrict the edit surface to this file (repeatable)", collect, []).option("-b, --budget <n>", "approx context token budget", "3000").option("--apply", "write the change (still requires --yes or an interactive confirm)").option("--yes", "consent to write / to a first-use package install, non-interactively").option("--auto", "autonomous agent: auto-approve every edit and command (use with care)").option("--max-steps <n>", "cap the number of agent steps", "24").option("--single", "one-shot planner (single edit) instead of the multi-step agent").option("--stream", "stream the model output live").option("--stream-json", "machine protocol: NDJSON agent events on stdout, approval decisions on stdin (for host UIs like the VS Code panel)").option("--session", "with --stream-json: stay open for further turns (warm graph and tools) instead of exiting after one").option("--verify [command]", "after the agent finishes, run tests and make it fix failures (uses the config testCommand if no command is given)").option("--continue", "resume the most recent session (recap + restore /undo)").option("--capsule", "use a source-bearing Task Capsule for first context (Fusion A/B; exact source ranges from the graph)").option("--no-capsule", "disable Task Capsule context even if enabled in .vibgrate/code.json").option("--security-tier <tier>", "shell isolation: L0 (host), L1 (Seatbelt/bubblewrap when available), L2/L3 reserved").option("--mock <file>", "use a scripted reply from <file> instead of a model (offline; for tests/CI)").option("-o, --out <file>", "write the JSON result to <file> (implies --json shape; for CI/benchmarks)").action(async function(instructionParts, opts) {
6111
6202
  const global = readGlobal(this);
6112
6203
  const instruction = (instructionParts ?? []).join(" ").trim();
6113
6204
  const config = loadCodeConfig(rootOf(global));
@@ -6120,7 +6211,7 @@ function registerCode(program) {
6120
6211
  try {
6121
6212
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6122
6213
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6123
- const { loadGraph: loadGraph2 } = await import('./load-WKIZF2AK.js');
6214
+ const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
6124
6215
  const state = readOrchestratorState2();
6125
6216
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6126
6217
  const pin = mode ? activePin2(mode, state) : null;
@@ -6204,7 +6295,7 @@ function registerCode(program) {
6204
6295
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6205
6296
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
6206
6297
  }
6207
- const { runInteractive } = await import('./interactive-R5VQGDWP.js');
6298
+ const { runInteractive } = await import('./interactive-MJVMY5JP.js');
6208
6299
  await runInteractive(
6209
6300
  rootOf(global),
6210
6301
  global,
@@ -6237,7 +6328,7 @@ function registerCode(program) {
6237
6328
  let mockReply;
6238
6329
  if (opts.mock) {
6239
6330
  try {
6240
- mockReply = fs7.readFileSync(opts.mock, "utf8");
6331
+ mockReply = fs8.readFileSync(opts.mock, "utf8");
6241
6332
  } catch {
6242
6333
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
6243
6334
  }
@@ -6286,18 +6377,18 @@ function registerCode(program) {
6286
6377
  };
6287
6378
  try {
6288
6379
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6289
- const { runCodeStreamJson } = await import('./stream-json-Y45JBNYP.js');
6290
- const { nodeCodeFs } = await import('./session-2JT4AUZT.js');
6380
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-MTPWWVRR.js');
6381
+ const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6291
6382
  const readline5 = await import('readline');
6292
6383
  const child = await import('child_process');
6293
6384
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6294
6385
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6295
6386
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6296
- const { startCodeRuntimeSession } = await import('./runtime-session-5NRB6BTR.js');
6297
- const { resolveGraphBackend } = await import('./graph-backend-GBL33GMW.js');
6387
+ const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6388
+ const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6298
6389
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6299
6390
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6300
- const { vgdRequest: vgdRequest2 } = await import('./vgd-KC5RCOP6.js');
6391
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6301
6392
  const federation = loadOrDiscoverFederation(root2);
6302
6393
  const modelProfile = mergeModelExecutionProfile(
6303
6394
  resolveModelExecutionProfile({
@@ -6343,7 +6434,7 @@ ${res.stderr}` : ""),
6343
6434
  exitCode: res.status ?? 1
6344
6435
  };
6345
6436
  };
6346
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-YXQS6HTO.js');
6437
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6347
6438
  const vgBuiltin = createVgBuiltinMcpTools({
6348
6439
  getGraph: () => graph,
6349
6440
  root: root2,
@@ -6363,50 +6454,187 @@ ${res.stderr}` : ""),
6363
6454
  };
6364
6455
  }
6365
6456
  const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
6457
+ const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
6458
+ const os5 = await import('os');
6459
+ const pathMod = await import('path');
6460
+ const checkpointIndex = pathMod.join(
6461
+ fs8.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
6462
+ "index"
6463
+ );
6464
+ const gitRunner = (gitArgs, gitEnv) => {
6465
+ const res = child.spawnSync("git", gitArgs, {
6466
+ cwd: root2,
6467
+ encoding: "utf8",
6468
+ env: { ...process.env, ...gitEnv ?? {} },
6469
+ timeout: 3e4,
6470
+ maxBuffer: 32 * 1024 * 1024
6471
+ });
6472
+ return { stdout: res.stdout ?? "", exitCode: res.status ?? 1 };
6473
+ };
6474
+ const checkpointSessionId = `r${Date.now().toString(36)}`;
6475
+ let checkpointSeq = 0;
6476
+ const takeCheckpoint = (files) => createCheckpoint(gitRunner, {
6477
+ sessionId: checkpointSessionId,
6478
+ seq: ++checkpointSeq,
6479
+ files,
6480
+ indexFile: checkpointIndex
6481
+ });
6482
+ const { loadProjectRules, nodeRulesReader } = await import('./rules-ASYEUNB5.js');
6483
+ const projectRules = loadProjectRules(nodeRulesReader(root2));
6484
+ if (projectRules.sources.length && !global.quiet) {
6485
+ emitStream({
6486
+ event: "event",
6487
+ type: "notice",
6488
+ text: `project instructions: ${projectRules.sources.join(", ")}`
6489
+ });
6490
+ }
6491
+ const baseAgentOptions = {
6492
+ graph,
6493
+ root: root2,
6494
+ providers: route.providers,
6495
+ fsImpl: nodeCodeFs(root2),
6496
+ run,
6497
+ executionEnv,
6498
+ graphBackend,
6499
+ modelProfile,
6500
+ auto: !!auto,
6501
+ maxSteps,
6502
+ budget: modelProfile.capsuleBudgetTokens,
6503
+ contextBudget,
6504
+ denyCommands: config.denyCommands,
6505
+ testCommand: config.testCommand,
6506
+ stream: true,
6507
+ verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
6508
+ capsule,
6509
+ files: opts.file.length ? opts.file : void 0,
6510
+ worktreeOverlay: true,
6511
+ advancedMode: !capsule,
6512
+ externalTools,
6513
+ attribution: {
6514
+ client: "vg-code",
6515
+ provider: primarySlug,
6516
+ model: route.providers[0]?.model
6517
+ },
6518
+ now: () => Date.now(),
6519
+ projectRules: projectRules.rendered || void 0,
6520
+ checkpoint: takeCheckpoint
6521
+ };
6366
6522
  try {
6367
- await runCodeStreamJson({
6368
- graph,
6369
- root: root2,
6370
- instruction,
6371
- providers: route.providers,
6372
- fsImpl: nodeCodeFs(root2),
6373
- run,
6374
- executionEnv,
6375
- graphBackend,
6376
- modelProfile,
6377
- auto: !!auto,
6378
- maxSteps,
6379
- budget: modelProfile.capsuleBudgetTokens,
6380
- contextBudget,
6381
- denyCommands: config.denyCommands,
6382
- testCommand: config.testCommand,
6383
- stream: true,
6384
- verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
6385
- capsule,
6386
- files: opts.file.length ? opts.file : void 0,
6387
- worktreeOverlay: true,
6388
- advancedMode: !capsule,
6389
- externalTools,
6390
- attribution: {
6391
- client: "vg-code",
6392
- provider: primarySlug,
6393
- model: route.providers[0]?.model
6394
- },
6395
- now: () => Date.now(),
6396
- emit: emitStream,
6397
- bindDecisions: (session) => {
6398
- streamApprove = (action) => session.approve(action);
6399
- const rl = readline5.createInterface({ input: process.stdin });
6400
- rl.on("line", (raw) => {
6401
- try {
6402
- const msg = JSON.parse(raw);
6403
- if (typeof msg.approveId === "number") session.submitDecision(msg.approveId, !!msg.approve);
6404
- if (typeof msg.answerId === "number") session.submitAnswer(msg.answerId, String(msg.answer ?? ""));
6405
- } catch {
6406
- }
6523
+ if (opts.session) {
6524
+ const { runCodeStreamJsonSession } = await import('./stream-json-MTPWWVRR.js');
6525
+ const { runAgent: runAgent2 } = await import('./agent-Z4Z66IGM.js');
6526
+ const {
6527
+ loadLatestSession,
6528
+ newSession,
6529
+ recordTask,
6530
+ saveSession,
6531
+ summarizeSession
6532
+ } = await import('./session-store-O4XPXKOV.js');
6533
+ const resumedRecord = opts.continue ? loadLatestSession(root2) : void 0;
6534
+ let record = resumedRecord ?? newSession(
6535
+ `s${Date.now().toString(36)}`,
6536
+ primarySlug ?? route.providers[0]?.id ?? "unknown",
6537
+ route.providers[0]?.model ?? "unknown",
6538
+ Date.now()
6539
+ );
6540
+ const pendingTurns = [];
6541
+ let wakeTurn;
6542
+ let ended = false;
6543
+ const pushTurn = (instruction2) => {
6544
+ if (wakeTurn) {
6545
+ const wake = wakeTurn;
6546
+ wakeTurn = void 0;
6547
+ wake(instruction2);
6548
+ } else if (instruction2 !== null) {
6549
+ pendingTurns.push(instruction2);
6550
+ }
6551
+ };
6552
+ const nextTurn = () => {
6553
+ if (ended) return Promise.resolve(null);
6554
+ const queued = pendingTurns.shift();
6555
+ if (queued !== void 0) return Promise.resolve(queued);
6556
+ return new Promise((resolve21) => {
6557
+ wakeTurn = resolve21;
6407
6558
  });
6408
- }
6409
- });
6559
+ };
6560
+ await runCodeStreamJsonSession({
6561
+ emit: emitStream,
6562
+ auto: !!auto,
6563
+ sessionId: record.id,
6564
+ resumed: !!resumedRecord,
6565
+ instruction,
6566
+ nextTurn,
6567
+ bindDecisions: (session) => {
6568
+ streamApprove = (action) => session.approve(action);
6569
+ const rl = readline5.createInterface({ input: process.stdin });
6570
+ rl.on("line", (raw) => {
6571
+ const msg = parseHostMessage(raw);
6572
+ if (!msg) return;
6573
+ if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
6574
+ else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6575
+ else if (msg.kind === "submit") pushTurn(msg.instruction);
6576
+ else if (msg.kind === "restore") {
6577
+ void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
6578
+ const outcome = restoreCheckpoint(gitRunner, {
6579
+ commit: msg.commit,
6580
+ files: msg.files
6581
+ });
6582
+ emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
6583
+ });
6584
+ } else if (msg.kind === "cancel") session.cancelTurn();
6585
+ else if (msg.kind === "end") {
6586
+ ended = true;
6587
+ pushTurn(null);
6588
+ }
6589
+ });
6590
+ rl.on("close", () => {
6591
+ ended = true;
6592
+ session.cancelTurn();
6593
+ pushTurn(null);
6594
+ });
6595
+ },
6596
+ runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => runAgent2({
6597
+ ...baseAgentOptions,
6598
+ instruction: turnInstruction,
6599
+ priorSummary,
6600
+ signal,
6601
+ approve: session.approve,
6602
+ askUser: session.askUser,
6603
+ onEvent: session.onEvent
6604
+ }),
6605
+ onTurnEnd: (turn) => {
6606
+ record = recordTask(
6607
+ record,
6608
+ {
6609
+ instruction: turn.instruction,
6610
+ summary: turn.result?.finalText ?? "turn failed",
6611
+ changes: turn.result?.changes ?? [],
6612
+ stopped: turn.result?.stopped ?? "error"
6613
+ },
6614
+ Date.now()
6615
+ );
6616
+ saveSession(root2, record);
6617
+ return summarizeSession(record);
6618
+ }
6619
+ });
6620
+ } else {
6621
+ await runCodeStreamJson({
6622
+ ...baseAgentOptions,
6623
+ instruction,
6624
+ emit: emitStream,
6625
+ bindDecisions: (session) => {
6626
+ streamApprove = (action) => session.approve(action);
6627
+ const rl = readline5.createInterface({ input: process.stdin });
6628
+ rl.on("line", (raw) => {
6629
+ const msg = parseHostMessage(raw);
6630
+ if (!msg) return;
6631
+ if (msg.kind === "approve") session.submitDecision(msg.id, msg.approve);
6632
+ else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6633
+ else if (msg.kind === "cancel") session.cancelTurn();
6634
+ });
6635
+ }
6636
+ });
6637
+ }
6410
6638
  } finally {
6411
6639
  await disposeMcpStream?.();
6412
6640
  await runtime.dispose();
@@ -6425,8 +6653,8 @@ ${res.stderr}` : ""),
6425
6653
  if (!autonomous && !tty) {
6426
6654
  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).");
6427
6655
  }
6428
- const { agentTask } = await import('./interactive-R5VQGDWP.js');
6429
- const { nodeCodeFs } = await import('./session-2JT4AUZT.js');
6656
+ const { agentTask } = await import('./interactive-MJVMY5JP.js');
6657
+ const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6430
6658
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6431
6659
  let priorSummary;
6432
6660
  if (opts.continue) {
@@ -6435,7 +6663,7 @@ ${res.stderr}` : ""),
6435
6663
  if (prev) priorSummary = summarizeSession(prev);
6436
6664
  }
6437
6665
  const prompter = tty ? new TtyPrompter() : void 0;
6438
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-YXQS6HTO.js');
6666
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6439
6667
  const vgBuiltin = createVgBuiltinMcpTools({
6440
6668
  getGraph: () => graph,
6441
6669
  root: root2,
@@ -6459,11 +6687,11 @@ ${res.stderr}` : ""),
6459
6687
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6460
6688
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6461
6689
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6462
- const { startCodeRuntimeSession } = await import('./runtime-session-5NRB6BTR.js');
6463
- const { resolveGraphBackend } = await import('./graph-backend-GBL33GMW.js');
6690
+ const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6691
+ const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6464
6692
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6465
6693
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6466
- const { vgdRequest: vgdRequest2 } = await import('./vgd-KC5RCOP6.js');
6694
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6467
6695
  const federation = loadFederation(root2);
6468
6696
  const modelProfile = mergeModelExecutionProfile(
6469
6697
  resolveModelExecutionProfile({
@@ -6555,7 +6783,7 @@ ${res.stderr}` : ""),
6555
6783
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
6556
6784
  });
6557
6785
  if (opts.out) {
6558
- fs7.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6786
+ fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6559
6787
  }
6560
6788
  if (global.json) {
6561
6789
  json(result);
@@ -6768,7 +6996,7 @@ async function addCmd(root2, rest, opts, asJson) {
6768
6996
  }
6769
6997
  function readPackageVersion(root2) {
6770
6998
  try {
6771
- const pkg = JSON.parse(fs7__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
6999
+ const pkg = JSON.parse(fs8__default.readFileSync(path38__default.join(root2, "package.json"), "utf8"));
6772
7000
  return typeof pkg.version === "string" ? pkg.version : void 0;
6773
7001
  } catch {
6774
7002
  return void 0;
@@ -6776,7 +7004,7 @@ function readPackageVersion(root2) {
6776
7004
  }
6777
7005
  function readOptionalFile(p) {
6778
7006
  try {
6779
- const t = fs7__default.readFileSync(p, "utf8");
7007
+ const t = fs8__default.readFileSync(p, "utf8");
6780
7008
  return t.trim() ? t : void 0;
6781
7009
  } catch {
6782
7010
  return void 0;
@@ -6791,8 +7019,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
6791
7019
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
6792
7020
  const version = (opts.version || readPackageVersion(root2) || "").trim();
6793
7021
  if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
6794
- const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6795
- const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
7022
+ const readme = readOptionalFile(opts.readme ? path38__default.resolve(opts.readme) : path38__default.join(root2, "README.md"));
7023
+ const dts = opts.dts ? readOptionalFile(path38__default.resolve(opts.dts)) : void 0;
6796
7024
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
6797
7025
  const result = await publishPrivateLibrary(
6798
7026
  { name, version, readme, dts, language: opts.language },
@@ -6924,8 +7152,8 @@ function registerExport(program) {
6924
7152
  out(content.trimEnd());
6925
7153
  return;
6926
7154
  }
6927
- fs7.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
6928
- fs7.writeFileSync(file, content);
7155
+ fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
7156
+ fs8.writeFileSync(file, content);
6929
7157
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
6930
7158
  });
6931
7159
  applyGlobalOptions(cmd);
@@ -6935,43 +7163,43 @@ function detectFormat(file) {
6935
7163
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
6936
7164
  if (lower.endsWith(".spdx.json")) return "spdx";
6937
7165
  if (file === "-") return "json";
6938
- return formatForExt(path37.extname(file));
7166
+ return formatForExt(path38.extname(file));
6939
7167
  }
6940
7168
  function registerBundle(program) {
6941
7169
  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) {
6942
7170
  const global = readGlobal(this);
6943
7171
  const root2 = rootOf(global);
6944
- const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
7172
+ const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
6945
7173
  let grammarFiles;
6946
7174
  try {
6947
7175
  grammarFiles = resolvedGrammarFiles();
6948
7176
  } catch {
6949
7177
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
6950
7178
  }
6951
- fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
7179
+ fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
6952
7180
  let grammarCount = 0;
6953
7181
  for (const { fileName, absPath } of grammarFiles) {
6954
- fs7.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
7182
+ fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
6955
7183
  grammarCount++;
6956
7184
  }
6957
7185
  const included = [`grammars/ (${grammarCount} .wasm)`];
6958
7186
  const graphSrc = resolveGraphPath(root2, global.graph);
6959
- if (fs7.existsSync(graphSrc)) {
6960
- fs7.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
7187
+ if (fs8.existsSync(graphSrc)) {
7188
+ fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
6961
7189
  included.push("graph.json");
6962
7190
  } else {
6963
7191
  const graph = loadGraphFileWithSnapshot(graphSrc);
6964
7192
  if (graph) {
6965
- fs7.writeFileSync(path37.join(outDir, "graph.json"), serializeGraph(graph));
7193
+ fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
6966
7194
  included.push("graph.json");
6967
7195
  }
6968
7196
  }
6969
7197
  const cat = catalogPath(root2);
6970
- if (fs7.existsSync(cat)) {
6971
- fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
7198
+ if (fs8.existsSync(cat)) {
7199
+ fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
6972
7200
  included.push("vibgrate.lib.json");
6973
- if (fs7.existsSync(libDir(root2))) {
6974
- fs7.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
7201
+ if (fs8.existsSync(libDir(root2))) {
7202
+ fs8.cpSync(libDir(root2), path38.join(outDir, "lib"), { recursive: true });
6975
7203
  included.push("lib/");
6976
7204
  }
6977
7205
  }
@@ -6983,15 +7211,15 @@ function registerBundle(program) {
6983
7211
  included,
6984
7212
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
6985
7213
  };
6986
- fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7214
+ fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
6987
7215
  `);
6988
7216
  if (global.json) {
6989
- json({ out: path37.relative(root2, outDir), ...manifest });
7217
+ json({ out: path38.relative(root2, outDir), ...manifest });
6990
7218
  return;
6991
7219
  }
6992
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
7220
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
6993
7221
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
6994
- info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
7222
+ info(c.dim(` offline: vg build --grammars "${path38.relative(root2, outDir)}/grammars"`));
6995
7223
  });
6996
7224
  applyGlobalOptions(cmd);
6997
7225
  }
@@ -7009,7 +7237,7 @@ async function runDoctor(global) {
7009
7237
  const root2 = rootOf(global);
7010
7238
  const local = global.local === true;
7011
7239
  const graphPath = resolveGraphPath(root2, global.graph);
7012
- const configFile = CONFIG_BASENAMES.find((f) => fs7.existsSync(path37.join(root2, f))) ?? null;
7240
+ const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path38.join(root2, f))) ?? null;
7013
7241
  const graph = loadGraph(root2, graphPath);
7014
7242
  let staleFiles = null;
7015
7243
  if (graph) {
@@ -7035,14 +7263,14 @@ async function runDoctor(global) {
7035
7263
  root: root2,
7036
7264
  configFile,
7037
7265
  map: {
7038
- path: path37.relative(root2, graphPath),
7266
+ path: path38.relative(root2, graphPath),
7039
7267
  built: graph !== null,
7040
7268
  generatedAt: graph?.generatedAt ?? null,
7041
7269
  staleFiles
7042
7270
  },
7043
7271
  libCatalog: {
7044
- path: path37.relative(root2, catalogPath(root2)),
7045
- present: fs7.existsSync(catalogPath(root2)),
7272
+ path: path38.relative(root2, catalogPath(root2)),
7273
+ present: fs8.existsSync(catalogPath(root2)),
7046
7274
  libraries: libCount
7047
7275
  },
7048
7276
  credentials: creds,
@@ -7099,7 +7327,7 @@ async function runDoctor(global) {
7099
7327
  );
7100
7328
  info(
7101
7329
  ` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
7102
- ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7330
+ ` \xB7 last ${path38.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7103
7331
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
7104
7332
  );
7105
7333
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -7179,7 +7407,9 @@ function registerDaemon(program) {
7179
7407
  if (await vgdIsRunning({ socketPath })) {
7180
7408
  throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);
7181
7409
  }
7182
- const server = await startVgdServer({ socketPath });
7410
+ let requestShutdown = () => {
7411
+ };
7412
+ const server = await startVgdServer({ socketPath, onShutdownRequest: () => requestShutdown() });
7183
7413
  if (!global.quiet) {
7184
7414
  info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
7185
7415
  info(c.dim(" register a workspace: vg daemon register"));
@@ -7190,6 +7420,7 @@ function registerDaemon(program) {
7190
7420
  if (!global.quiet) info(c.dim("vgd \xB7 stopped"));
7191
7421
  process.exit(0);
7192
7422
  };
7423
+ requestShutdown = () => void shutdown();
7193
7424
  process.on("SIGINT", () => void shutdown());
7194
7425
  process.on("SIGTERM", () => void shutdown());
7195
7426
  await new Promise(() => {
@@ -7209,33 +7440,70 @@ function registerDaemon(program) {
7209
7440
  }
7210
7441
  return;
7211
7442
  }
7212
- const child = spawnDetachedDaemonStart(socketPath);
7213
- child.unref();
7214
- const deadline = Date.now() + 8e3;
7215
- let ready = false;
7216
- while (Date.now() < deadline) {
7217
- await sleep(100);
7218
- if (await vgdIsRunning({ socketPath })) {
7219
- ready = true;
7220
- break;
7221
- }
7222
- }
7223
- if (!ready) {
7224
- throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
7225
- }
7443
+ const child = await startDetachedVgd(socketPath);
7226
7444
  const res = await vgdRequest({ op: "status" }, { socketPath });
7227
7445
  if (global.json) {
7228
7446
  json({ running: true, ensured: true, ...res.ok ? res : { socketPath } });
7229
7447
  } else if (!global.quiet) {
7230
- const pid = res.ok && "pid" in res ? res.pid : child.pid;
7448
+ const pid = res.ok && "pid" in res ? res.pid : child;
7231
7449
  info(`vgd \xB7 started in background pid ${pid} \xB7 ${c.dim(socketPath)}`);
7232
7450
  }
7233
7451
  });
7234
7452
  applyGlobalOptions(ensure);
7453
+ const stop = cmd.command("stop").description("stop the running vgd (idempotent \u2014 succeeds if none is running)").action(async function() {
7454
+ const global = readGlobal(this);
7455
+ const socketPath = socketOf(this);
7456
+ const result = await stopVgd(socketPath);
7457
+ if (global.json) {
7458
+ json({ stopped: result === "stopped", result, socketPath });
7459
+ } else if (!global.quiet) {
7460
+ if (result === "stopped") info(`vgd \xB7 stopped ${c.dim(socketPath)}`);
7461
+ else if (result === "not-running") info(c.dim(`vgd \xB7 not running (${socketPath})`));
7462
+ }
7463
+ if (result === "refused") {
7464
+ throw new CliError(
7465
+ "this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
7466
+ ExitCode.ERROR
7467
+ );
7468
+ }
7469
+ if (result === "failed") {
7470
+ throw new CliError(
7471
+ `vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
7472
+ ExitCode.ERROR
7473
+ );
7474
+ }
7475
+ });
7476
+ applyGlobalOptions(stop);
7477
+ const restart = cmd.command("restart").description("restart vgd (stop if running, then start in the background)").action(async function() {
7478
+ const global = readGlobal(this);
7479
+ const socketPath = socketOf(this);
7480
+ const stopResult = await stopVgd(socketPath);
7481
+ if (stopResult === "refused") {
7482
+ throw new CliError(
7483
+ "this vgd is embedded in another process (e.g. vg code) \u2014 stop that process instead",
7484
+ ExitCode.ERROR
7485
+ );
7486
+ }
7487
+ if (stopResult === "failed") {
7488
+ throw new CliError(
7489
+ `vgd did not stop within 5s (${socketPath}) \u2014 check \`vg daemon status\` and stop the process manually`,
7490
+ ExitCode.ERROR
7491
+ );
7492
+ }
7493
+ await startDetachedVgd(socketPath);
7494
+ const res = await vgdRequest({ op: "status" }, { socketPath });
7495
+ if (global.json) {
7496
+ json({ running: true, restarted: true, ...res.ok ? res : { socketPath } });
7497
+ } else if (!global.quiet) {
7498
+ const pid = res.ok && "pid" in res ? res.pid : "?";
7499
+ info(`vgd \xB7 restarted pid ${pid} \xB7 ${c.dim(socketPath)}`);
7500
+ }
7501
+ });
7502
+ applyGlobalOptions(restart);
7235
7503
  const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
7236
7504
  const global = readGlobal(this);
7237
7505
  const socketPath = socketOf(this);
7238
- const root2 = path37.resolve(rootArg ?? rootOf(global));
7506
+ const root2 = path38.resolve(rootArg ?? rootOf(global));
7239
7507
  if (!await vgdIsRunning({ socketPath })) {
7240
7508
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7241
7509
  }
@@ -7271,7 +7539,7 @@ function registerDaemon(program) {
7271
7539
  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) {
7272
7540
  const global = readGlobal(this);
7273
7541
  const socketPath = socketOf(this);
7274
- const primary = path37.resolve(rootArg ?? rootOf(global));
7542
+ const primary = path38.resolve(rootArg ?? rootOf(global));
7275
7543
  if (!await vgdIsRunning({ socketPath })) {
7276
7544
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7277
7545
  }
@@ -7299,32 +7567,42 @@ function registerDaemon(program) {
7299
7567
  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) {
7300
7568
  const global = readGlobal(this);
7301
7569
  const socketPath = socketOf(this);
7302
- const root2 = path37.resolve(rootArg ?? rootOf(global));
7570
+ const root2 = path38.resolve(rootArg ?? rootOf(global));
7303
7571
  if (!await vgdIsRunning({ socketPath })) {
7304
7572
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
7305
7573
  }
7306
- const { loadGraph: loadGraph2 } = await import('./load-WKIZF2AK.js');
7307
- const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7308
- const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7309
7574
  const opts = this.opts();
7310
- const graph = loadGraph2(root2, global.graph);
7311
- if (!graph) {
7312
- throw new CliError(
7313
- `no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
7314
- ExitCode.NOT_FOUND
7315
- );
7316
- }
7317
- const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
7318
- if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
7319
- const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
7320
- const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
7321
- const put = await vgdRequest(
7322
- { op: "put-graph", repositoryId, gitRef: git2, graph },
7575
+ const loaded = await vgdRequest(
7576
+ { op: "load-graph", root: root2, gitRef: opts.gitRef?.trim() || void 0, graphPath: global.graph },
7323
7577
  { socketPath }
7324
7578
  );
7325
- if (!put.ok) throw new CliError(put.error, ExitCode.ERROR);
7579
+ let put = loaded;
7580
+ if (!loaded.ok && loaded.code === "no_map") {
7581
+ throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7582
+ }
7583
+ if (!loaded.ok) {
7584
+ const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
7585
+ const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7586
+ const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7587
+ const graph = loadGraph2(root2, global.graph);
7588
+ if (!graph) {
7589
+ throw new CliError(
7590
+ `no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
7591
+ ExitCode.NOT_FOUND
7592
+ );
7593
+ }
7594
+ const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
7595
+ if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
7596
+ const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
7597
+ const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
7598
+ put = await vgdRequest(
7599
+ { op: "put-graph", repositoryId, gitRef: git2, graph },
7600
+ { socketPath }
7601
+ );
7602
+ if (!put.ok) throw new CliError(put.error, ExitCode.ERROR);
7603
+ }
7326
7604
  if (global.json) json(put);
7327
- else if ("stored" in put) {
7605
+ else if (put.ok && "stored" in put) {
7328
7606
  info(`vgd \xB7 published graph \xB7 ${put.nodeCount} node(s) \xB7 ref ${put.gitRef}`);
7329
7607
  info(c.dim(` repositoryId ${put.repositoryId}`));
7330
7608
  }
@@ -7419,7 +7697,7 @@ function socketOf(cmd) {
7419
7697
  let c2 = cmd;
7420
7698
  while (c2) {
7421
7699
  const opts = c2.opts();
7422
- if (opts.socket) return path37.resolve(opts.socket);
7700
+ if (opts.socket) return path38.resolve(opts.socket);
7423
7701
  c2 = c2.parent;
7424
7702
  }
7425
7703
  return vgdSocketPath();
@@ -7442,6 +7720,62 @@ function spawnDetachedDaemonStart(socketPath) {
7442
7720
  function sleep(ms) {
7443
7721
  return new Promise((r) => setTimeout(r, ms));
7444
7722
  }
7723
+ async function startDetachedVgd(socketPath) {
7724
+ const child = spawnDetachedDaemonStart(socketPath);
7725
+ child.unref();
7726
+ const deadline = Date.now() + 8e3;
7727
+ while (Date.now() < deadline) {
7728
+ await sleep(100);
7729
+ if (await vgdIsRunning({ socketPath })) return child.pid;
7730
+ }
7731
+ throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
7732
+ }
7733
+ async function stopVgd(socketPath) {
7734
+ if (!await vgdIsRunning({ socketPath })) return "not-running";
7735
+ let acknowledged = false;
7736
+ try {
7737
+ const res = await vgdRequest({ op: "shutdown" }, { socketPath });
7738
+ if (res.ok) acknowledged = true;
7739
+ else if (res.code === "shutdown_unsupported") return "refused";
7740
+ } catch {
7741
+ }
7742
+ if (!acknowledged) {
7743
+ const pid = readVgdPid();
7744
+ if (pid == null) return "failed";
7745
+ try {
7746
+ process.kill(pid, "SIGTERM");
7747
+ } catch {
7748
+ return "failed";
7749
+ }
7750
+ }
7751
+ const deadline = Date.now() + 5e3;
7752
+ while (Date.now() < deadline) {
7753
+ await sleep(100);
7754
+ if (!await vgdIsRunning({ socketPath })) return "stopped";
7755
+ }
7756
+ return "failed";
7757
+ }
7758
+ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
7759
+ try {
7760
+ const stopResult = await stopVgd(socketPath);
7761
+ if (stopResult === "not-running") return "not-running";
7762
+ if (stopResult === "refused") return "refused";
7763
+ if (stopResult === "failed") return "failed";
7764
+ await startDetachedVgd(socketPath);
7765
+ return "restarted";
7766
+ } catch {
7767
+ return "failed";
7768
+ }
7769
+ }
7770
+ function readVgdPid() {
7771
+ try {
7772
+ const raw = fs8.readFileSync(vgdPidPath(), "utf8").trim();
7773
+ const pid = Number.parseInt(raw, 10);
7774
+ return Number.isInteger(pid) && pid > 0 ? pid : null;
7775
+ } catch {
7776
+ return null;
7777
+ }
7778
+ }
7445
7779
  async function repositoryIdForCwd(socketPath, root2) {
7446
7780
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7447
7781
  const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
@@ -7520,7 +7854,7 @@ function registerPolicy(program) {
7520
7854
  const global = readGlobal(this);
7521
7855
  let raw;
7522
7856
  try {
7523
- raw = fs7.readFileSync(file, "utf8");
7857
+ raw = fs8.readFileSync(file, "utf8");
7524
7858
  } catch {
7525
7859
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
7526
7860
  }
@@ -7640,11 +7974,11 @@ function registerLlmHost(program) {
7640
7974
  applyGlobalOptions(cmd);
7641
7975
  }
7642
7976
  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) => {
7643
- const rootDir = path37.resolve(targetPath);
7644
- const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7977
+ const rootDir = path38.resolve(targetPath);
7978
+ const vibgrateDir2 = path38.join(rootDir, ".vibgrate");
7645
7979
  await ensureDir(vibgrateDir2);
7646
7980
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7647
- const configPath = path37.join(rootDir, "vibgrate.config.ts");
7981
+ const configPath = path38.join(rootDir, "vibgrate.config.ts");
7648
7982
  if (await pathExists(configPath)) {
7649
7983
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7650
7984
  } else {
@@ -7652,7 +7986,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7652
7986
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7653
7987
  }
7654
7988
  if (opts.baseline) {
7655
- const { runBaseline } = await import('./baseline-MROWBNK7.js');
7989
+ const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
7656
7990
  await runBaseline(rootDir);
7657
7991
  }
7658
7992
  console.log("");
@@ -7755,16 +8089,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
7755
8089
  };
7756
8090
  }
7757
8091
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
7758
- const content = await readFile3(path37.join(rootDir, relFile));
8092
+ const content = await readFile3(path38.join(rootDir, relFile));
7759
8093
  if (!content) return false;
7760
8094
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7761
8095
  return new RegExp(`\\b${escaped}\\b`).test(content);
7762
8096
  }
7763
8097
  async function defaultReadFile(absPath) {
7764
8098
  try {
7765
- const stat2 = await fs20.stat(absPath);
8099
+ const stat2 = await fs22.stat(absPath);
7766
8100
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
7767
- return await fs20.readFile(absPath, "utf8");
8101
+ return await fs22.readFile(absPath, "utf8");
7768
8102
  } catch {
7769
8103
  return null;
7770
8104
  }
@@ -7950,7 +8284,7 @@ var AI_ASSISTANT_DETECTORS = [
7950
8284
  async function detectAiAssistant(rootDir) {
7951
8285
  for (const detector of AI_ASSISTANT_DETECTORS) {
7952
8286
  for (const file of detector.files) {
7953
- if (await pathExists$1(path37.join(rootDir, file))) {
8287
+ if (await pathExists$1(path38.join(rootDir, file))) {
7954
8288
  return detector.name;
7955
8289
  }
7956
8290
  }
@@ -8144,7 +8478,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8144
8478
  collectExcludes,
8145
8479
  []
8146
8480
  ).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) => {
8147
- const rootDir = path37.resolve(targetPath);
8481
+ const rootDir = path38.resolve(targetPath);
8148
8482
  if (!await pathExists$1(rootDir)) {
8149
8483
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8150
8484
  process.exit(1);
@@ -8152,7 +8486,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8152
8486
  const hasDsn = !!resolveDsn(opts.dsn);
8153
8487
  const willPush = !opts.offline && (opts.push || hasDsn);
8154
8488
  const noLocalArtifacts = opts.localArtifacts === false;
8155
- const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
8489
+ const isFirstRun = !await pathExists$1(path38.join(rootDir, ".vibgrate", "scan_result.json"));
8156
8490
  let pinnedRegion;
8157
8491
  let planTier;
8158
8492
  let upgradeUrl;
@@ -8411,40 +8745,40 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
8411
8745
  function scanStaleness(rootDir, artifactPath) {
8412
8746
  let ref;
8413
8747
  try {
8414
- ref = fs7.statSync(artifactPath).mtimeMs;
8748
+ ref = fs8.statSync(artifactPath).mtimeMs;
8415
8749
  } catch {
8416
8750
  return { stale: false };
8417
8751
  }
8418
8752
  let newest = -Infinity;
8419
8753
  let newestChanged;
8420
- const MAX_ENTRIES = 2e4;
8754
+ const MAX_ENTRIES2 = 2e4;
8421
8755
  let scanned = 0;
8422
8756
  const walk2 = (dir, depth) => {
8423
- if (depth > 8 || scanned > MAX_ENTRIES) return;
8757
+ if (depth > 8 || scanned > MAX_ENTRIES2) return;
8424
8758
  let entries;
8425
8759
  try {
8426
- entries = fs7.readdirSync(dir, { withFileTypes: true });
8760
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
8427
8761
  } catch {
8428
8762
  return;
8429
8763
  }
8430
8764
  for (const e of entries) {
8431
8765
  scanned++;
8432
- if (scanned > MAX_ENTRIES) break;
8766
+ if (scanned > MAX_ENTRIES2) break;
8433
8767
  if (e.isDirectory()) {
8434
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
8768
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path38.join(dir, e.name), depth + 1);
8435
8769
  continue;
8436
8770
  }
8437
8771
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
8438
- const abs = path37.join(dir, e.name);
8772
+ const abs = path38.join(dir, e.name);
8439
8773
  let mtimeMs;
8440
8774
  try {
8441
- mtimeMs = fs7.statSync(abs).mtimeMs;
8775
+ mtimeMs = fs8.statSync(abs).mtimeMs;
8442
8776
  } catch {
8443
8777
  continue;
8444
8778
  }
8445
8779
  if (mtimeMs > newest) {
8446
8780
  newest = mtimeMs;
8447
- newestChanged = path37.relative(rootDir, abs) || e.name;
8781
+ newestChanged = path38.relative(rootDir, abs) || e.name;
8448
8782
  }
8449
8783
  }
8450
8784
  };
@@ -8575,7 +8909,7 @@ function analyzeTree(root2, packages) {
8575
8909
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
8576
8910
  let entries;
8577
8911
  try {
8578
- entries = fs7.readdirSync(dir, { withFileTypes: true });
8912
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
8579
8913
  } catch {
8580
8914
  return;
8581
8915
  }
@@ -8584,17 +8918,17 @@ function analyzeTree(root2, packages) {
8584
8918
  if (filesSeen >= MAX_FILES) return;
8585
8919
  if (entry.isDirectory()) {
8586
8920
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8587
- walk2(path37.join(dir, entry.name), depth + 1);
8921
+ walk2(path38.join(dir, entry.name), depth + 1);
8588
8922
  continue;
8589
8923
  }
8590
- const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8924
+ const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
8591
8925
  if (!fileEco || fileEco === "unknown") continue;
8592
8926
  filesSeen++;
8593
- const full = path37.join(dir, entry.name);
8927
+ const full = path38.join(dir, entry.name);
8594
8928
  let content;
8595
8929
  try {
8596
- if (fs7.statSync(full).size > MAX_FILE_BYTES2) continue;
8597
- content = fs7.readFileSync(full, "utf8");
8930
+ if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
8931
+ content = fs8.readFileSync(full, "utf8");
8598
8932
  } catch {
8599
8933
  continue;
8600
8934
  }
@@ -8905,7 +9239,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8905
9239
  }
8906
9240
  const outcomes = effective.map((t) => {
8907
9241
  const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
8908
- return { t, res: run(c2, path37.join(rootDir, t.dir)) };
9242
+ return { t, res: run(c2, path38.join(rootDir, t.dir)) };
8909
9243
  });
8910
9244
  const failures = outcomes.filter((o) => !o.res.ok);
8911
9245
  if (failures.length === 0) {
@@ -8934,8 +9268,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8934
9268
  return results;
8935
9269
  }
8936
9270
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
8937
- var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
8938
- var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
9271
+ var CACHE_DIR = path38.join(os.homedir(), ".vibgrate");
9272
+ var CACHE_FILE = path38.join(CACHE_DIR, "update-check.json");
8939
9273
  async function fetchLatestVersion() {
8940
9274
  try {
8941
9275
  const controller = new AbortController();
@@ -8953,7 +9287,7 @@ async function fetchLatestVersion() {
8953
9287
  if (!response.ok) return null;
8954
9288
  const data = await response.json();
8955
9289
  const latest = data.version;
8956
- if (!latest || !semver2.valid(latest)) return null;
9290
+ if (!latest || !semver3__default.valid(latest)) return null;
8957
9291
  await writeCache({ latest, checkedAt: Date.now() });
8958
9292
  return latest;
8959
9293
  } catch {
@@ -8962,8 +9296,8 @@ async function fetchLatestVersion() {
8962
9296
  }
8963
9297
  async function writeCache(data) {
8964
9298
  try {
8965
- await fs20.mkdir(CACHE_DIR, { recursive: true });
8966
- await fs20.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9299
+ await fs22.mkdir(CACHE_DIR, { recursive: true });
9300
+ await fs22.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
8967
9301
  } catch {
8968
9302
  }
8969
9303
  }
@@ -8974,7 +9308,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
8974
9308
  if (!execPath) return null;
8975
9309
  let resolved = execPath;
8976
9310
  try {
8977
- resolved = fs7.realpathSync(execPath);
9311
+ resolved = fs8.realpathSync(execPath);
8978
9312
  } catch {
8979
9313
  }
8980
9314
  const p = resolved.replace(/\\/g, "/");
@@ -9004,14 +9338,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
9004
9338
  pm: "yarn",
9005
9339
  root: () => {
9006
9340
  const dir = tryRun("yarn global dir");
9007
- return dir ? path37.join(dir, "node_modules") : null;
9341
+ return dir ? path38.join(dir, "node_modules") : null;
9008
9342
  }
9009
9343
  },
9010
- { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9344
+ { pm: "bun", root: () => path38.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9011
9345
  ];
9012
9346
  for (const probe of probes) {
9013
9347
  const root2 = probe.root();
9014
- if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
9348
+ if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
9015
9349
  }
9016
9350
  return null;
9017
9351
  }
@@ -9030,15 +9364,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
9030
9364
  }
9031
9365
  }
9032
9366
  async function detectPackageManager(cwd) {
9033
- if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9034
- if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
9035
- if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
9367
+ if (await pathExists(path38.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9368
+ if (await pathExists(path38.join(cwd, "bun.lockb"))) return "bun";
9369
+ if (await pathExists(path38.join(cwd, "yarn.lock"))) return "yarn";
9036
9370
  return "npm";
9037
9371
  }
9038
9372
  async function detectWorkspaceRoot(cwd) {
9039
- if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
9373
+ if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
9040
9374
  try {
9041
- const pkgPath = path37.join(cwd, "package.json");
9375
+ const pkgPath = path38.join(cwd, "package.json");
9042
9376
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9043
9377
  const pkg = JSON.parse(raw);
9044
9378
  return pkg.workspaces != null;
@@ -9063,7 +9397,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
9063
9397
  }
9064
9398
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
9065
9399
  try {
9066
- const pkgPath = path37.join(cwd, "package.json");
9400
+ const pkgPath = path38.join(cwd, "package.json");
9067
9401
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9068
9402
  const parsed = JSON.parse(raw);
9069
9403
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -9092,8 +9426,8 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
9092
9426
  console.error(chalk7.red("Could not reach the npm registry. Check your network connection."));
9093
9427
  process.exit(1);
9094
9428
  }
9095
- const semver3 = await import('semver');
9096
- if (!semver3.gt(latest, VERSION)) {
9429
+ const semver4 = await import('semver');
9430
+ if (!semver4.gt(latest, VERSION)) {
9097
9431
  console.log(chalk7.green("\u2714") + ` You are on the latest version (${VERSION}).`);
9098
9432
  if (opts.reap !== false) reapAndReport(process.cwd(), VERSION);
9099
9433
  return;
@@ -9152,8 +9486,29 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
9152
9486
  process.exit(1);
9153
9487
  }
9154
9488
  if (opts.reap !== false) reapAndReport(cwd, latest);
9489
+ if (opts.reap !== false) await restartVgdAndReport();
9155
9490
  }
9156
9491
  );
9492
+ async function restartVgdAndReport() {
9493
+ let result;
9494
+ try {
9495
+ result = await restartVgdIfRunning();
9496
+ } catch {
9497
+ return;
9498
+ }
9499
+ if (result === "not-running") return;
9500
+ if (result === "restarted") {
9501
+ console.log(chalk7.dim("Restarted the vgd daemon on the new version."));
9502
+ } else if (result === "refused") {
9503
+ console.log(
9504
+ chalk7.dim("A vgd embedded in another process (e.g. vg code) is running \u2014 restart that session to pick up the update.")
9505
+ );
9506
+ } else {
9507
+ console.log(
9508
+ chalk7.dim('Could not restart the vgd daemon automatically \u2014 run "vg daemon restart" to pick up the update.')
9509
+ );
9510
+ }
9511
+ }
9157
9512
  function reapAndReport(cwd, keepVersion) {
9158
9513
  let reaped = [];
9159
9514
  try {
@@ -9211,13 +9566,13 @@ function collectCandidates(artifact) {
9211
9566
  return out2;
9212
9567
  }
9213
9568
  var defaultFixScanner = async (rootDir) => {
9214
- const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9569
+ const scratch = path38.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9215
9570
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
9216
9571
  const advanced = await loadAdvancedScanHook();
9217
9572
  return runCoreScan(rootDir, scanOpts, advanced);
9218
9573
  };
9219
9574
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
9220
- const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
9575
+ const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
9221
9576
  if (await pathExists(artifactPath)) {
9222
9577
  const staleness = scanStaleness(rootDir, artifactPath);
9223
9578
  if (!staleness.stale) {
@@ -9244,7 +9599,7 @@ async function repositoryIdentity(rootDir, override) {
9244
9599
  }
9245
9600
  }
9246
9601
  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) => {
9247
- const rootDir = path37.resolve(targetPath);
9602
+ const rootDir = path38.resolve(targetPath);
9248
9603
  if (!await pathExists(rootDir)) {
9249
9604
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
9250
9605
  process.exit(1);
@@ -9405,7 +9760,7 @@ function emit(report, format) {
9405
9760
  }
9406
9761
  }
9407
9762
  function relProjectDir(rootDir, projectPath) {
9408
- const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
9763
+ const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
9409
9764
  return rel === "" ? "." : rel;
9410
9765
  }
9411
9766
  async function buildTargetResolver(rootDir, artifact) {
@@ -10240,7 +10595,7 @@ function formatMarkdown(artifact) {
10240
10595
 
10241
10596
  // src/reporting/commands/report.ts
10242
10597
  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) => {
10243
- const artifactPath = path37.resolve(opts.in);
10598
+ const artifactPath = path38.resolve(opts.in);
10244
10599
  if (!await pathExists(artifactPath)) {
10245
10600
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
10246
10601
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -10289,8 +10644,8 @@ function openUrl(url) {
10289
10644
  // src/reporting/commands/login.ts
10290
10645
  var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
10291
10646
  function isInside(dir, file) {
10292
- const rel = path37.relative(dir, file);
10293
- return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
10647
+ const rel = path38.relative(dir, file);
10648
+ return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
10294
10649
  }
10295
10650
  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(
10296
10651
  "--local",
@@ -10545,7 +10900,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10545
10900
  try {
10546
10901
  const statements = [];
10547
10902
  if (opts.from) {
10548
- const fromPath = path37.resolve(opts.from);
10903
+ const fromPath = path38.resolve(opts.from);
10549
10904
  if (!await pathExists(fromPath)) {
10550
10905
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
10551
10906
  `));
@@ -10563,9 +10918,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10563
10918
  });
10564
10919
  const json2 = JSON.stringify(doc, null, 2);
10565
10920
  if (opts.out) {
10566
- await writeTextFile(path37.resolve(opts.out), json2 + "\n");
10921
+ await writeTextFile(path38.resolve(opts.out), json2 + "\n");
10567
10922
  process.stderr.write(
10568
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
10923
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path38.resolve(opts.out)}
10569
10924
  `
10570
10925
  );
10571
10926
  } else {
@@ -10748,7 +11103,7 @@ function formatDeltaText(base, current) {
10748
11103
  return lines.join("\n");
10749
11104
  }
10750
11105
  async function readArtifactOrExit(filePath) {
10751
- const absolutePath = path37.resolve(filePath);
11106
+ const absolutePath = path38.resolve(filePath);
10752
11107
  if (!await pathExists(absolutePath)) {
10753
11108
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
10754
11109
  process.exit(1);
@@ -10765,7 +11120,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
10765
11120
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
10766
11121
  const body = JSON.stringify(sbom, null, 2);
10767
11122
  if (opts.out) {
10768
- await writeTextFile(path37.resolve(opts.out), body);
11123
+ await writeTextFile(path38.resolve(opts.out), body);
10769
11124
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
10770
11125
  } else {
10771
11126
  console.log(body);
@@ -10776,7 +11131,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
10776
11131
  const current = await readArtifactOrExit(opts.to);
10777
11132
  const report = formatDeltaText(base, current);
10778
11133
  if (opts.out) {
10779
- await writeTextFile(path37.resolve(opts.out), report);
11134
+ await writeTextFile(path38.resolve(opts.out), report);
10780
11135
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
10781
11136
  } else {
10782
11137
  console.log(report);
@@ -10907,20 +11262,20 @@ function resolveRegime(id) {
10907
11262
  return regime;
10908
11263
  }
10909
11264
  function evidenceDir(root2) {
10910
- return path37.join(root2, ".vibgrate", "evidence");
11265
+ return path38.join(root2, ".vibgrate", "evidence");
10911
11266
  }
10912
11267
  function orgPath(root2) {
10913
- return path37.join(evidenceDir(root2), "org.json");
11268
+ return path38.join(evidenceDir(root2), "org.json");
10914
11269
  }
10915
11270
  function productsPath(root2) {
10916
- return path37.join(evidenceDir(root2), "products.json");
11271
+ return path38.join(evidenceDir(root2), "products.json");
10917
11272
  }
10918
11273
  function releasesDir(root2) {
10919
- return path37.join(evidenceDir(root2), "releases");
11274
+ return path38.join(evidenceDir(root2), "releases");
10920
11275
  }
10921
11276
  function releasePath(root2, productId, version) {
10922
11277
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
10923
- return path37.join(releasesDir(root2), `${safe}.json`);
11278
+ return path38.join(releasesDir(root2), `${safe}.json`);
10924
11279
  }
10925
11280
  var DEFAULT_ORG = {
10926
11281
  responsiblePersons: [],
@@ -10951,7 +11306,7 @@ async function freezeRelease(root2, release) {
10951
11306
  const p = releasePath(root2, release.productId, release.version);
10952
11307
  if (await pathExists(p)) {
10953
11308
  throw new CliError(
10954
- `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`,
11309
+ `release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${path38.relative(root2, p)} only if it was frozen in error`,
10955
11310
  ExitCode.USAGE_ERROR
10956
11311
  );
10957
11312
  }
@@ -10965,15 +11320,15 @@ async function loadReleases(root2, productId) {
10965
11320
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
10966
11321
  const releases = [];
10967
11322
  for (const f of files) {
10968
- const rel = await readJsonFile(path37.join(dir, f));
11323
+ const rel = await readJsonFile(path38.join(dir, f));
10969
11324
  if (!productId || rel.productId === productId) releases.push(rel);
10970
11325
  }
10971
11326
  return releases;
10972
11327
  }
10973
11328
  function coerce(version) {
10974
- const parsed = semver2.parse(version, { loose: true });
11329
+ const parsed = semver3__default.parse(version, { loose: true });
10975
11330
  if (parsed) return parsed.version;
10976
- const c2 = semver2.coerce(version);
11331
+ const c2 = semver3__default.coerce(version);
10977
11332
  return c2 ? c2.version : null;
10978
11333
  }
10979
11334
  function versionAffected(version, range) {
@@ -10983,11 +11338,11 @@ function versionAffected(version, range) {
10983
11338
  if (!range.introduced && !range.fixed && !range.versions) return false;
10984
11339
  const introduced = range.introduced ? coerce(range.introduced) : "0.0.0";
10985
11340
  if (!introduced) return false;
10986
- if (semver2.lt(v, introduced)) return false;
11341
+ if (semver3__default.lt(v, introduced)) return false;
10987
11342
  if (range.fixed) {
10988
11343
  const fixed = coerce(range.fixed);
10989
11344
  if (!fixed) return false;
10990
- if (semver2.gte(v, fixed)) return false;
11345
+ if (semver3__default.gte(v, fixed)) return false;
10991
11346
  }
10992
11347
  return true;
10993
11348
  }
@@ -11068,8 +11423,8 @@ function computeExposure(input) {
11068
11423
  productName: product.name,
11069
11424
  classification: product.classification,
11070
11425
  status,
11071
- affectedVersions: [...affectedVersions].sort(semver2.compareLoose),
11072
- releases: affectedReleases.sort((a, b) => semver2.compareLoose(a.version, b.version)),
11426
+ affectedVersions: [...affectedVersions].sort(semver3__default.compareLoose),
11427
+ releases: affectedReleases.sort((a, b) => semver3__default.compareLoose(a.version, b.version)),
11073
11428
  memberStates: product.memberStates,
11074
11429
  supportStatus: support.status,
11075
11430
  supportDetail: support.detail
@@ -11660,19 +12015,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
11660
12015
  var DEFAULT_KEY = "attest-key.pem";
11661
12016
  function resolveSigningKey(root2, explicit) {
11662
12017
  const chosen = process.env.VG_ATTEST_KEY;
11663
- const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
12018
+ const keyPath = chosen ? path38.resolve(chosen) : path38.join(root2, ".vibgrate", DEFAULT_KEY);
11664
12019
  let minted = false;
11665
- if (!fs7.existsSync(keyPath)) {
12020
+ if (!fs8.existsSync(keyPath)) {
11666
12021
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
11667
12022
  const kp = generateKeypair();
11668
- fs7.mkdirSync(path37.dirname(keyPath), { recursive: true });
11669
- fs7.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11670
- fs7.writeFileSync(`${keyPath}.pub`, kp.publicPem);
12023
+ fs8.mkdirSync(path38.dirname(keyPath), { recursive: true });
12024
+ fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
12025
+ fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
11671
12026
  minted = true;
11672
12027
  }
11673
12028
  let key2;
11674
12029
  try {
11675
- key2 = crypto3.createPrivateKey(fs7.readFileSync(keyPath, "utf8"));
12030
+ key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
11676
12031
  } catch {
11677
12032
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
11678
12033
  }
@@ -11683,16 +12038,16 @@ function resolveSigningKey(root2, explicit) {
11683
12038
  }
11684
12039
  function writeBundle(input) {
11685
12040
  const dir = input.outDir;
11686
- fs7.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11687
- const write = (rel, data) => fs7.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
12041
+ fs8.mkdirSync(path38.join(dir, "inputs", "releases"), { recursive: true });
12042
+ const write = (rel, data) => fs8.writeFileSync(path38.join(dir, rel), `${JSON.stringify(data, null, 2)}
11688
12043
  `);
11689
12044
  write("result.json", input.result);
11690
- write(path37.join("inputs", "advisory.json"), input.advisory);
12045
+ write(path38.join("inputs", "advisory.json"), input.advisory);
11691
12046
  for (const rel of input.releases) {
11692
12047
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11693
- write(path37.join("inputs", "releases", `${safe}.json`), rel);
12048
+ write(path38.join("inputs", "releases", `${safe}.json`), rel);
11694
12049
  }
11695
- write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
12050
+ write(path38.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11696
12051
  write("provenance.json", {
11697
12052
  method: "deterministic",
11698
12053
  modelDrafted: [],
@@ -11708,13 +12063,13 @@ function writeBundle(input) {
11708
12063
  disclaimer: input.regime.disclaimer
11709
12064
  });
11710
12065
  if (input.envelope) {
11711
- fs7.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
12066
+ fs8.writeFileSync(path38.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11712
12067
  `);
11713
12068
  }
11714
12069
  if (input.timestampToken) {
11715
- fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
12070
+ fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
11716
12071
  }
11717
- fs7.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
12072
+ fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
11718
12073
  return dir;
11719
12074
  }
11720
12075
  function verifyDoc(input) {
@@ -11775,13 +12130,13 @@ function undeterminedFields(result, regime) {
11775
12130
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
11776
12131
  }
11777
12132
  async function recordDrill(root2, record) {
11778
- const dir = path37.join(evidenceDir(root2), "drills");
11779
- const p = path37.join(dir, `${record.drillId}.json`);
12133
+ const dir = path38.join(evidenceDir(root2), "drills");
12134
+ const p = path38.join(dir, `${record.drillId}.json`);
11780
12135
  await writeJsonFile(p, record);
11781
12136
  return p;
11782
12137
  }
11783
12138
  async function hasRecentDrill(root2, asOf) {
11784
- const dir = path37.join(evidenceDir(root2), "drills");
12139
+ const dir = path38.join(evidenceDir(root2), "drills");
11785
12140
  if (!await pathExists(dir)) return void 0;
11786
12141
  const { readdir } = await import('fs/promises');
11787
12142
  const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
@@ -11789,7 +12144,7 @@ async function hasRecentDrill(root2, asOf) {
11789
12144
  if (files.length === 0) return void 0;
11790
12145
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
11791
12146
  for (const f of files) {
11792
- const rec = await readJsonFile2(path37.join(dir, f));
12147
+ const rec = await readJsonFile2(path38.join(dir, f));
11793
12148
  if (rec.ranAt >= cutoff) return true;
11794
12149
  }
11795
12150
  return false;
@@ -11869,7 +12224,7 @@ function formatRegimeList() {
11869
12224
 
11870
12225
  // src/reporting/commands/evidence/index.ts
11871
12226
  function root(opts) {
11872
- return path37.resolve(opts.cwd ?? process.cwd());
12227
+ return path38.resolve(opts.cwd ?? process.cwd());
11873
12228
  }
11874
12229
  function slug(name) {
11875
12230
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -11957,7 +12312,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11957
12312
  const release = await buildRelease({
11958
12313
  productId: product.id,
11959
12314
  version,
11960
- from: path37.resolve(rootDir, opts.from),
12315
+ from: path38.resolve(rootDir, opts.from),
11961
12316
  shipDate: opts.shipDate,
11962
12317
  buildId: opts.buildId,
11963
12318
  artefactDigest: opts.digest,
@@ -11965,7 +12320,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11965
12320
  frozenAt: nowIso()
11966
12321
  });
11967
12322
  const p = await freezeRelease(rootDir, release);
11968
- console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
12323
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path38.relative(rootDir, p)}`);
11969
12324
  });
11970
12325
  async function runExposure(rootDir, vuln, opts) {
11971
12326
  const org = await loadOrg(rootDir);
@@ -12017,7 +12372,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12017
12372
  console.log("\n" + buildPack(result, regime, org, stage));
12018
12373
  }
12019
12374
  if (opts.bundle) {
12020
- const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12375
+ const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12021
12376
  let envelope;
12022
12377
  if (opts.sign !== false) {
12023
12378
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -12025,7 +12380,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12025
12380
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
12026
12381
  }
12027
12382
  writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
12028
- console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12383
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path38.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12029
12384
  }
12030
12385
  process.exitCode = exposureExit(result.overallStatus);
12031
12386
  });
@@ -12057,7 +12412,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
12057
12412
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
12058
12413
  const md = buildPack(result, regime, org, stage);
12059
12414
  if (opts.out) {
12060
- fs7.writeFileSync(path37.resolve(rootDir, opts.out), md);
12415
+ fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
12061
12416
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
12062
12417
  } else {
12063
12418
  console.log(md);
@@ -12099,20 +12454,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
12099
12454
  }
12100
12455
  });
12101
12456
  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) => {
12102
- const abs = path37.resolve(bundlePath);
12103
- const envPath = fs7.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
12104
- if (!fs7.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12105
- const envelope = JSON.parse(fs7.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12106
- const resultPath = path37.join(path37.dirname(envPath), "result.json");
12107
- const result = fs7.existsSync(resultPath) ? JSON.parse(fs7.readFileSync(resultPath, "utf8")) : void 0;
12108
- const publicKeyPem = opts.pub ? fs7.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
12457
+ const abs = path38.resolve(bundlePath);
12458
+ const envPath = fs8.statSync(abs).isDirectory() ? path38.join(abs, "evidence.intoto.jsonl") : abs;
12459
+ if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12460
+ const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12461
+ const resultPath = path38.join(path38.dirname(envPath), "result.json");
12462
+ const result = fs8.existsSync(resultPath) ? JSON.parse(fs8.readFileSync(resultPath, "utf8")) : void 0;
12463
+ const publicKeyPem = opts.pub ? fs8.readFileSync(path38.resolve(opts.pub), "utf8") : void 0;
12109
12464
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
12110
12465
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
12111
12466
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
12112
12467
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
12113
- const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
12114
- if (fs7.existsSync(tsrPath) && result) {
12115
- const t = verifyTimestamp(fs7.readFileSync(tsrPath), exposureSubjectDigest(result));
12468
+ const tsrPath = path38.join(path38.dirname(envPath), "timestamp.tsr");
12469
+ if (fs8.existsSync(tsrPath) && result) {
12470
+ const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
12116
12471
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
12117
12472
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
12118
12473
  }
@@ -12179,12 +12534,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
12179
12534
  const releases = [];
12180
12535
  for (const list of releasesByProduct.values()) releases.push(...list);
12181
12536
  const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
12182
- const dir = path37.resolve(rootDir, opts.out);
12183
- await writeJsonFile(path37.join(dir, "org.json"), org);
12184
- await writeJsonFile(path37.join(dir, "products.json"), products);
12185
- for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12186
- await writeJsonFile(path37.join(dir, "readiness.json"), report);
12187
- console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
12537
+ const dir = path38.resolve(rootDir, opts.out);
12538
+ await writeJsonFile(path38.join(dir, "org.json"), org);
12539
+ await writeJsonFile(path38.join(dir, "products.json"), products);
12540
+ for (const r of releases) await writeJsonFile(path38.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12541
+ await writeJsonFile(path38.join(dir, "readiness.json"), report);
12542
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path38.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
12188
12543
  });
12189
12544
  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) => {
12190
12545
  const rootDir = root(opts);
@@ -12210,10 +12565,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
12210
12565
  }));
12211
12566
  let exposure;
12212
12567
  if (opts.result) {
12213
- const raw = path37.resolve(rootDir, opts.result);
12214
- const resultPath = fs7.existsSync(raw) && fs7.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
12215
- if (!fs7.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12216
- exposure = JSON.parse(fs7.readFileSync(resultPath, "utf8"));
12568
+ const raw = path38.resolve(rootDir, opts.result);
12569
+ const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path38.join(raw, "result.json") : raw;
12570
+ if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12571
+ exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
12217
12572
  }
12218
12573
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
12219
12574
  const body = JSON.stringify(payload);
@@ -12403,7 +12758,7 @@ function dispatch(argv, cwd) {
12403
12758
  }
12404
12759
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
12405
12760
  if (looksLikeQuestion) return ["ask", ...args];
12406
- if (fs7.existsSync(path37.resolve(cwd, first))) {
12761
+ if (fs8.existsSync(path38.resolve(cwd, first))) {
12407
12762
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
12408
12763
  }
12409
12764
  const moved = MOVED_COMMANDS[first];
@@ -12448,9 +12803,9 @@ async function main(argv = process.argv) {
12448
12803
  }
12449
12804
  function readCwd(raw) {
12450
12805
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
12451
- if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
12806
+ if (i >= 0 && raw[i + 1]) return path38.resolve(raw[i + 1]);
12452
12807
  const eq = raw.find((a) => a.startsWith("--cwd="));
12453
- if (eq) return path37.resolve(eq.slice("--cwd=".length));
12808
+ if (eq) return path38.resolve(eq.slice("--cwd=".length));
12454
12809
  return process.cwd();
12455
12810
  }
12456
12811
  function handleError(err) {