@vibgrate/cli 2026.729.3 → 2026.730.1

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 (73) hide show
  1. package/dist/{agent-Z4Z66IGM.js → agent-33BMKWJC.js} +4 -4
  2. package/dist/{agent-Z4Z66IGM.js.map → agent-33BMKWJC.js.map} +1 -1
  3. package/dist/baseline-V6MYDEMS.js +9 -0
  4. package/dist/{baseline-Q3QQF5QF.js.map → baseline-V6MYDEMS.js.map} +1 -1
  5. package/dist/{chunk-JXMZCTVZ.js → chunk-5G7C6H2G.js} +14 -204
  6. package/dist/chunk-5G7C6H2G.js.map +1 -0
  7. package/dist/{chunk-RIEUPFXO.js → chunk-6D4BCGRQ.js} +6 -62
  8. package/dist/chunk-6D4BCGRQ.js.map +1 -0
  9. package/dist/{chunk-YMSXP6AO.js → chunk-6WNJJXFY.js} +4 -4
  10. package/dist/{chunk-YMSXP6AO.js.map → chunk-6WNJJXFY.js.map} +1 -1
  11. package/dist/{chunk-HWFVBYX4.js → chunk-CFL3QQQZ.js} +7 -6
  12. package/dist/chunk-CFL3QQQZ.js.map +1 -0
  13. package/dist/{chunk-EQ3IOFIG.js → chunk-CQDCZQFV.js} +3 -3
  14. package/dist/{chunk-EQ3IOFIG.js.map → chunk-CQDCZQFV.js.map} +1 -1
  15. package/dist/{chunk-KBPNH67Q.js → chunk-DBMYWNLC.js} +3 -3
  16. package/dist/{chunk-KBPNH67Q.js.map → chunk-DBMYWNLC.js.map} +1 -1
  17. package/dist/{chunk-5MNX3OLS.js → chunk-EKCNSRNJ.js} +7 -6
  18. package/dist/chunk-EKCNSRNJ.js.map +1 -0
  19. package/dist/{chunk-G4HTI4ZM.js → chunk-FHJBGPJZ.js} +3 -2
  20. package/dist/chunk-FHJBGPJZ.js.map +1 -0
  21. package/dist/{chunk-3FQSBVQD.js → chunk-GLT3N7T2.js} +8 -5
  22. package/dist/chunk-GLT3N7T2.js.map +1 -0
  23. package/dist/chunk-HTLDXEHW.js +60 -0
  24. package/dist/chunk-HTLDXEHW.js.map +1 -0
  25. package/dist/{chunk-GI6W53LM.js → chunk-IDAQV3NQ.js} +4 -2
  26. package/dist/chunk-IDAQV3NQ.js.map +1 -0
  27. package/dist/{chunk-42RDYQFF.js → chunk-KGWEBM2J.js} +3 -3
  28. package/dist/{chunk-42RDYQFF.js.map → chunk-KGWEBM2J.js.map} +1 -1
  29. package/dist/{chunk-4BOWWYSE.js → chunk-ON7PZNYV.js} +12 -11
  30. package/dist/chunk-ON7PZNYV.js.map +1 -0
  31. package/dist/chunk-Q4UQ73NA.js +6 -0
  32. package/dist/{chunk-N3HCPBFY.js.map → chunk-Q4UQ73NA.js.map} +1 -1
  33. package/dist/chunk-TJ3WIJ7H.js +216 -0
  34. package/dist/chunk-TJ3WIJ7H.js.map +1 -0
  35. package/dist/chunk-VOEYUAER.js +203 -0
  36. package/dist/chunk-VOEYUAER.js.map +1 -0
  37. package/dist/cli.js +390 -507
  38. package/dist/cli.js.map +1 -1
  39. package/dist/{fs-6JKZNQ3U.js → fs-HNR6LAI7.js} +3 -3
  40. package/dist/fs-HNR6LAI7.js.map +1 -0
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.js +10 -8
  43. package/dist/index.js.map +1 -1
  44. package/dist/{interactive-MJVMY5JP.js → interactive-NJG6467J.js} +16 -14
  45. package/dist/interactive-NJG6467J.js.map +1 -0
  46. package/dist/load-YPSEDYIW.js +10 -0
  47. package/dist/{load-4PARCNMD.js.map → load-YPSEDYIW.js.map} +1 -1
  48. package/dist/run-outcome-5FQWHWYK.js +253 -0
  49. package/dist/run-outcome-5FQWHWYK.js.map +1 -0
  50. package/dist/{runtime-session-AILFASQV.js → runtime-session-Y4ZD3QDO.js} +7 -6
  51. package/dist/{runtime-session-AILFASQV.js.map → runtime-session-Y4ZD3QDO.js.map} +1 -1
  52. package/dist/{stream-json-MTPWWVRR.js → stream-json-3YOPU3LF.js} +4 -4
  53. package/dist/{stream-json-MTPWWVRR.js.map → stream-json-3YOPU3LF.js.map} +1 -1
  54. package/dist/{vg-mcp-bridge-BLHEIWMT.js → vg-mcp-bridge-PZFGTZSA.js} +8 -7
  55. package/dist/vg-mcp-bridge-PZFGTZSA.js.map +1 -0
  56. package/dist/{vgd-S7D2SITC.js → vgd-DH7AHQ23.js} +6 -5
  57. package/dist/vgd-DH7AHQ23.js.map +1 -0
  58. package/package.json +1 -1
  59. package/dist/baseline-Q3QQF5QF.js +0 -9
  60. package/dist/chunk-3FQSBVQD.js.map +0 -1
  61. package/dist/chunk-4BOWWYSE.js.map +0 -1
  62. package/dist/chunk-5MNX3OLS.js.map +0 -1
  63. package/dist/chunk-G4HTI4ZM.js.map +0 -1
  64. package/dist/chunk-GI6W53LM.js.map +0 -1
  65. package/dist/chunk-HWFVBYX4.js.map +0 -1
  66. package/dist/chunk-JXMZCTVZ.js.map +0 -1
  67. package/dist/chunk-N3HCPBFY.js +0 -6
  68. package/dist/chunk-RIEUPFXO.js.map +0 -1
  69. package/dist/fs-6JKZNQ3U.js.map +0 -1
  70. package/dist/interactive-MJVMY5JP.js.map +0 -1
  71. package/dist/load-4PARCNMD.js +0 -9
  72. package/dist/vg-mcp-bridge-BLHEIWMT.js.map +0 -1
  73. package/dist/vgd-S7D2SITC.js.map +0 -1
package/dist/cli.js CHANGED
@@ -1,11 +1,12 @@
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-5MNX3OLS.js';
3
- export { runBuild } from './chunk-5MNX3OLS.js';
4
- import { loadAdvancedScanHook, baselineCommand } from './chunk-YMSXP6AO.js';
2
+ import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-EKCNSRNJ.js';
3
+ export { runBuild } from './chunk-EKCNSRNJ.js';
4
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-TJ3WIJ7H.js';
5
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-6WNJJXFY.js';
5
6
  import { buildModelInstallPlan } from './chunk-WHJMS7XC.js';
6
7
  import { runCodeSession } from './chunk-WBMMRERH.js';
7
8
  import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
8
- import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-EQ3IOFIG.js';
9
+ import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-CQDCZQFV.js';
9
10
  import './chunk-5I4VSBWQ.js';
10
11
  import './chunk-IS7VTH2Q.js';
11
12
  import { init_resolve_ollama, gatherSystemMemory, resolveOllamaBinary, hasOllamaBinary, resolve_ollama_exports } from './chunk-OWSFZQOP.js';
@@ -14,7 +15,7 @@ import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
14
15
  import './chunk-IZDH67DX.js';
15
16
  import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-EVLS2M5G.js';
16
17
  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 { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-KGWEBM2J.js';
18
19
  import './chunk-543E6WDJ.js';
19
20
  import { summarizeDiffs, ScriptedProvider } from './chunk-MYM5VIJ4.js';
20
21
  import { ensurePackage, ensureUnavailableMessage } from './chunk-REIGWTTH.js';
@@ -22,13 +23,14 @@ import './chunk-RGEVBSLK.js';
22
23
  import { vgdSocketPath, vgdIsRunning, vgdRequest, vgdPidPath } from './chunk-RBIRXQR6.js';
23
24
  import { buildIdentifierTrieFromGraph } from './chunk-5HYCB55P.js';
24
25
  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';
26
+ import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-CFL3QQQZ.js';
27
+ 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-GLT3N7T2.js';
28
+ import { resolveDsn, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, parseDsn as parseDsn$1, uploadScanArtifact, dsnCommand, pushCommand, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, coveringTests, FREE_PACK, readScanArtifact, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath } from './chunk-6D4BCGRQ.js';
29
+ import { resolveIngestHost, dashHostForIngestHost, availableRegionIds, ingestHostForRegionId } from './chunk-HTLDXEHW.js';
30
+ 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-ON7PZNYV.js';
29
31
  import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
30
32
  import './chunk-IPICO2RV.js';
31
- import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-G4HTI4ZM.js';
33
+ import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-FHJBGPJZ.js';
32
34
  import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-US2DAKCM.js';
33
35
  import { init_cli_invocation, resolveCliInvocation, NPX_INVOCATION } from './chunk-3LSG7Z4I.js';
34
36
  import { resolveOne } from './chunk-J7LKEB2R.js';
@@ -37,29 +39,30 @@ import { discoverModels } from './chunk-CQDUBAQY.js';
37
39
  import { freeBytesOnVolume, weightStoreDir, listCachedWeights, ensureWeightCached, catalogIntegrityReport } from './chunk-OV4KGXPD.js';
38
40
  import { resolvedGrammarFiles, grammarSetVersion } from './chunk-UTNNGKKX.js';
39
41
  import './chunk-RXP66R2E.js';
40
- import { resolveGraphPath, renderReport, loadGraph, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, SCHEMA_VERSION } from './chunk-JXMZCTVZ.js';
41
- import { VERSION } from './chunk-N3HCPBFY.js';
42
+ import { loadGraph, SCHEMA_VERSION } from './chunk-VOEYUAER.js';
43
+ import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-5G7C6H2G.js';
44
+ import { VERSION } from './chunk-Q4UQ73NA.js';
42
45
  import { cacheDir, serializeGraph, stableStringify } from './chunk-ZKNB4YH4.js';
43
46
  import './chunk-BWPBB45M.js';
44
47
  import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
45
48
  import './chunk-BPF3YX2U.js';
46
- import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
49
+ import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-IDAQV3NQ.js';
47
50
  import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
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
+ import * as fs7 from 'fs';
52
+ import fs7__default, { realpathSync } from 'fs';
53
+ import * as path37 from 'path';
54
+ import path37__default from 'path';
52
55
  import { fileURLToPath, pathToFileURL } from 'url';
53
56
  import { Command, CommanderError, Option } from 'commander';
54
- import * as os from 'os';
55
- import * as crypto3 from 'crypto';
56
- import { randomUUID } from 'crypto';
57
57
  import * as semver3 from 'semver';
58
58
  import semver3__default from 'semver';
59
59
  import { execSync, spawn, spawnSync, execFileSync } from 'child_process';
60
60
  import * as readline from 'readline';
61
+ import * as crypto3 from 'crypto';
62
+ import { randomUUID } from 'crypto';
61
63
  import chalk7 from 'chalk';
62
- import * as fs22 from 'fs/promises';
64
+ import * as fs21 from 'fs/promises';
65
+ import * as os from 'os';
63
66
 
64
67
  init_cli_invocation();
65
68
  function registerStatus(program) {
@@ -69,10 +72,10 @@ function registerStatus(program) {
69
72
  applyGlobalOptions(cmd);
70
73
  }
71
74
  async function runStatus(global) {
72
- const root2 = path38.resolve(global.cwd ?? ".");
75
+ const root2 = path37.resolve(global.cwd ?? ".");
73
76
  const graphPath = resolveGraphPath(root2, global.graph);
74
77
  const graph = loadGraph(root2, graphPath);
75
- const hasCache = fs8.existsSync(path38.join(cacheDir(root2), "parse-cache.json"));
78
+ const hasCache = fs7.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
76
79
  let stale = null;
77
80
  let staleExact = false;
78
81
  if (graph) {
@@ -92,8 +95,8 @@ async function runStatus(global) {
92
95
  }
93
96
  if (global.json) {
94
97
  json({
95
- root: path38.relative(process.cwd(), root2) || ".",
96
- graphPath: path38.relative(root2, graphPath),
98
+ root: path37.relative(process.cwd(), root2) || ".",
99
+ graphPath: path37.relative(root2, graphPath),
97
100
  built: graph !== null,
98
101
  generatedAt: graph?.generatedAt ?? null,
99
102
  counts: graph?.meta.counts ?? null,
@@ -108,11 +111,11 @@ async function runStatus(global) {
108
111
  return;
109
112
  }
110
113
  if (!graph) {
111
- info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path38.relative(root2, graphPath))}`);
114
+ info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
112
115
  info(` run ${c.bold("vg")} to build one`);
113
116
  return;
114
117
  }
115
- info(`${c.cyan("vg")} \xB7 ${path38.relative(root2, graphPath)}`);
118
+ info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
116
119
  info(` generated ${graph.generatedAt}`);
117
120
  info(
118
121
  ` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
@@ -129,7 +132,7 @@ async function runStatus(global) {
129
132
  if (vibgrateDir(root2)) ;
130
133
  }
131
134
  function rootOf(global) {
132
- return path38.resolve(global.cwd ?? ".");
135
+ return path37.resolve(global.cwd ?? ".");
133
136
  }
134
137
  function requireGraph(global) {
135
138
  const root2 = rootOf(global);
@@ -838,210 +841,6 @@ function fmtRef(r) {
838
841
  function pad2(s, n) {
839
842
  return s.padStart(n, " ");
840
843
  }
841
- var SCHEMA_VERSION2 = "1";
842
- var OFFSET_FILE = "stats-share.json";
843
- var INSTALL_ID_DIR = path38.join(os.homedir(), ".vibgrate");
844
- var INSTALL_ID_FILE = path38.join(INSTALL_ID_DIR, "install-id");
845
- var SEND_TIMEOUT_MS = 4e3;
846
- function telemetryOptOut(env = process.env) {
847
- const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
848
- if (dnt !== "" && dnt !== "0" && dnt !== "false") return "DO_NOT_TRACK";
849
- const vt = (env.VIBGRATE_TELEMETRY ?? "").trim().toLowerCase();
850
- if (vt === "0" || vt === "false" || vt === "off") return "VIBGRATE_TELEMETRY";
851
- return null;
852
- }
853
- var CI_ENV_VARS = [
854
- "CI",
855
- "GITHUB_ACTIONS",
856
- "GITLAB_CI",
857
- "CIRCLECI",
858
- "TRAVIS",
859
- "BUILDKITE",
860
- "JENKINS_URL",
861
- "TF_BUILD"
862
- ];
863
- function isCI(env = process.env) {
864
- return CI_ENV_VARS.some((v) => {
865
- const val = (env[v] ?? "").trim().toLowerCase();
866
- return val !== "" && val !== "0" && val !== "false";
867
- });
868
- }
869
- function installId(env = process.env) {
870
- if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
871
- try {
872
- const existing = fs8.readFileSync(INSTALL_ID_FILE, "utf8").trim();
873
- if (isUuid(existing)) return existing;
874
- } catch {
875
- }
876
- const id = randomUuid();
877
- try {
878
- fs8.mkdirSync(INSTALL_ID_DIR, { recursive: true });
879
- fs8.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
880
- } catch {
881
- }
882
- return id;
883
- }
884
- function isUuid(s) {
885
- return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(s);
886
- }
887
- function randomUuid() {
888
- return randomUUID();
889
- }
890
- function statsEndpoint() {
891
- const override = process.env.VIBGRATE_STATS_ENDPOINT;
892
- if (override && /^https?:\/\//.test(override)) return override;
893
- return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
894
- }
895
- function offsetPath(root2) {
896
- return path38.join(cacheDir(root2), OFFSET_FILE);
897
- }
898
- function ledgerFilePath(root2) {
899
- return path38.join(cacheDir(root2), "savings.jsonl");
900
- }
901
- function readOffset(root2) {
902
- try {
903
- const raw = JSON.parse(fs8.readFileSync(offsetPath(root2), "utf8"));
904
- return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
905
- } catch {
906
- return 0;
907
- }
908
- }
909
- function writeOffset(root2, offset) {
910
- try {
911
- fs8.mkdirSync(cacheDir(root2), { recursive: true });
912
- fs8.writeFileSync(offsetPath(root2), JSON.stringify({ offset }) + "\n");
913
- } catch {
914
- }
915
- }
916
- function buildBatch(root2, fromOffset, id = installId()) {
917
- const file = ledgerFilePath(root2);
918
- let size = 0;
919
- try {
920
- size = fs8.statSync(file).size;
921
- } catch {
922
- return { batch: null, newOffset: 0 };
923
- }
924
- const start = fromOffset > size ? 0 : fromOffset;
925
- if (start >= size) return { batch: null, newOffset: size };
926
- let text = "";
927
- try {
928
- const fd = fs8.openSync(file, "r");
929
- try {
930
- const buf = Buffer.alloc(size - start);
931
- fs8.readSync(fd, buf, 0, buf.length, start);
932
- text = buf.toString("utf8");
933
- } finally {
934
- fs8.closeSync(fd);
935
- }
936
- } catch {
937
- return { batch: null, newOffset: fromOffset };
938
- }
939
- const lastNl = text.lastIndexOf("\n");
940
- if (lastNl < 0) return { batch: null, newOffset: start };
941
- const consumed = start + lastNl + 1;
942
- const rows = /* @__PURE__ */ new Map();
943
- let total = 0;
944
- let minTs = Infinity;
945
- let maxTs = -Infinity;
946
- for (const line of text.slice(0, lastNl).split("\n")) {
947
- if (!line.trim()) continue;
948
- let e;
949
- try {
950
- e = JSON.parse(line);
951
- } catch {
952
- continue;
953
- }
954
- const source = e.source ?? "mcp";
955
- const client = e.client ?? "unknown";
956
- const outcome = e.outcome ?? "complete";
957
- const key2 = `${source}|${client}|${e.tool}|${outcome}`;
958
- const row = rows.get(key2) ?? {
959
- source,
960
- client,
961
- tool: e.tool,
962
- outcome,
963
- calls: 0,
964
- vgTokens: 0,
965
- baselineTokens: 0
966
- };
967
- row.calls++;
968
- row.vgTokens += e.vgTokens ?? 0;
969
- row.baselineTokens += e.baselineTokens ?? 0;
970
- rows.set(key2, row);
971
- total++;
972
- if (typeof e.ts === "number") {
973
- if (e.ts < minTs) minTs = e.ts;
974
- if (e.ts > maxTs) maxTs = e.ts;
975
- }
976
- }
977
- if (total === 0 || !Number.isFinite(minTs)) return { batch: null, newOffset: consumed };
978
- const batch = {
979
- schemaVersion: SCHEMA_VERSION2,
980
- installId: id,
981
- vgVersion: VERSION,
982
- os: process.platform,
983
- arch: process.arch,
984
- windowStart: new Date(minTs).toISOString(),
985
- windowEnd: new Date(maxTs).toISOString(),
986
- totalCalls: total,
987
- rows: [...rows.values()]
988
- };
989
- return { batch, newOffset: consumed };
990
- }
991
- async function postBatch(batch) {
992
- const controller = new AbortController();
993
- const timer = setTimeout(() => controller.abort(), SEND_TIMEOUT_MS);
994
- timer.unref?.();
995
- try {
996
- const res = await fetch(statsEndpoint(), {
997
- method: "POST",
998
- headers: { "Content-Type": "application/json", Connection: "close" },
999
- body: JSON.stringify(batch),
1000
- signal: controller.signal
1001
- });
1002
- return res.ok;
1003
- } catch {
1004
- return false;
1005
- } finally {
1006
- clearTimeout(timer);
1007
- }
1008
- }
1009
- var StatsSharer = class {
1010
- constructor(root2) {
1011
- this.root = root2;
1012
- this.offset = readOffset(root2);
1013
- }
1014
- root;
1015
- id = installId();
1016
- offset;
1017
- flushing = false;
1018
- /**
1019
- * Flush any new ledger entries. Single-flight (a slow POST won't overlap the
1020
- * next tick). Best-effort: any failure is swallowed and retried next time.
1021
- */
1022
- async flush() {
1023
- if (this.flushing) return;
1024
- this.flushing = true;
1025
- try {
1026
- const { batch, newOffset } = buildBatch(this.root, this.offset, this.id);
1027
- if (!batch) {
1028
- if (newOffset > this.offset) {
1029
- this.offset = newOffset;
1030
- writeOffset(this.root, newOffset);
1031
- }
1032
- return;
1033
- }
1034
- const ok = await postBatch(batch);
1035
- if (ok) {
1036
- this.offset = newOffset;
1037
- writeOffset(this.root, newOffset);
1038
- }
1039
- } catch {
1040
- } finally {
1041
- this.flushing = false;
1042
- }
1043
- }
1044
- };
1045
844
 
1046
845
  // src/util/origin.ts
1047
846
  function originAllowed(origin, allowlist) {
@@ -1067,12 +866,12 @@ var PUBLISH_INTERVAL_MS = 2e3;
1067
866
  var KEEPALIVE_MS = 1e4;
1068
867
  var STALE_MS = 6e4;
1069
868
  function liveStatsDir(root2) {
1070
- return path38.join(cacheDir(root2), "serve-live");
869
+ return path37.join(cacheDir(root2), "serve-live");
1071
870
  }
1072
871
  function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
1073
872
  let entries;
1074
873
  try {
1075
- entries = fs8.readdirSync(dir);
874
+ entries = fs7.readdirSync(dir);
1076
875
  } catch {
1077
876
  return [];
1078
877
  }
@@ -1081,7 +880,7 @@ function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid
1081
880
  if (!/^serve-\d+\.json$/.test(name)) continue;
1082
881
  let parsed;
1083
882
  try {
1084
- parsed = JSON.parse(fs8.readFileSync(path38.join(dir, name), "utf8"));
883
+ parsed = JSON.parse(fs7.readFileSync(path37.join(dir, name), "utf8"));
1085
884
  } catch {
1086
885
  continue;
1087
886
  }
@@ -1103,7 +902,7 @@ var LiveStatsBus = class {
1103
902
  this.dir = dir;
1104
903
  this.stats = stats;
1105
904
  this.pid = pid;
1106
- this.file = path38.join(dir, `serve-${this.pid}.json`);
905
+ this.file = path37.join(dir, `serve-${this.pid}.json`);
1107
906
  }
1108
907
  dir;
1109
908
  stats;
@@ -1135,10 +934,10 @@ var LiveStatsBus = class {
1135
934
  this.lastWriteAt = now;
1136
935
  const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
1137
936
  try {
1138
- fs8.mkdirSync(this.dir, { recursive: true });
937
+ fs7.mkdirSync(this.dir, { recursive: true });
1139
938
  const tmp = `${this.file}.tmp`;
1140
- fs8.writeFileSync(tmp, JSON.stringify(body));
1141
- fs8.renameSync(tmp, this.file);
939
+ fs7.writeFileSync(tmp, JSON.stringify(body));
940
+ fs7.renameSync(tmp, this.file);
1142
941
  } catch {
1143
942
  }
1144
943
  }
@@ -1149,24 +948,24 @@ var LiveStatsBus = class {
1149
948
  siblings(now = Date.now()) {
1150
949
  let entries;
1151
950
  try {
1152
- entries = fs8.readdirSync(this.dir);
951
+ entries = fs7.readdirSync(this.dir);
1153
952
  } catch {
1154
953
  return [];
1155
954
  }
1156
955
  const out2 = [];
1157
956
  for (const name of entries.sort()) {
1158
957
  if (!/^serve-\d+\.json$/.test(name)) continue;
1159
- const file = path38.join(this.dir, name);
958
+ const file = path37.join(this.dir, name);
1160
959
  let parsed;
1161
960
  try {
1162
- parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
961
+ parsed = JSON.parse(fs7.readFileSync(file, "utf8"));
1163
962
  } catch {
1164
963
  continue;
1165
964
  }
1166
965
  if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
1167
966
  if (now - parsed.updatedAt > STALE_MS) {
1168
967
  try {
1169
- fs8.unlinkSync(file);
968
+ fs7.unlinkSync(file);
1170
969
  } catch {
1171
970
  }
1172
971
  continue;
@@ -1178,7 +977,7 @@ var LiveStatsBus = class {
1178
977
  }
1179
978
  unlinkOwn = () => {
1180
979
  try {
1181
- fs8.unlinkSync(this.file);
980
+ fs7.unlinkSync(this.file);
1182
981
  } catch {
1183
982
  }
1184
983
  };
@@ -1491,12 +1290,12 @@ var LedgerTail = class {
1491
1290
  if (size === this.offset) return;
1492
1291
  let chunk;
1493
1292
  try {
1494
- const fd = fs8.openSync(this.file, "r");
1293
+ const fd = fs7.openSync(this.file, "r");
1495
1294
  try {
1496
1295
  chunk = Buffer.alloc(size - this.offset);
1497
- fs8.readSync(fd, chunk, 0, chunk.length, this.offset);
1296
+ fs7.readSync(fd, chunk, 0, chunk.length, this.offset);
1498
1297
  } finally {
1499
- fs8.closeSync(fd);
1298
+ fs7.closeSync(fd);
1500
1299
  }
1501
1300
  } catch {
1502
1301
  return;
@@ -1509,7 +1308,7 @@ var LedgerTail = class {
1509
1308
  }
1510
1309
  sizeOf() {
1511
1310
  try {
1512
- return fs8.statSync(this.file).size;
1311
+ return fs7.statSync(this.file).size;
1513
1312
  } catch {
1514
1313
  return 0;
1515
1314
  }
@@ -1894,19 +1693,19 @@ function endOfLine(text, line) {
1894
1693
  }
1895
1694
  var CACHE_VERSION = "vg-lsp-scan-cache/2";
1896
1695
  function cachePath(root2) {
1897
- return path38.join(cacheDir(root2), "lsp-scan.json");
1696
+ return path37.join(cacheDir(root2), "lsp-scan.json");
1898
1697
  }
1899
1698
  function manifestHash(root2) {
1900
1699
  const files = [];
1901
1700
  const walk2 = (dir) => {
1902
1701
  let entries;
1903
1702
  try {
1904
- entries = fs8.readdirSync(dir, { withFileTypes: true });
1703
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
1905
1704
  } catch {
1906
1705
  return;
1907
1706
  }
1908
1707
  for (const entry of entries) {
1909
- const abs = path38.join(dir, entry.name);
1708
+ const abs = path37.join(dir, entry.name);
1910
1709
  if (entry.isDirectory()) {
1911
1710
  if (SKIP_DIRS.has(entry.name)) continue;
1912
1711
  walk2(abs);
@@ -1916,8 +1715,8 @@ function manifestHash(root2) {
1916
1715
  const base = entry.name.toLowerCase();
1917
1716
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
1918
1717
  try {
1919
- const rel = path38.relative(root2, abs).split(path38.sep).join("/");
1920
- files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
1718
+ const rel = path37.relative(root2, abs).split(path37.sep).join("/");
1719
+ files.push({ rel, hash: hashBytes(fs7.readFileSync(abs)) });
1921
1720
  } catch {
1922
1721
  }
1923
1722
  }
@@ -1927,16 +1726,16 @@ function manifestHash(root2) {
1927
1726
  return hashString(canonicalize(files));
1928
1727
  }
1929
1728
  function isDependencyFile(root2, filePath) {
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);
1729
+ const rel = path37.relative(path37.resolve(root2), path37.resolve(filePath));
1730
+ if (rel === "" || rel.startsWith("..") || path37.isAbsolute(rel)) return false;
1731
+ const parts = rel.split(path37.sep);
1933
1732
  if (parts.slice(0, -1).some((dir) => SKIP_DIRS.has(dir))) return false;
1934
1733
  const base = parts[parts.length - 1].toLowerCase();
1935
1734
  return isManifest(filePath) || SKIP_FILES.has(base);
1936
1735
  }
1937
1736
  function loadScanCache(root2, key2) {
1938
1737
  try {
1939
- const raw = JSON.parse(fs8.readFileSync(cachePath(root2), "utf8"));
1738
+ const raw = JSON.parse(fs7.readFileSync(cachePath(root2), "utf8"));
1940
1739
  if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
1941
1740
  return { manifestHash: raw.manifestHash, artifact: raw.artifact };
1942
1741
  }
@@ -1946,8 +1745,8 @@ function loadScanCache(root2, key2) {
1946
1745
  }
1947
1746
  function writeScanCache(root2, key2, artifact) {
1948
1747
  try {
1949
- fs8.mkdirSync(cacheDir(root2), { recursive: true });
1950
- fs8.writeFileSync(
1748
+ fs7.mkdirSync(cacheDir(root2), { recursive: true });
1749
+ fs7.writeFileSync(
1951
1750
  cachePath(root2),
1952
1751
  stableStringify(
1953
1752
  { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
@@ -1960,7 +1759,7 @@ function writeScanCache(root2, key2, artifact) {
1960
1759
  var MAX_ENTRIES = 1e3;
1961
1760
  var KEEP_ENTRIES = 500;
1962
1761
  function historyPath(root2) {
1963
- return path38.join(root2, ".vibgrate", "score-history.jsonl");
1762
+ return path37.join(root2, ".vibgrate", "score-history.jsonl");
1964
1763
  }
1965
1764
  function parseLine(line) {
1966
1765
  try {
@@ -1974,7 +1773,7 @@ function parseLine(line) {
1974
1773
  }
1975
1774
  function readHistory(root2) {
1976
1775
  try {
1977
- return fs8.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1776
+ return fs7.readFileSync(historyPath(root2), "utf8").split("\n").filter((l) => l.trim()).map(parseLine).filter((e) => e !== null);
1978
1777
  } catch {
1979
1778
  return [];
1980
1779
  }
@@ -2001,13 +1800,14 @@ function recordScore(root2, entry) {
2001
1800
  }
2002
1801
  }
2003
1802
  const file = historyPath(root2);
2004
- fs8.mkdirSync(path38.dirname(file), { recursive: true });
2005
- fs8.appendFileSync(file, `${JSON.stringify(entry)}
1803
+ fs7.mkdirSync(path37.dirname(file), { recursive: true });
1804
+ ensureVibgrateGitignore(root2);
1805
+ fs7.appendFileSync(file, `${JSON.stringify(entry)}
2006
1806
  `);
2007
1807
  const all = readHistory(root2);
2008
1808
  if (all.length > MAX_ENTRIES) {
2009
1809
  const kept = all.slice(-KEEP_ENTRIES);
2010
- fs8.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
1810
+ fs7.writeFileSync(file, kept.map((e) => JSON.stringify(e)).join("\n") + "\n");
2011
1811
  }
2012
1812
  } catch {
2013
1813
  }
@@ -2469,6 +2269,12 @@ var VibgrateLanguageServer = class {
2469
2269
  artifact = null;
2470
2270
  scanning = false;
2471
2271
  queued = false;
2272
+ /**
2273
+ * Sticky until the next `scan()` runs: set by explicit "Rescan Workspace"
2274
+ * (and preserved if a non-force schedule races the debounce). Bypasses the
2275
+ * LSP scan cache so config/SKIP_DIRS changes actually re-score.
2276
+ */
2277
+ forceNextScan = false;
2472
2278
  debounce = null;
2473
2279
  shuttingDown = false;
2474
2280
  graph = null;
@@ -2538,7 +2344,7 @@ var VibgrateLanguageServer = class {
2538
2344
  this.conn.onRequest("workspace/executeCommand", (_m, params) => {
2539
2345
  const p = params;
2540
2346
  if (p.command === "vibgrate.rescan") {
2541
- this.scheduleScan(0);
2347
+ this.scheduleScan(0, { force: true });
2542
2348
  return { ok: true };
2543
2349
  }
2544
2350
  return null;
@@ -2553,7 +2359,8 @@ var VibgrateLanguageServer = class {
2553
2359
  });
2554
2360
  }
2555
2361
  // ── Scanning ─────────────────────────────────────────────────────────────
2556
- scheduleScan(delayMs) {
2362
+ scheduleScan(delayMs, opts) {
2363
+ if (opts?.force) this.forceNextScan = true;
2557
2364
  if (this.debounce) clearTimeout(this.debounce);
2558
2365
  this.debounce = setTimeout(() => void this.scan(), delayMs);
2559
2366
  }
@@ -2563,11 +2370,13 @@ var VibgrateLanguageServer = class {
2563
2370
  return;
2564
2371
  }
2565
2372
  this.scanning = true;
2373
+ const force = this.forceNextScan;
2374
+ this.forceNextScan = false;
2566
2375
  try {
2567
2376
  const cacheKey = { manifestHash: manifestHash(this.opts.root), toolVersion: VERSION, offline: this.opts.offline };
2568
- const cached = loadScanCache(this.opts.root, cacheKey);
2377
+ const cached = force ? null : loadScanCache(this.opts.root, cacheKey);
2569
2378
  if (cached) {
2570
- this.artifact = cached.artifact;
2379
+ this.artifact = pruneArtifactProjects(cached.artifact);
2571
2380
  } else {
2572
2381
  const scanOpts = {
2573
2382
  format: "json",
@@ -2582,7 +2391,7 @@ var VibgrateLanguageServer = class {
2582
2391
  vibgrateVersion: VERSION
2583
2392
  };
2584
2393
  const advanced = await loadAdvancedScanHook();
2585
- this.artifact = await runCoreScan(this.opts.root, scanOpts, advanced);
2394
+ this.artifact = pruneArtifactProjects(await runCoreScan(this.opts.root, scanOpts, advanced));
2586
2395
  writeScanCache(this.opts.root, cacheKey, this.artifact);
2587
2396
  }
2588
2397
  this.publishScore();
@@ -2644,7 +2453,8 @@ var VibgrateLanguageServer = class {
2644
2453
  rootPath: a.rootPath,
2645
2454
  scannedAt: a.timestamp,
2646
2455
  ...delta !== void 0 ? { delta } : {},
2647
- ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
2456
+ ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {},
2457
+ ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {}
2648
2458
  };
2649
2459
  this.conn.notify("vibgrate/score", payload);
2650
2460
  }
@@ -2830,13 +2640,16 @@ var VibgrateLanguageServer = class {
2830
2640
  const reachedPkgs = packageReachSet(this.graph);
2831
2641
  const targets = [];
2832
2642
  for (const proj of a.projects ?? []) {
2643
+ if (isPrunedWorkspacePath(proj.path) || isPrunedWorkspacePath(manifestRelativePath(proj))) {
2644
+ continue;
2645
+ }
2833
2646
  const ecosystem = osvEcosystem(proj.type);
2834
2647
  if (!ecosystem) continue;
2835
2648
  const relManifest = manifestRelativePath(proj);
2836
- const absManifest = path38.resolve(this.opts.root, relManifest);
2649
+ const absManifest = path37.resolve(this.opts.root, relManifest);
2837
2650
  let text = null;
2838
2651
  try {
2839
- if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
2652
+ if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2840
2653
  } catch {
2841
2654
  text = null;
2842
2655
  }
@@ -2881,13 +2694,31 @@ function uriToPath(uri) {
2881
2694
  return uri;
2882
2695
  }
2883
2696
  }
2697
+ function isPrunedWorkspacePath(relPath) {
2698
+ if (!relPath || relPath === "." || relPath === "") return false;
2699
+ const parts = relPath.split(/[/\\]/).filter(Boolean);
2700
+ if (parts.includes(".claude")) return true;
2701
+ return parts.some((p) => SKIP_DIRS.has(p));
2702
+ }
2703
+ function pruneArtifactProjects(a) {
2704
+ const projects = (a.projects ?? []).filter(
2705
+ (p) => !isPrunedWorkspacePath(p.path) && !isPrunedWorkspacePath(manifestRelativePath(p))
2706
+ );
2707
+ if (projects.length === (a.projects ?? []).length) {
2708
+ const findings2 = (a.findings ?? []).filter((f) => !isPrunedWorkspacePath(f.location));
2709
+ if (findings2.length === (a.findings ?? []).length) return a;
2710
+ return { ...a, findings: findings2 };
2711
+ }
2712
+ const findings = (a.findings ?? []).filter((f) => !isPrunedWorkspacePath(f.location));
2713
+ return { ...a, projects, findings };
2714
+ }
2884
2715
  function projectForFile(root2, a, filePath) {
2885
- const dir = path38.dirname(path38.resolve(filePath));
2716
+ const dir = path37.dirname(path37.resolve(filePath));
2886
2717
  let best;
2887
2718
  let bestLen = -1;
2888
2719
  for (const proj of a.projects ?? []) {
2889
- const projDir = path38.resolve(root2, proj.path);
2890
- if ((dir === projDir || dir.startsWith(projDir + path38.sep)) && projDir.length > bestLen) {
2720
+ const projDir = path37.resolve(root2, proj.path);
2721
+ if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2891
2722
  best = proj;
2892
2723
  bestLen = projDir.length;
2893
2724
  }
@@ -2895,7 +2726,7 @@ function projectForFile(root2, a, filePath) {
2895
2726
  return best;
2896
2727
  }
2897
2728
  function sameProject(location, projectPath) {
2898
- return path38.normalize(location) === path38.normalize(projectPath);
2729
+ return path37.normalize(location) === path37.normalize(projectPath);
2899
2730
  }
2900
2731
  function hasReleaseDates(a) {
2901
2732
  for (const proj of a.projects ?? []) {
@@ -2928,9 +2759,31 @@ function scoreForProject(a, proj) {
2928
2759
  counts: { behind, eol, unmaintained, total },
2929
2760
  rootPath: proj.path,
2930
2761
  scannedAt: a.timestamp,
2931
- ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {}
2762
+ ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {},
2763
+ ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {}
2932
2764
  };
2933
2765
  }
2766
+ function runtimeHorizonLabel(project) {
2767
+ const kind = project.type === "node" ? "Node.js" : project.type === "dotnet" ? ".NET" : project.type === "python" ? "Python" : project.type === "java" ? "Java" : project.type;
2768
+ return project.runtime ? `${kind} ${project.runtime}` : kind;
2769
+ }
2770
+ function buildEolHorizon(projects, now = Date.now()) {
2771
+ const byLabel = /* @__PURE__ */ new Map();
2772
+ for (const p of projects) {
2773
+ if (!p.runtimeEolDate) continue;
2774
+ const t = Date.parse(p.runtimeEolDate);
2775
+ if (!Number.isFinite(t)) continue;
2776
+ const label = runtimeHorizonLabel(p);
2777
+ if (byLabel.has(label)) continue;
2778
+ byLabel.set(label, {
2779
+ runtime: label,
2780
+ eolDate: p.runtimeEolDate,
2781
+ daysUntil: Math.round((t - now) / (24 * 60 * 60 * 1e3))
2782
+ });
2783
+ }
2784
+ if (byLabel.size === 0) return void 0;
2785
+ return [...byLabel.values()].sort((a, b) => a.daysUntil - b.daysUntil).slice(0, 5);
2786
+ }
2934
2787
  function bandForScore(n) {
2935
2788
  if (n <= 30) return "low";
2936
2789
  if (n <= 60) return "moderate";
@@ -2968,34 +2821,34 @@ function buildBreakdown(drift, projects) {
2968
2821
  }
2969
2822
  function manifestRelativePath(proj) {
2970
2823
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2971
- const join28 = (name) => base ? path38.join(base, name) : name;
2824
+ const join27 = (name) => base ? path37.join(base, name) : name;
2972
2825
  switch (proj.type) {
2973
2826
  case "node":
2974
2827
  case "typescript":
2975
- return join28("package.json");
2828
+ return join27("package.json");
2976
2829
  case "python":
2977
- return join28("pyproject.toml");
2830
+ return join27("pyproject.toml");
2978
2831
  case "go":
2979
- return join28("go.mod");
2832
+ return join27("go.mod");
2980
2833
  case "rust":
2981
- return join28("Cargo.toml");
2834
+ return join27("Cargo.toml");
2982
2835
  case "ruby":
2983
- return join28("Gemfile");
2836
+ return join27("Gemfile");
2984
2837
  case "php":
2985
- return join28("composer.json");
2838
+ return join27("composer.json");
2986
2839
  case "java":
2987
2840
  case "kotlin":
2988
2841
  case "scala":
2989
2842
  case "groovy":
2990
- return join28("pom.xml");
2843
+ return join27("pom.xml");
2991
2844
  case "dotnet":
2992
- return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2845
+ return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2993
2846
  case "dart":
2994
- return join28("pubspec.yaml");
2847
+ return join27("pubspec.yaml");
2995
2848
  case "elixir":
2996
- return join28("mix.exs");
2849
+ return join27("mix.exs");
2997
2850
  default:
2998
- return join28("package.json");
2851
+ return join27("package.json");
2999
2852
  }
3000
2853
  }
3001
2854
  function packageReachSet(graph) {
@@ -3155,7 +3008,7 @@ function hoverMarkdown(dep, contribution) {
3155
3008
  return lines.join("\n");
3156
3009
  }
3157
3010
  function startLanguageServer(opts) {
3158
- if (!fs8.existsSync(opts.root)) {
3011
+ if (!fs7.existsSync(opts.root)) {
3159
3012
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3160
3013
  `);
3161
3014
  process.exit(1);
@@ -3292,8 +3145,8 @@ function registerShare(program) {
3292
3145
  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) {
3293
3146
  const global = readGlobal(this);
3294
3147
  const root2 = rootOf(global);
3295
- const gitDir = path38.join(root2, ".git");
3296
- if (!fs8.existsSync(gitDir)) {
3148
+ const gitDir = path37.join(root2, ".git");
3149
+ if (!fs7.existsSync(gitDir)) {
3297
3150
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3298
3151
  }
3299
3152
  if (opts.undo) {
@@ -3314,23 +3167,23 @@ function registerShare(program) {
3314
3167
  applyGlobalOptions(cmd);
3315
3168
  }
3316
3169
  function writeVibgrateGitignore(root2, reports) {
3317
- const dir = path38.join(root2, ".vibgrate");
3318
- fs8.mkdirSync(dir, { recursive: true });
3170
+ const dir = path37.join(root2, ".vibgrate");
3171
+ fs7.mkdirSync(dir, { recursive: true });
3319
3172
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
3320
3173
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3321
- fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
3174
+ fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
3322
3175
  `);
3323
3176
  }
3324
3177
  function writeGitAttributes(root2) {
3325
- const file = path38.join(root2, ".gitattributes");
3178
+ const file = path37.join(root2, ".gitattributes");
3326
3179
  const line = ".vibgrate/graph.json merge=vg";
3327
- let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
3180
+ let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "";
3328
3181
  if (!content.split("\n").some((l) => l.trim() === line)) {
3329
3182
  content = content.length ? `${content.replace(/\s*$/, "")}
3330
3183
  ${line}
3331
3184
  ` : `${line}
3332
3185
  `;
3333
- fs8.writeFileSync(file, content);
3186
+ fs7.writeFileSync(file, content);
3334
3187
  }
3335
3188
  }
3336
3189
  function configureMergeDriver(root2) {
@@ -3339,8 +3192,8 @@ function configureMergeDriver(root2) {
3339
3192
  }
3340
3193
  function installPreCommitHook(root2) {
3341
3194
  const hooksDir = hookDir(root2);
3342
- fs8.mkdirSync(hooksDir, { recursive: true });
3343
- const file = path38.join(hooksDir, "pre-commit");
3195
+ fs7.mkdirSync(hooksDir, { recursive: true });
3196
+ const file = path37.join(hooksDir, "pre-commit");
3344
3197
  const block = [
3345
3198
  HOOK_BEGIN,
3346
3199
  "if command -v vg >/dev/null 2>&1; then",
@@ -3349,7 +3202,7 @@ function installPreCommitHook(root2) {
3349
3202
  "fi",
3350
3203
  HOOK_END
3351
3204
  ].join("\n");
3352
- let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "#!/bin/sh\n";
3205
+ let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "#!/bin/sh\n";
3353
3206
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3354
3207
  if (re.test(content)) content = content.replace(re, block);
3355
3208
  else content = `${content.replace(/\s*$/, "")}
@@ -3358,21 +3211,21 @@ ${block}
3358
3211
  `;
3359
3212
  if (!content.startsWith("#!")) content = `#!/bin/sh
3360
3213
  ${content}`;
3361
- fs8.writeFileSync(file, content);
3362
- fs8.chmodSync(file, 493);
3214
+ fs7.writeFileSync(file, content);
3215
+ fs7.chmodSync(file, 493);
3363
3216
  }
3364
3217
  function undo(root2) {
3365
- const hookFile = path38.join(hookDir(root2), "pre-commit");
3366
- if (fs8.existsSync(hookFile)) {
3218
+ const hookFile = path37.join(hookDir(root2), "pre-commit");
3219
+ if (fs7.existsSync(hookFile)) {
3367
3220
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
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);
3221
+ const next2 = fs7.readFileSync(hookFile, "utf8").replace(re, "\n");
3222
+ if (next2.trim() === "#!/bin/sh") fs7.rmSync(hookFile);
3223
+ else fs7.writeFileSync(hookFile, next2);
3371
3224
  }
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);
3225
+ const attr = path37.join(root2, ".gitattributes");
3226
+ if (fs7.existsSync(attr)) {
3227
+ const next2 = fs7.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3228
+ fs7.writeFileSync(attr, next2);
3376
3229
  }
3377
3230
  try {
3378
3231
  git(root2, ["config", "--remove-section", "merge.vg"]);
@@ -3382,10 +3235,10 @@ function undo(root2) {
3382
3235
  function hookDir(root2) {
3383
3236
  try {
3384
3237
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
3385
- if (configured) return path38.resolve(root2, configured);
3238
+ if (configured) return path37.resolve(root2, configured);
3386
3239
  } catch {
3387
3240
  }
3388
- return path38.join(root2, ".git", "hooks");
3241
+ return path37.join(root2, ".git", "hooks");
3389
3242
  }
3390
3243
  function git(root2, args) {
3391
3244
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -3413,9 +3266,9 @@ function registerWatch(program) {
3413
3266
  const global = readGlobal(this);
3414
3267
  const root2 = rootOf(global);
3415
3268
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3416
- const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
3269
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3417
3270
  for (const w of watchRoots) {
3418
- if (!fs8.existsSync(w)) {
3271
+ if (!fs7.existsSync(w)) {
3419
3272
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3420
3273
  }
3421
3274
  }
@@ -3468,14 +3321,14 @@ function registerWatch(program) {
3468
3321
  const watchers = [];
3469
3322
  for (const w of watchRoots) {
3470
3323
  try {
3471
- const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3324
+ const watcher = fs7.watch(w, { recursive: true }, (_event, filename) => {
3472
3325
  if (!filename) {
3473
3326
  schedule("change");
3474
3327
  return;
3475
3328
  }
3476
- const parts = filename.split(path38.sep);
3329
+ const parts = filename.split(path37.sep);
3477
3330
  if (parts.some((p) => SKIP_NAME.has(p))) return;
3478
- if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
3331
+ if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3479
3332
  return;
3480
3333
  }
3481
3334
  schedule(filename);
@@ -3485,7 +3338,7 @@ function registerWatch(program) {
3485
3338
  throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3486
3339
  }
3487
3340
  }
3488
- info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path38.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3341
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3489
3342
  await new Promise((resolve21) => {
3490
3343
  const stop = () => {
3491
3344
  for (const w of watchers) w.close();
@@ -3818,10 +3671,10 @@ function normalizeStandards(raw) {
3818
3671
  }
3819
3672
  function loadStandards(root2) {
3820
3673
  for (const rel of STANDARDS_FILES) {
3821
- const p = path38__default.join(root2, rel);
3674
+ const p = path37__default.join(root2, rel);
3822
3675
  let text;
3823
3676
  try {
3824
- text = fs8__default.readFileSync(p, "utf8");
3677
+ text = fs7__default.readFileSync(p, "utf8");
3825
3678
  } catch {
3826
3679
  continue;
3827
3680
  }
@@ -4539,8 +4392,8 @@ async function runHostBench(options = {}) {
4539
4392
  }
4540
4393
  async function runArmSimulate(input) {
4541
4394
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4542
- const path40 = `${modelPath}#${arm.id}`;
4543
- const session = await acquireHostSession(lib, path40);
4395
+ const path39 = `${modelPath}#${arm.id}`;
4396
+ const session = await acquireHostSession(lib, path39);
4544
4397
  const system = "You are a coding agent with a Task Capsule.";
4545
4398
  const capsule = "function readConfig(): Config { return load(); }";
4546
4399
  let last = null;
@@ -5752,7 +5605,7 @@ function registerModels(program) {
5752
5605
  );
5753
5606
  }
5754
5607
  } else {
5755
- if (!target.path || !fs8.existsSync(target.path)) {
5608
+ if (!target.path || !fs7.existsSync(target.path)) {
5756
5609
  throw new CliError(
5757
5610
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
5758
5611
  ExitCode.NOT_FOUND
@@ -5766,7 +5619,7 @@ function registerModels(program) {
5766
5619
  }
5767
5620
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
5768
5621
  try {
5769
- fs8.unlinkSync(target.path);
5622
+ fs7.unlinkSync(target.path);
5770
5623
  } catch (e) {
5771
5624
  const msg = e instanceof Error ? e.message : String(e);
5772
5625
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -5904,9 +5757,9 @@ function registerModels(program) {
5904
5757
  }
5905
5758
  });
5906
5759
  if (opts.out) {
5907
- const outPath = path38.resolve(opts.out);
5908
- fs8.mkdirSync(path38.dirname(outPath), { recursive: true });
5909
- fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5760
+ const outPath = path37.resolve(opts.out);
5761
+ fs7.mkdirSync(path37.dirname(outPath), { recursive: true });
5762
+ fs7.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5910
5763
  `);
5911
5764
  if (!global.json) info(c.dim(` wrote ${outPath}`));
5912
5765
  }
@@ -6055,14 +5908,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
6055
5908
  }
6056
5909
  return exact[0];
6057
5910
  }
6058
- const base = path38.basename(wantLc);
5911
+ const base = path37.basename(wantLc);
6059
5912
  const soft = fleet.filter((m) => {
6060
5913
  const n = m.name.toLowerCase();
6061
- return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path38.basename(n) === base;
5914
+ return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path37.basename(n) === base;
6062
5915
  });
6063
5916
  if (soft.length === 1) return soft[0];
6064
5917
  if (soft.length > 1) {
6065
- const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
5918
+ const baseHits = soft.filter((m) => path37.basename(m.name).toLowerCase() === base);
6066
5919
  const pool = baseHits.length ? baseHits : soft;
6067
5920
  const order = ["ollama", "gguf", "lm-studio"];
6068
5921
  for (const rt of order) {
@@ -6100,11 +5953,11 @@ function printBackends(backends) {
6100
5953
  }
6101
5954
  }
6102
5955
  function codeConfigPath(root2) {
6103
- return path38.join(root2, ".vibgrate", "code.json");
5956
+ return path37.join(root2, ".vibgrate", "code.json");
6104
5957
  }
6105
5958
  function loadCodeConfig(root2) {
6106
5959
  try {
6107
- const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
5960
+ const raw = JSON.parse(fs7.readFileSync(codeConfigPath(root2), "utf8"));
6108
5961
  return sanitize(raw);
6109
5962
  } catch {
6110
5963
  return {};
@@ -6171,7 +6024,7 @@ function contextBudgetFor(config, modelContextWindow) {
6171
6024
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
6172
6025
  function readMcpServersFile(file) {
6173
6026
  try {
6174
- const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
6027
+ const raw = JSON.parse(fs7.readFileSync(file, "utf8"));
6175
6028
  const map = raw.mcpServers ?? raw.servers;
6176
6029
  return map && typeof map === "object" ? parseMcpServers(map) : {};
6177
6030
  } catch {
@@ -6182,7 +6035,7 @@ function discoverMcpServers(root2, ownServers) {
6182
6035
  const servers = {};
6183
6036
  const sources = [];
6184
6037
  for (const rel of MCP_CONFIG_FILES) {
6185
- const found = readMcpServersFile(path38.join(root2, rel));
6038
+ const found = readMcpServersFile(path37.join(root2, rel));
6186
6039
  const names = Object.keys(found);
6187
6040
  if (names.length) {
6188
6041
  sources.push(rel);
@@ -6211,7 +6064,7 @@ function registerCode(program) {
6211
6064
  try {
6212
6065
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6213
6066
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6214
- const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
6067
+ const { loadGraph: loadGraph2 } = await import('./load-YPSEDYIW.js');
6215
6068
  const state = readOrchestratorState2();
6216
6069
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6217
6070
  const pin = mode ? activePin2(mode, state) : null;
@@ -6295,7 +6148,7 @@ function registerCode(program) {
6295
6148
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6296
6149
  throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
6297
6150
  }
6298
- const { runInteractive } = await import('./interactive-MJVMY5JP.js');
6151
+ const { runInteractive } = await import('./interactive-NJG6467J.js');
6299
6152
  await runInteractive(
6300
6153
  rootOf(global),
6301
6154
  global,
@@ -6328,7 +6181,7 @@ function registerCode(program) {
6328
6181
  let mockReply;
6329
6182
  if (opts.mock) {
6330
6183
  try {
6331
- mockReply = fs8.readFileSync(opts.mock, "utf8");
6184
+ mockReply = fs7.readFileSync(opts.mock, "utf8");
6332
6185
  } catch {
6333
6186
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
6334
6187
  }
@@ -6376,19 +6229,20 @@ function registerCode(program) {
6376
6229
  process.stdout.write(JSON.stringify(line) + "\n");
6377
6230
  };
6378
6231
  try {
6232
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-5FQWHWYK.js');
6379
6233
  const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
6380
- const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-MTPWWVRR.js');
6234
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3YOPU3LF.js');
6381
6235
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6382
6236
  const readline5 = await import('readline');
6383
6237
  const child = await import('child_process');
6384
6238
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6385
6239
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6386
6240
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6387
- const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6241
+ const { startCodeRuntimeSession } = await import('./runtime-session-Y4ZD3QDO.js');
6388
6242
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6389
6243
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6390
6244
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6391
- const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6245
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-DH7AHQ23.js');
6392
6246
  const federation = loadOrDiscoverFederation(root2);
6393
6247
  const modelProfile = mergeModelExecutionProfile(
6394
6248
  resolveModelExecutionProfile({
@@ -6405,6 +6259,18 @@ function registerCode(program) {
6405
6259
  const runtime = await startCodeRuntimeSession({ root: root2 });
6406
6260
  const git2 = detectGitRef(root2);
6407
6261
  const repositoryId = repositoryIdFromRoot(root2);
6262
+ const runOutcome = new RunOutcomeRecorder(
6263
+ root2,
6264
+ repositoryId,
6265
+ git2.ref || null,
6266
+ { mode: codeModeActive ? modeFlag : void 0, provider: primarySlug, model: route.providers[0]?.model },
6267
+ tier,
6268
+ !!auto
6269
+ );
6270
+ const emitAndRecord = (line) => {
6271
+ runOutcome.observe(line);
6272
+ emitStream(line);
6273
+ };
6408
6274
  if (runtime.socketPath && git2.ref) {
6409
6275
  try {
6410
6276
  await vgdRequest2(
@@ -6434,7 +6300,7 @@ ${res.stderr}` : ""),
6434
6300
  exitCode: res.status ?? 1
6435
6301
  };
6436
6302
  };
6437
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6303
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PZFGTZSA.js');
6438
6304
  const vgBuiltin = createVgBuiltinMcpTools({
6439
6305
  getGraph: () => graph,
6440
6306
  root: root2,
@@ -6455,10 +6321,10 @@ ${res.stderr}` : ""),
6455
6321
  }
6456
6322
  const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
6457
6323
  const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
6458
- const os5 = await import('os');
6324
+ const os4 = await import('os');
6459
6325
  const pathMod = await import('path');
6460
6326
  const checkpointIndex = pathMod.join(
6461
- fs8.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
6327
+ fs7.mkdtempSync(pathMod.join(os4.tmpdir(), "vg-code-cp-")),
6462
6328
  "index"
6463
6329
  );
6464
6330
  const gitRunner = (gitArgs, gitEnv) => {
@@ -6521,8 +6387,8 @@ ${res.stderr}` : ""),
6521
6387
  };
6522
6388
  try {
6523
6389
  if (opts.session) {
6524
- const { runCodeStreamJsonSession } = await import('./stream-json-MTPWWVRR.js');
6525
- const { runAgent: runAgent2 } = await import('./agent-Z4Z66IGM.js');
6390
+ const { runCodeStreamJsonSession } = await import('./stream-json-3YOPU3LF.js');
6391
+ const { runAgent: runAgent2 } = await import('./agent-33BMKWJC.js');
6526
6392
  const {
6527
6393
  loadLatestSession,
6528
6394
  newSession,
@@ -6557,8 +6423,9 @@ ${res.stderr}` : ""),
6557
6423
  wakeTurn = resolve21;
6558
6424
  });
6559
6425
  };
6426
+ let turnIndex = 0;
6560
6427
  await runCodeStreamJsonSession({
6561
- emit: emitStream,
6428
+ emit: emitAndRecord,
6562
6429
  auto: !!auto,
6563
6430
  sessionId: record.id,
6564
6431
  resumed: !!resumedRecord,
@@ -6570,8 +6437,10 @@ ${res.stderr}` : ""),
6570
6437
  rl.on("line", (raw) => {
6571
6438
  const msg = parseHostMessage(raw);
6572
6439
  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);
6440
+ if (msg.kind === "approve") {
6441
+ session.submitDecision(msg.id, msg.approve);
6442
+ runOutcome.noteDecision(msg.id, msg.approve);
6443
+ } else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6575
6444
  else if (msg.kind === "submit") pushTurn(msg.instruction);
6576
6445
  else if (msg.kind === "restore") {
6577
6446
  void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
@@ -6581,8 +6450,10 @@ ${res.stderr}` : ""),
6581
6450
  });
6582
6451
  emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
6583
6452
  });
6584
- } else if (msg.kind === "cancel") session.cancelTurn();
6585
- else if (msg.kind === "end") {
6453
+ } else if (msg.kind === "cancel") {
6454
+ session.cancelTurn();
6455
+ runOutcome.cancelPending();
6456
+ } else if (msg.kind === "end") {
6586
6457
  ended = true;
6587
6458
  pushTurn(null);
6588
6459
  }
@@ -6590,18 +6461,23 @@ ${res.stderr}` : ""),
6590
6461
  rl.on("close", () => {
6591
6462
  ended = true;
6592
6463
  session.cancelTurn();
6464
+ runOutcome.cancelPending();
6593
6465
  pushTurn(null);
6594
6466
  });
6595
6467
  },
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
- }),
6468
+ runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => {
6469
+ turnIndex++;
6470
+ runOutcome.beginRun(turnRunId(record.id, turnIndex), turnInstruction);
6471
+ return runAgent2({
6472
+ ...baseAgentOptions,
6473
+ instruction: turnInstruction,
6474
+ priorSummary,
6475
+ signal,
6476
+ approve: session.approve,
6477
+ askUser: session.askUser,
6478
+ onEvent: session.onEvent
6479
+ });
6480
+ },
6605
6481
  onTurnEnd: (turn) => {
6606
6482
  record = recordTask(
6607
6483
  record,
@@ -6618,20 +6494,27 @@ ${res.stderr}` : ""),
6618
6494
  }
6619
6495
  });
6620
6496
  } else {
6497
+ runOutcome.beginRun(newOneShotRunId(), instruction);
6621
6498
  await runCodeStreamJson({
6622
6499
  ...baseAgentOptions,
6623
6500
  instruction,
6624
- emit: emitStream,
6501
+ emit: emitAndRecord,
6625
6502
  bindDecisions: (session) => {
6626
6503
  streamApprove = (action) => session.approve(action);
6627
6504
  const rl = readline5.createInterface({ input: process.stdin });
6628
6505
  rl.on("line", (raw) => {
6629
6506
  const msg = parseHostMessage(raw);
6630
6507
  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();
6508
+ if (msg.kind === "approve") {
6509
+ session.submitDecision(msg.id, msg.approve);
6510
+ runOutcome.noteDecision(msg.id, msg.approve);
6511
+ } else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6512
+ else if (msg.kind === "cancel") {
6513
+ session.cancelTurn();
6514
+ runOutcome.cancelPending();
6515
+ }
6634
6516
  });
6517
+ rl.on("close", () => runOutcome.cancelPending());
6635
6518
  }
6636
6519
  });
6637
6520
  }
@@ -6653,7 +6536,7 @@ ${res.stderr}` : ""),
6653
6536
  if (!autonomous && !tty) {
6654
6537
  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).");
6655
6538
  }
6656
- const { agentTask } = await import('./interactive-MJVMY5JP.js');
6539
+ const { agentTask } = await import('./interactive-NJG6467J.js');
6657
6540
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6658
6541
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6659
6542
  let priorSummary;
@@ -6663,7 +6546,7 @@ ${res.stderr}` : ""),
6663
6546
  if (prev) priorSummary = summarizeSession(prev);
6664
6547
  }
6665
6548
  const prompter = tty ? new TtyPrompter() : void 0;
6666
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6549
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-PZFGTZSA.js');
6667
6550
  const vgBuiltin = createVgBuiltinMcpTools({
6668
6551
  getGraph: () => graph,
6669
6552
  root: root2,
@@ -6687,11 +6570,11 @@ ${res.stderr}` : ""),
6687
6570
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6688
6571
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6689
6572
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6690
- const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6573
+ const { startCodeRuntimeSession } = await import('./runtime-session-Y4ZD3QDO.js');
6691
6574
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6692
6575
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6693
6576
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6694
- const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6577
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-DH7AHQ23.js');
6695
6578
  const federation = loadFederation(root2);
6696
6579
  const modelProfile = mergeModelExecutionProfile(
6697
6580
  resolveModelExecutionProfile({
@@ -6783,7 +6666,7 @@ ${res.stderr}` : ""),
6783
6666
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
6784
6667
  });
6785
6668
  if (opts.out) {
6786
- fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6669
+ fs7.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6787
6670
  }
6788
6671
  if (global.json) {
6789
6672
  json(result);
@@ -6996,7 +6879,7 @@ async function addCmd(root2, rest, opts, asJson) {
6996
6879
  }
6997
6880
  function readPackageVersion(root2) {
6998
6881
  try {
6999
- const pkg = JSON.parse(fs8__default.readFileSync(path38__default.join(root2, "package.json"), "utf8"));
6882
+ const pkg = JSON.parse(fs7__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
7000
6883
  return typeof pkg.version === "string" ? pkg.version : void 0;
7001
6884
  } catch {
7002
6885
  return void 0;
@@ -7004,7 +6887,7 @@ function readPackageVersion(root2) {
7004
6887
  }
7005
6888
  function readOptionalFile(p) {
7006
6889
  try {
7007
- const t = fs8__default.readFileSync(p, "utf8");
6890
+ const t = fs7__default.readFileSync(p, "utf8");
7008
6891
  return t.trim() ? t : void 0;
7009
6892
  } catch {
7010
6893
  return void 0;
@@ -7019,8 +6902,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
7019
6902
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
7020
6903
  const version = (opts.version || readPackageVersion(root2) || "").trim();
7021
6904
  if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
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;
6905
+ const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6906
+ const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
7024
6907
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
7025
6908
  const result = await publishPrivateLibrary(
7026
6909
  { name, version, readme, dts, language: opts.language },
@@ -7152,8 +7035,8 @@ function registerExport(program) {
7152
7035
  out(content.trimEnd());
7153
7036
  return;
7154
7037
  }
7155
- fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
7156
- fs8.writeFileSync(file, content);
7038
+ fs7.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
7039
+ fs7.writeFileSync(file, content);
7157
7040
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
7158
7041
  });
7159
7042
  applyGlobalOptions(cmd);
@@ -7163,43 +7046,43 @@ function detectFormat(file) {
7163
7046
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
7164
7047
  if (lower.endsWith(".spdx.json")) return "spdx";
7165
7048
  if (file === "-") return "json";
7166
- return formatForExt(path38.extname(file));
7049
+ return formatForExt(path37.extname(file));
7167
7050
  }
7168
7051
  function registerBundle(program) {
7169
7052
  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) {
7170
7053
  const global = readGlobal(this);
7171
7054
  const root2 = rootOf(global);
7172
- const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
7055
+ const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
7173
7056
  let grammarFiles;
7174
7057
  try {
7175
7058
  grammarFiles = resolvedGrammarFiles();
7176
7059
  } catch {
7177
7060
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
7178
7061
  }
7179
- fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
7062
+ fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
7180
7063
  let grammarCount = 0;
7181
7064
  for (const { fileName, absPath } of grammarFiles) {
7182
- fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
7065
+ fs7.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
7183
7066
  grammarCount++;
7184
7067
  }
7185
7068
  const included = [`grammars/ (${grammarCount} .wasm)`];
7186
7069
  const graphSrc = resolveGraphPath(root2, global.graph);
7187
- if (fs8.existsSync(graphSrc)) {
7188
- fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
7070
+ if (fs7.existsSync(graphSrc)) {
7071
+ fs7.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
7189
7072
  included.push("graph.json");
7190
7073
  } else {
7191
7074
  const graph = loadGraphFileWithSnapshot(graphSrc);
7192
7075
  if (graph) {
7193
- fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
7076
+ fs7.writeFileSync(path37.join(outDir, "graph.json"), serializeGraph(graph));
7194
7077
  included.push("graph.json");
7195
7078
  }
7196
7079
  }
7197
7080
  const cat = catalogPath(root2);
7198
- if (fs8.existsSync(cat)) {
7199
- fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
7081
+ if (fs7.existsSync(cat)) {
7082
+ fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
7200
7083
  included.push("vibgrate.lib.json");
7201
- if (fs8.existsSync(libDir(root2))) {
7202
- fs8.cpSync(libDir(root2), path38.join(outDir, "lib"), { recursive: true });
7084
+ if (fs7.existsSync(libDir(root2))) {
7085
+ fs7.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
7203
7086
  included.push("lib/");
7204
7087
  }
7205
7088
  }
@@ -7211,15 +7094,15 @@ function registerBundle(program) {
7211
7094
  included,
7212
7095
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
7213
7096
  };
7214
- fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7097
+ fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7215
7098
  `);
7216
7099
  if (global.json) {
7217
- json({ out: path38.relative(root2, outDir), ...manifest });
7100
+ json({ out: path37.relative(root2, outDir), ...manifest });
7218
7101
  return;
7219
7102
  }
7220
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
7103
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
7221
7104
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
7222
- info(c.dim(` offline: vg build --grammars "${path38.relative(root2, outDir)}/grammars"`));
7105
+ info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
7223
7106
  });
7224
7107
  applyGlobalOptions(cmd);
7225
7108
  }
@@ -7237,7 +7120,7 @@ async function runDoctor(global) {
7237
7120
  const root2 = rootOf(global);
7238
7121
  const local = global.local === true;
7239
7122
  const graphPath = resolveGraphPath(root2, global.graph);
7240
- const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path38.join(root2, f))) ?? null;
7123
+ const configFile = CONFIG_BASENAMES.find((f) => fs7.existsSync(path37.join(root2, f))) ?? null;
7241
7124
  const graph = loadGraph(root2, graphPath);
7242
7125
  let staleFiles = null;
7243
7126
  if (graph) {
@@ -7263,14 +7146,14 @@ async function runDoctor(global) {
7263
7146
  root: root2,
7264
7147
  configFile,
7265
7148
  map: {
7266
- path: path38.relative(root2, graphPath),
7149
+ path: path37.relative(root2, graphPath),
7267
7150
  built: graph !== null,
7268
7151
  generatedAt: graph?.generatedAt ?? null,
7269
7152
  staleFiles
7270
7153
  },
7271
7154
  libCatalog: {
7272
- path: path38.relative(root2, catalogPath(root2)),
7273
- present: fs8.existsSync(catalogPath(root2)),
7155
+ path: path37.relative(root2, catalogPath(root2)),
7156
+ present: fs7.existsSync(catalogPath(root2)),
7274
7157
  libraries: libCount
7275
7158
  },
7276
7159
  credentials: creds,
@@ -7327,7 +7210,7 @@ async function runDoctor(global) {
7327
7210
  );
7328
7211
  info(
7329
7212
  ` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
7330
- ` \xB7 last ${path38.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7213
+ ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7331
7214
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
7332
7215
  );
7333
7216
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -7503,7 +7386,7 @@ function registerDaemon(program) {
7503
7386
  const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
7504
7387
  const global = readGlobal(this);
7505
7388
  const socketPath = socketOf(this);
7506
- const root2 = path38.resolve(rootArg ?? rootOf(global));
7389
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
7507
7390
  if (!await vgdIsRunning({ socketPath })) {
7508
7391
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7509
7392
  }
@@ -7539,7 +7422,7 @@ function registerDaemon(program) {
7539
7422
  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) {
7540
7423
  const global = readGlobal(this);
7541
7424
  const socketPath = socketOf(this);
7542
- const primary = path38.resolve(rootArg ?? rootOf(global));
7425
+ const primary = path37.resolve(rootArg ?? rootOf(global));
7543
7426
  if (!await vgdIsRunning({ socketPath })) {
7544
7427
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7545
7428
  }
@@ -7567,7 +7450,7 @@ function registerDaemon(program) {
7567
7450
  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) {
7568
7451
  const global = readGlobal(this);
7569
7452
  const socketPath = socketOf(this);
7570
- const root2 = path38.resolve(rootArg ?? rootOf(global));
7453
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
7571
7454
  if (!await vgdIsRunning({ socketPath })) {
7572
7455
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
7573
7456
  }
@@ -7581,7 +7464,7 @@ function registerDaemon(program) {
7581
7464
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7582
7465
  }
7583
7466
  if (!loaded.ok) {
7584
- const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
7467
+ const { loadGraph: loadGraph2 } = await import('./load-YPSEDYIW.js');
7585
7468
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7586
7469
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7587
7470
  const graph = loadGraph2(root2, global.graph);
@@ -7697,7 +7580,7 @@ function socketOf(cmd) {
7697
7580
  let c2 = cmd;
7698
7581
  while (c2) {
7699
7582
  const opts = c2.opts();
7700
- if (opts.socket) return path38.resolve(opts.socket);
7583
+ if (opts.socket) return path37.resolve(opts.socket);
7701
7584
  c2 = c2.parent;
7702
7585
  }
7703
7586
  return vgdSocketPath();
@@ -7769,7 +7652,7 @@ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
7769
7652
  }
7770
7653
  function readVgdPid() {
7771
7654
  try {
7772
- const raw = fs8.readFileSync(vgdPidPath(), "utf8").trim();
7655
+ const raw = fs7.readFileSync(vgdPidPath(), "utf8").trim();
7773
7656
  const pid = Number.parseInt(raw, 10);
7774
7657
  return Number.isInteger(pid) && pid > 0 ? pid : null;
7775
7658
  } catch {
@@ -7854,7 +7737,7 @@ function registerPolicy(program) {
7854
7737
  const global = readGlobal(this);
7855
7738
  let raw;
7856
7739
  try {
7857
- raw = fs8.readFileSync(file, "utf8");
7740
+ raw = fs7.readFileSync(file, "utf8");
7858
7741
  } catch {
7859
7742
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
7860
7743
  }
@@ -7974,11 +7857,11 @@ function registerLlmHost(program) {
7974
7857
  applyGlobalOptions(cmd);
7975
7858
  }
7976
7859
  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) => {
7977
- const rootDir = path38.resolve(targetPath);
7978
- const vibgrateDir2 = path38.join(rootDir, ".vibgrate");
7860
+ const rootDir = path37.resolve(targetPath);
7861
+ const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7979
7862
  await ensureDir(vibgrateDir2);
7980
7863
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7981
- const configPath = path38.join(rootDir, "vibgrate.config.ts");
7864
+ const configPath = path37.join(rootDir, "vibgrate.config.ts");
7982
7865
  if (await pathExists(configPath)) {
7983
7866
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7984
7867
  } else {
@@ -7986,7 +7869,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7986
7869
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7987
7870
  }
7988
7871
  if (opts.baseline) {
7989
- const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
7872
+ const { runBaseline } = await import('./baseline-V6MYDEMS.js');
7990
7873
  await runBaseline(rootDir);
7991
7874
  }
7992
7875
  console.log("");
@@ -8089,16 +7972,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
8089
7972
  };
8090
7973
  }
8091
7974
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
8092
- const content = await readFile3(path38.join(rootDir, relFile));
7975
+ const content = await readFile3(path37.join(rootDir, relFile));
8093
7976
  if (!content) return false;
8094
7977
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8095
7978
  return new RegExp(`\\b${escaped}\\b`).test(content);
8096
7979
  }
8097
7980
  async function defaultReadFile(absPath) {
8098
7981
  try {
8099
- const stat2 = await fs22.stat(absPath);
7982
+ const stat2 = await fs21.stat(absPath);
8100
7983
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
8101
- return await fs22.readFile(absPath, "utf8");
7984
+ return await fs21.readFile(absPath, "utf8");
8102
7985
  } catch {
8103
7986
  return null;
8104
7987
  }
@@ -8284,7 +8167,7 @@ var AI_ASSISTANT_DETECTORS = [
8284
8167
  async function detectAiAssistant(rootDir) {
8285
8168
  for (const detector of AI_ASSISTANT_DETECTORS) {
8286
8169
  for (const file of detector.files) {
8287
- if (await pathExists$1(path38.join(rootDir, file))) {
8170
+ if (await pathExists$1(path37.join(rootDir, file))) {
8288
8171
  return detector.name;
8289
8172
  }
8290
8173
  }
@@ -8478,7 +8361,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8478
8361
  collectExcludes,
8479
8362
  []
8480
8363
  ).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) => {
8481
- const rootDir = path38.resolve(targetPath);
8364
+ const rootDir = path37.resolve(targetPath);
8482
8365
  if (!await pathExists$1(rootDir)) {
8483
8366
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8484
8367
  process.exit(1);
@@ -8486,7 +8369,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8486
8369
  const hasDsn = !!resolveDsn(opts.dsn);
8487
8370
  const willPush = !opts.offline && (opts.push || hasDsn);
8488
8371
  const noLocalArtifacts = opts.localArtifacts === false;
8489
- const isFirstRun = !await pathExists$1(path38.join(rootDir, ".vibgrate", "scan_result.json"));
8372
+ const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
8490
8373
  let pinnedRegion;
8491
8374
  let planTier;
8492
8375
  let upgradeUrl;
@@ -8745,7 +8628,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
8745
8628
  function scanStaleness(rootDir, artifactPath) {
8746
8629
  let ref;
8747
8630
  try {
8748
- ref = fs8.statSync(artifactPath).mtimeMs;
8631
+ ref = fs7.statSync(artifactPath).mtimeMs;
8749
8632
  } catch {
8750
8633
  return { stale: false };
8751
8634
  }
@@ -8757,7 +8640,7 @@ function scanStaleness(rootDir, artifactPath) {
8757
8640
  if (depth > 8 || scanned > MAX_ENTRIES2) return;
8758
8641
  let entries;
8759
8642
  try {
8760
- entries = fs8.readdirSync(dir, { withFileTypes: true });
8643
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
8761
8644
  } catch {
8762
8645
  return;
8763
8646
  }
@@ -8765,20 +8648,20 @@ function scanStaleness(rootDir, artifactPath) {
8765
8648
  scanned++;
8766
8649
  if (scanned > MAX_ENTRIES2) break;
8767
8650
  if (e.isDirectory()) {
8768
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path38.join(dir, e.name), depth + 1);
8651
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
8769
8652
  continue;
8770
8653
  }
8771
8654
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
8772
- const abs = path38.join(dir, e.name);
8655
+ const abs = path37.join(dir, e.name);
8773
8656
  let mtimeMs;
8774
8657
  try {
8775
- mtimeMs = fs8.statSync(abs).mtimeMs;
8658
+ mtimeMs = fs7.statSync(abs).mtimeMs;
8776
8659
  } catch {
8777
8660
  continue;
8778
8661
  }
8779
8662
  if (mtimeMs > newest) {
8780
8663
  newest = mtimeMs;
8781
- newestChanged = path38.relative(rootDir, abs) || e.name;
8664
+ newestChanged = path37.relative(rootDir, abs) || e.name;
8782
8665
  }
8783
8666
  }
8784
8667
  };
@@ -8909,7 +8792,7 @@ function analyzeTree(root2, packages) {
8909
8792
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
8910
8793
  let entries;
8911
8794
  try {
8912
- entries = fs8.readdirSync(dir, { withFileTypes: true });
8795
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
8913
8796
  } catch {
8914
8797
  return;
8915
8798
  }
@@ -8918,17 +8801,17 @@ function analyzeTree(root2, packages) {
8918
8801
  if (filesSeen >= MAX_FILES) return;
8919
8802
  if (entry.isDirectory()) {
8920
8803
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8921
- walk2(path38.join(dir, entry.name), depth + 1);
8804
+ walk2(path37.join(dir, entry.name), depth + 1);
8922
8805
  continue;
8923
8806
  }
8924
- const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
8807
+ const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8925
8808
  if (!fileEco || fileEco === "unknown") continue;
8926
8809
  filesSeen++;
8927
- const full = path38.join(dir, entry.name);
8810
+ const full = path37.join(dir, entry.name);
8928
8811
  let content;
8929
8812
  try {
8930
- if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
8931
- content = fs8.readFileSync(full, "utf8");
8813
+ if (fs7.statSync(full).size > MAX_FILE_BYTES2) continue;
8814
+ content = fs7.readFileSync(full, "utf8");
8932
8815
  } catch {
8933
8816
  continue;
8934
8817
  }
@@ -9239,7 +9122,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9239
9122
  }
9240
9123
  const outcomes = effective.map((t) => {
9241
9124
  const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
9242
- return { t, res: run(c2, path38.join(rootDir, t.dir)) };
9125
+ return { t, res: run(c2, path37.join(rootDir, t.dir)) };
9243
9126
  });
9244
9127
  const failures = outcomes.filter((o) => !o.res.ok);
9245
9128
  if (failures.length === 0) {
@@ -9268,8 +9151,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9268
9151
  return results;
9269
9152
  }
9270
9153
  var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
9271
- var CACHE_DIR = path38.join(os.homedir(), ".vibgrate");
9272
- var CACHE_FILE = path38.join(CACHE_DIR, "update-check.json");
9154
+ var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
9155
+ var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
9273
9156
  async function fetchLatestVersion() {
9274
9157
  try {
9275
9158
  const controller = new AbortController();
@@ -9296,8 +9179,8 @@ async function fetchLatestVersion() {
9296
9179
  }
9297
9180
  async function writeCache(data) {
9298
9181
  try {
9299
- await fs22.mkdir(CACHE_DIR, { recursive: true });
9300
- await fs22.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9182
+ await fs21.mkdir(CACHE_DIR, { recursive: true });
9183
+ await fs21.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9301
9184
  } catch {
9302
9185
  }
9303
9186
  }
@@ -9308,7 +9191,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
9308
9191
  if (!execPath) return null;
9309
9192
  let resolved = execPath;
9310
9193
  try {
9311
- resolved = fs8.realpathSync(execPath);
9194
+ resolved = fs7.realpathSync(execPath);
9312
9195
  } catch {
9313
9196
  }
9314
9197
  const p = resolved.replace(/\\/g, "/");
@@ -9338,14 +9221,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
9338
9221
  pm: "yarn",
9339
9222
  root: () => {
9340
9223
  const dir = tryRun("yarn global dir");
9341
- return dir ? path38.join(dir, "node_modules") : null;
9224
+ return dir ? path37.join(dir, "node_modules") : null;
9342
9225
  }
9343
9226
  },
9344
- { pm: "bun", root: () => path38.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9227
+ { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9345
9228
  ];
9346
9229
  for (const probe of probes) {
9347
9230
  const root2 = probe.root();
9348
- if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
9231
+ if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
9349
9232
  }
9350
9233
  return null;
9351
9234
  }
@@ -9364,15 +9247,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
9364
9247
  }
9365
9248
  }
9366
9249
  async function detectPackageManager(cwd) {
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";
9250
+ if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9251
+ if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
9252
+ if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
9370
9253
  return "npm";
9371
9254
  }
9372
9255
  async function detectWorkspaceRoot(cwd) {
9373
- if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
9256
+ if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
9374
9257
  try {
9375
- const pkgPath = path38.join(cwd, "package.json");
9258
+ const pkgPath = path37.join(cwd, "package.json");
9376
9259
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9377
9260
  const pkg = JSON.parse(raw);
9378
9261
  return pkg.workspaces != null;
@@ -9397,7 +9280,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
9397
9280
  }
9398
9281
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
9399
9282
  try {
9400
- const pkgPath = path38.join(cwd, "package.json");
9283
+ const pkgPath = path37.join(cwd, "package.json");
9401
9284
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9402
9285
  const parsed = JSON.parse(raw);
9403
9286
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -9566,13 +9449,13 @@ function collectCandidates(artifact) {
9566
9449
  return out2;
9567
9450
  }
9568
9451
  var defaultFixScanner = async (rootDir) => {
9569
- const scratch = path38.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9452
+ const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9570
9453
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
9571
9454
  const advanced = await loadAdvancedScanHook();
9572
9455
  return runCoreScan(rootDir, scanOpts, advanced);
9573
9456
  };
9574
9457
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
9575
- const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
9458
+ const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
9576
9459
  if (await pathExists(artifactPath)) {
9577
9460
  const staleness = scanStaleness(rootDir, artifactPath);
9578
9461
  if (!staleness.stale) {
@@ -9599,7 +9482,7 @@ async function repositoryIdentity(rootDir, override) {
9599
9482
  }
9600
9483
  }
9601
9484
  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) => {
9602
- const rootDir = path38.resolve(targetPath);
9485
+ const rootDir = path37.resolve(targetPath);
9603
9486
  if (!await pathExists(rootDir)) {
9604
9487
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
9605
9488
  process.exit(1);
@@ -9760,7 +9643,7 @@ function emit(report, format) {
9760
9643
  }
9761
9644
  }
9762
9645
  function relProjectDir(rootDir, projectPath) {
9763
- const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
9646
+ const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
9764
9647
  return rel === "" ? "." : rel;
9765
9648
  }
9766
9649
  async function buildTargetResolver(rootDir, artifact) {
@@ -10595,7 +10478,7 @@ function formatMarkdown(artifact) {
10595
10478
 
10596
10479
  // src/reporting/commands/report.ts
10597
10480
  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) => {
10598
- const artifactPath = path38.resolve(opts.in);
10481
+ const artifactPath = path37.resolve(opts.in);
10599
10482
  if (!await pathExists(artifactPath)) {
10600
10483
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
10601
10484
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -10644,8 +10527,8 @@ function openUrl(url) {
10644
10527
  // src/reporting/commands/login.ts
10645
10528
  var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
10646
10529
  function isInside(dir, file) {
10647
- const rel = path38.relative(dir, file);
10648
- return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
10530
+ const rel = path37.relative(dir, file);
10531
+ return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
10649
10532
  }
10650
10533
  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(
10651
10534
  "--local",
@@ -10900,7 +10783,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10900
10783
  try {
10901
10784
  const statements = [];
10902
10785
  if (opts.from) {
10903
- const fromPath = path38.resolve(opts.from);
10786
+ const fromPath = path37.resolve(opts.from);
10904
10787
  if (!await pathExists(fromPath)) {
10905
10788
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
10906
10789
  `));
@@ -10918,9 +10801,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10918
10801
  });
10919
10802
  const json2 = JSON.stringify(doc, null, 2);
10920
10803
  if (opts.out) {
10921
- await writeTextFile(path38.resolve(opts.out), json2 + "\n");
10804
+ await writeTextFile(path37.resolve(opts.out), json2 + "\n");
10922
10805
  process.stderr.write(
10923
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path38.resolve(opts.out)}
10806
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
10924
10807
  `
10925
10808
  );
10926
10809
  } else {
@@ -11103,7 +10986,7 @@ function formatDeltaText(base, current) {
11103
10986
  return lines.join("\n");
11104
10987
  }
11105
10988
  async function readArtifactOrExit(filePath) {
11106
- const absolutePath = path38.resolve(filePath);
10989
+ const absolutePath = path37.resolve(filePath);
11107
10990
  if (!await pathExists(absolutePath)) {
11108
10991
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
11109
10992
  process.exit(1);
@@ -11120,7 +11003,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
11120
11003
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
11121
11004
  const body = JSON.stringify(sbom, null, 2);
11122
11005
  if (opts.out) {
11123
- await writeTextFile(path38.resolve(opts.out), body);
11006
+ await writeTextFile(path37.resolve(opts.out), body);
11124
11007
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
11125
11008
  } else {
11126
11009
  console.log(body);
@@ -11131,7 +11014,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
11131
11014
  const current = await readArtifactOrExit(opts.to);
11132
11015
  const report = formatDeltaText(base, current);
11133
11016
  if (opts.out) {
11134
- await writeTextFile(path38.resolve(opts.out), report);
11017
+ await writeTextFile(path37.resolve(opts.out), report);
11135
11018
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
11136
11019
  } else {
11137
11020
  console.log(report);
@@ -11262,20 +11145,20 @@ function resolveRegime(id) {
11262
11145
  return regime;
11263
11146
  }
11264
11147
  function evidenceDir(root2) {
11265
- return path38.join(root2, ".vibgrate", "evidence");
11148
+ return path37.join(root2, ".vibgrate", "evidence");
11266
11149
  }
11267
11150
  function orgPath(root2) {
11268
- return path38.join(evidenceDir(root2), "org.json");
11151
+ return path37.join(evidenceDir(root2), "org.json");
11269
11152
  }
11270
11153
  function productsPath(root2) {
11271
- return path38.join(evidenceDir(root2), "products.json");
11154
+ return path37.join(evidenceDir(root2), "products.json");
11272
11155
  }
11273
11156
  function releasesDir(root2) {
11274
- return path38.join(evidenceDir(root2), "releases");
11157
+ return path37.join(evidenceDir(root2), "releases");
11275
11158
  }
11276
11159
  function releasePath(root2, productId, version) {
11277
11160
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11278
- return path38.join(releasesDir(root2), `${safe}.json`);
11161
+ return path37.join(releasesDir(root2), `${safe}.json`);
11279
11162
  }
11280
11163
  var DEFAULT_ORG = {
11281
11164
  responsiblePersons: [],
@@ -11306,7 +11189,7 @@ async function freezeRelease(root2, release) {
11306
11189
  const p = releasePath(root2, release.productId, release.version);
11307
11190
  if (await pathExists(p)) {
11308
11191
  throw new CliError(
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`,
11192
+ `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`,
11310
11193
  ExitCode.USAGE_ERROR
11311
11194
  );
11312
11195
  }
@@ -11320,7 +11203,7 @@ async function loadReleases(root2, productId) {
11320
11203
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
11321
11204
  const releases = [];
11322
11205
  for (const f of files) {
11323
- const rel = await readJsonFile(path38.join(dir, f));
11206
+ const rel = await readJsonFile(path37.join(dir, f));
11324
11207
  if (!productId || rel.productId === productId) releases.push(rel);
11325
11208
  }
11326
11209
  return releases;
@@ -12015,19 +11898,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
12015
11898
  var DEFAULT_KEY = "attest-key.pem";
12016
11899
  function resolveSigningKey(root2, explicit) {
12017
11900
  const chosen = process.env.VG_ATTEST_KEY;
12018
- const keyPath = chosen ? path38.resolve(chosen) : path38.join(root2, ".vibgrate", DEFAULT_KEY);
11901
+ const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
12019
11902
  let minted = false;
12020
- if (!fs8.existsSync(keyPath)) {
11903
+ if (!fs7.existsSync(keyPath)) {
12021
11904
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
12022
11905
  const kp = generateKeypair();
12023
- fs8.mkdirSync(path38.dirname(keyPath), { recursive: true });
12024
- fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
12025
- fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
11906
+ fs7.mkdirSync(path37.dirname(keyPath), { recursive: true });
11907
+ fs7.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11908
+ fs7.writeFileSync(`${keyPath}.pub`, kp.publicPem);
12026
11909
  minted = true;
12027
11910
  }
12028
11911
  let key2;
12029
11912
  try {
12030
- key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
11913
+ key2 = crypto3.createPrivateKey(fs7.readFileSync(keyPath, "utf8"));
12031
11914
  } catch {
12032
11915
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
12033
11916
  }
@@ -12038,16 +11921,16 @@ function resolveSigningKey(root2, explicit) {
12038
11921
  }
12039
11922
  function writeBundle(input) {
12040
11923
  const dir = input.outDir;
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)}
11924
+ fs7.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11925
+ const write = (rel, data) => fs7.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
12043
11926
  `);
12044
11927
  write("result.json", input.result);
12045
- write(path38.join("inputs", "advisory.json"), input.advisory);
11928
+ write(path37.join("inputs", "advisory.json"), input.advisory);
12046
11929
  for (const rel of input.releases) {
12047
11930
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
12048
- write(path38.join("inputs", "releases", `${safe}.json`), rel);
11931
+ write(path37.join("inputs", "releases", `${safe}.json`), rel);
12049
11932
  }
12050
- write(path38.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11933
+ write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
12051
11934
  write("provenance.json", {
12052
11935
  method: "deterministic",
12053
11936
  modelDrafted: [],
@@ -12063,13 +11946,13 @@ function writeBundle(input) {
12063
11946
  disclaimer: input.regime.disclaimer
12064
11947
  });
12065
11948
  if (input.envelope) {
12066
- fs8.writeFileSync(path38.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11949
+ fs7.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
12067
11950
  `);
12068
11951
  }
12069
11952
  if (input.timestampToken) {
12070
- fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
11953
+ fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
12071
11954
  }
12072
- fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
11955
+ fs7.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
12073
11956
  return dir;
12074
11957
  }
12075
11958
  function verifyDoc(input) {
@@ -12130,13 +12013,13 @@ function undeterminedFields(result, regime) {
12130
12013
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
12131
12014
  }
12132
12015
  async function recordDrill(root2, record) {
12133
- const dir = path38.join(evidenceDir(root2), "drills");
12134
- const p = path38.join(dir, `${record.drillId}.json`);
12016
+ const dir = path37.join(evidenceDir(root2), "drills");
12017
+ const p = path37.join(dir, `${record.drillId}.json`);
12135
12018
  await writeJsonFile(p, record);
12136
12019
  return p;
12137
12020
  }
12138
12021
  async function hasRecentDrill(root2, asOf) {
12139
- const dir = path38.join(evidenceDir(root2), "drills");
12022
+ const dir = path37.join(evidenceDir(root2), "drills");
12140
12023
  if (!await pathExists(dir)) return void 0;
12141
12024
  const { readdir } = await import('fs/promises');
12142
12025
  const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
@@ -12144,7 +12027,7 @@ async function hasRecentDrill(root2, asOf) {
12144
12027
  if (files.length === 0) return void 0;
12145
12028
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
12146
12029
  for (const f of files) {
12147
- const rec = await readJsonFile2(path38.join(dir, f));
12030
+ const rec = await readJsonFile2(path37.join(dir, f));
12148
12031
  if (rec.ranAt >= cutoff) return true;
12149
12032
  }
12150
12033
  return false;
@@ -12224,7 +12107,7 @@ function formatRegimeList() {
12224
12107
 
12225
12108
  // src/reporting/commands/evidence/index.ts
12226
12109
  function root(opts) {
12227
- return path38.resolve(opts.cwd ?? process.cwd());
12110
+ return path37.resolve(opts.cwd ?? process.cwd());
12228
12111
  }
12229
12112
  function slug(name) {
12230
12113
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -12312,7 +12195,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12312
12195
  const release = await buildRelease({
12313
12196
  productId: product.id,
12314
12197
  version,
12315
- from: path38.resolve(rootDir, opts.from),
12198
+ from: path37.resolve(rootDir, opts.from),
12316
12199
  shipDate: opts.shipDate,
12317
12200
  buildId: opts.buildId,
12318
12201
  artefactDigest: opts.digest,
@@ -12320,7 +12203,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12320
12203
  frozenAt: nowIso()
12321
12204
  });
12322
12205
  const p = await freezeRelease(rootDir, release);
12323
- console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path38.relative(rootDir, p)}`);
12206
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
12324
12207
  });
12325
12208
  async function runExposure(rootDir, vuln, opts) {
12326
12209
  const org = await loadOrg(rootDir);
@@ -12372,7 +12255,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12372
12255
  console.log("\n" + buildPack(result, regime, org, stage));
12373
12256
  }
12374
12257
  if (opts.bundle) {
12375
- const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12258
+ const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12376
12259
  let envelope;
12377
12260
  if (opts.sign !== false) {
12378
12261
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -12380,7 +12263,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12380
12263
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
12381
12264
  }
12382
12265
  writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
12383
- console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path38.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12266
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12384
12267
  }
12385
12268
  process.exitCode = exposureExit(result.overallStatus);
12386
12269
  });
@@ -12412,7 +12295,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
12412
12295
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
12413
12296
  const md = buildPack(result, regime, org, stage);
12414
12297
  if (opts.out) {
12415
- fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
12298
+ fs7.writeFileSync(path37.resolve(rootDir, opts.out), md);
12416
12299
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
12417
12300
  } else {
12418
12301
  console.log(md);
@@ -12454,20 +12337,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
12454
12337
  }
12455
12338
  });
12456
12339
  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) => {
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;
12340
+ const abs = path37.resolve(bundlePath);
12341
+ const envPath = fs7.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
12342
+ if (!fs7.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12343
+ const envelope = JSON.parse(fs7.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12344
+ const resultPath = path37.join(path37.dirname(envPath), "result.json");
12345
+ const result = fs7.existsSync(resultPath) ? JSON.parse(fs7.readFileSync(resultPath, "utf8")) : void 0;
12346
+ const publicKeyPem = opts.pub ? fs7.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
12464
12347
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
12465
12348
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
12466
12349
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
12467
12350
  if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
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));
12351
+ const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
12352
+ if (fs7.existsSync(tsrPath) && result) {
12353
+ const t = verifyTimestamp(fs7.readFileSync(tsrPath), exposureSubjectDigest(result));
12471
12354
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
12472
12355
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
12473
12356
  }
@@ -12534,12 +12417,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
12534
12417
  const releases = [];
12535
12418
  for (const list of releasesByProduct.values()) releases.push(...list);
12536
12419
  const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
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)`);
12420
+ const dir = path37.resolve(rootDir, opts.out);
12421
+ await writeJsonFile(path37.join(dir, "org.json"), org);
12422
+ await writeJsonFile(path37.join(dir, "products.json"), products);
12423
+ for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12424
+ await writeJsonFile(path37.join(dir, "readiness.json"), report);
12425
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
12543
12426
  });
12544
12427
  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) => {
12545
12428
  const rootDir = root(opts);
@@ -12565,10 +12448,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
12565
12448
  }));
12566
12449
  let exposure;
12567
12450
  if (opts.result) {
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"));
12451
+ const raw = path37.resolve(rootDir, opts.result);
12452
+ const resultPath = fs7.existsSync(raw) && fs7.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
12453
+ if (!fs7.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12454
+ exposure = JSON.parse(fs7.readFileSync(resultPath, "utf8"));
12572
12455
  }
12573
12456
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
12574
12457
  const body = JSON.stringify(payload);
@@ -12758,7 +12641,7 @@ function dispatch(argv, cwd) {
12758
12641
  }
12759
12642
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
12760
12643
  if (looksLikeQuestion) return ["ask", ...args];
12761
- if (fs8.existsSync(path38.resolve(cwd, first))) {
12644
+ if (fs7.existsSync(path37.resolve(cwd, first))) {
12762
12645
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
12763
12646
  }
12764
12647
  const moved = MOVED_COMMANDS[first];
@@ -12803,9 +12686,9 @@ async function main(argv = process.argv) {
12803
12686
  }
12804
12687
  function readCwd(raw) {
12805
12688
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
12806
- if (i >= 0 && raw[i + 1]) return path38.resolve(raw[i + 1]);
12689
+ if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
12807
12690
  const eq = raw.find((a) => a.startsWith("--cwd="));
12808
- if (eq) return path38.resolve(eq.slice("--cwd=".length));
12691
+ if (eq) return path37.resolve(eq.slice("--cwd=".length));
12809
12692
  return process.cwd();
12810
12693
  }
12811
12694
  function handleError(err) {