@vibgrate/cli 2026.729.3 → 2026.730.2

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-536TQZIB.js +9 -0
  4. package/dist/{baseline-Q3QQF5QF.js.map → baseline-536TQZIB.js.map} +1 -1
  5. package/dist/{chunk-3FQSBVQD.js → chunk-A5LF4VS4.js} +8 -5
  6. package/dist/chunk-A5LF4VS4.js.map +1 -0
  7. package/dist/chunk-BZPZ3OM6.js +6 -0
  8. package/dist/{chunk-N3HCPBFY.js.map → chunk-BZPZ3OM6.js.map} +1 -1
  9. package/dist/{chunk-4BOWWYSE.js → chunk-CPX7XP3O.js} +13 -12
  10. package/dist/chunk-CPX7XP3O.js.map +1 -0
  11. package/dist/{chunk-KBPNH67Q.js → chunk-EGCB5K3P.js} +3 -3
  12. package/dist/{chunk-KBPNH67Q.js.map → chunk-EGCB5K3P.js.map} +1 -1
  13. package/dist/{chunk-G4HTI4ZM.js → chunk-FHJBGPJZ.js} +3 -2
  14. package/dist/chunk-FHJBGPJZ.js.map +1 -0
  15. package/dist/chunk-HTLDXEHW.js +60 -0
  16. package/dist/chunk-HTLDXEHW.js.map +1 -0
  17. package/dist/chunk-HWN4P64B.js +203 -0
  18. package/dist/chunk-HWN4P64B.js.map +1 -0
  19. package/dist/{chunk-GI6W53LM.js → chunk-IDAQV3NQ.js} +4 -2
  20. package/dist/chunk-IDAQV3NQ.js.map +1 -0
  21. package/dist/{chunk-42RDYQFF.js → chunk-KGWEBM2J.js} +3 -3
  22. package/dist/{chunk-42RDYQFF.js.map → chunk-KGWEBM2J.js.map} +1 -1
  23. package/dist/chunk-LCQILWQL.js +216 -0
  24. package/dist/chunk-LCQILWQL.js.map +1 -0
  25. package/dist/{chunk-EQ3IOFIG.js → chunk-NSK25UT2.js} +3 -3
  26. package/dist/{chunk-EQ3IOFIG.js.map → chunk-NSK25UT2.js.map} +1 -1
  27. package/dist/{chunk-JXMZCTVZ.js → chunk-PHVVVOW7.js} +14 -204
  28. package/dist/chunk-PHVVVOW7.js.map +1 -0
  29. package/dist/{chunk-RIEUPFXO.js → chunk-RV5DTGYT.js} +6 -62
  30. package/dist/chunk-RV5DTGYT.js.map +1 -0
  31. package/dist/{chunk-YMSXP6AO.js → chunk-UPH2RJ7L.js} +4 -4
  32. package/dist/{chunk-YMSXP6AO.js.map → chunk-UPH2RJ7L.js.map} +1 -1
  33. package/dist/{chunk-HWFVBYX4.js → chunk-WHXVU23K.js} +7 -6
  34. package/dist/chunk-WHXVU23K.js.map +1 -0
  35. package/dist/{chunk-5MNX3OLS.js → chunk-ZW5W627G.js} +7 -6
  36. package/dist/chunk-ZW5W627G.js.map +1 -0
  37. package/dist/cli.js +459 -532
  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-MR7DTVYS.js} +16 -14
  45. package/dist/interactive-MR7DTVYS.js.map +1 -0
  46. package/dist/load-RFQFTTIT.js +10 -0
  47. package/dist/{load-4PARCNMD.js.map → load-RFQFTTIT.js.map} +1 -1
  48. package/dist/run-outcome-EKB6YQIK.js +253 -0
  49. package/dist/run-outcome-EKB6YQIK.js.map +1 -0
  50. package/dist/{runtime-session-AILFASQV.js → runtime-session-23RZLEA4.js} +7 -6
  51. package/dist/{runtime-session-AILFASQV.js.map → runtime-session-23RZLEA4.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-UZFHPP2Q.js} +8 -7
  55. package/dist/vg-mcp-bridge-UZFHPP2Q.js.map +1 -0
  56. package/dist/{vgd-S7D2SITC.js → vgd-VIPBL7W4.js} +6 -5
  57. package/dist/vgd-VIPBL7W4.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-ZW5W627G.js';
3
+ export { runBuild } from './chunk-ZW5W627G.js';
4
+ import { telemetryOptOut, StatsSharer, statsEndpoint, isCI } from './chunk-LCQILWQL.js';
5
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-UPH2RJ7L.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-NSK25UT2.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-WHXVU23K.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-A5LF4VS4.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-RV5DTGYT.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, perDependencyDrift } from './chunk-CPX7XP3O.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-HWN4P64B.js';
43
+ import { resolveGraphPath, renderReport, loadGraphFileWithSnapshot, writeArtifacts, vibgrateDir, mapFileExists, ensureVibgrateGitignore } from './chunk-PHVVVOW7.js';
44
+ import { VERSION } from './chunk-BZPZ3OM6.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;
@@ -2528,6 +2334,7 @@ var VibgrateLanguageServer = class {
2528
2334
  this.conn.onRequest("textDocument/codeLens", (_m, params) => this.onCodeLens(params));
2529
2335
  this.conn.onRequest("vibgrate/graph/query", (_m, params) => this.onGraphQuery(params));
2530
2336
  this.conn.onRequest("vibgrate/score/forFile", (_m, params) => this.onScoreForFile(params));
2337
+ this.conn.onRequest("vibgrate/score/forProject", (_m, params) => this.onScoreForProject(params));
2531
2338
  this.conn.onRequest("vibgrate/score/history", (_m, params) => {
2532
2339
  const p = params;
2533
2340
  const days = typeof p?.days === "number" && p.days > 0 && p.days <= 365 ? p.days : 90;
@@ -2538,7 +2345,7 @@ var VibgrateLanguageServer = class {
2538
2345
  this.conn.onRequest("workspace/executeCommand", (_m, params) => {
2539
2346
  const p = params;
2540
2347
  if (p.command === "vibgrate.rescan") {
2541
- this.scheduleScan(0);
2348
+ this.scheduleScan(0, { force: true });
2542
2349
  return { ok: true };
2543
2350
  }
2544
2351
  return null;
@@ -2553,7 +2360,8 @@ var VibgrateLanguageServer = class {
2553
2360
  });
2554
2361
  }
2555
2362
  // ── Scanning ─────────────────────────────────────────────────────────────
2556
- scheduleScan(delayMs) {
2363
+ scheduleScan(delayMs, opts) {
2364
+ if (opts?.force) this.forceNextScan = true;
2557
2365
  if (this.debounce) clearTimeout(this.debounce);
2558
2366
  this.debounce = setTimeout(() => void this.scan(), delayMs);
2559
2367
  }
@@ -2563,11 +2371,13 @@ var VibgrateLanguageServer = class {
2563
2371
  return;
2564
2372
  }
2565
2373
  this.scanning = true;
2374
+ const force = this.forceNextScan;
2375
+ this.forceNextScan = false;
2566
2376
  try {
2567
2377
  const cacheKey = { manifestHash: manifestHash(this.opts.root), toolVersion: VERSION, offline: this.opts.offline };
2568
- const cached = loadScanCache(this.opts.root, cacheKey);
2378
+ const cached = force ? null : loadScanCache(this.opts.root, cacheKey);
2569
2379
  if (cached) {
2570
- this.artifact = cached.artifact;
2380
+ this.artifact = pruneArtifactProjects(cached.artifact);
2571
2381
  } else {
2572
2382
  const scanOpts = {
2573
2383
  format: "json",
@@ -2582,7 +2392,7 @@ var VibgrateLanguageServer = class {
2582
2392
  vibgrateVersion: VERSION
2583
2393
  };
2584
2394
  const advanced = await loadAdvancedScanHook();
2585
- this.artifact = await runCoreScan(this.opts.root, scanOpts, advanced);
2395
+ this.artifact = pruneArtifactProjects(await runCoreScan(this.opts.root, scanOpts, advanced));
2586
2396
  writeScanCache(this.opts.root, cacheKey, this.artifact);
2587
2397
  }
2588
2398
  this.publishScore();
@@ -2644,7 +2454,9 @@ var VibgrateLanguageServer = class {
2644
2454
  rootPath: a.rootPath,
2645
2455
  scannedAt: a.timestamp,
2646
2456
  ...delta !== void 0 ? { delta } : {},
2647
- ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {}
2457
+ ...buildBreakdown(a.drift, a.projects ?? []) ? { breakdown: buildBreakdown(a.drift, a.projects ?? []) } : {},
2458
+ ...buildEolHorizon(a.projects ?? []) ? { eolHorizon: buildEolHorizon(a.projects ?? []) } : {},
2459
+ ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2648
2460
  };
2649
2461
  this.conn.notify("vibgrate/score", payload);
2650
2462
  }
@@ -2830,13 +2642,16 @@ var VibgrateLanguageServer = class {
2830
2642
  const reachedPkgs = packageReachSet(this.graph);
2831
2643
  const targets = [];
2832
2644
  for (const proj of a.projects ?? []) {
2645
+ if (isPrunedWorkspacePath(proj.path) || isPrunedWorkspacePath(manifestRelativePath(proj))) {
2646
+ continue;
2647
+ }
2833
2648
  const ecosystem = osvEcosystem(proj.type);
2834
2649
  if (!ecosystem) continue;
2835
2650
  const relManifest = manifestRelativePath(proj);
2836
- const absManifest = path38.resolve(this.opts.root, relManifest);
2651
+ const absManifest = path37.resolve(this.opts.root, relManifest);
2837
2652
  let text = null;
2838
2653
  try {
2839
- if (fs8.existsSync(absManifest)) text = fs8.readFileSync(absManifest, "utf8");
2654
+ if (fs7.existsSync(absManifest)) text = fs7.readFileSync(absManifest, "utf8");
2840
2655
  } catch {
2841
2656
  text = null;
2842
2657
  }
@@ -2873,6 +2688,17 @@ var VibgrateLanguageServer = class {
2873
2688
  const project = projectForFile(this.opts.root, a, uriToPath(p.uri));
2874
2689
  return project ? scoreForProject(a, project) : null;
2875
2690
  }
2691
+ /**
2692
+ * `vibgrate/score/forProject` — monorepo scope picker. Returns the same
2693
+ * shape as the whole-repo score, scoped to one scanned project path.
2694
+ */
2695
+ onScoreForProject(params) {
2696
+ const p = params;
2697
+ const a = this.artifact;
2698
+ if (!a || typeof p.path !== "string") return null;
2699
+ const project = projectByPath(a, p.path);
2700
+ return project ? scoreForProject(a, project) : null;
2701
+ }
2876
2702
  };
2877
2703
  function uriToPath(uri) {
2878
2704
  try {
@@ -2881,13 +2707,55 @@ function uriToPath(uri) {
2881
2707
  return uri;
2882
2708
  }
2883
2709
  }
2710
+ function isPrunedWorkspacePath(relPath) {
2711
+ if (!relPath || relPath === "." || relPath === "") return false;
2712
+ const parts = relPath.split(/[/\\]/).filter(Boolean);
2713
+ if (parts.includes(".claude")) return true;
2714
+ return parts.some((p) => SKIP_DIRS.has(p));
2715
+ }
2716
+ function pruneArtifactProjects(a) {
2717
+ const projects = (a.projects ?? []).filter(
2718
+ (p) => !isPrunedWorkspacePath(p.path) && !isPrunedWorkspacePath(manifestRelativePath(p))
2719
+ );
2720
+ if (projects.length === (a.projects ?? []).length) {
2721
+ const findings2 = (a.findings ?? []).filter((f) => !isPrunedWorkspacePath(f.location));
2722
+ if (findings2.length === (a.findings ?? []).length) return a;
2723
+ return { ...a, findings: findings2 };
2724
+ }
2725
+ const findings = (a.findings ?? []).filter((f) => !isPrunedWorkspacePath(f.location));
2726
+ return { ...a, projects, findings };
2727
+ }
2728
+ function projectByPath(a, projectPath) {
2729
+ const want = path37.normalize(projectPath === "" ? "." : projectPath);
2730
+ for (const proj of a.projects ?? []) {
2731
+ const got = path37.normalize(proj.path === "" ? "." : proj.path);
2732
+ if (got === want) return proj;
2733
+ }
2734
+ return void 0;
2735
+ }
2736
+ function buildProjectRefs(projects) {
2737
+ if (projects.length === 0) return void 0;
2738
+ return projects.map((p) => {
2739
+ const rel = p.path === "" ? "." : p.path;
2740
+ const base = rel === "." ? "." : path37.basename(rel);
2741
+ return {
2742
+ path: rel,
2743
+ name: p.name || base,
2744
+ ...p.drift ? {
2745
+ score: p.drift.score,
2746
+ band: p.drift.riskLevel ?? "low",
2747
+ mode: p.drift.mode ?? "verified"
2748
+ } : {}
2749
+ };
2750
+ }).sort((a, b) => a.path.localeCompare(b.path));
2751
+ }
2884
2752
  function projectForFile(root2, a, filePath) {
2885
- const dir = path38.dirname(path38.resolve(filePath));
2753
+ const dir = path37.dirname(path37.resolve(filePath));
2886
2754
  let best;
2887
2755
  let bestLen = -1;
2888
2756
  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) {
2757
+ const projDir = path37.resolve(root2, proj.path);
2758
+ if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
2891
2759
  best = proj;
2892
2760
  bestLen = projDir.length;
2893
2761
  }
@@ -2895,7 +2763,7 @@ function projectForFile(root2, a, filePath) {
2895
2763
  return best;
2896
2764
  }
2897
2765
  function sameProject(location, projectPath) {
2898
- return path38.normalize(location) === path38.normalize(projectPath);
2766
+ return path37.normalize(location) === path37.normalize(projectPath);
2899
2767
  }
2900
2768
  function hasReleaseDates(a) {
2901
2769
  for (const proj of a.projects ?? []) {
@@ -2926,76 +2794,105 @@ function scoreForProject(a, proj) {
2926
2794
  methodology: proj.drift.methodologyVersion ?? a.drift.methodologyVersion ?? "unknown",
2927
2795
  scale: "0 best, 100 worst",
2928
2796
  counts: { behind, eol, unmaintained, total },
2929
- rootPath: proj.path,
2797
+ rootPath: proj.path === "" ? "." : proj.path,
2930
2798
  scannedAt: a.timestamp,
2931
- ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {}
2799
+ ...buildBreakdown(proj.drift, [proj]) ? { breakdown: buildBreakdown(proj.drift, [proj]) } : {},
2800
+ ...buildEolHorizon([proj]) ? { eolHorizon: buildEolHorizon([proj]) } : {},
2801
+ ...buildProjectRefs(a.projects ?? []) ? { projects: buildProjectRefs(a.projects ?? []) } : {}
2932
2802
  };
2933
2803
  }
2804
+ function runtimeHorizonLabel(project) {
2805
+ const kind = project.type === "node" ? "Node.js" : project.type === "dotnet" ? ".NET" : project.type === "python" ? "Python" : project.type === "java" ? "Java" : project.type;
2806
+ return project.runtime ? `${kind} ${project.runtime}` : kind;
2807
+ }
2808
+ function buildEolHorizon(projects, now = Date.now()) {
2809
+ const byLabel = /* @__PURE__ */ new Map();
2810
+ for (const p of projects) {
2811
+ if (!p.runtimeEolDate) continue;
2812
+ const t = Date.parse(p.runtimeEolDate);
2813
+ if (!Number.isFinite(t)) continue;
2814
+ const label = runtimeHorizonLabel(p);
2815
+ if (byLabel.has(label)) continue;
2816
+ byLabel.set(label, {
2817
+ runtime: label,
2818
+ eolDate: p.runtimeEolDate,
2819
+ daysUntil: Math.round((t - now) / (24 * 60 * 60 * 1e3))
2820
+ });
2821
+ }
2822
+ if (byLabel.size === 0) return void 0;
2823
+ return [...byLabel.values()].sort((a, b) => a.daysUntil - b.daysUntil).slice(0, 5);
2824
+ }
2934
2825
  function bandForScore(n) {
2935
2826
  if (n <= 30) return "low";
2936
2827
  if (n <= 60) return "moderate";
2937
2828
  return "high";
2938
2829
  }
2939
- function buildBreakdown(drift, projects) {
2940
- const top = drift.dependencyDrift?.top;
2941
- if (!top || top.length === 0) return void 0;
2830
+ function buildBreakdown(_drift, projects) {
2942
2831
  const byPkg = /* @__PURE__ */ new Map();
2943
2832
  for (const p of projects) {
2944
2833
  const ecosystem = osvEcosystem(p.type);
2945
- for (const d of p.dependencies ?? []) if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
2834
+ for (const d of p.dependencies ?? []) {
2835
+ if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
2836
+ }
2946
2837
  }
2947
- const items = top.filter((t) => t.drift > 0).map((t) => {
2948
- const found = byPkg.get(t.package);
2949
- const row = found?.row;
2950
- return {
2951
- package: t.package,
2952
- section: row?.section ?? "dependencies",
2953
- ecosystem: found?.ecosystem ?? null,
2954
- drift: t.drift,
2955
- band: bandForScore(t.drift),
2956
- currentSpec: row?.currentSpec ?? "",
2957
- resolvedVersion: row?.resolvedVersion ?? null,
2958
- latestStable: row?.latestStable ?? null,
2959
- majorsBehind: row?.majorsBehind ?? null,
2960
- ageDays: row?.ageDays ?? null,
2961
- mode: t.mode,
2962
- unsupported: t.unsupported,
2963
- abandoned: t.flags.includes("abandoned-floor"),
2964
- flags: t.flags
2965
- };
2966
- });
2838
+ if (byPkg.size === 0) return void 0;
2839
+ const items = [];
2840
+ for (const [, { row, ecosystem }] of byPkg) {
2841
+ const scored = perDependencyDrift(row, {
2842
+ unsupported: row.unsupported === true,
2843
+ abandoned: row.abandoned === true
2844
+ });
2845
+ if (scored.excluded) continue;
2846
+ items.push({
2847
+ package: row.package,
2848
+ section: row.section ?? "dependencies",
2849
+ ecosystem,
2850
+ drift: scored.drift,
2851
+ band: bandForScore(scored.drift),
2852
+ currentSpec: row.currentSpec ?? "",
2853
+ resolvedVersion: row.resolvedVersion ?? null,
2854
+ latestStable: row.latestStable ?? null,
2855
+ majorsBehind: row.majorsBehind ?? null,
2856
+ ageDays: row.ageDays ?? null,
2857
+ mode: scored.mode,
2858
+ unsupported: scored.unsupported || row.unsupported === true,
2859
+ abandoned: scored.flags.includes("abandoned-floor") || row.abandoned === true,
2860
+ flags: scored.flags
2861
+ });
2862
+ }
2863
+ items.sort((a, b) => b.drift - a.drift || a.package.localeCompare(b.package));
2967
2864
  return items.length > 0 ? items : void 0;
2968
2865
  }
2969
2866
  function manifestRelativePath(proj) {
2970
2867
  const base = proj.path === "." || proj.path === "" ? "" : proj.path;
2971
- const join28 = (name) => base ? path38.join(base, name) : name;
2868
+ const join27 = (name) => base ? path37.join(base, name) : name;
2972
2869
  switch (proj.type) {
2973
2870
  case "node":
2974
2871
  case "typescript":
2975
- return join28("package.json");
2872
+ return join27("package.json");
2976
2873
  case "python":
2977
- return join28("pyproject.toml");
2874
+ return join27("pyproject.toml");
2978
2875
  case "go":
2979
- return join28("go.mod");
2876
+ return join27("go.mod");
2980
2877
  case "rust":
2981
- return join28("Cargo.toml");
2878
+ return join27("Cargo.toml");
2982
2879
  case "ruby":
2983
- return join28("Gemfile");
2880
+ return join27("Gemfile");
2984
2881
  case "php":
2985
- return join28("composer.json");
2882
+ return join27("composer.json");
2986
2883
  case "java":
2987
2884
  case "kotlin":
2988
2885
  case "scala":
2989
2886
  case "groovy":
2990
- return join28("pom.xml");
2887
+ return join27("pom.xml");
2991
2888
  case "dotnet":
2992
- return join28(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2889
+ return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
2993
2890
  case "dart":
2994
- return join28("pubspec.yaml");
2891
+ return join27("pubspec.yaml");
2995
2892
  case "elixir":
2996
- return join28("mix.exs");
2893
+ return join27("mix.exs");
2997
2894
  default:
2998
- return join28("package.json");
2895
+ return join27("package.json");
2999
2896
  }
3000
2897
  }
3001
2898
  function packageReachSet(graph) {
@@ -3155,7 +3052,7 @@ function hoverMarkdown(dep, contribution) {
3155
3052
  return lines.join("\n");
3156
3053
  }
3157
3054
  function startLanguageServer(opts) {
3158
- if (!fs8.existsSync(opts.root)) {
3055
+ if (!fs7.existsSync(opts.root)) {
3159
3056
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3160
3057
  `);
3161
3058
  process.exit(1);
@@ -3292,8 +3189,8 @@ function registerShare(program) {
3292
3189
  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
3190
  const global = readGlobal(this);
3294
3191
  const root2 = rootOf(global);
3295
- const gitDir = path38.join(root2, ".git");
3296
- if (!fs8.existsSync(gitDir)) {
3192
+ const gitDir = path37.join(root2, ".git");
3193
+ if (!fs7.existsSync(gitDir)) {
3297
3194
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3298
3195
  }
3299
3196
  if (opts.undo) {
@@ -3314,23 +3211,23 @@ function registerShare(program) {
3314
3211
  applyGlobalOptions(cmd);
3315
3212
  }
3316
3213
  function writeVibgrateGitignore(root2, reports) {
3317
- const dir = path38.join(root2, ".vibgrate");
3318
- fs8.mkdirSync(dir, { recursive: true });
3214
+ const dir = path37.join(root2, ".vibgrate");
3215
+ fs7.mkdirSync(dir, { recursive: true });
3319
3216
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl", "graph.snap"];
3320
3217
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3321
- fs8.writeFileSync(path38.join(dir, ".gitignore"), `${lines.join("\n")}
3218
+ fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
3322
3219
  `);
3323
3220
  }
3324
3221
  function writeGitAttributes(root2) {
3325
- const file = path38.join(root2, ".gitattributes");
3222
+ const file = path37.join(root2, ".gitattributes");
3326
3223
  const line = ".vibgrate/graph.json merge=vg";
3327
- let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
3224
+ let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "";
3328
3225
  if (!content.split("\n").some((l) => l.trim() === line)) {
3329
3226
  content = content.length ? `${content.replace(/\s*$/, "")}
3330
3227
  ${line}
3331
3228
  ` : `${line}
3332
3229
  `;
3333
- fs8.writeFileSync(file, content);
3230
+ fs7.writeFileSync(file, content);
3334
3231
  }
3335
3232
  }
3336
3233
  function configureMergeDriver(root2) {
@@ -3339,8 +3236,8 @@ function configureMergeDriver(root2) {
3339
3236
  }
3340
3237
  function installPreCommitHook(root2) {
3341
3238
  const hooksDir = hookDir(root2);
3342
- fs8.mkdirSync(hooksDir, { recursive: true });
3343
- const file = path38.join(hooksDir, "pre-commit");
3239
+ fs7.mkdirSync(hooksDir, { recursive: true });
3240
+ const file = path37.join(hooksDir, "pre-commit");
3344
3241
  const block = [
3345
3242
  HOOK_BEGIN,
3346
3243
  "if command -v vg >/dev/null 2>&1; then",
@@ -3349,7 +3246,7 @@ function installPreCommitHook(root2) {
3349
3246
  "fi",
3350
3247
  HOOK_END
3351
3248
  ].join("\n");
3352
- let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "#!/bin/sh\n";
3249
+ let content = fs7.existsSync(file) ? fs7.readFileSync(file, "utf8") : "#!/bin/sh\n";
3353
3250
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3354
3251
  if (re.test(content)) content = content.replace(re, block);
3355
3252
  else content = `${content.replace(/\s*$/, "")}
@@ -3358,21 +3255,21 @@ ${block}
3358
3255
  `;
3359
3256
  if (!content.startsWith("#!")) content = `#!/bin/sh
3360
3257
  ${content}`;
3361
- fs8.writeFileSync(file, content);
3362
- fs8.chmodSync(file, 493);
3258
+ fs7.writeFileSync(file, content);
3259
+ fs7.chmodSync(file, 493);
3363
3260
  }
3364
3261
  function undo(root2) {
3365
- const hookFile = path38.join(hookDir(root2), "pre-commit");
3366
- if (fs8.existsSync(hookFile)) {
3262
+ const hookFile = path37.join(hookDir(root2), "pre-commit");
3263
+ if (fs7.existsSync(hookFile)) {
3367
3264
  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);
3265
+ const next2 = fs7.readFileSync(hookFile, "utf8").replace(re, "\n");
3266
+ if (next2.trim() === "#!/bin/sh") fs7.rmSync(hookFile);
3267
+ else fs7.writeFileSync(hookFile, next2);
3371
3268
  }
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);
3269
+ const attr = path37.join(root2, ".gitattributes");
3270
+ if (fs7.existsSync(attr)) {
3271
+ const next2 = fs7.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3272
+ fs7.writeFileSync(attr, next2);
3376
3273
  }
3377
3274
  try {
3378
3275
  git(root2, ["config", "--remove-section", "merge.vg"]);
@@ -3382,10 +3279,10 @@ function undo(root2) {
3382
3279
  function hookDir(root2) {
3383
3280
  try {
3384
3281
  const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
3385
- if (configured) return path38.resolve(root2, configured);
3282
+ if (configured) return path37.resolve(root2, configured);
3386
3283
  } catch {
3387
3284
  }
3388
- return path38.join(root2, ".git", "hooks");
3285
+ return path37.join(root2, ".git", "hooks");
3389
3286
  }
3390
3287
  function git(root2, args) {
3391
3288
  return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
@@ -3413,9 +3310,9 @@ function registerWatch(program) {
3413
3310
  const global = readGlobal(this);
3414
3311
  const root2 = rootOf(global);
3415
3312
  const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
3416
- const watchRoots = (paths.length ? paths : ["."]).map((p) => path38.resolve(root2, p));
3313
+ const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
3417
3314
  for (const w of watchRoots) {
3418
- if (!fs8.existsSync(w)) {
3315
+ if (!fs7.existsSync(w)) {
3419
3316
  throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
3420
3317
  }
3421
3318
  }
@@ -3468,14 +3365,14 @@ function registerWatch(program) {
3468
3365
  const watchers = [];
3469
3366
  for (const w of watchRoots) {
3470
3367
  try {
3471
- const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
3368
+ const watcher = fs7.watch(w, { recursive: true }, (_event, filename) => {
3472
3369
  if (!filename) {
3473
3370
  schedule("change");
3474
3371
  return;
3475
3372
  }
3476
- const parts = filename.split(path38.sep);
3373
+ const parts = filename.split(path37.sep);
3477
3374
  if (parts.some((p) => SKIP_NAME.has(p))) return;
3478
- if (filename.includes(`${path38.sep}.vibgrate${path38.sep}`) || filename.startsWith(".vibgrate")) {
3375
+ if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
3479
3376
  return;
3480
3377
  }
3481
3378
  schedule(filename);
@@ -3485,7 +3382,7 @@ function registerWatch(program) {
3485
3382
  throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
3486
3383
  }
3487
3384
  }
3488
- info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path38.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3385
+ info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
3489
3386
  await new Promise((resolve21) => {
3490
3387
  const stop = () => {
3491
3388
  for (const w of watchers) w.close();
@@ -3818,10 +3715,10 @@ function normalizeStandards(raw) {
3818
3715
  }
3819
3716
  function loadStandards(root2) {
3820
3717
  for (const rel of STANDARDS_FILES) {
3821
- const p = path38__default.join(root2, rel);
3718
+ const p = path37__default.join(root2, rel);
3822
3719
  let text;
3823
3720
  try {
3824
- text = fs8__default.readFileSync(p, "utf8");
3721
+ text = fs7__default.readFileSync(p, "utf8");
3825
3722
  } catch {
3826
3723
  continue;
3827
3724
  }
@@ -4539,8 +4436,8 @@ async function runHostBench(options = {}) {
4539
4436
  }
4540
4437
  async function runArmSimulate(input) {
4541
4438
  const { arm, lib, modelPath, turns, trie, env, live } = input;
4542
- const path40 = `${modelPath}#${arm.id}`;
4543
- const session = await acquireHostSession(lib, path40);
4439
+ const path39 = `${modelPath}#${arm.id}`;
4440
+ const session = await acquireHostSession(lib, path39);
4544
4441
  const system = "You are a coding agent with a Task Capsule.";
4545
4442
  const capsule = "function readConfig(): Config { return load(); }";
4546
4443
  let last = null;
@@ -5752,7 +5649,7 @@ function registerModels(program) {
5752
5649
  );
5753
5650
  }
5754
5651
  } else {
5755
- if (!target.path || !fs8.existsSync(target.path)) {
5652
+ if (!target.path || !fs7.existsSync(target.path)) {
5756
5653
  throw new CliError(
5757
5654
  `model file not found at ${target.path || "(unknown path)"} \u2014 it may already be removed.`,
5758
5655
  ExitCode.NOT_FOUND
@@ -5766,7 +5663,7 @@ function registerModels(program) {
5766
5663
  }
5767
5664
  if (!global.json) info(c.dim(` $ rm ${target.path}`));
5768
5665
  try {
5769
- fs8.unlinkSync(target.path);
5666
+ fs7.unlinkSync(target.path);
5770
5667
  } catch (e) {
5771
5668
  const msg = e instanceof Error ? e.message : String(e);
5772
5669
  throw new CliError(`could not delete ${target.path}: ${msg}`, ExitCode.ERROR);
@@ -5904,9 +5801,9 @@ function registerModels(program) {
5904
5801
  }
5905
5802
  });
5906
5803
  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)}
5804
+ const outPath = path37.resolve(opts.out);
5805
+ fs7.mkdirSync(path37.dirname(outPath), { recursive: true });
5806
+ fs7.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
5910
5807
  `);
5911
5808
  if (!global.json) info(c.dim(` wrote ${outPath}`));
5912
5809
  }
@@ -6055,14 +5952,14 @@ function resolveUninstallTarget(name, runtimeOpt) {
6055
5952
  }
6056
5953
  return exact[0];
6057
5954
  }
6058
- const base = path38.basename(wantLc);
5955
+ const base = path37.basename(wantLc);
6059
5956
  const soft = fleet.filter((m) => {
6060
5957
  const n = m.name.toLowerCase();
6061
- return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path38.basename(n) === base;
5958
+ return n === base || n.endsWith("/" + base) || n.endsWith(wantLc) || path37.basename(n) === base;
6062
5959
  });
6063
5960
  if (soft.length === 1) return soft[0];
6064
5961
  if (soft.length > 1) {
6065
- const baseHits = soft.filter((m) => path38.basename(m.name).toLowerCase() === base);
5962
+ const baseHits = soft.filter((m) => path37.basename(m.name).toLowerCase() === base);
6066
5963
  const pool = baseHits.length ? baseHits : soft;
6067
5964
  const order = ["ollama", "gguf", "lm-studio"];
6068
5965
  for (const rt of order) {
@@ -6100,11 +5997,11 @@ function printBackends(backends) {
6100
5997
  }
6101
5998
  }
6102
5999
  function codeConfigPath(root2) {
6103
- return path38.join(root2, ".vibgrate", "code.json");
6000
+ return path37.join(root2, ".vibgrate", "code.json");
6104
6001
  }
6105
6002
  function loadCodeConfig(root2) {
6106
6003
  try {
6107
- const raw = JSON.parse(fs8.readFileSync(codeConfigPath(root2), "utf8"));
6004
+ const raw = JSON.parse(fs7.readFileSync(codeConfigPath(root2), "utf8"));
6108
6005
  return sanitize(raw);
6109
6006
  } catch {
6110
6007
  return {};
@@ -6171,7 +6068,7 @@ function contextBudgetFor(config, modelContextWindow) {
6171
6068
  var MCP_CONFIG_FILES = [".cursor/mcp.json", ".vscode/mcp.json", ".mcp.json"];
6172
6069
  function readMcpServersFile(file) {
6173
6070
  try {
6174
- const raw = JSON.parse(fs8.readFileSync(file, "utf8"));
6071
+ const raw = JSON.parse(fs7.readFileSync(file, "utf8"));
6175
6072
  const map = raw.mcpServers ?? raw.servers;
6176
6073
  return map && typeof map === "object" ? parseMcpServers(map) : {};
6177
6074
  } catch {
@@ -6182,7 +6079,7 @@ function discoverMcpServers(root2, ownServers) {
6182
6079
  const servers = {};
6183
6080
  const sources = [];
6184
6081
  for (const rel of MCP_CONFIG_FILES) {
6185
- const found = readMcpServersFile(path38.join(root2, rel));
6082
+ const found = readMcpServersFile(path37.join(root2, rel));
6186
6083
  const names = Object.keys(found);
6187
6084
  if (names.length) {
6188
6085
  sources.push(rel);
@@ -6211,7 +6108,7 @@ function registerCode(program) {
6211
6108
  try {
6212
6109
  const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2 } = await import('./model-orchestrator-LHYPJBFH.js');
6213
6110
  const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-2ED33KK6.js');
6214
- const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
6111
+ const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
6215
6112
  const state = readOrchestratorState2();
6216
6113
  const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
6217
6114
  const pin = mode ? activePin2(mode, state) : null;
@@ -6295,7 +6192,7 @@ function registerCode(program) {
6295
6192
  if (!(process.stdin.isTTY && process.stdout.isTTY)) {
6296
6193
  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
6194
  }
6298
- const { runInteractive } = await import('./interactive-MJVMY5JP.js');
6195
+ const { runInteractive } = await import('./interactive-MR7DTVYS.js');
6299
6196
  await runInteractive(
6300
6197
  rootOf(global),
6301
6198
  global,
@@ -6328,7 +6225,7 @@ function registerCode(program) {
6328
6225
  let mockReply;
6329
6226
  if (opts.mock) {
6330
6227
  try {
6331
- mockReply = fs8.readFileSync(opts.mock, "utf8");
6228
+ mockReply = fs7.readFileSync(opts.mock, "utf8");
6332
6229
  } catch {
6333
6230
  throw new CliError(`couldn't read the --mock file: ${opts.mock}`, ExitCode.USAGE_ERROR);
6334
6231
  }
@@ -6376,19 +6273,20 @@ function registerCode(program) {
6376
6273
  process.stdout.write(JSON.stringify(line) + "\n");
6377
6274
  };
6378
6275
  try {
6276
+ const { RunOutcomeRecorder, newOneShotRunId, turnRunId } = await import('./run-outcome-EKB6YQIK.js');
6379
6277
  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');
6278
+ const { runCodeStreamJson, parseHostMessage } = await import('./stream-json-3YOPU3LF.js');
6381
6279
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6382
6280
  const readline5 = await import('readline');
6383
6281
  const child = await import('child_process');
6384
6282
  const { loadOrDiscoverFederation } = await import('./federation-MDQPO3PW.js');
6385
6283
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6386
6284
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6387
- const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6285
+ const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6388
6286
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6389
6287
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6390
6288
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6391
- const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6289
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6392
6290
  const federation = loadOrDiscoverFederation(root2);
6393
6291
  const modelProfile = mergeModelExecutionProfile(
6394
6292
  resolveModelExecutionProfile({
@@ -6405,6 +6303,18 @@ function registerCode(program) {
6405
6303
  const runtime = await startCodeRuntimeSession({ root: root2 });
6406
6304
  const git2 = detectGitRef(root2);
6407
6305
  const repositoryId = repositoryIdFromRoot(root2);
6306
+ const runOutcome = new RunOutcomeRecorder(
6307
+ root2,
6308
+ repositoryId,
6309
+ git2.ref || null,
6310
+ { mode: codeModeActive ? modeFlag : void 0, provider: primarySlug, model: route.providers[0]?.model },
6311
+ tier,
6312
+ !!auto
6313
+ );
6314
+ const emitAndRecord = (line) => {
6315
+ runOutcome.observe(line);
6316
+ emitStream(line);
6317
+ };
6408
6318
  if (runtime.socketPath && git2.ref) {
6409
6319
  try {
6410
6320
  await vgdRequest2(
@@ -6434,7 +6344,7 @@ ${res.stderr}` : ""),
6434
6344
  exitCode: res.status ?? 1
6435
6345
  };
6436
6346
  };
6437
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6347
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6438
6348
  const vgBuiltin = createVgBuiltinMcpTools({
6439
6349
  getGraph: () => graph,
6440
6350
  root: root2,
@@ -6455,10 +6365,10 @@ ${res.stderr}` : ""),
6455
6365
  }
6456
6366
  const externalTools = mergeExternalToolsets(vgBuiltin, projectMcp);
6457
6367
  const { createCheckpoint } = await import('./checkpoint-4WFZMKEO.js');
6458
- const os5 = await import('os');
6368
+ const os4 = await import('os');
6459
6369
  const pathMod = await import('path');
6460
6370
  const checkpointIndex = pathMod.join(
6461
- fs8.mkdtempSync(pathMod.join(os5.tmpdir(), "vg-code-cp-")),
6371
+ fs7.mkdtempSync(pathMod.join(os4.tmpdir(), "vg-code-cp-")),
6462
6372
  "index"
6463
6373
  );
6464
6374
  const gitRunner = (gitArgs, gitEnv) => {
@@ -6521,8 +6431,8 @@ ${res.stderr}` : ""),
6521
6431
  };
6522
6432
  try {
6523
6433
  if (opts.session) {
6524
- const { runCodeStreamJsonSession } = await import('./stream-json-MTPWWVRR.js');
6525
- const { runAgent: runAgent2 } = await import('./agent-Z4Z66IGM.js');
6434
+ const { runCodeStreamJsonSession } = await import('./stream-json-3YOPU3LF.js');
6435
+ const { runAgent: runAgent2 } = await import('./agent-33BMKWJC.js');
6526
6436
  const {
6527
6437
  loadLatestSession,
6528
6438
  newSession,
@@ -6557,8 +6467,9 @@ ${res.stderr}` : ""),
6557
6467
  wakeTurn = resolve21;
6558
6468
  });
6559
6469
  };
6470
+ let turnIndex = 0;
6560
6471
  await runCodeStreamJsonSession({
6561
- emit: emitStream,
6472
+ emit: emitAndRecord,
6562
6473
  auto: !!auto,
6563
6474
  sessionId: record.id,
6564
6475
  resumed: !!resumedRecord,
@@ -6570,8 +6481,10 @@ ${res.stderr}` : ""),
6570
6481
  rl.on("line", (raw) => {
6571
6482
  const msg = parseHostMessage(raw);
6572
6483
  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);
6484
+ if (msg.kind === "approve") {
6485
+ session.submitDecision(msg.id, msg.approve);
6486
+ runOutcome.noteDecision(msg.id, msg.approve);
6487
+ } else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6575
6488
  else if (msg.kind === "submit") pushTurn(msg.instruction);
6576
6489
  else if (msg.kind === "restore") {
6577
6490
  void import('./checkpoint-4WFZMKEO.js').then(({ restoreCheckpoint }) => {
@@ -6581,8 +6494,10 @@ ${res.stderr}` : ""),
6581
6494
  });
6582
6495
  emitStream({ event: "checkpoint-restored", commit: msg.commit, ...outcome });
6583
6496
  });
6584
- } else if (msg.kind === "cancel") session.cancelTurn();
6585
- else if (msg.kind === "end") {
6497
+ } else if (msg.kind === "cancel") {
6498
+ session.cancelTurn();
6499
+ runOutcome.cancelPending();
6500
+ } else if (msg.kind === "end") {
6586
6501
  ended = true;
6587
6502
  pushTurn(null);
6588
6503
  }
@@ -6590,18 +6505,23 @@ ${res.stderr}` : ""),
6590
6505
  rl.on("close", () => {
6591
6506
  ended = true;
6592
6507
  session.cancelTurn();
6508
+ runOutcome.cancelPending();
6593
6509
  pushTurn(null);
6594
6510
  });
6595
6511
  },
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
- }),
6512
+ runTurn: ({ instruction: turnInstruction, priorSummary, signal, session }) => {
6513
+ turnIndex++;
6514
+ runOutcome.beginRun(turnRunId(record.id, turnIndex), turnInstruction);
6515
+ return runAgent2({
6516
+ ...baseAgentOptions,
6517
+ instruction: turnInstruction,
6518
+ priorSummary,
6519
+ signal,
6520
+ approve: session.approve,
6521
+ askUser: session.askUser,
6522
+ onEvent: session.onEvent
6523
+ });
6524
+ },
6605
6525
  onTurnEnd: (turn) => {
6606
6526
  record = recordTask(
6607
6527
  record,
@@ -6618,20 +6538,27 @@ ${res.stderr}` : ""),
6618
6538
  }
6619
6539
  });
6620
6540
  } else {
6541
+ runOutcome.beginRun(newOneShotRunId(), instruction);
6621
6542
  await runCodeStreamJson({
6622
6543
  ...baseAgentOptions,
6623
6544
  instruction,
6624
- emit: emitStream,
6545
+ emit: emitAndRecord,
6625
6546
  bindDecisions: (session) => {
6626
6547
  streamApprove = (action) => session.approve(action);
6627
6548
  const rl = readline5.createInterface({ input: process.stdin });
6628
6549
  rl.on("line", (raw) => {
6629
6550
  const msg = parseHostMessage(raw);
6630
6551
  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();
6552
+ if (msg.kind === "approve") {
6553
+ session.submitDecision(msg.id, msg.approve);
6554
+ runOutcome.noteDecision(msg.id, msg.approve);
6555
+ } else if (msg.kind === "answer") session.submitAnswer(msg.id, msg.answer);
6556
+ else if (msg.kind === "cancel") {
6557
+ session.cancelTurn();
6558
+ runOutcome.cancelPending();
6559
+ }
6634
6560
  });
6561
+ rl.on("close", () => runOutcome.cancelPending());
6635
6562
  }
6636
6563
  });
6637
6564
  }
@@ -6653,7 +6580,7 @@ ${res.stderr}` : ""),
6653
6580
  if (!autonomous && !tty) {
6654
6581
  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
6582
  }
6656
- const { agentTask } = await import('./interactive-MJVMY5JP.js');
6583
+ const { agentTask } = await import('./interactive-MR7DTVYS.js');
6657
6584
  const { nodeCodeFs } = await import('./session-3OBIQLE4.js');
6658
6585
  const { TtyPrompter } = await import('./ui-K7D3BCHD.js');
6659
6586
  let priorSummary;
@@ -6663,7 +6590,7 @@ ${res.stderr}` : ""),
6663
6590
  if (prev) priorSummary = summarizeSession(prev);
6664
6591
  }
6665
6592
  const prompter = tty ? new TtyPrompter() : void 0;
6666
- const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-BLHEIWMT.js');
6593
+ const { createVgBuiltinMcpTools, mergeExternalToolsets } = await import('./vg-mcp-bridge-UZFHPP2Q.js');
6667
6594
  const vgBuiltin = createVgBuiltinMcpTools({
6668
6595
  getGraph: () => graph,
6669
6596
  root: root2,
@@ -6687,11 +6614,11 @@ ${res.stderr}` : ""),
6687
6614
  const { loadFederation } = await import('./federation-MDQPO3PW.js');
6688
6615
  const { resolveExecutionEnv } = await import('./execution-env-4MS5AYAN.js');
6689
6616
  const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-ELWF3Z6H.js');
6690
- const { startCodeRuntimeSession } = await import('./runtime-session-AILFASQV.js');
6617
+ const { startCodeRuntimeSession } = await import('./runtime-session-23RZLEA4.js');
6691
6618
  const { resolveGraphBackend } = await import('./graph-backend-G5Y6QQV4.js');
6692
6619
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
6693
6620
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
6694
- const { vgdRequest: vgdRequest2 } = await import('./vgd-S7D2SITC.js');
6621
+ const { vgdRequest: vgdRequest2 } = await import('./vgd-VIPBL7W4.js');
6695
6622
  const federation = loadFederation(root2);
6696
6623
  const modelProfile = mergeModelExecutionProfile(
6697
6624
  resolveModelExecutionProfile({
@@ -6783,7 +6710,7 @@ ${res.stderr}` : ""),
6783
6710
  attribution: { client: "vg-code", provider: providerSlug, model: primary?.model }
6784
6711
  });
6785
6712
  if (opts.out) {
6786
- fs8.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6713
+ fs7.writeFileSync(opts.out, JSON.stringify(result, null, 2) + "\n");
6787
6714
  }
6788
6715
  if (global.json) {
6789
6716
  json(result);
@@ -6996,7 +6923,7 @@ async function addCmd(root2, rest, opts, asJson) {
6996
6923
  }
6997
6924
  function readPackageVersion(root2) {
6998
6925
  try {
6999
- const pkg = JSON.parse(fs8__default.readFileSync(path38__default.join(root2, "package.json"), "utf8"));
6926
+ const pkg = JSON.parse(fs7__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
7000
6927
  return typeof pkg.version === "string" ? pkg.version : void 0;
7001
6928
  } catch {
7002
6929
  return void 0;
@@ -7004,7 +6931,7 @@ function readPackageVersion(root2) {
7004
6931
  }
7005
6932
  function readOptionalFile(p) {
7006
6933
  try {
7007
- const t = fs8__default.readFileSync(p, "utf8");
6934
+ const t = fs7__default.readFileSync(p, "utf8");
7008
6935
  return t.trim() ? t : void 0;
7009
6936
  } catch {
7010
6937
  return void 0;
@@ -7019,8 +6946,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
7019
6946
  if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
7020
6947
  const version = (opts.version || readPackageVersion(root2) || "").trim();
7021
6948
  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;
6949
+ const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
6950
+ const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
7024
6951
  if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
7025
6952
  const result = await publishPrivateLibrary(
7026
6953
  { name, version, readme, dts, language: opts.language },
@@ -7152,8 +7079,8 @@ function registerExport(program) {
7152
7079
  out(content.trimEnd());
7153
7080
  return;
7154
7081
  }
7155
- fs8.mkdirSync(path38.dirname(path38.resolve(file)), { recursive: true });
7156
- fs8.writeFileSync(file, content);
7082
+ fs7.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
7083
+ fs7.writeFileSync(file, content);
7157
7084
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
7158
7085
  });
7159
7086
  applyGlobalOptions(cmd);
@@ -7163,43 +7090,43 @@ function detectFormat(file) {
7163
7090
  if (lower.endsWith(".cdx.json")) return "cyclonedx";
7164
7091
  if (lower.endsWith(".spdx.json")) return "spdx";
7165
7092
  if (file === "-") return "json";
7166
- return formatForExt(path38.extname(file));
7093
+ return formatForExt(path37.extname(file));
7167
7094
  }
7168
7095
  function registerBundle(program) {
7169
7096
  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
7097
  const global = readGlobal(this);
7171
7098
  const root2 = rootOf(global);
7172
- const outDir = path38.resolve(root2, opts.out ?? "vg-bundle");
7099
+ const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
7173
7100
  let grammarFiles;
7174
7101
  try {
7175
7102
  grammarFiles = resolvedGrammarFiles();
7176
7103
  } catch {
7177
7104
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
7178
7105
  }
7179
- fs8.mkdirSync(path38.join(outDir, "grammars"), { recursive: true });
7106
+ fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
7180
7107
  let grammarCount = 0;
7181
7108
  for (const { fileName, absPath } of grammarFiles) {
7182
- fs8.copyFileSync(absPath, path38.join(outDir, "grammars", fileName));
7109
+ fs7.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
7183
7110
  grammarCount++;
7184
7111
  }
7185
7112
  const included = [`grammars/ (${grammarCount} .wasm)`];
7186
7113
  const graphSrc = resolveGraphPath(root2, global.graph);
7187
- if (fs8.existsSync(graphSrc)) {
7188
- fs8.copyFileSync(graphSrc, path38.join(outDir, "graph.json"));
7114
+ if (fs7.existsSync(graphSrc)) {
7115
+ fs7.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
7189
7116
  included.push("graph.json");
7190
7117
  } else {
7191
7118
  const graph = loadGraphFileWithSnapshot(graphSrc);
7192
7119
  if (graph) {
7193
- fs8.writeFileSync(path38.join(outDir, "graph.json"), serializeGraph(graph));
7120
+ fs7.writeFileSync(path37.join(outDir, "graph.json"), serializeGraph(graph));
7194
7121
  included.push("graph.json");
7195
7122
  }
7196
7123
  }
7197
7124
  const cat = catalogPath(root2);
7198
- if (fs8.existsSync(cat)) {
7199
- fs8.copyFileSync(cat, path38.join(outDir, "vibgrate.lib.json"));
7125
+ if (fs7.existsSync(cat)) {
7126
+ fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
7200
7127
  included.push("vibgrate.lib.json");
7201
- if (fs8.existsSync(libDir(root2))) {
7202
- fs8.cpSync(libDir(root2), path38.join(outDir, "lib"), { recursive: true });
7128
+ if (fs7.existsSync(libDir(root2))) {
7129
+ fs7.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
7203
7130
  included.push("lib/");
7204
7131
  }
7205
7132
  }
@@ -7211,15 +7138,15 @@ function registerBundle(program) {
7211
7138
  included,
7212
7139
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
7213
7140
  };
7214
- fs8.writeFileSync(path38.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7141
+ fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
7215
7142
  `);
7216
7143
  if (global.json) {
7217
- json({ out: path38.relative(root2, outDir), ...manifest });
7144
+ json({ out: path37.relative(root2, outDir), ...manifest });
7218
7145
  return;
7219
7146
  }
7220
- info(`${c.cyan("vg bundle")} \xB7 wrote ${path38.relative(root2, outDir)}/`);
7147
+ info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
7221
7148
  for (const i of included) info(` ${c.green("\u2714")} ${i}`);
7222
- info(c.dim(` offline: vg build --grammars "${path38.relative(root2, outDir)}/grammars"`));
7149
+ info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
7223
7150
  });
7224
7151
  applyGlobalOptions(cmd);
7225
7152
  }
@@ -7237,7 +7164,7 @@ async function runDoctor(global) {
7237
7164
  const root2 = rootOf(global);
7238
7165
  const local = global.local === true;
7239
7166
  const graphPath = resolveGraphPath(root2, global.graph);
7240
- const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path38.join(root2, f))) ?? null;
7167
+ const configFile = CONFIG_BASENAMES.find((f) => fs7.existsSync(path37.join(root2, f))) ?? null;
7241
7168
  const graph = loadGraph(root2, graphPath);
7242
7169
  let staleFiles = null;
7243
7170
  if (graph) {
@@ -7263,14 +7190,14 @@ async function runDoctor(global) {
7263
7190
  root: root2,
7264
7191
  configFile,
7265
7192
  map: {
7266
- path: path38.relative(root2, graphPath),
7193
+ path: path37.relative(root2, graphPath),
7267
7194
  built: graph !== null,
7268
7195
  generatedAt: graph?.generatedAt ?? null,
7269
7196
  staleFiles
7270
7197
  },
7271
7198
  libCatalog: {
7272
- path: path38.relative(root2, catalogPath(root2)),
7273
- present: fs8.existsSync(catalogPath(root2)),
7199
+ path: path37.relative(root2, catalogPath(root2)),
7200
+ present: fs7.existsSync(catalogPath(root2)),
7274
7201
  libraries: libCount
7275
7202
  },
7276
7203
  credentials: creds,
@@ -7327,7 +7254,7 @@ async function runDoctor(global) {
7327
7254
  );
7328
7255
  info(
7329
7256
  ` 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}`
7257
+ ` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
7331
7258
  ) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
7332
7259
  );
7333
7260
  if (li.dynamicOnToken || li.dynamicCustomSampler) {
@@ -7503,7 +7430,7 @@ function registerDaemon(program) {
7503
7430
  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
7431
  const global = readGlobal(this);
7505
7432
  const socketPath = socketOf(this);
7506
- const root2 = path38.resolve(rootArg ?? rootOf(global));
7433
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
7507
7434
  if (!await vgdIsRunning({ socketPath })) {
7508
7435
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7509
7436
  }
@@ -7539,7 +7466,7 @@ function registerDaemon(program) {
7539
7466
  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
7467
  const global = readGlobal(this);
7541
7468
  const socketPath = socketOf(this);
7542
- const primary = path38.resolve(rootArg ?? rootOf(global));
7469
+ const primary = path37.resolve(rootArg ?? rootOf(global));
7543
7470
  if (!await vgdIsRunning({ socketPath })) {
7544
7471
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
7545
7472
  }
@@ -7567,7 +7494,7 @@ function registerDaemon(program) {
7567
7494
  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
7495
  const global = readGlobal(this);
7569
7496
  const socketPath = socketOf(this);
7570
- const root2 = path38.resolve(rootArg ?? rootOf(global));
7497
+ const root2 = path37.resolve(rootArg ?? rootOf(global));
7571
7498
  if (!await vgdIsRunning({ socketPath })) {
7572
7499
  throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
7573
7500
  }
@@ -7581,7 +7508,7 @@ function registerDaemon(program) {
7581
7508
  throw new CliError(loaded.error, ExitCode.NOT_FOUND);
7582
7509
  }
7583
7510
  if (!loaded.ok) {
7584
- const { loadGraph: loadGraph2 } = await import('./load-4PARCNMD.js');
7511
+ const { loadGraph: loadGraph2 } = await import('./load-RFQFTTIT.js');
7585
7512
  const { detectGitRef } = await import('./git-ref-RSRAN4OH.js');
7586
7513
  const { repositoryIdFromRoot } = await import('./paths-62AKTFSR.js');
7587
7514
  const graph = loadGraph2(root2, global.graph);
@@ -7697,7 +7624,7 @@ function socketOf(cmd) {
7697
7624
  let c2 = cmd;
7698
7625
  while (c2) {
7699
7626
  const opts = c2.opts();
7700
- if (opts.socket) return path38.resolve(opts.socket);
7627
+ if (opts.socket) return path37.resolve(opts.socket);
7701
7628
  c2 = c2.parent;
7702
7629
  }
7703
7630
  return vgdSocketPath();
@@ -7769,7 +7696,7 @@ async function restartVgdIfRunning(socketPath = vgdSocketPath()) {
7769
7696
  }
7770
7697
  function readVgdPid() {
7771
7698
  try {
7772
- const raw = fs8.readFileSync(vgdPidPath(), "utf8").trim();
7699
+ const raw = fs7.readFileSync(vgdPidPath(), "utf8").trim();
7773
7700
  const pid = Number.parseInt(raw, 10);
7774
7701
  return Number.isInteger(pid) && pid > 0 ? pid : null;
7775
7702
  } catch {
@@ -7854,7 +7781,7 @@ function registerPolicy(program) {
7854
7781
  const global = readGlobal(this);
7855
7782
  let raw;
7856
7783
  try {
7857
- raw = fs8.readFileSync(file, "utf8");
7784
+ raw = fs7.readFileSync(file, "utf8");
7858
7785
  } catch {
7859
7786
  throw new CliError(`cannot read ${file}`, ExitCode.NOT_FOUND);
7860
7787
  }
@@ -7974,11 +7901,11 @@ function registerLlmHost(program) {
7974
7901
  applyGlobalOptions(cmd);
7975
7902
  }
7976
7903
  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");
7904
+ const rootDir = path37.resolve(targetPath);
7905
+ const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
7979
7906
  await ensureDir(vibgrateDir2);
7980
7907
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
7981
- const configPath = path38.join(rootDir, "vibgrate.config.ts");
7908
+ const configPath = path37.join(rootDir, "vibgrate.config.ts");
7982
7909
  if (await pathExists(configPath)) {
7983
7910
  console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
7984
7911
  } else {
@@ -7986,7 +7913,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
7986
7913
  console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
7987
7914
  }
7988
7915
  if (opts.baseline) {
7989
- const { runBaseline } = await import('./baseline-Q3QQF5QF.js');
7916
+ const { runBaseline } = await import('./baseline-536TQZIB.js');
7990
7917
  await runBaseline(rootDir);
7991
7918
  }
7992
7919
  console.log("");
@@ -8089,16 +8016,16 @@ function collectPackageImports(graph, ecosystem, pkg) {
8089
8016
  };
8090
8017
  }
8091
8018
  async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
8092
- const content = await readFile3(path38.join(rootDir, relFile));
8019
+ const content = await readFile3(path37.join(rootDir, relFile));
8093
8020
  if (!content) return false;
8094
8021
  const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8095
8022
  return new RegExp(`\\b${escaped}\\b`).test(content);
8096
8023
  }
8097
8024
  async function defaultReadFile(absPath) {
8098
8025
  try {
8099
- const stat2 = await fs22.stat(absPath);
8026
+ const stat2 = await fs21.stat(absPath);
8100
8027
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
8101
- return await fs22.readFile(absPath, "utf8");
8028
+ return await fs21.readFile(absPath, "utf8");
8102
8029
  } catch {
8103
8030
  return null;
8104
8031
  }
@@ -8284,7 +8211,7 @@ var AI_ASSISTANT_DETECTORS = [
8284
8211
  async function detectAiAssistant(rootDir) {
8285
8212
  for (const detector of AI_ASSISTANT_DETECTORS) {
8286
8213
  for (const file of detector.files) {
8287
- if (await pathExists$1(path38.join(rootDir, file))) {
8214
+ if (await pathExists$1(path37.join(rootDir, file))) {
8288
8215
  return detector.name;
8289
8216
  }
8290
8217
  }
@@ -8478,7 +8405,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8478
8405
  collectExcludes,
8479
8406
  []
8480
8407
  ).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);
8408
+ const rootDir = path37.resolve(targetPath);
8482
8409
  if (!await pathExists$1(rootDir)) {
8483
8410
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
8484
8411
  process.exit(1);
@@ -8486,7 +8413,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
8486
8413
  const hasDsn = !!resolveDsn(opts.dsn);
8487
8414
  const willPush = !opts.offline && (opts.push || hasDsn);
8488
8415
  const noLocalArtifacts = opts.localArtifacts === false;
8489
- const isFirstRun = !await pathExists$1(path38.join(rootDir, ".vibgrate", "scan_result.json"));
8416
+ const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
8490
8417
  let pinnedRegion;
8491
8418
  let planTier;
8492
8419
  let upgradeUrl;
@@ -8745,7 +8672,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
8745
8672
  function scanStaleness(rootDir, artifactPath) {
8746
8673
  let ref;
8747
8674
  try {
8748
- ref = fs8.statSync(artifactPath).mtimeMs;
8675
+ ref = fs7.statSync(artifactPath).mtimeMs;
8749
8676
  } catch {
8750
8677
  return { stale: false };
8751
8678
  }
@@ -8757,7 +8684,7 @@ function scanStaleness(rootDir, artifactPath) {
8757
8684
  if (depth > 8 || scanned > MAX_ENTRIES2) return;
8758
8685
  let entries;
8759
8686
  try {
8760
- entries = fs8.readdirSync(dir, { withFileTypes: true });
8687
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
8761
8688
  } catch {
8762
8689
  return;
8763
8690
  }
@@ -8765,20 +8692,20 @@ function scanStaleness(rootDir, artifactPath) {
8765
8692
  scanned++;
8766
8693
  if (scanned > MAX_ENTRIES2) break;
8767
8694
  if (e.isDirectory()) {
8768
- if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path38.join(dir, e.name), depth + 1);
8695
+ if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
8769
8696
  continue;
8770
8697
  }
8771
8698
  if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
8772
- const abs = path38.join(dir, e.name);
8699
+ const abs = path37.join(dir, e.name);
8773
8700
  let mtimeMs;
8774
8701
  try {
8775
- mtimeMs = fs8.statSync(abs).mtimeMs;
8702
+ mtimeMs = fs7.statSync(abs).mtimeMs;
8776
8703
  } catch {
8777
8704
  continue;
8778
8705
  }
8779
8706
  if (mtimeMs > newest) {
8780
8707
  newest = mtimeMs;
8781
- newestChanged = path38.relative(rootDir, abs) || e.name;
8708
+ newestChanged = path37.relative(rootDir, abs) || e.name;
8782
8709
  }
8783
8710
  }
8784
8711
  };
@@ -8909,7 +8836,7 @@ function analyzeTree(root2, packages) {
8909
8836
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
8910
8837
  let entries;
8911
8838
  try {
8912
- entries = fs8.readdirSync(dir, { withFileTypes: true });
8839
+ entries = fs7.readdirSync(dir, { withFileTypes: true });
8913
8840
  } catch {
8914
8841
  return;
8915
8842
  }
@@ -8918,17 +8845,17 @@ function analyzeTree(root2, packages) {
8918
8845
  if (filesSeen >= MAX_FILES) return;
8919
8846
  if (entry.isDirectory()) {
8920
8847
  if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
8921
- walk2(path38.join(dir, entry.name), depth + 1);
8848
+ walk2(path37.join(dir, entry.name), depth + 1);
8922
8849
  continue;
8923
8850
  }
8924
- const fileEco = EXT_ECOSYSTEM[path38.extname(entry.name)];
8851
+ const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
8925
8852
  if (!fileEco || fileEco === "unknown") continue;
8926
8853
  filesSeen++;
8927
- const full = path38.join(dir, entry.name);
8854
+ const full = path37.join(dir, entry.name);
8928
8855
  let content;
8929
8856
  try {
8930
- if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
8931
- content = fs8.readFileSync(full, "utf8");
8857
+ if (fs7.statSync(full).size > MAX_FILE_BYTES2) continue;
8858
+ content = fs7.readFileSync(full, "utf8");
8932
8859
  } catch {
8933
8860
  continue;
8934
8861
  }
@@ -9239,7 +9166,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9239
9166
  }
9240
9167
  const outcomes = effective.map((t) => {
9241
9168
  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)) };
9169
+ return { t, res: run(c2, path37.join(rootDir, t.dir)) };
9243
9170
  });
9244
9171
  const failures = outcomes.filter((o) => !o.res.ok);
9245
9172
  if (failures.length === 0) {
@@ -9268,8 +9195,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
9268
9195
  return results;
9269
9196
  }
9270
9197
  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");
9198
+ var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
9199
+ var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
9273
9200
  async function fetchLatestVersion() {
9274
9201
  try {
9275
9202
  const controller = new AbortController();
@@ -9296,8 +9223,8 @@ async function fetchLatestVersion() {
9296
9223
  }
9297
9224
  async function writeCache(data) {
9298
9225
  try {
9299
- await fs22.mkdir(CACHE_DIR, { recursive: true });
9300
- await fs22.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9226
+ await fs21.mkdir(CACHE_DIR, { recursive: true });
9227
+ await fs21.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
9301
9228
  } catch {
9302
9229
  }
9303
9230
  }
@@ -9308,7 +9235,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
9308
9235
  if (!execPath) return null;
9309
9236
  let resolved = execPath;
9310
9237
  try {
9311
- resolved = fs8.realpathSync(execPath);
9238
+ resolved = fs7.realpathSync(execPath);
9312
9239
  } catch {
9313
9240
  }
9314
9241
  const p = resolved.replace(/\\/g, "/");
@@ -9338,14 +9265,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
9338
9265
  pm: "yarn",
9339
9266
  root: () => {
9340
9267
  const dir = tryRun("yarn global dir");
9341
- return dir ? path38.join(dir, "node_modules") : null;
9268
+ return dir ? path37.join(dir, "node_modules") : null;
9342
9269
  }
9343
9270
  },
9344
- { pm: "bun", root: () => path38.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9271
+ { pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
9345
9272
  ];
9346
9273
  for (const probe of probes) {
9347
9274
  const root2 = probe.root();
9348
- if (root2 && await pathExists(path38.join(root2, pkg))) return probe.pm;
9275
+ if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
9349
9276
  }
9350
9277
  return null;
9351
9278
  }
@@ -9364,15 +9291,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
9364
9291
  }
9365
9292
  }
9366
9293
  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";
9294
+ if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
9295
+ if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
9296
+ if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
9370
9297
  return "npm";
9371
9298
  }
9372
9299
  async function detectWorkspaceRoot(cwd) {
9373
- if (await pathExists(path38.join(cwd, "pnpm-workspace.yaml"))) return true;
9300
+ if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
9374
9301
  try {
9375
- const pkgPath = path38.join(cwd, "package.json");
9302
+ const pkgPath = path37.join(cwd, "package.json");
9376
9303
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9377
9304
  const pkg = JSON.parse(raw);
9378
9305
  return pkg.workspaces != null;
@@ -9397,7 +9324,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
9397
9324
  }
9398
9325
  async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
9399
9326
  try {
9400
- const pkgPath = path38.join(cwd, "package.json");
9327
+ const pkgPath = path37.join(cwd, "package.json");
9401
9328
  const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
9402
9329
  const parsed = JSON.parse(raw);
9403
9330
  if (parsed.devDependencies?.[pkg]) return "dev";
@@ -9566,13 +9493,13 @@ function collectCandidates(artifact) {
9566
9493
  return out2;
9567
9494
  }
9568
9495
  var defaultFixScanner = async (rootDir) => {
9569
- const scratch = path38.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9496
+ const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
9570
9497
  const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
9571
9498
  const advanced = await loadAdvancedScanHook();
9572
9499
  return runCoreScan(rootDir, scanOpts, advanced);
9573
9500
  };
9574
9501
  async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
9575
- const artifactPath = path38.isAbsolute(inFile) ? inFile : path38.join(rootDir, inFile);
9502
+ const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
9576
9503
  if (await pathExists(artifactPath)) {
9577
9504
  const staleness = scanStaleness(rootDir, artifactPath);
9578
9505
  if (!staleness.stale) {
@@ -9599,7 +9526,7 @@ async function repositoryIdentity(rootDir, override) {
9599
9526
  }
9600
9527
  }
9601
9528
  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);
9529
+ const rootDir = path37.resolve(targetPath);
9603
9530
  if (!await pathExists(rootDir)) {
9604
9531
  console.error(chalk7.red(`Path does not exist: ${rootDir}`));
9605
9532
  process.exit(1);
@@ -9760,7 +9687,7 @@ function emit(report, format) {
9760
9687
  }
9761
9688
  }
9762
9689
  function relProjectDir(rootDir, projectPath) {
9763
- const rel = path38.isAbsolute(projectPath) ? path38.relative(rootDir, projectPath) : projectPath;
9690
+ const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
9764
9691
  return rel === "" ? "." : rel;
9765
9692
  }
9766
9693
  async function buildTargetResolver(rootDir, artifact) {
@@ -10595,7 +10522,7 @@ function formatMarkdown(artifact) {
10595
10522
 
10596
10523
  // src/reporting/commands/report.ts
10597
10524
  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);
10525
+ const artifactPath = path37.resolve(opts.in);
10599
10526
  if (!await pathExists(artifactPath)) {
10600
10527
  console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
10601
10528
  console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
@@ -10644,8 +10571,8 @@ function openUrl(url) {
10644
10571
  // src/reporting/commands/login.ts
10645
10572
  var delay = (ms) => new Promise((resolve21) => setTimeout(resolve21, ms));
10646
10573
  function isInside(dir, file) {
10647
- const rel = path38.relative(dir, file);
10648
- return !!rel && !rel.startsWith("..") && !path38.isAbsolute(rel);
10574
+ const rel = path37.relative(dir, file);
10575
+ return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
10649
10576
  }
10650
10577
  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
10578
  "--local",
@@ -10900,7 +10827,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10900
10827
  try {
10901
10828
  const statements = [];
10902
10829
  if (opts.from) {
10903
- const fromPath = path38.resolve(opts.from);
10830
+ const fromPath = path37.resolve(opts.from);
10904
10831
  if (!await pathExists(fromPath)) {
10905
10832
  process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
10906
10833
  `));
@@ -10918,9 +10845,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
10918
10845
  });
10919
10846
  const json2 = JSON.stringify(doc, null, 2);
10920
10847
  if (opts.out) {
10921
- await writeTextFile(path38.resolve(opts.out), json2 + "\n");
10848
+ await writeTextFile(path37.resolve(opts.out), json2 + "\n");
10922
10849
  process.stderr.write(
10923
- chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path38.resolve(opts.out)}
10850
+ chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
10924
10851
  `
10925
10852
  );
10926
10853
  } else {
@@ -11103,7 +11030,7 @@ function formatDeltaText(base, current) {
11103
11030
  return lines.join("\n");
11104
11031
  }
11105
11032
  async function readArtifactOrExit(filePath) {
11106
- const absolutePath = path38.resolve(filePath);
11033
+ const absolutePath = path37.resolve(filePath);
11107
11034
  if (!await pathExists(absolutePath)) {
11108
11035
  console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
11109
11036
  process.exit(1);
@@ -11120,7 +11047,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
11120
11047
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
11121
11048
  const body = JSON.stringify(sbom, null, 2);
11122
11049
  if (opts.out) {
11123
- await writeTextFile(path38.resolve(opts.out), body);
11050
+ await writeTextFile(path37.resolve(opts.out), body);
11124
11051
  console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
11125
11052
  } else {
11126
11053
  console.log(body);
@@ -11131,7 +11058,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
11131
11058
  const current = await readArtifactOrExit(opts.to);
11132
11059
  const report = formatDeltaText(base, current);
11133
11060
  if (opts.out) {
11134
- await writeTextFile(path38.resolve(opts.out), report);
11061
+ await writeTextFile(path37.resolve(opts.out), report);
11135
11062
  console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
11136
11063
  } else {
11137
11064
  console.log(report);
@@ -11262,20 +11189,20 @@ function resolveRegime(id) {
11262
11189
  return regime;
11263
11190
  }
11264
11191
  function evidenceDir(root2) {
11265
- return path38.join(root2, ".vibgrate", "evidence");
11192
+ return path37.join(root2, ".vibgrate", "evidence");
11266
11193
  }
11267
11194
  function orgPath(root2) {
11268
- return path38.join(evidenceDir(root2), "org.json");
11195
+ return path37.join(evidenceDir(root2), "org.json");
11269
11196
  }
11270
11197
  function productsPath(root2) {
11271
- return path38.join(evidenceDir(root2), "products.json");
11198
+ return path37.join(evidenceDir(root2), "products.json");
11272
11199
  }
11273
11200
  function releasesDir(root2) {
11274
- return path38.join(evidenceDir(root2), "releases");
11201
+ return path37.join(evidenceDir(root2), "releases");
11275
11202
  }
11276
11203
  function releasePath(root2, productId, version) {
11277
11204
  const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
11278
- return path38.join(releasesDir(root2), `${safe}.json`);
11205
+ return path37.join(releasesDir(root2), `${safe}.json`);
11279
11206
  }
11280
11207
  var DEFAULT_ORG = {
11281
11208
  responsiblePersons: [],
@@ -11306,7 +11233,7 @@ async function freezeRelease(root2, release) {
11306
11233
  const p = releasePath(root2, release.productId, release.version);
11307
11234
  if (await pathExists(p)) {
11308
11235
  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`,
11236
+ `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
11237
  ExitCode.USAGE_ERROR
11311
11238
  );
11312
11239
  }
@@ -11320,7 +11247,7 @@ async function loadReleases(root2, productId) {
11320
11247
  const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
11321
11248
  const releases = [];
11322
11249
  for (const f of files) {
11323
- const rel = await readJsonFile(path38.join(dir, f));
11250
+ const rel = await readJsonFile(path37.join(dir, f));
11324
11251
  if (!productId || rel.productId === productId) releases.push(rel);
11325
11252
  }
11326
11253
  return releases;
@@ -12015,19 +11942,19 @@ function verifyEvidenceEnvelope(env, opts = {}) {
12015
11942
  var DEFAULT_KEY = "attest-key.pem";
12016
11943
  function resolveSigningKey(root2, explicit) {
12017
11944
  const chosen = process.env.VG_ATTEST_KEY;
12018
- const keyPath = chosen ? path38.resolve(chosen) : path38.join(root2, ".vibgrate", DEFAULT_KEY);
11945
+ const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
12019
11946
  let minted = false;
12020
- if (!fs8.existsSync(keyPath)) {
11947
+ if (!fs7.existsSync(keyPath)) {
12021
11948
  if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
12022
11949
  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);
11950
+ fs7.mkdirSync(path37.dirname(keyPath), { recursive: true });
11951
+ fs7.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
11952
+ fs7.writeFileSync(`${keyPath}.pub`, kp.publicPem);
12026
11953
  minted = true;
12027
11954
  }
12028
11955
  let key2;
12029
11956
  try {
12030
- key2 = crypto3.createPrivateKey(fs8.readFileSync(keyPath, "utf8"));
11957
+ key2 = crypto3.createPrivateKey(fs7.readFileSync(keyPath, "utf8"));
12031
11958
  } catch {
12032
11959
  throw new CliError(`could not read an Ed25519 private key from ${keyPath}`, ExitCode.USAGE_ERROR);
12033
11960
  }
@@ -12038,16 +11965,16 @@ function resolveSigningKey(root2, explicit) {
12038
11965
  }
12039
11966
  function writeBundle(input) {
12040
11967
  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)}
11968
+ fs7.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
11969
+ const write = (rel, data) => fs7.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
12043
11970
  `);
12044
11971
  write("result.json", input.result);
12045
- write(path38.join("inputs", "advisory.json"), input.advisory);
11972
+ write(path37.join("inputs", "advisory.json"), input.advisory);
12046
11973
  for (const rel of input.releases) {
12047
11974
  const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
12048
- write(path38.join("inputs", "releases", `${safe}.json`), rel);
11975
+ write(path37.join("inputs", "releases", `${safe}.json`), rel);
12049
11976
  }
12050
- write(path38.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
11977
+ write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
12051
11978
  write("provenance.json", {
12052
11979
  method: "deterministic",
12053
11980
  modelDrafted: [],
@@ -12063,13 +11990,13 @@ function writeBundle(input) {
12063
11990
  disclaimer: input.regime.disclaimer
12064
11991
  });
12065
11992
  if (input.envelope) {
12066
- fs8.writeFileSync(path38.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
11993
+ fs7.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
12067
11994
  `);
12068
11995
  }
12069
11996
  if (input.timestampToken) {
12070
- fs8.writeFileSync(path38.join(dir, "timestamp.tsr"), input.timestampToken);
11997
+ fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
12071
11998
  }
12072
- fs8.writeFileSync(path38.join(dir, "VERIFY.md"), verifyDoc(input));
11999
+ fs7.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
12073
12000
  return dir;
12074
12001
  }
12075
12002
  function verifyDoc(input) {
@@ -12130,13 +12057,13 @@ function undeterminedFields(result, regime) {
12130
12057
  return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
12131
12058
  }
12132
12059
  async function recordDrill(root2, record) {
12133
- const dir = path38.join(evidenceDir(root2), "drills");
12134
- const p = path38.join(dir, `${record.drillId}.json`);
12060
+ const dir = path37.join(evidenceDir(root2), "drills");
12061
+ const p = path37.join(dir, `${record.drillId}.json`);
12135
12062
  await writeJsonFile(p, record);
12136
12063
  return p;
12137
12064
  }
12138
12065
  async function hasRecentDrill(root2, asOf) {
12139
- const dir = path38.join(evidenceDir(root2), "drills");
12066
+ const dir = path37.join(evidenceDir(root2), "drills");
12140
12067
  if (!await pathExists(dir)) return void 0;
12141
12068
  const { readdir } = await import('fs/promises');
12142
12069
  const { readJsonFile: readJsonFile2 } = await import('./fs-4G5A65KS.js');
@@ -12144,7 +12071,7 @@ async function hasRecentDrill(root2, asOf) {
12144
12071
  if (files.length === 0) return void 0;
12145
12072
  const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
12146
12073
  for (const f of files) {
12147
- const rec = await readJsonFile2(path38.join(dir, f));
12074
+ const rec = await readJsonFile2(path37.join(dir, f));
12148
12075
  if (rec.ranAt >= cutoff) return true;
12149
12076
  }
12150
12077
  return false;
@@ -12224,7 +12151,7 @@ function formatRegimeList() {
12224
12151
 
12225
12152
  // src/reporting/commands/evidence/index.ts
12226
12153
  function root(opts) {
12227
- return path38.resolve(opts.cwd ?? process.cwd());
12154
+ return path37.resolve(opts.cwd ?? process.cwd());
12228
12155
  }
12229
12156
  function slug(name) {
12230
12157
  return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
@@ -12312,7 +12239,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12312
12239
  const release = await buildRelease({
12313
12240
  productId: product.id,
12314
12241
  version,
12315
- from: path38.resolve(rootDir, opts.from),
12242
+ from: path37.resolve(rootDir, opts.from),
12316
12243
  shipDate: opts.shipDate,
12317
12244
  buildId: opts.buildId,
12318
12245
  artefactDigest: opts.digest,
@@ -12320,7 +12247,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
12320
12247
  frozenAt: nowIso()
12321
12248
  });
12322
12249
  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)}`);
12250
+ console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
12324
12251
  });
12325
12252
  async function runExposure(rootDir, vuln, opts) {
12326
12253
  const org = await loadOrg(rootDir);
@@ -12372,7 +12299,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12372
12299
  console.log("\n" + buildPack(result, regime, org, stage));
12373
12300
  }
12374
12301
  if (opts.bundle) {
12375
- const dir = path38.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12302
+ const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
12376
12303
  let envelope;
12377
12304
  if (opts.sign !== false) {
12378
12305
  const { key: key2, minted } = resolveSigningKey(rootDir);
@@ -12380,7 +12307,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
12380
12307
  envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
12381
12308
  }
12382
12309
  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" : ""}`);
12310
+ console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
12384
12311
  }
12385
12312
  process.exitCode = exposureExit(result.overallStatus);
12386
12313
  });
@@ -12412,7 +12339,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
12412
12339
  const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
12413
12340
  const md = buildPack(result, regime, org, stage);
12414
12341
  if (opts.out) {
12415
- fs8.writeFileSync(path38.resolve(rootDir, opts.out), md);
12342
+ fs7.writeFileSync(path37.resolve(rootDir, opts.out), md);
12416
12343
  console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
12417
12344
  } else {
12418
12345
  console.log(md);
@@ -12454,20 +12381,20 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
12454
12381
  }
12455
12382
  });
12456
12383
  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;
12384
+ const abs = path37.resolve(bundlePath);
12385
+ const envPath = fs7.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
12386
+ if (!fs7.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
12387
+ const envelope = JSON.parse(fs7.readFileSync(envPath, "utf8").trim().split("\n")[0]);
12388
+ const resultPath = path37.join(path37.dirname(envPath), "result.json");
12389
+ const result = fs7.existsSync(resultPath) ? JSON.parse(fs7.readFileSync(resultPath, "utf8")) : void 0;
12390
+ const publicKeyPem = opts.pub ? fs7.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
12464
12391
  const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
12465
12392
  const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
12466
12393
  console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
12467
12394
  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));
12395
+ const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
12396
+ if (fs7.existsSync(tsrPath) && result) {
12397
+ const t = verifyTimestamp(fs7.readFileSync(tsrPath), exposureSubjectDigest(result));
12471
12398
  const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
12472
12399
  console.log(" " + tcolor("TIMESTAMP") + ` ${t.reason}`);
12473
12400
  }
@@ -12534,12 +12461,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
12534
12461
  const releases = [];
12535
12462
  for (const list of releasesByProduct.values()) releases.push(...list);
12536
12463
  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)`);
12464
+ const dir = path37.resolve(rootDir, opts.out);
12465
+ await writeJsonFile(path37.join(dir, "org.json"), org);
12466
+ await writeJsonFile(path37.join(dir, "products.json"), products);
12467
+ for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
12468
+ await writeJsonFile(path37.join(dir, "readiness.json"), report);
12469
+ console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
12543
12470
  });
12544
12471
  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
12472
  const rootDir = root(opts);
@@ -12565,10 +12492,10 @@ var pushCmd = new Command("push").description("Push the product registry (and an
12565
12492
  }));
12566
12493
  let exposure;
12567
12494
  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"));
12495
+ const raw = path37.resolve(rootDir, opts.result);
12496
+ const resultPath = fs7.existsSync(raw) && fs7.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
12497
+ if (!fs7.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
12498
+ exposure = JSON.parse(fs7.readFileSync(resultPath, "utf8"));
12572
12499
  }
12573
12500
  const payload = { schemaVersion: "evidence-push-1", regime: regime.id, generatedAt: nowIso(), signed: Boolean(opts.signed), products: productPayload, exposure };
12574
12501
  const body = JSON.stringify(payload);
@@ -12758,7 +12685,7 @@ function dispatch(argv, cwd) {
12758
12685
  }
12759
12686
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
12760
12687
  if (looksLikeQuestion) return ["ask", ...args];
12761
- if (fs8.existsSync(path38.resolve(cwd, first))) {
12688
+ if (fs7.existsSync(path37.resolve(cwd, first))) {
12762
12689
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
12763
12690
  }
12764
12691
  const moved = MOVED_COMMANDS[first];
@@ -12803,9 +12730,9 @@ async function main(argv = process.argv) {
12803
12730
  }
12804
12731
  function readCwd(raw) {
12805
12732
  const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
12806
- if (i >= 0 && raw[i + 1]) return path38.resolve(raw[i + 1]);
12733
+ if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
12807
12734
  const eq = raw.find((a) => a.startsWith("--cwd="));
12808
- if (eq) return path38.resolve(eq.slice("--cwd=".length));
12735
+ if (eq) return path37.resolve(eq.slice("--cwd=".length));
12809
12736
  return process.cwd();
12810
12737
  }
12811
12738
  function handleError(err) {