@vibgrate/cli 2026.729.2 → 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-UOTGTJYT.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-CYC3ZI32.js → chunk-3FQSBVQD.js} +6 -6
  9. package/dist/{chunk-CYC3ZI32.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-HDQG3QYV.js → chunk-4BOWWYSE.js} +32 -17
  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-QDZ47G45.js → chunk-5MNX3OLS.js} +19 -11
  19. package/dist/chunk-5MNX3OLS.js.map +1 -0
  20. package/dist/{chunk-74ZMAOVF.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-PXXVLX7K.js → chunk-HWFVBYX4.js} +6 -6
  25. package/dist/{chunk-PXXVLX7K.js.map → chunk-HWFVBYX4.js.map} +1 -1
  26. package/dist/{chunk-P3QIO4ZU.js → chunk-JXMZCTVZ.js} +3 -3
  27. package/dist/{chunk-P3QIO4ZU.js.map → chunk-JXMZCTVZ.js.map} +1 -1
  28. package/dist/{chunk-VZRQUI54.js → chunk-KBPNH67Q.js} +4 -4
  29. package/dist/{chunk-VZRQUI54.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-WQE4OIZS.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-67YG3R5F.js → chunk-RIEUPFXO.js} +4 -4
  39. package/dist/{chunk-67YG3R5F.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-F6ZPUKED.js → chunk-YMSXP6AO.js} +3 -3
  45. package/dist/{chunk-F6ZPUKED.js.map → chunk-YMSXP6AO.js.map} +1 -1
  46. package/dist/cli.js +713 -373
  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-HLGJJFLI.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-4MLIHGXF.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-5M6QZZOS.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-ZCKBYQ2D.js → vg-mcp-bridge-BLHEIWMT.js} +6 -6
  67. package/dist/{vg-mcp-bridge-ZCKBYQ2D.js.map → vg-mcp-bridge-BLHEIWMT.js.map} +1 -1
  68. package/dist/{vgd-TGGEAGQZ.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-UOTGTJYT.js +0 -9
  72. package/dist/chunk-2ZHWF7C6.js.map +0 -1
  73. package/dist/chunk-74ZMAOVF.js.map +0 -1
  74. package/dist/chunk-HDQG3QYV.js.map +0 -1
  75. package/dist/chunk-JIBOJTGS.js.map +0 -1
  76. package/dist/chunk-PMYWZRRS.js.map +0 -1
  77. package/dist/chunk-QDZ47G45.js.map +0 -1
  78. package/dist/chunk-RZEXHDCF.js.map +0 -1
  79. package/dist/chunk-WQE4OIZS.js +0 -6
  80. package/dist/interactive-HLGJJFLI.js.map +0 -1
  81. package/dist/load-4MLIHGXF.js +0 -9
  82. package/dist/runtime-session-5M6QZZOS.js +0 -19
  83. package/dist/stream-json-Y45JBNYP.js.map +0 -1
  84. package/dist/vgd-TGGEAGQZ.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,53 +1,54 @@
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-QDZ47G45.js';
3
- export { runBuild } from './chunk-QDZ47G45.js';
4
- import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-2ZHWF7C6.js';
5
- import { loadAdvancedScanHook, baselineCommand } from './chunk-F6ZPUKED.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-74ZMAOVF.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-PXXVLX7K.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-CYC3ZI32.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-67YG3R5F.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-HDQG3QYV.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-P3QIO4ZU.js';
40
- import { VERSION } from './chunk-WQE4OIZS.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';
@@ -58,7 +59,7 @@ import semver3__default from 'semver';
58
59
  import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
59
60
  import * as readline from 'readline';
60
61
  import chalk7 from 'chalk';
61
- import * as fs20 from 'fs/promises';
62
+ import * as fs22 from 'fs/promises';
62
63
 
63
64
  init_cli_invocation();
64
65
  function registerStatus(program) {
@@ -68,10 +69,10 @@ function registerStatus(program) {
68
69
  applyGlobalOptions(cmd);
69
70
  }
70
71
  async function runStatus(global) {
71
- const root2 = path37.resolve(global.cwd ?? ".");
72
+ const root2 = path38.resolve(global.cwd ?? ".");
72
73
  const graphPath = resolveGraphPath(root2, global.graph);
73
74
  const graph = loadGraph(root2, graphPath);
74
- const hasCache = fs7.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
75
+ const hasCache = fs8.existsSync(path38.join(cacheDir(root2), "parse-cache.json"));
75
76
  let stale = null;
76
77
  let staleExact = false;
77
78
  if (graph) {
@@ -91,8 +92,8 @@ async function runStatus(global) {
91
92
  }
92
93
  if (global.json) {
93
94
  json({
94
- root: path37.relative(process.cwd(), root2) || ".",
95
- graphPath: path37.relative(root2, graphPath),
95
+ root: path38.relative(process.cwd(), root2) || ".",
96
+ graphPath: path38.relative(root2, graphPath),
96
97
  built: graph !== null,
97
98
  generatedAt: graph?.generatedAt ?? null,
98
99
  counts: graph?.meta.counts ?? null,
@@ -107,11 +108,11 @@ async function runStatus(global) {
107
108
  return;
108
109
  }
109
110
  if (!graph) {
110
- 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))}`);
111
112
  info(` run ${c.bold("vg")} to build one`);
112
113
  return;
113
114
  }
114
- info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
115
+ info(`${c.cyan("vg")} \xB7 ${path38.relative(root2, graphPath)}`);
115
116
  info(` generated ${graph.generatedAt}`);
116
117
  info(
117
118
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -128,7 +129,7 @@ async function runStatus(global) {
128
129
  if (vibgrateDir(root2)) ;
129
130
  }
130
131
  function rootOf(global) {
131
- return path37.resolve(global.cwd ?? ".");
132
+ return path38.resolve(global.cwd ?? ".");
132
133
  }
133
134
  function requireGraph(global) {
134
135
  const root2 = rootOf(global);
@@ -839,8 +840,8 @@ function pad2(s, n) {
839
840
  }
840
841
  var SCHEMA_VERSION2 = "1";
841
842
  var OFFSET_FILE = "stats-share.json";
842
- var INSTALL_ID_DIR = path37.join(os.homedir(), ".vibgrate");
843
- 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");
844
845
  var SEND_TIMEOUT_MS = 4e3;
845
846
  function telemetryOptOut(env = process.env) {
846
847
  const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
@@ -868,14 +869,14 @@ function isCI(env = process.env) {
868
869
  function installId(env = process.env) {
869
870
  if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
870
871
  try {
871
- const existing = fs7.readFileSync(INSTALL_ID_FILE, "utf8").trim();
872
+ const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
872
873
  if (isUuid(existing)) return existing;
873
874
  } catch {
874
875
  }
875
876
  const id = randomUuid();
876
877
  try {
877
- fs7.mkdirSync(INSTALL_ID_DIR, { recursive: true });
878
- 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 });
879
880
  } catch {
880
881
  }
881
882
  return id;
@@ -892,14 +893,14 @@ function statsEndpoint() {
892
893
  return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
893
894
  }
894
895
  function offsetPath(root2) {
895
- return path37.join(cacheDir(root2), OFFSET_FILE);
896
+ return path38.join(cacheDir(root2), OFFSET_FILE);
896
897
  }
897
898
  function ledgerFilePath(root2) {
898
- return path37.join(cacheDir(root2), "savings.jsonl");
899
+ return path38.join(cacheDir(root2), "savings.jsonl");
899
900
  }
900
901
  function readOffset(root2) {
901
902
  try {
902
- const raw = JSON.parse(fs7.readFileSync(offsetPath(root2), "utf8"));
903
+ const raw = JSON.parse(fs8.readFileSync(offsetPath(root2), "utf8"));
903
904
  return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
904
905
  } catch {
905
906
  return 0;
@@ -907,8 +908,8 @@ function readOffset(root2) {
907
908
  }
908
909
  function writeOffset(root2, offset) {
909
910
  try {
910
- fs7.mkdirSync(cacheDir(root2), { recursive: true });
911
- fs7.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
911
+ fs8.mkdirSync(cacheDir(root2), { recursive: true });
912
+ fs8.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
912
913
  } catch {
913
914
  }
914
915
  }
@@ -916,7 +917,7 @@ function buildBatch(root2, fromOffset, id = installId()) {
916
917
  const file = ledgerFilePath(root2);
917
918
  let size = 0;
918
919
  try {
919
- size = fs7.statSync(file).size;
920
+ size = fs8.statSync(file).size;
920
921
  } catch {
921
922
  return { batch: null, newOffset: 0 };
922
923
  }
@@ -924,13 +925,13 @@ function buildBatch(root2, fromOffset, id = installId()) {
924
925
  if (start >= size) return { batch: null, newOffset: size };
925
926
  let text = "";
926
927
  try {
927
- const fd = fs7.openSync(file, "r");
928
+ const fd = fs8.openSync(file, "r");
928
929
  try {
929
930
  const buf = Buffer.alloc(size - start);
930
- fs7.readSync(fd, buf, 0, buf.length, start);
931
+ fs8.readSync(fd, buf, 0, buf.length, start);
931
932
  text = buf.toString("utf8");
932
933
  } finally {
933
- fs7.closeSync(fd);
934
+ fs8.closeSync(fd);
934
935
  }
935
936
  } catch {
936
937
  return { batch: null, newOffset: fromOffset };
@@ -1066,12 +1067,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
1066
1067
  var KEEPALIVE_MS = 1e4;
1067
1068
  var STALE_MS = 6e4;
1068
1069
  function liveStatsDir(root2) {
1069
- return path37.join(cacheDir(root2), "serve-live");
1070
+ return path38.join(cacheDir(root2), "serve-live");
1070
1071
  }
1071
1072
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
1072
1073
  let entries;
1073
1074
  try {
1074
- entries = fs7.readdirSync(dir);
1075
+ entries = fs8.readdirSync(dir);
1075
1076
  } catch {
1076
1077
  return [];
1077
1078
  }
@@ -1080,7 +1081,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
1080
1081
  if (!/^serve-\d+\.json$/.test(name)) continue;
1081
1082
  let parsed;
1082
1083
  try {
1083
- parsed = JSON.parse(fs7.readFileSync(path37.join(dir, name), "utf8"));
1084
+ parsed = JSON.parse(fs8.readFileSync(path38.join(dir, name), "utf8"));
1084
1085
  } catch {
1085
1086
  continue;
1086
1087
  }
@@ -1102,7 +1103,7 @@ var LiveStatsBus = class {
1102
1103
  this.dir = dir;
1103
1104
  this.stats = stats;
1104
1105
  this.pid = pid;
1105
- this.file = path37.join(dir, `serve-${this.pid}.json`);
1106
+ this.file = path38.join(dir, `serve-${this.pid}.json`);
1106
1107
  }
1107
1108
  dir;
1108
1109
  stats;
@@ -1134,10 +1135,10 @@ var LiveStatsBus = class {
1134
1135
  this.lastWriteAt = now;
1135
1136
  const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
1136
1137
  try {
1137
- fs7.mkdirSync(this.dir, { recursive: true });
1138
+ fs8.mkdirSync(this.dir, { recursive: true });
1138
1139
  const tmp = `${this.file}.tmp`;
1139
- fs7.writeFileSync(tmp, JSON.stringify(body));
1140
- fs7.renameSync(tmp, this.file);
1140
+ fs8.writeFileSync(tmp, JSON.stringify(body));
1141
+ fs8.renameSync(tmp, this.file);
1141
1142
  } catch {
1142
1143
  }
1143
1144
  }
@@ -1148,24 +1149,24 @@ var LiveStatsBus = class {
1148
1149
  siblings(now = Date.now()) {
1149
1150
  let entries;
1150
1151
  try {
1151
- entries = fs7.readdirSync(this.dir);
1152
+ entries = fs8.readdirSync(this.dir);
1152
1153
  } catch {
1153
1154
  return [];
1154
1155
  }
1155
1156
  const out2 = [];
1156
1157
  for (const name of entries.sort()) {
1157
1158
  if (!/^serve-\d+\.json$/.test(name)) continue;
1158
- const file = path37.join(this.dir, name);
1159
+ const file = path38.join(this.dir, name);
1159
1160
  let parsed;
1160
1161
  try {
1161
- parsed = JSON.parse(fs7.readFileSync(file, "utf8"));
1162
+ parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
1162
1163
  } catch {
1163
1164
  continue;
1164
1165
  }
1165
1166
  if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
1166
1167
  if (now - parsed.updatedAt > STALE_MS) {
1167
1168
  try {
1168
- fs7.unlinkSync(file);
1169
+ fs8.unlinkSync(file);
1169
1170
  } catch {
1170
1171
  }
1171
1172
  continue;
@@ -1177,7 +1178,7 @@ var LiveStatsBus = class {
1177
1178
  }
1178
1179
  unlinkOwn = () => {
1179
1180
  try {
1180
- fs7.unlinkSync(this.file);
1181
+ fs8.unlinkSync(this.file);
1181
1182
  } catch {
1182
1183
  }
1183
1184
  };
@@ -1490,12 +1491,12 @@ var LedgerTail = class {
1490
1491
  if (size === this.offset) return;
1491
1492
  let chunk;
1492
1493
  try {
1493
- const fd = fs7.openSync(this.file, "r");
1494
+ const fd = fs8.openSync(this.file, "r");
1494
1495
  try {
1495
1496
  chunk = Buffer.alloc(size - this.offset);
1496
- fs7.readSync(fd, chunk, 0, chunk.length, this.offset);
1497
+ fs8.readSync(fd, chunk, 0, chunk.length, this.offset);
1497
1498
  } finally {
1498
- fs7.closeSync(fd);
1499
+ fs8.closeSync(fd);
1499
1500
  }
1500
1501
  } catch {
1501
1502
  return;
@@ -1508,7 +1509,7 @@ var LedgerTail = class {
1508
1509
  }
1509
1510
  sizeOf() {
1510
1511
  try {
1511
- return fs7.statSync(this.file).size;
1512
+ return fs8.statSync(this.file).size;
1512
1513
  } catch {
1513
1514
  return 0;
1514
1515
  }
@@ -1893,19 +1894,19 @@ function endOfLine(text, line) {
1893
1894
  }
1894
1895
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1895
1896
  function cachePath(root2) {
1896
- return path37.join(cacheDir(root2), "lsp-scan.json");
1897
+ return path38.join(cacheDir(root2), "lsp-scan.json");
1897
1898
  }
1898
1899
  function manifestHash(root2) {
1899
1900
  const files = [];
1900
1901
  const walk2 = (dir) => {
1901
1902
  let entries;
1902
1903
  try {
1903
- entries = fs7.readdirSync(dir, { withFileTypes: true });
1904
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
1904
1905
  } catch {
1905
1906
  return;
1906
1907
  }
1907
1908
  for (const entry of entries) {
1908
- const abs = path37.join(dir, entry.name);
1909
+ const abs = path38.join(dir, entry.name);
1909
1910
  if (entry.isDirectory()) {
1910
1911
  if (SKIP_DIRS.has(entry.name)) continue;
1911
1912
  walk2(abs);
@@ -1915,8 +1916,8 @@ function manifestHash(root2) {
1915
1916
  const base = entry.name.toLowerCase();
1916
1917
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1917
1918
  try {
1918
- const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1919
- 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)) });
1920
1921
  } catch {
1921
1922
  }
1922
1923
  }
@@ -1926,16 +1927,16 @@ function manifestHash(root2) {
1926
1927
  return hashString(canonicalize(files));
1927
1928
  }
1928
1929
  function isDependencyFile(root2, filePath) {
1929
- const rel = path37.relative(path37.resolve(root2), path37.resolve(filePath));
1930
- if (rel === "" || rel.startsWith("..") || path37.isAbsolute(rel)) return false;
1931
- 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);
1932
1933
  if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
1933
1934
  const base = parts[parts.length - 1].toLowerCase();
1934
1935
  return isManifest(filePath) || SKIP_FILES.has(base);
1935
1936
  }
1936
1937
  function loadScanCache(root2, key2) {
1937
1938
  try {
1938
- const raw = JSON.parse(fs7.readFileSync(cachePath(root2), "utf8"));
1939
+ const raw = JSON.parse(fs8.readFileSync(cachePath(root2), "utf8"));
1939
1940
  if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
1940
1941
  return { manifestHash: raw.manifestHash, artifact: raw.artifact };
1941
1942
  }
@@ -1945,8 +1946,8 @@ function loadScanCache(root2, key2) {
1945
1946
  }
1946
1947
  function writeScanCache(root2, key2, artifact) {
1947
1948
  try {
1948
- fs7.mkdirSync(cacheDir(root2), { recursive: true });
1949
- fs7.writeFileSync(
1949
+ fs8.mkdirSync(cacheDir(root2), { recursive: true });
1950
+ fs8.writeFileSync(
1950
1951
  cachePath(root2),
1951
1952
  stableStringify(
1952
1953
  { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
@@ -1956,6 +1957,66 @@ function writeScanCache(root2, key2, artifact) {
1956
1957
  } catch {
1957
1958
  }
1958
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
+ }
1959
2020
 
1960
2021
  // src/lsp/graph-query.ts
1961
2022
  async function runGraphQuery(graph, params, ctx) {
@@ -2467,6 +2528,11 @@ var VibgrateLanguageServer = class {
2467
2528
  this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
2468
2529
  this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
2469
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
+ });
2470
2536
  this.conn.onRequest("vibgrate/enrich", (_m, params) => this.onEnrich(params));
2471
2537
  this.conn.onRequest("vibgrate/vulns", (_m, _params) => this.onVulns());
2472
2538
  this.conn.onRequest("workspace/executeCommand", (_m, params) => {
@@ -2555,6 +2621,15 @@ var VibgrateLanguageServer = class {
2555
2621
  (f) => f.ruleId === "vibgrate/unmaintained" || f.ruleId === "vibgrate/abandoned"
2556
2622
  ).length;
2557
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);
2558
2633
  const payload = {
2559
2634
  score: a.drift.score,
2560
2635
  band,
@@ -2562,12 +2637,13 @@ var VibgrateLanguageServer = class {
2562
2637
  // offline marker. An air-gapped scan against a dated snapshot is Verified.
2563
2638
  // The score now carries the authoritative provenance (driftscore-3.0
2564
2639
  // envelope); fall back to the artifact heuristic for pre-v3 engines.
2565
- mode: a.drift.mode ?? (hasReleaseDates(a) ? "verified" : "estimated"),
2566
- methodology: a.drift.methodologyVersion ?? "unknown",
2640
+ mode: historyEntry.mode,
2641
+ methodology: historyEntry.methodology,
2567
2642
  scale: "0 best, 100 worst",
2568
2643
  counts: { behind, eol, unmaintained, total },
2569
2644
  rootPath: a.rootPath,
2570
2645
  scannedAt: a.timestamp,
2646
+ ...delta !== void 0 ? { delta } : {},
2571
2647
  ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
2572
2648
  };
2573
2649
  this.conn.notify("vibgrate/score", payload);
@@ -2757,10 +2833,10 @@ var VibgrateLanguageServer = class {
2757
2833
  const ecosystem = osvEcosystem(proj.type);
2758
2834
  if (!ecosystem) continue;
2759
2835
  const relManifest = manifestRelativePath(proj);
2760
- const absManifest = path37.resolve(this.opts.root, relManifest);
2836
+ const absManifest = path38.resolve(this.opts.root, relManifest);
2761
2837
  let text = null;
2762
2838
  try {
2763
- if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2839
+ if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
2764
2840
  } catch {
2765
2841
  text = null;
2766
2842
  }
@@ -2806,12 +2882,12 @@ function uriToPath(uri) {
2806
2882
  }
2807
2883
  }
2808
2884
  function projectForFile(root2, a, filePath) {
2809
- const dir = path37.dirname(path37.resolve(filePath));
2885
+ const dir = path38.dirname(path38.resolve(filePath));
2810
2886
  let best;
2811
2887
  let bestLen = -1;
2812
2888
  for (const proj of a.projects ?? []) {
2813
- const projDir = path37.resolve(root2, proj.path);
2814
- 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) {
2815
2891
  best = proj;
2816
2892
  bestLen = projDir.length;
2817
2893
  }
@@ -2819,7 +2895,7 @@ function projectForFile(root2, a, filePath) {
2819
2895
  return best;
2820
2896
  }
2821
2897
  function sameProject(location, projectPath) {
2822
- return path37.normalize(location) === path37.normalize(projectPath);
2898
+ return path38.normalize(location) === path38.normalize(projectPath);
2823
2899
  }
2824
2900
  function hasReleaseDates(a) {
2825
2901
  for (const proj of a.projects ?? []) {
@@ -2892,34 +2968,34 @@ function buildBreakdown(drift, projects) {
2892
2968
  }
2893
2969
  function manifestRelativePath(proj) {
2894
2970
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2895
- const join27 = (name) => base ? path37.join(base, name) : name;
2971
+ const join28 = (name) => base ? path38.join(base, name) : name;
2896
2972
  switch (proj.type) {
2897
2973
  case "node":
2898
2974
  case "typescript":
2899
- return join27("package.json");
2975
+ return join28("package.json");
2900
2976
  case "python":
2901
- return join27("pyproject.toml");
2977
+ return join28("pyproject.toml");
2902
2978
  case "go":
2903
- return join27("go.mod");
2979
+ return join28("go.mod");
2904
2980
  case "rust":
2905
- return join27("Cargo.toml");
2981
+ return join28("Cargo.toml");
2906
2982
  case "ruby":
2907
- return join27("Gemfile");
2983
+ return join28("Gemfile");
2908
2984
  case "php":
2909
- return join27("composer.json");
2985
+ return join28("composer.json");
2910
2986
  case "java":
2911
2987
  case "kotlin":
2912
2988
  case "scala":
2913
2989
  case "groovy":
2914
- return join27("pom.xml");
2990
+ return join28("pom.xml");
2915
2991
  case "dotnet":
2916
- return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2992
+ return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2917
2993
  case "dart":
2918
- return join27("pubspec.yaml");
2994
+ return join28("pubspec.yaml");
2919
2995
  case "elixir":
2920
- return join27("mix.exs");
2996
+ return join28("mix.exs");
2921
2997
  default:
2922
- return join27("package.json");
2998
+ return join28("package.json");
2923
2999
  }
2924
3000
  }
2925
3001
  function packageReachSet(graph) {
@@ -3079,7 +3155,7 @@ function hoverMarkdown(dep, contribution) {
3079
3155
  return lines.join("\n");
3080
3156
  }
3081
3157
  function startLanguageServer(opts) {
3082
- if (!fs7.existsSync(opts.root)) {
3158
+ if (!fs8.existsSync(opts.root)) {
3083
3159
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3084
3160
  `);
3085
3161
  process.exit(1);
@@ -3216,8 +3292,8 @@ function registerShare(program) {
3216
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) {
3217
3293
  const global = readGlobal(this);
3218
3294
  const root2 = rootOf(global);
3219
- const gitDir = path37.join(root2, ".git");
3220
- if (!fs7.existsSync(gitDir)) {
3295
+ const gitDir = path38.join(root2, ".git");
3296
+ if (!fs8.existsSync(gitDir)) {
3221
3297
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3222
3298
  }
3223
3299
  if (opts.undo) {
@@ -3238,23 +3314,23 @@ function registerShare(program) {
3238
3314
  applyGlobalOptions(cmd);
3239
3315
  }
3240
3316
  function writeVibgrateGitignore(root2, reports) {
3241
- const dir = path37.join(root2, ".vibgrate");
3242
- fs7.mkdirSync(dir, { recursive: true });
3317
+ const dir = path38.join(root2, ".vibgrate");
3318
+ fs8.mkdirSync(dir, { recursive: true });
3243
3319
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
3244
3320
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3245
- fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
3321
+ fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
3246
3322
  `);
3247
3323
  }
3248
3324
  function writeGitAttributes(root2) {
3249
- const file = path37.join(root2, ".gitattributes");
3325
+ const file = path38.join(root2, ".gitattributes");
3250
3326
  const line = ".vibgrate/graph.json merge=vg";
3251
- let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "";
3327
+ let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
3252
3328
  if (!content.split("\n").some((l) => l.trim() === line)) {
3253
3329
  content = content.length ? `${content.replace(/\s*$/, "")}
3254
3330
  ${line}
3255
3331
  ` : `${line}
3256
3332
  `;
3257
- fs7.writeFileSync(file, content);
3333
+ fs8.writeFileSync(file, content);
3258
3334
  }
3259
3335
  }
3260
3336
  function configureMergeDriver(root2) {
@@ -3263,8 +3339,8 @@ function configureMergeDriver(root2) {
3263
3339
  }
3264
3340
  function installPreCommitHook(root2) {
3265
3341
  const hooksDir = hookDir(root2);
3266
- fs7.mkdirSync(hooksDir, { recursive: true });
3267
- const file = path37.join(hooksDir, "pre-commit");
3342
+ fs8.mkdirSync(hooksDir, { recursive: true });
3343
+ const file = path38.join(hooksDir, "pre-commit");
3268
3344
  const block = [
3269
3345
  HOOK_BEGIN,
3270
3346
  "if command -v vg >/dev/null 2>&1; then",
@@ -3273,7 +3349,7 @@ function installPreCommitHook(root2) {
3273
3349
  "fi",
3274
3350
  HOOK_END
3275
3351
  ].join("\n");
3276
- 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";
3277
3353
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3278
3354
  if (re.test(content)) content = content.replace(re, block);
3279
3355
  else content = `${content.replace(/\s*$/, "")}
@@ -3282,21 +3358,21 @@ ${block}
3282
3358
  `;
3283
3359
  if (!content.startsWith("#!")) content = `#!/bin/sh
3284
3360
  ${content}`;
3285
- fs7.writeFileSync(file, content);
3286
- fs7.chmodSync(file, 493);
3361
+ fs8.writeFileSync(file, content);
3362
+ fs8.chmodSync(file, 493);
3287
3363
  }
3288
3364
  function undo(root2) {
3289
- const hookFile = path37.join(hookDir(root2), "pre-commit");
3290
- if (fs7.existsSync(hookFile)) {
3365
+ const hookFile = path38.join(hookDir(root2), "pre-commit");
3366
+ if (fs8.existsSync(hookFile)) {
3291
3367
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
3292
- const next2 = fs7.readFileSync(hookFile, "utf8").replace(re, "\n");
3293
- if (next2.trim() === "#!/bin/sh") fs7.rmSync(hookFile);
3294
- 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);
3295
3371
  }
3296
- const attr = path37.join(root2, ".gitattributes");
3297
- if (fs7.existsSync(attr)) {
3298
- const next2 = fs7.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3299
- 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);
3300
3376
  }
3301
3377
  try {
3302
3378
  git(root2, ["config", "--remove-section", "merge.vg"]);
@@ -3306,10 +3382,10 @@ function undo(root2) {
3306
3382
  function hookDir(root2) {
3307
3383
  try {
3308
3384
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
3309
- if (configured) return path37.resolve(root2, configured);
3385
+ if (configured) return path38.resolve(root2, configured);
3310
3386
  } catch {
3311
3387
  }
3312
- return path37.join(root2, ".git", "hooks");
3388
+ return path38.join(root2, ".git", "hooks");
3313
3389
  }
3314
3390
  function git(root2, args) {
3315
3391
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -3337,9 +3413,9 @@ function registerWatch(program) {
3337
3413
  const global = readGlobal(this);
3338
3414
  const root2 = rootOf(global);
3339
3415
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3340
- const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3416
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
3341
3417
  for (const w of watchRoots) {
3342
- if (!fs7.existsSync(w)) {
3418
+ if (!fs8.existsSync(w)) {
3343
3419
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3344
3420
  }
3345
3421
  }
@@ -3392,14 +3468,14 @@ function registerWatch(program) {
3392
3468
  const watchers = [];
3393
3469
  for (const w of watchRoots) {
3394
3470
  try {
3395
- const watcher = fs7.watch(w, { recursive: true }, (_event, filename) => {
3471
+ const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3396
3472
  if (!filename) {
3397
3473
  schedule("change");
3398
3474
  return;
3399
3475
  }
3400
- const parts = filename.split(path37.sep);
3476
+ const parts = filename.split(path38.sep);
3401
3477
  if (parts.some((p) => SKIP_NAME.has(p))) return;
3402
- if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3478
+ if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
3403
3479
  return;
3404
3480
  }
3405
3481
  schedule(filename);
@@ -3409,7 +3485,7 @@ function registerWatch(program) {
3409
3485
  throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3410
3486
  }
3411
3487
  }
3412
- 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`));
3413
3489
  await new Promise((resolve21) => {
3414
3490
  const stop = () => {
3415
3491
  for (const w of watchers) w.close();
@@ -3742,10 +3818,10 @@ function normalizeStandards(raw) {
3742
3818
  }
3743
3819
  function loadStandards(root2) {
3744
3820
  for (const rel of STANDARDS_FILES) {
3745
- const p = path37__default.join(root2, rel);
3821
+ const p = path38__default.join(root2, rel);
3746
3822
  let text;
3747
3823
  try {
3748
- text = fs7__default.readFileSync(p, "utf8");
3824
+ text = fs8__default.readFileSync(p, "utf8");
3749
3825
  } catch {
3750
3826
  continue;
3751
3827
  }
@@ -4463,8 +4539,8 @@ async function runHostBench(options = {}) {
4463
4539
  }
4464
4540
  async function runArmSimulate(input) {
4465
4541
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4466
- const path39 = `${modelPath}#${arm.id}`;
4467
- const session = await acquireHostSession(lib, path39);
4542
+ const path40 = `${modelPath}#${arm.id}`;
4543
+ const session = await acquireHostSession(lib, path40);
4468
4544
  const system = "You are a coding agent with a Task Capsule.";
4469
4545
  const capsule = "function readConfig(): Config { return load(); }";
4470
4546
  let last = null;
@@ -5676,7 +5752,7 @@ function registerModels(program) {
5676
5752
  );
5677
5753
  }
5678
5754
  } else {
5679
- if (!target.path || !fs7.existsSync(target.path)) {
5755
+ if (!target.path || !fs8.existsSync(target.path)) {
5680
5756
  throw new CliError(
5681
5757
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
5682
5758
  ExitCode.NOT_FOUND
@@ -5690,7 +5766,7 @@ function registerModels(program) {
5690
5766
  }
5691
5767
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
5692
5768
  try {
5693
- fs7.unlinkSync(target.path);
5769
+ fs8.unlinkSync(target.path);
5694
5770
  } catch (e) {
5695
5771
  const msg = e instanceof Error ? e.message : String(e);
5696
5772
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -5828,9 +5904,9 @@ function registerModels(program) {
5828
5904
  }
5829
5905
  });
5830
5906
  if (opts.out) {
5831
- const outPath = path37.resolve(opts.out);
5832
- fs7.mkdirSync(path37.dirname(outPath), { recursive: true });
5833
- 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)}
5834
5910
  `);
5835
5911
  if (!global.json) info(c.dim(` wrote ${outPath}`));
5836
5912
  }
@@ -5979,14 +6055,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
5979
6055
  }
5980
6056
  return exact[0];
5981
6057
  }
5982
- const base = path37.basename(wantLc);
6058
+ const base = path38.basename(wantLc);
5983
6059
  const soft = fleet.filter((m) => {
5984
6060
  const n = m.name.toLowerCase();
5985
- 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;
5986
6062
  });
5987
6063
  if (soft.length === 1) return soft[0];
5988
6064
  if (soft.length > 1) {
5989
- const baseHits = soft.filter((m) => path37.basename(m.name).toLowerCase() === base);
6065
+ const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
5990
6066
  const pool = baseHits.length ? baseHits : soft;
5991
6067
  const order = ["ollama", "gguf", "lm-studio"];
5992
6068
  for (const rt of order) {
@@ -6024,11 +6100,11 @@ function printBackends(backends) {
6024
6100
  }
6025
6101
  }
6026
6102
  function codeConfigPath(root2) {
6027
- return path37.join(root2, ".vibgrate", "code.json");
6103
+ return path38.join(root2, ".vibgrate", "code.json");
6028
6104
  }
6029
6105
  function loadCodeConfig(root2) {
6030
6106
  try {
6031
- const raw = JSON.parse(fs7.readFileSync(codeConfigPath(root2), "utf8"));
6107
+ const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
6032
6108
  return sanitize(raw);
6033
6109
  } catch {
6034
6110
  return {};
@@ -6095,7 +6171,7 @@ function contextBudgetFor(config, modelContextWindow) {
6095
6171
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
6096
6172
  function readMcpServersFile(file) {
6097
6173
  try {
6098
- const raw = JSON.parse(fs7.readFileSync(file, "utf8"));
6174
+ const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
6099
6175
  const map = raw.mcpServers ?? raw.servers;
6100
6176
  return map && typeof map === "object" ? parseMcpServers(map) : {};
6101
6177
  } catch {
@@ -6106,7 +6182,7 @@ function discoverMcpServers(root2, ownServers) {
6106
6182
  const servers = {};
6107
6183
  const sources = [];
6108
6184
  for (const rel of MCP_CONFIG_FILES) {
6109
- const found = readMcpServersFile(path37.join(root2, rel));
6185
+ const found = readMcpServersFile(path38.join(root2, rel));
6110
6186
  const names = Object.keys(found);
6111
6187
  if (names.length) {
6112
6188
  sources.push(rel);
@@ -6122,7 +6198,7 @@ function discoverMcpServers(root2, ownServers) {
6122
6198
 
6123
6199
  // src/commands/code.ts
6124
6200
  function registerCode(program) {
6125
- 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) {
6126
6202
  const global = readGlobal(this);
6127
6203
  const instruction = (instructionParts ?? []).join(" ").trim();
6128
6204
  const config = loadCodeConfig(rootOf(global));
@@ -6135,7 +6211,7 @@ function registerCode(program) {
6135
6211
  try {
6136
6212
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6137
6213
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6138
- const { loadGraph: loadGraph2 } = await import('./load-4MLIHGXF.js');
6214
+ const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
6139
6215
  const state = readOrchestratorState2();
6140
6216
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6141
6217
  const pin = mode ? activePin2(mode, state) : null;
@@ -6219,7 +6295,7 @@ function registerCode(program) {
6219
6295
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6220
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)');
6221
6297
  }
6222
- const { runInteractive } = await import('./interactive-HLGJJFLI.js');
6298
+ const { runInteractive } = await import('./interactive-MJVMY5JP.js');
6223
6299
  await runInteractive(
6224
6300
  rootOf(global),
6225
6301
  global,
@@ -6252,7 +6328,7 @@ function registerCode(program) {
6252
6328
  let mockReply;
6253
6329
  if (opts.mock) {
6254
6330
  try {
6255
- mockReply = fs7.readFileSync(opts.mock, "utf8");
6331
+ mockReply = fs8.readFileSync(opts.mock, "utf8");
6256
6332
  } catch {
6257
6333
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
6258
6334
  }
@@ -6301,18 +6377,18 @@ function registerCode(program) {
6301
6377
  };
6302
6378
  try {
6303
6379
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6304
- const { runCodeStreamJson } = await import('./stream-json-Y45JBNYP.js');
6305
- 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');
6306
6382
  const readline5 = await import('readline');
6307
6383
  const child = await import('child_process');
6308
6384
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6309
6385
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6310
6386
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6311
- const { startCodeRuntimeSession } = await import('./runtime-session-5M6QZZOS.js');
6312
- 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');
6313
6389
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6314
6390
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6315
- const { vgdRequest: vgdRequest2 } = await import('./vgd-TGGEAGQZ.js');
6391
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6316
6392
  const federation = loadOrDiscoverFederation(root2);
6317
6393
  const modelProfile = mergeModelExecutionProfile(
6318
6394
  resolveModelExecutionProfile({
@@ -6358,7 +6434,7 @@ ${res.stderr}` : ""),
6358
6434
  exitCode: res.status ?? 1
6359
6435
  };
6360
6436
  };
6361
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-ZCKBYQ2D.js');
6437
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6362
6438
  const vgBuiltin = createVgBuiltinMcpTools({
6363
6439
  getGraph: () => graph,
6364
6440
  root: root2,
@@ -6378,50 +6454,187 @@ ${res.stderr}` : ""),
6378
6454
  };
6379
6455
  }
6380
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
+ };
6381
6522
  try {
6382
- await runCodeStreamJson({
6383
- graph,
6384
- root: root2,
6385
- instruction,
6386
- providers: route.providers,
6387
- fsImpl: nodeCodeFs(root2),
6388
- run,
6389
- executionEnv,
6390
- graphBackend,
6391
- modelProfile,
6392
- auto: !!auto,
6393
- maxSteps,
6394
- budget: modelProfile.capsuleBudgetTokens,
6395
- contextBudget,
6396
- denyCommands: config.denyCommands,
6397
- testCommand: config.testCommand,
6398
- stream: true,
6399
- verify: verify3 ? { command: verify3.command, maxRounds: modelProfile.maxRepairRounds } : void 0,
6400
- capsule,
6401
- files: opts.file.length ? opts.file : void 0,
6402
- worktreeOverlay: true,
6403
- advancedMode: !capsule,
6404
- externalTools,
6405
- attribution: {
6406
- client: "vg-code",
6407
- provider: primarySlug,
6408
- model: route.providers[0]?.model
6409
- },
6410
- now: () => Date.now(),
6411
- emit: emitStream,
6412
- bindDecisions: (session) => {
6413
- streamApprove = (action) => session.approve(action);
6414
- const rl = readline5.createInterface({ input: process.stdin });
6415
- rl.on("line", (raw) => {
6416
- try {
6417
- const msg = JSON.parse(raw);
6418
- if (typeof msg.approveId === "number") session.submitDecision(msg.approveId, !!msg.approve);
6419
- if (typeof msg.answerId === "number") session.submitAnswer(msg.answerId, String(msg.answer ?? ""));
6420
- } catch {
6421
- }
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;
6422
6558
  });
6423
- }
6424
- });
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
+ }
6425
6638
  } finally {
6426
6639
  await disposeMcpStream?.();
6427
6640
  await runtime.dispose();
@@ -6440,8 +6653,8 @@ ${res.stderr}` : ""),
6440
6653
  if (!autonomous && !tty) {
6441
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).");
6442
6655
  }
6443
- const { agentTask } = await import('./interactive-HLGJJFLI.js');
6444
- const { nodeCodeFs } = await import('./session-2JT4AUZT.js');
6656
+ const { agentTask } = await import('./interactive-MJVMY5JP.js');
6657
+ const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6445
6658
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6446
6659
  let priorSummary;
6447
6660
  if (opts.continue) {
@@ -6450,7 +6663,7 @@ ${res.stderr}` : ""),
6450
6663
  if (prev) priorSummary = summarizeSession(prev);
6451
6664
  }
6452
6665
  const prompter = tty ? new TtyPrompter() : void 0;
6453
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-ZCKBYQ2D.js');
6666
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6454
6667
  const vgBuiltin = createVgBuiltinMcpTools({
6455
6668
  getGraph: () => graph,
6456
6669
  root: root2,
@@ -6474,11 +6687,11 @@ ${res.stderr}` : ""),
6474
6687
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6475
6688
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6476
6689
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6477
- const { startCodeRuntimeSession } = await import('./runtime-session-5M6QZZOS.js');
6478
- 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');
6479
6692
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6480
6693
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6481
- const { vgdRequest: vgdRequest2 } = await import('./vgd-TGGEAGQZ.js');
6694
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6482
6695
  const federation = loadFederation(root2);
6483
6696
  const modelProfile = mergeModelExecutionProfile(
6484
6697
  resolveModelExecutionProfile({
@@ -6570,7 +6783,7 @@ ${res.stderr}` : ""),
6570
6783
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
6571
6784
  });
6572
6785
  if (opts.out) {
6573
- fs7.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6786
+ fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6574
6787
  }
6575
6788
  if (global.json) {
6576
6789
  json(result);
@@ -6783,7 +6996,7 @@ async function addCmd(root2, rest, opts, asJson) {
6783
6996
  }
6784
6997
  function readPackageVersion(root2) {
6785
6998
  try {
6786
- 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"));
6787
7000
  return typeof pkg.version === "string" ? pkg.version : void 0;
6788
7001
  } catch {
6789
7002
  return void 0;
@@ -6791,7 +7004,7 @@ function readPackageVersion(root2) {
6791
7004
  }
6792
7005
  function readOptionalFile(p) {
6793
7006
  try {
6794
- const t = fs7__default.readFileSync(p, "utf8");
7007
+ const t = fs8__default.readFileSync(p, "utf8");
6795
7008
  return t.trim() ? t : void 0;
6796
7009
  } catch {
6797
7010
  return void 0;
@@ -6806,8 +7019,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
6806
7019
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
6807
7020
  const version = (opts.version || readPackageVersion(root2) || "").trim();
6808
7021
  if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
6809
- const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6810
- 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;
6811
7024
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
6812
7025
  const result = await publishPrivateLibrary(
6813
7026
  { name, version, readme, dts, language: opts.language },
@@ -6939,8 +7152,8 @@ function registerExport(program) {
6939
7152
  out(content.trimEnd());
6940
7153
  return;
6941
7154
  }
6942
- fs7.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
6943
- fs7.writeFileSync(file, content);
7155
+ fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
7156
+ fs8.writeFileSync(file, content);
6944
7157
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
6945
7158
  });
6946
7159
  applyGlobalOptions(cmd);
@@ -6950,43 +7163,43 @@ function detectFormat(file) {
6950
7163
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
6951
7164
  if (lower.endsWith(".spdx.json")) return "spdx";
6952
7165
  if (file === "-") return "json";
6953
- return formatForExt(path37.extname(file));
7166
+ return formatForExt(path38.extname(file));
6954
7167
  }
6955
7168
  function registerBundle(program) {
6956
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) {
6957
7170
  const global = readGlobal(this);
6958
7171
  const root2 = rootOf(global);
6959
- const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
7172
+ const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
6960
7173
  let grammarFiles;
6961
7174
  try {
6962
7175
  grammarFiles = resolvedGrammarFiles();
6963
7176
  } catch {
6964
7177
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
6965
7178
  }
6966
- fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
7179
+ fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
6967
7180
  let grammarCount = 0;
6968
7181
  for (const { fileName, absPath } of grammarFiles) {
6969
- fs7.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
7182
+ fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
6970
7183
  grammarCount++;
6971
7184
  }
6972
7185
  const included = [`grammars/ (${grammarCount} .wasm)`];
6973
7186
  const graphSrc = resolveGraphPath(root2, global.graph);
6974
- if (fs7.existsSync(graphSrc)) {
6975
- fs7.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
7187
+ if (fs8.existsSync(graphSrc)) {
7188
+ fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
6976
7189
  included.push("graph.json");
6977
7190
  } else {
6978
7191
  const graph = loadGraphFileWithSnapshot(graphSrc);
6979
7192
  if (graph) {
6980
- fs7.writeFileSync(path37.join(outDir, "graph.json"), serializeGraph(graph));
7193
+ fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
6981
7194
  included.push("graph.json");
6982
7195
  }
6983
7196
  }
6984
7197
  const cat = catalogPath(root2);
6985
- if (fs7.existsSync(cat)) {
6986
- fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
7198
+ if (fs8.existsSync(cat)) {
7199
+ fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
6987
7200
  included.push("vibgrate.lib.json");
6988
- if (fs7.existsSync(libDir(root2))) {
6989
- 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 });
6990
7203
  included.push("lib/");
6991
7204
  }
6992
7205
  }
@@ -6998,15 +7211,15 @@ function registerBundle(program) {
6998
7211
  included,
6999
7212
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
7000
7213
  };
7001
- fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7214
+ fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7002
7215
  `);
7003
7216
  if (global.json) {
7004
- json({ out: path37.relative(root2, outDir), ...manifest });
7217
+ json({ out: path38.relative(root2, outDir), ...manifest });
7005
7218
  return;
7006
7219
  }
7007
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
7220
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
7008
7221
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
7009
- 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"`));
7010
7223
  });
7011
7224
  applyGlobalOptions(cmd);
7012
7225
  }
@@ -7024,7 +7237,7 @@ async function runDoctor(global) {
7024
7237
  const root2 = rootOf(global);
7025
7238
  const local = global.local === true;
7026
7239
  const graphPath = resolveGraphPath(root2, global.graph);
7027
- 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;
7028
7241
  const graph = loadGraph(root2, graphPath);
7029
7242
  let staleFiles = null;
7030
7243
  if (graph) {
@@ -7050,14 +7263,14 @@ async function runDoctor(global) {
7050
7263
  root: root2,
7051
7264
  configFile,
7052
7265
  map: {
7053
- path: path37.relative(root2, graphPath),
7266
+ path: path38.relative(root2, graphPath),
7054
7267
  built: graph !== null,
7055
7268
  generatedAt: graph?.generatedAt ?? null,
7056
7269
  staleFiles
7057
7270
  },
7058
7271
  libCatalog: {
7059
- path: path37.relative(root2, catalogPath(root2)),
7060
- present: fs7.existsSync(catalogPath(root2)),
7272
+ path: path38.relative(root2, catalogPath(root2)),
7273
+ present: fs8.existsSync(catalogPath(root2)),
7061
7274
  libraries: libCount
7062
7275
  },
7063
7276
  credentials: creds,
@@ -7114,7 +7327,7 @@ async function runDoctor(global) {
7114
7327
  );
7115
7328
  info(
7116
7329
  ` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
7117
- ` \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}`
7118
7331
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
7119
7332
  );
7120
7333
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -7194,7 +7407,9 @@ function registerDaemon(program) {
7194
7407
  if (await vgdIsRunning({ socketPath })) {
7195
7408
  throw new CliError(`vgd is already running at ${socketPath}`, ExitCode.ERROR);
7196
7409
  }
7197
- const server = await startVgdServer({ socketPath });
7410
+ let requestShutdown = () => {
7411
+ };
7412
+ const server = await startVgdServer({ socketPath, onShutdownRequest: () => requestShutdown() });
7198
7413
  if (!global.quiet) {
7199
7414
  info(`vgd \xB7 listening on ${c.dim(server.socketPath)} (${VGD_PROTOCOL_VERSION})`);
7200
7415
  info(c.dim(" register a workspace: vg daemon register"));
@@ -7205,6 +7420,7 @@ function registerDaemon(program) {
7205
7420
  if (!global.quiet) info(c.dim("vgd \xB7 stopped"));
7206
7421
  process.exit(0);
7207
7422
  };
7423
+ requestShutdown = () => void shutdown();
7208
7424
  process.on("SIGINT", () => void shutdown());
7209
7425
  process.on("SIGTERM", () => void shutdown());
7210
7426
  await new Promise(() => {
@@ -7224,33 +7440,70 @@ function registerDaemon(program) {
7224
7440
  }
7225
7441
  return;
7226
7442
  }
7227
- const child = spawnDetachedDaemonStart(socketPath);
7228
- child.unref();
7229
- const deadline = Date.now() + 8e3;
7230
- let ready = false;
7231
- while (Date.now() < deadline) {
7232
- await sleep(100);
7233
- if (await vgdIsRunning({ socketPath })) {
7234
- ready = true;
7235
- break;
7236
- }
7237
- }
7238
- if (!ready) {
7239
- throw new CliError(`vgd failed to become ready at ${socketPath}`, ExitCode.ERROR);
7240
- }
7443
+ const child = await startDetachedVgd(socketPath);
7241
7444
  const res = await vgdRequest({ op: "status" }, { socketPath });
7242
7445
  if (global.json) {
7243
7446
  json({ running: true, ensured: true, ...res.ok ? res : { socketPath } });
7244
7447
  } else if (!global.quiet) {
7245
- const pid = res.ok && "pid" in res ? res.pid : child.pid;
7448
+ const pid = res.ok && "pid" in res ? res.pid : child;
7246
7449
  info(`vgd \xB7 started in background pid ${pid} \xB7 ${c.dim(socketPath)}`);
7247
7450
  }
7248
7451
  });
7249
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);
7250
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) {
7251
7504
  const global = readGlobal(this);
7252
7505
  const socketPath = socketOf(this);
7253
- const root2 = path37.resolve(rootArg ?? rootOf(global));
7506
+ const root2 = path38.resolve(rootArg ?? rootOf(global));
7254
7507
  if (!await vgdIsRunning({ socketPath })) {
7255
7508
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7256
7509
  }
@@ -7286,7 +7539,7 @@ function registerDaemon(program) {
7286
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) {
7287
7540
  const global = readGlobal(this);
7288
7541
  const socketPath = socketOf(this);
7289
- const primary = path37.resolve(rootArg ?? rootOf(global));
7542
+ const primary = path38.resolve(rootArg ?? rootOf(global));
7290
7543
  if (!await vgdIsRunning({ socketPath })) {
7291
7544
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7292
7545
  }
@@ -7314,32 +7567,42 @@ function registerDaemon(program) {
7314
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) {
7315
7568
  const global = readGlobal(this);
7316
7569
  const socketPath = socketOf(this);
7317
- const root2 = path37.resolve(rootArg ?? rootOf(global));
7570
+ const root2 = path38.resolve(rootArg ?? rootOf(global));
7318
7571
  if (!await vgdIsRunning({ socketPath })) {
7319
7572
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
7320
7573
  }
7321
- const { loadGraph: loadGraph2 } = await import('./load-4MLIHGXF.js');
7322
- const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7323
- const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7324
7574
  const opts = this.opts();
7325
- const graph = loadGraph2(root2, global.graph);
7326
- if (!graph) {
7327
- throw new CliError(
7328
- `no code map found for ${root2} \u2014 run \`vg build\` (or bare \`vg\`) first`,
7329
- ExitCode.NOT_FOUND
7330
- );
7331
- }
7332
- const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
7333
- if (!reg.ok) throw new CliError(reg.error, ExitCode.ERROR);
7334
- const git2 = opts.gitRef?.trim() || detectGitRef(root2).ref || "HEAD";
7335
- const repositoryId = reg.ok && "workspace" in reg ? reg.workspace.id : repositoryIdFromRoot(root2);
7336
- const put = await vgdRequest(
7337
- { 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 },
7338
7577
  { socketPath }
7339
7578
  );
7340
- 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
+ }
7341
7604
  if (global.json) json(put);
7342
- else if ("stored" in put) {
7605
+ else if (put.ok && "stored" in put) {
7343
7606
  info(`vgd \xB7 published graph \xB7 ${put.nodeCount} node(s) \xB7 ref ${put.gitRef}`);
7344
7607
  info(c.dim(` repositoryId ${put.repositoryId}`));
7345
7608
  }
@@ -7434,7 +7697,7 @@ function socketOf(cmd) {
7434
7697
  let c2 = cmd;
7435
7698
  while (c2) {
7436
7699
  const opts = c2.opts();
7437
- if (opts.socket) return path37.resolve(opts.socket);
7700
+ if (opts.socket) return path38.resolve(opts.socket);
7438
7701
  c2 = c2.parent;
7439
7702
  }
7440
7703
  return vgdSocketPath();
@@ -7457,6 +7720,62 @@ function spawnDetachedDaemonStart(socketPath) {
7457
7720
  function sleep(ms) {
7458
7721
  return new Promise((r) => setTimeout(r, ms));
7459
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
+ }
7460
7779
  async function repositoryIdForCwd(socketPath, root2) {
7461
7780
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7462
7781
  const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
@@ -7535,7 +7854,7 @@ function registerPolicy(program) {
7535
7854
  const global = readGlobal(this);
7536
7855
  let raw;
7537
7856
  try {
7538
- raw = fs7.readFileSync(file, "utf8");
7857
+ raw = fs8.readFileSync(file, "utf8");
7539
7858
  } catch {
7540
7859
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
7541
7860
  }
@@ -7655,11 +7974,11 @@ function registerLlmHost(program) {
7655
7974
  applyGlobalOptions(cmd);
7656
7975
  }
7657
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) => {
7658
- const rootDir = path37.resolve(targetPath);
7659
- const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7977
+ const rootDir = path38.resolve(targetPath);
7978
+ const vibgrateDir2 = path38.join(rootDir, ".vibgrate");
7660
7979
  await ensureDir(vibgrateDir2);
7661
7980
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7662
- const configPath = path37.join(rootDir, "vibgrate.config.ts");
7981
+ const configPath = path38.join(rootDir, "vibgrate.config.ts");
7663
7982
  if (await pathExists(configPath)) {
7664
7983
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7665
7984
  } else {
@@ -7667,7 +7986,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7667
7986
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7668
7987
  }
7669
7988
  if (opts.baseline) {
7670
- const { runBaseline } = await import('./baseline-UOTGTJYT.js');
7989
+ const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
7671
7990
  await runBaseline(rootDir);
7672
7991
  }
7673
7992
  console.log("");
@@ -7770,16 +8089,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
7770
8089
  };
7771
8090
  }
7772
8091
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
7773
- const content = await readFile3(path37.join(rootDir, relFile));
8092
+ const content = await readFile3(path38.join(rootDir, relFile));
7774
8093
  if (!content) return false;
7775
8094
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
7776
8095
  return new RegExp(`\\b${escaped}\\b`).test(content);
7777
8096
  }
7778
8097
  async function defaultReadFile(absPath) {
7779
8098
  try {
7780
- const stat2 = await fs20.stat(absPath);
8099
+ const stat2 = await fs22.stat(absPath);
7781
8100
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
7782
- return await fs20.readFile(absPath, "utf8");
8101
+ return await fs22.readFile(absPath, "utf8");
7783
8102
  } catch {
7784
8103
  return null;
7785
8104
  }
@@ -7965,7 +8284,7 @@ var AI_ASSISTANT_DETECTORS = [
7965
8284
  async function detectAiAssistant(rootDir) {
7966
8285
  for (const detector of AI_ASSISTANT_DETECTORS) {
7967
8286
  for (const file of detector.files) {
7968
- if (await pathExists$1(path37.join(rootDir, file))) {
8287
+ if (await pathExists$1(path38.join(rootDir, file))) {
7969
8288
  return detector.name;
7970
8289
  }
7971
8290
  }
@@ -8159,7 +8478,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8159
8478
  collectExcludes,
8160
8479
  []
8161
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) => {
8162
- const rootDir = path37.resolve(targetPath);
8481
+ const rootDir = path38.resolve(targetPath);
8163
8482
  if (!await pathExists$1(rootDir)) {
8164
8483
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8165
8484
  process.exit(1);
@@ -8167,7 +8486,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8167
8486
  const hasDsn = !!resolveDsn(opts.dsn);
8168
8487
  const willPush = !opts.offline && (opts.push || hasDsn);
8169
8488
  const noLocalArtifacts = opts.localArtifacts === false;
8170
- 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"));
8171
8490
  let pinnedRegion;
8172
8491
  let planTier;
8173
8492
  let upgradeUrl;
@@ -8426,40 +8745,40 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
8426
8745
  function scanStaleness(rootDir, artifactPath) {
8427
8746
  let ref;
8428
8747
  try {
8429
- ref = fs7.statSync(artifactPath).mtimeMs;
8748
+ ref = fs8.statSync(artifactPath).mtimeMs;
8430
8749
  } catch {
8431
8750
  return { stale: false };
8432
8751
  }
8433
8752
  let newest = -Infinity;
8434
8753
  let newestChanged;
8435
- const MAX_ENTRIES = 2e4;
8754
+ const MAX_ENTRIES2 = 2e4;
8436
8755
  let scanned = 0;
8437
8756
  const walk2 = (dir, depth) => {
8438
- if (depth > 8 || scanned > MAX_ENTRIES) return;
8757
+ if (depth > 8 || scanned > MAX_ENTRIES2) return;
8439
8758
  let entries;
8440
8759
  try {
8441
- entries = fs7.readdirSync(dir, { withFileTypes: true });
8760
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
8442
8761
  } catch {
8443
8762
  return;
8444
8763
  }
8445
8764
  for (const e of entries) {
8446
8765
  scanned++;
8447
- if (scanned > MAX_ENTRIES) break;
8766
+ if (scanned > MAX_ENTRIES2) break;
8448
8767
  if (e.isDirectory()) {
8449
- 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);
8450
8769
  continue;
8451
8770
  }
8452
8771
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
8453
- const abs = path37.join(dir, e.name);
8772
+ const abs = path38.join(dir, e.name);
8454
8773
  let mtimeMs;
8455
8774
  try {
8456
- mtimeMs = fs7.statSync(abs).mtimeMs;
8775
+ mtimeMs = fs8.statSync(abs).mtimeMs;
8457
8776
  } catch {
8458
8777
  continue;
8459
8778
  }
8460
8779
  if (mtimeMs > newest) {
8461
8780
  newest = mtimeMs;
8462
- newestChanged = path37.relative(rootDir, abs) || e.name;
8781
+ newestChanged = path38.relative(rootDir, abs) || e.name;
8463
8782
  }
8464
8783
  }
8465
8784
  };
@@ -8590,7 +8909,7 @@ function analyzeTree(root2, packages) {
8590
8909
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
8591
8910
  let entries;
8592
8911
  try {
8593
- entries = fs7.readdirSync(dir, { withFileTypes: true });
8912
+ entries = fs8.readdirSync(dir, { withFileTypes: true });
8594
8913
  } catch {
8595
8914
  return;
8596
8915
  }
@@ -8599,17 +8918,17 @@ function analyzeTree(root2, packages) {
8599
8918
  if (filesSeen >= MAX_FILES) return;
8600
8919
  if (entry.isDirectory()) {
8601
8920
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8602
- walk2(path37.join(dir, entry.name), depth + 1);
8921
+ walk2(path38.join(dir, entry.name), depth + 1);
8603
8922
  continue;
8604
8923
  }
8605
- const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8924
+ const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
8606
8925
  if (!fileEco || fileEco === "unknown") continue;
8607
8926
  filesSeen++;
8608
- const full = path37.join(dir, entry.name);
8927
+ const full = path38.join(dir, entry.name);
8609
8928
  let content;
8610
8929
  try {
8611
- if (fs7.statSync(full).size > MAX_FILE_BYTES2) continue;
8612
- content = fs7.readFileSync(full, "utf8");
8930
+ if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
8931
+ content = fs8.readFileSync(full, "utf8");
8613
8932
  } catch {
8614
8933
  continue;
8615
8934
  }
@@ -8920,7 +9239,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8920
9239
  }
8921
9240
  const outcomes = effective.map((t) => {
8922
9241
  const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
8923
- return { t, res: run(c2, path37.join(rootDir, t.dir)) };
9242
+ return { t, res: run(c2, path38.join(rootDir, t.dir)) };
8924
9243
  });
8925
9244
  const failures = outcomes.filter((o) => !o.res.ok);
8926
9245
  if (failures.length === 0) {
@@ -8949,8 +9268,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
8949
9268
  return results;
8950
9269
  }
8951
9270
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
8952
- var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
8953
- 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");
8954
9273
  async function fetchLatestVersion() {
8955
9274
  try {
8956
9275
  const controller = new AbortController();
@@ -8977,8 +9296,8 @@ async function fetchLatestVersion() {
8977
9296
  }
8978
9297
  async function writeCache(data) {
8979
9298
  try {
8980
- await fs20.mkdir(CACHE_DIR, { recursive: true });
8981
- 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");
8982
9301
  } catch {
8983
9302
  }
8984
9303
  }
@@ -8989,7 +9308,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
8989
9308
  if (!execPath) return null;
8990
9309
  let resolved = execPath;
8991
9310
  try {
8992
- resolved = fs7.realpathSync(execPath);
9311
+ resolved = fs8.realpathSync(execPath);
8993
9312
  } catch {
8994
9313
  }
8995
9314
  const p = resolved.replace(/\\/g, "/");
@@ -9019,14 +9338,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
9019
9338
  pm: "yarn",
9020
9339
  root: () => {
9021
9340
  const dir = tryRun("yarn global dir");
9022
- return dir ? path37.join(dir, "node_modules") : null;
9341
+ return dir ? path38.join(dir, "node_modules") : null;
9023
9342
  }
9024
9343
  },
9025
- { 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") }
9026
9345
  ];
9027
9346
  for (const probe of probes) {
9028
9347
  const root2 = probe.root();
9029
- if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
9348
+ if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
9030
9349
  }
9031
9350
  return null;
9032
9351
  }
@@ -9045,15 +9364,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
9045
9364
  }
9046
9365
  }
9047
9366
  async function detectPackageManager(cwd) {
9048
- if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9049
- if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
9050
- 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";
9051
9370
  return "npm";
9052
9371
  }
9053
9372
  async function detectWorkspaceRoot(cwd) {
9054
- if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
9373
+ if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
9055
9374
  try {
9056
- const pkgPath = path37.join(cwd, "package.json");
9375
+ const pkgPath = path38.join(cwd, "package.json");
9057
9376
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9058
9377
  const pkg = JSON.parse(raw);
9059
9378
  return pkg.workspaces != null;
@@ -9078,7 +9397,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
9078
9397
  }
9079
9398
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
9080
9399
  try {
9081
- const pkgPath = path37.join(cwd, "package.json");
9400
+ const pkgPath = path38.join(cwd, "package.json");
9082
9401
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9083
9402
  const parsed = JSON.parse(raw);
9084
9403
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -9167,8 +9486,29 @@ var updateCommand = new Command("update").description("Update vibgrate to the la
9167
9486
  process.exit(1);
9168
9487
  }
9169
9488
  if (opts.reap !== false) reapAndReport(cwd, latest);
9489
+ if (opts.reap !== false) await restartVgdAndReport();
9170
9490
  }
9171
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
+ }
9172
9512
  function reapAndReport(cwd, keepVersion) {
9173
9513
  let reaped = [];
9174
9514
  try {
@@ -9226,13 +9566,13 @@ function collectCandidates(artifact) {
9226
9566
  return out2;
9227
9567
  }
9228
9568
  var defaultFixScanner = async (rootDir) => {
9229
- 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`);
9230
9570
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
9231
9571
  const advanced = await loadAdvancedScanHook();
9232
9572
  return runCoreScan(rootDir, scanOpts, advanced);
9233
9573
  };
9234
9574
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
9235
- const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
9575
+ const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
9236
9576
  if (await pathExists(artifactPath)) {
9237
9577
  const staleness = scanStaleness(rootDir, artifactPath);
9238
9578
  if (!staleness.stale) {
@@ -9259,7 +9599,7 @@ async function repositoryIdentity(rootDir, override) {
9259
9599
  }
9260
9600
  }
9261
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) => {
9262
- const rootDir = path37.resolve(targetPath);
9602
+ const rootDir = path38.resolve(targetPath);
9263
9603
  if (!await pathExists(rootDir)) {
9264
9604
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
9265
9605
  process.exit(1);
@@ -9420,7 +9760,7 @@ function emit(report, format) {
9420
9760
  }
9421
9761
  }
9422
9762
  function relProjectDir(rootDir, projectPath) {
9423
- const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
9763
+ const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
9424
9764
  return rel === "" ? "." : rel;
9425
9765
  }
9426
9766
  async function buildTargetResolver(rootDir, artifact) {
@@ -10255,7 +10595,7 @@ function formatMarkdown(artifact) {
10255
10595
 
10256
10596
  // src/reporting/commands/report.ts
10257
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) => {
10258
- const artifactPath = path37.resolve(opts.in);
10598
+ const artifactPath = path38.resolve(opts.in);
10259
10599
  if (!await pathExists(artifactPath)) {
10260
10600
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
10261
10601
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -10304,8 +10644,8 @@ function openUrl(url) {
10304
10644
  // src/reporting/commands/login.ts
10305
10645
  var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
10306
10646
  function isInside(dir, file) {
10307
- const rel = path37.relative(dir, file);
10308
- return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
10647
+ const rel = path38.relative(dir, file);
10648
+ return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
10309
10649
  }
10310
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(
10311
10651
  "--local",
@@ -10560,7 +10900,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10560
10900
  try {
10561
10901
  const statements = [];
10562
10902
  if (opts.from) {
10563
- const fromPath = path37.resolve(opts.from);
10903
+ const fromPath = path38.resolve(opts.from);
10564
10904
  if (!await pathExists(fromPath)) {
10565
10905
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
10566
10906
  `));
@@ -10578,9 +10918,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10578
10918
  });
10579
10919
  const json2 = JSON.stringify(doc, null, 2);
10580
10920
  if (opts.out) {
10581
- await writeTextFile(path37.resolve(opts.out), json2 + "\n");
10921
+ await writeTextFile(path38.resolve(opts.out), json2 + "\n");
10582
10922
  process.stderr.write(
10583
- 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)}
10584
10924
  `
10585
10925
  );
10586
10926
  } else {
@@ -10763,7 +11103,7 @@ function formatDeltaText(base, current) {
10763
11103
  return lines.join("\n");
10764
11104
  }
10765
11105
  async function readArtifactOrExit(filePath) {
10766
- const absolutePath = path37.resolve(filePath);
11106
+ const absolutePath = path38.resolve(filePath);
10767
11107
  if (!await pathExists(absolutePath)) {
10768
11108
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
10769
11109
  process.exit(1);
@@ -10780,7 +11120,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
10780
11120
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
10781
11121
  const body = JSON.stringify(sbom, null, 2);
10782
11122
  if (opts.out) {
10783
- await writeTextFile(path37.resolve(opts.out), body);
11123
+ await writeTextFile(path38.resolve(opts.out), body);
10784
11124
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
10785
11125
  } else {
10786
11126
  console.log(body);
@@ -10791,7 +11131,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
10791
11131
  const current = await readArtifactOrExit(opts.to);
10792
11132
  const report = formatDeltaText(base, current);
10793
11133
  if (opts.out) {
10794
- await writeTextFile(path37.resolve(opts.out), report);
11134
+ await writeTextFile(path38.resolve(opts.out), report);
10795
11135
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
10796
11136
  } else {
10797
11137
  console.log(report);
@@ -10922,20 +11262,20 @@ function resolveRegime(id) {
10922
11262
  return regime;
10923
11263
  }
10924
11264
  function evidenceDir(root2) {
10925
- return path37.join(root2, ".vibgrate", "evidence");
11265
+ return path38.join(root2, ".vibgrate", "evidence");
10926
11266
  }
10927
11267
  function orgPath(root2) {
10928
- return path37.join(evidenceDir(root2), "org.json");
11268
+ return path38.join(evidenceDir(root2), "org.json");
10929
11269
  }
10930
11270
  function productsPath(root2) {
10931
- return path37.join(evidenceDir(root2), "products.json");
11271
+ return path38.join(evidenceDir(root2), "products.json");
10932
11272
  }
10933
11273
  function releasesDir(root2) {
10934
- return path37.join(evidenceDir(root2), "releases");
11274
+ return path38.join(evidenceDir(root2), "releases");
10935
11275
  }
10936
11276
  function releasePath(root2, productId, version) {
10937
11277
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
10938
- return path37.join(releasesDir(root2), `${safe}.json`);
11278
+ return path38.join(releasesDir(root2), `${safe}.json`);
10939
11279
  }
10940
11280
  var DEFAULT_ORG = {
10941
11281
  responsiblePersons: [],
@@ -10966,7 +11306,7 @@ async function freezeRelease(root2, release) {
10966
11306
  const p = releasePath(root2, release.productId, release.version);
10967
11307
  if (await pathExists(p)) {
10968
11308
  throw new CliError(
10969
- `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`,
10970
11310
  ExitCode.USAGE_ERROR
10971
11311
  );
10972
11312
  }
@@ -10980,7 +11320,7 @@ async function loadReleases(root2, productId) {
10980
11320
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
10981
11321
  const releases = [];
10982
11322
  for (const f of files) {
10983
- const rel = await readJsonFile(path37.join(dir, f));
11323
+ const rel = await readJsonFile(path38.join(dir, f));
10984
11324
  if (!productId || rel.productId === productId) releases.push(rel);
10985
11325
  }
10986
11326
  return releases;
@@ -11675,19 +12015,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
11675
12015
  var DEFAULT_KEY = "attest-key.pem";
11676
12016
  function resolveSigningKey(root2, explicit) {
11677
12017
  const chosen = process.env.VG_ATTEST_KEY;
11678
- 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);
11679
12019
  let minted = false;
11680
- if (!fs7.existsSync(keyPath)) {
12020
+ if (!fs8.existsSync(keyPath)) {
11681
12021
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
11682
12022
  const kp = generateKeypair();
11683
- fs7.mkdirSync(path37.dirname(keyPath), { recursive: true });
11684
- fs7.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11685
- 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);
11686
12026
  minted = true;
11687
12027
  }
11688
12028
  let key2;
11689
12029
  try {
11690
- key2 = crypto3.createPrivateKey(fs7.readFileSync(keyPath, "utf8"));
12030
+ key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
11691
12031
  } catch {
11692
12032
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
11693
12033
  }
@@ -11698,16 +12038,16 @@ function resolveSigningKey(root2, explicit) {
11698
12038
  }
11699
12039
  function writeBundle(input) {
11700
12040
  const dir = input.outDir;
11701
- fs7.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11702
- 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)}
11703
12043
  `);
11704
12044
  write("result.json", input.result);
11705
- write(path37.join("inputs", "advisory.json"), input.advisory);
12045
+ write(path38.join("inputs", "advisory.json"), input.advisory);
11706
12046
  for (const rel of input.releases) {
11707
12047
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11708
- write(path37.join("inputs", "releases", `${safe}.json`), rel);
12048
+ write(path38.join("inputs", "releases", `${safe}.json`), rel);
11709
12049
  }
11710
- 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 });
11711
12051
  write("provenance.json", {
11712
12052
  method: "deterministic",
11713
12053
  modelDrafted: [],
@@ -11723,13 +12063,13 @@ function writeBundle(input) {
11723
12063
  disclaimer: input.regime.disclaimer
11724
12064
  });
11725
12065
  if (input.envelope) {
11726
- 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)}
11727
12067
  `);
11728
12068
  }
11729
12069
  if (input.timestampToken) {
11730
- fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
12070
+ fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
11731
12071
  }
11732
- fs7.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
12072
+ fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
11733
12073
  return dir;
11734
12074
  }
11735
12075
  function verifyDoc(input) {
@@ -11790,13 +12130,13 @@ function undeterminedFields(result, regime) {
11790
12130
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
11791
12131
  }
11792
12132
  async function recordDrill(root2, record) {
11793
- const dir = path37.join(evidenceDir(root2), "drills");
11794
- 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`);
11795
12135
  await writeJsonFile(p, record);
11796
12136
  return p;
11797
12137
  }
11798
12138
  async function hasRecentDrill(root2, asOf) {
11799
- const dir = path37.join(evidenceDir(root2), "drills");
12139
+ const dir = path38.join(evidenceDir(root2), "drills");
11800
12140
  if (!await pathExists(dir)) return void 0;
11801
12141
  const { readdir } = await import('fs/promises');
11802
12142
  const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
@@ -11804,7 +12144,7 @@ async function hasRecentDrill(root2, asOf) {
11804
12144
  if (files.length === 0) return void 0;
11805
12145
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
11806
12146
  for (const f of files) {
11807
- const rec = await readJsonFile2(path37.join(dir, f));
12147
+ const rec = await readJsonFile2(path38.join(dir, f));
11808
12148
  if (rec.ranAt >= cutoff) return true;
11809
12149
  }
11810
12150
  return false;
@@ -11884,7 +12224,7 @@ function formatRegimeList() {
11884
12224
 
11885
12225
  // src/reporting/commands/evidence/index.ts
11886
12226
  function root(opts) {
11887
- return path37.resolve(opts.cwd ?? process.cwd());
12227
+ return path38.resolve(opts.cwd ?? process.cwd());
11888
12228
  }
11889
12229
  function slug(name) {
11890
12230
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -11972,7 +12312,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11972
12312
  const release = await buildRelease({
11973
12313
  productId: product.id,
11974
12314
  version,
11975
- from: path37.resolve(rootDir, opts.from),
12315
+ from: path38.resolve(rootDir, opts.from),
11976
12316
  shipDate: opts.shipDate,
11977
12317
  buildId: opts.buildId,
11978
12318
  artefactDigest: opts.digest,
@@ -11980,7 +12320,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
11980
12320
  frozenAt: nowIso()
11981
12321
  });
11982
12322
  const p = await freezeRelease(rootDir, release);
11983
- 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)}`);
11984
12324
  });
11985
12325
  async function runExposure(rootDir, vuln, opts) {
11986
12326
  const org = await loadOrg(rootDir);
@@ -12032,7 +12372,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12032
12372
  console.log("\n" + buildPack(result, regime, org, stage));
12033
12373
  }
12034
12374
  if (opts.bundle) {
12035
- const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12375
+ const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12036
12376
  let envelope;
12037
12377
  if (opts.sign !== false) {
12038
12378
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -12040,7 +12380,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12040
12380
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
12041
12381
  }
12042
12382
  writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
12043
- 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" : ""}`);
12044
12384
  }
12045
12385
  process.exitCode = exposureExit(result.overallStatus);
12046
12386
  });
@@ -12072,7 +12412,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
12072
12412
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
12073
12413
  const md = buildPack(result, regime, org, stage);
12074
12414
  if (opts.out) {
12075
- fs7.writeFileSync(path37.resolve(rootDir, opts.out), md);
12415
+ fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
12076
12416
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
12077
12417
  } else {
12078
12418
  console.log(md);
@@ -12114,20 +12454,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
12114
12454
  }
12115
12455
  });
12116
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) => {
12117
- const abs = path37.resolve(bundlePath);
12118
- const envPath = fs7.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
12119
- if (!fs7.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12120
- const envelope = JSON.parse(fs7.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12121
- const resultPath = path37.join(path37.dirname(envPath), "result.json");
12122
- const result = fs7.existsSync(resultPath) ? JSON.parse(fs7.readFileSync(resultPath, "utf8")) : void 0;
12123
- 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;
12124
12464
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
12125
12465
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
12126
12466
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
12127
12467
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
12128
- const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
12129
- if (fs7.existsSync(tsrPath) && result) {
12130
- 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));
12131
12471
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
12132
12472
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
12133
12473
  }
@@ -12194,12 +12534,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
12194
12534
  const releases = [];
12195
12535
  for (const list of releasesByProduct.values()) releases.push(...list);
12196
12536
  const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
12197
- const dir = path37.resolve(rootDir, opts.out);
12198
- await writeJsonFile(path37.join(dir, "org.json"), org);
12199
- await writeJsonFile(path37.join(dir, "products.json"), products);
12200
- for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12201
- await writeJsonFile(path37.join(dir, "readiness.json"), report);
12202
- 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)`);
12203
12543
  });
12204
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) => {
12205
12545
  const rootDir = root(opts);
@@ -12225,10 +12565,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
12225
12565
  }));
12226
12566
  let exposure;
12227
12567
  if (opts.result) {
12228
- const raw = path37.resolve(rootDir, opts.result);
12229
- const resultPath = fs7.existsSync(raw) && fs7.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
12230
- if (!fs7.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12231
- 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"));
12232
12572
  }
12233
12573
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
12234
12574
  const body = JSON.stringify(payload);
@@ -12418,7 +12758,7 @@ function dispatch(argv, cwd) {
12418
12758
  }
12419
12759
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
12420
12760
  if (looksLikeQuestion) return ["ask", ...args];
12421
- if (fs7.existsSync(path37.resolve(cwd, first))) {
12761
+ if (fs8.existsSync(path38.resolve(cwd, first))) {
12422
12762
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
12423
12763
  }
12424
12764
  const moved = MOVED_COMMANDS[first];
@@ -12463,9 +12803,9 @@ async function main(argv = process.argv) {
12463
12803
  }
12464
12804
  function readCwd(raw) {
12465
12805
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
12466
- 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]);
12467
12807
  const eq = raw.find((a) => a.startsWith("--cwd="));
12468
- if (eq) return path37.resolve(eq.slice("--cwd=".length));
12808
+ if (eq) return path38.resolve(eq.slice("--cwd=".length));
12469
12809
  return process.cwd();
12470
12810
  }
12471
12811
  function handleError(err) {