@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.
- package/dist/{agent-Z4Z66IGM.js → agent-33BMKWJC.js} +4 -4
- package/dist/{agent-Z4Z66IGM.js.map → agent-33BMKWJC.js.map} +1 -1
- package/dist/baseline-536TQZIB.js +9 -0
- package/dist/{baseline-Q3QQF5QF.js.map → baseline-536TQZIB.js.map} +1 -1
- package/dist/{chunk-3FQSBVQD.js → chunk-A5LF4VS4.js} +8 -5
- package/dist/chunk-A5LF4VS4.js.map +1 -0
- package/dist/chunk-BZPZ3OM6.js +6 -0
- package/dist/{chunk-N3HCPBFY.js.map → chunk-BZPZ3OM6.js.map} +1 -1
- package/dist/{chunk-4BOWWYSE.js → chunk-CPX7XP3O.js} +13 -12
- package/dist/chunk-CPX7XP3O.js.map +1 -0
- package/dist/{chunk-KBPNH67Q.js → chunk-EGCB5K3P.js} +3 -3
- package/dist/{chunk-KBPNH67Q.js.map → chunk-EGCB5K3P.js.map} +1 -1
- package/dist/{chunk-G4HTI4ZM.js → chunk-FHJBGPJZ.js} +3 -2
- package/dist/chunk-FHJBGPJZ.js.map +1 -0
- package/dist/chunk-HTLDXEHW.js +60 -0
- package/dist/chunk-HTLDXEHW.js.map +1 -0
- package/dist/chunk-HWN4P64B.js +203 -0
- package/dist/chunk-HWN4P64B.js.map +1 -0
- package/dist/{chunk-GI6W53LM.js → chunk-IDAQV3NQ.js} +4 -2
- package/dist/chunk-IDAQV3NQ.js.map +1 -0
- package/dist/{chunk-42RDYQFF.js → chunk-KGWEBM2J.js} +3 -3
- package/dist/{chunk-42RDYQFF.js.map → chunk-KGWEBM2J.js.map} +1 -1
- package/dist/chunk-LCQILWQL.js +216 -0
- package/dist/chunk-LCQILWQL.js.map +1 -0
- package/dist/{chunk-EQ3IOFIG.js → chunk-NSK25UT2.js} +3 -3
- package/dist/{chunk-EQ3IOFIG.js.map → chunk-NSK25UT2.js.map} +1 -1
- package/dist/{chunk-JXMZCTVZ.js → chunk-PHVVVOW7.js} +14 -204
- package/dist/chunk-PHVVVOW7.js.map +1 -0
- package/dist/{chunk-RIEUPFXO.js → chunk-RV5DTGYT.js} +6 -62
- package/dist/chunk-RV5DTGYT.js.map +1 -0
- package/dist/{chunk-YMSXP6AO.js → chunk-UPH2RJ7L.js} +4 -4
- package/dist/{chunk-YMSXP6AO.js.map → chunk-UPH2RJ7L.js.map} +1 -1
- package/dist/{chunk-HWFVBYX4.js → chunk-WHXVU23K.js} +7 -6
- package/dist/chunk-WHXVU23K.js.map +1 -0
- package/dist/{chunk-5MNX3OLS.js → chunk-ZW5W627G.js} +7 -6
- package/dist/chunk-ZW5W627G.js.map +1 -0
- package/dist/cli.js +459 -532
- package/dist/cli.js.map +1 -1
- package/dist/{fs-6JKZNQ3U.js → fs-HNR6LAI7.js} +3 -3
- package/dist/fs-HNR6LAI7.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +10 -8
- package/dist/index.js.map +1 -1
- package/dist/{interactive-MJVMY5JP.js → interactive-MR7DTVYS.js} +16 -14
- package/dist/interactive-MR7DTVYS.js.map +1 -0
- package/dist/load-RFQFTTIT.js +10 -0
- package/dist/{load-4PARCNMD.js.map → load-RFQFTTIT.js.map} +1 -1
- package/dist/run-outcome-EKB6YQIK.js +253 -0
- package/dist/run-outcome-EKB6YQIK.js.map +1 -0
- package/dist/{runtime-session-AILFASQV.js → runtime-session-23RZLEA4.js} +7 -6
- package/dist/{runtime-session-AILFASQV.js.map → runtime-session-23RZLEA4.js.map} +1 -1
- package/dist/{stream-json-MTPWWVRR.js → stream-json-3YOPU3LF.js} +4 -4
- package/dist/{stream-json-MTPWWVRR.js.map → stream-json-3YOPU3LF.js.map} +1 -1
- package/dist/{vg-mcp-bridge-BLHEIWMT.js → vg-mcp-bridge-UZFHPP2Q.js} +8 -7
- package/dist/vg-mcp-bridge-UZFHPP2Q.js.map +1 -0
- package/dist/{vgd-S7D2SITC.js → vgd-VIPBL7W4.js} +6 -5
- package/dist/vgd-VIPBL7W4.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-Q3QQF5QF.js +0 -9
- package/dist/chunk-3FQSBVQD.js.map +0 -1
- package/dist/chunk-4BOWWYSE.js.map +0 -1
- package/dist/chunk-5MNX3OLS.js.map +0 -1
- package/dist/chunk-G4HTI4ZM.js.map +0 -1
- package/dist/chunk-GI6W53LM.js.map +0 -1
- package/dist/chunk-HWFVBYX4.js.map +0 -1
- package/dist/chunk-JXMZCTVZ.js.map +0 -1
- package/dist/chunk-N3HCPBFY.js +0 -6
- package/dist/chunk-RIEUPFXO.js.map +0 -1
- package/dist/fs-6JKZNQ3U.js.map +0 -1
- package/dist/interactive-MJVMY5JP.js.map +0 -1
- package/dist/load-4PARCNMD.js +0 -9
- package/dist/vg-mcp-bridge-BLHEIWMT.js.map +0 -1
- 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-
|
|
3
|
-
export { runBuild } from './chunk-
|
|
4
|
-
import {
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
27
|
-
import { resolveDsn,
|
|
28
|
-
import {
|
|
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-
|
|
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 {
|
|
41
|
-
import {
|
|
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-
|
|
49
|
+
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-IDAQV3NQ.js';
|
|
47
50
|
import { __toCommonJS } from './chunk-Z6ZWNWWR.js';
|
|
48
|
-
import * as
|
|
49
|
-
import
|
|
50
|
-
import * as
|
|
51
|
-
import
|
|
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
|
|
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 =
|
|
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 =
|
|
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:
|
|
96
|
-
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(
|
|
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 ${
|
|
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
|
|
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
|
|
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 =
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
937
|
+
fs7.mkdirSync(this.dir, { recursive: true });
|
|
1139
938
|
const tmp = `${this.file}.tmp`;
|
|
1140
|
-
|
|
1141
|
-
|
|
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 =
|
|
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 =
|
|
958
|
+
const file = path37.join(this.dir, name);
|
|
1160
959
|
let parsed;
|
|
1161
960
|
try {
|
|
1162
|
-
parsed = JSON.parse(
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
1293
|
+
const fd = fs7.openSync(this.file, "r");
|
|
1495
1294
|
try {
|
|
1496
1295
|
chunk = Buffer.alloc(size - this.offset);
|
|
1497
|
-
|
|
1296
|
+
fs7.readSync(fd, chunk, 0, chunk.length, this.offset);
|
|
1498
1297
|
} finally {
|
|
1499
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
1920
|
-
files.push({ rel, hash: hashBytes(
|
|
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 =
|
|
1931
|
-
if (rel === "" || rel.startsWith("..") ||
|
|
1932
|
-
const parts = rel.split(
|
|
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(
|
|
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
|
-
|
|
1950
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
2005
|
-
|
|
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
|
-
|
|
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 =
|
|
2651
|
+
const absManifest = path37.resolve(this.opts.root, relManifest);
|
|
2837
2652
|
let text = null;
|
|
2838
2653
|
try {
|
|
2839
|
-
if (
|
|
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 =
|
|
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 =
|
|
2890
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
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
|
|
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(
|
|
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 ?? [])
|
|
2834
|
+
for (const d of p.dependencies ?? []) {
|
|
2835
|
+
if (!byPkg.has(d.package)) byPkg.set(d.package, { row: d, ecosystem });
|
|
2836
|
+
}
|
|
2946
2837
|
}
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
|
|
2954
|
-
|
|
2955
|
-
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
|
|
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
|
|
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
|
|
2872
|
+
return join27("package.json");
|
|
2976
2873
|
case "python":
|
|
2977
|
-
return
|
|
2874
|
+
return join27("pyproject.toml");
|
|
2978
2875
|
case "go":
|
|
2979
|
-
return
|
|
2876
|
+
return join27("go.mod");
|
|
2980
2877
|
case "rust":
|
|
2981
|
-
return
|
|
2878
|
+
return join27("Cargo.toml");
|
|
2982
2879
|
case "ruby":
|
|
2983
|
-
return
|
|
2880
|
+
return join27("Gemfile");
|
|
2984
2881
|
case "php":
|
|
2985
|
-
return
|
|
2882
|
+
return join27("composer.json");
|
|
2986
2883
|
case "java":
|
|
2987
2884
|
case "kotlin":
|
|
2988
2885
|
case "scala":
|
|
2989
2886
|
case "groovy":
|
|
2990
|
-
return
|
|
2887
|
+
return join27("pom.xml");
|
|
2991
2888
|
case "dotnet":
|
|
2992
|
-
return
|
|
2889
|
+
return join27(proj.name ? `${proj.name}.csproj` : "Directory.Build.props");
|
|
2993
2890
|
case "dart":
|
|
2994
|
-
return
|
|
2891
|
+
return join27("pubspec.yaml");
|
|
2995
2892
|
case "elixir":
|
|
2996
|
-
return
|
|
2893
|
+
return join27("mix.exs");
|
|
2997
2894
|
default:
|
|
2998
|
-
return
|
|
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 (!
|
|
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 =
|
|
3296
|
-
if (!
|
|
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 =
|
|
3318
|
-
|
|
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
|
-
|
|
3218
|
+
fs7.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
3322
3219
|
`);
|
|
3323
3220
|
}
|
|
3324
3221
|
function writeGitAttributes(root2) {
|
|
3325
|
-
const file =
|
|
3222
|
+
const file = path37.join(root2, ".gitattributes");
|
|
3326
3223
|
const line = ".vibgrate/graph.json merge=vg";
|
|
3327
|
-
let content =
|
|
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
|
-
|
|
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
|
-
|
|
3343
|
-
const file =
|
|
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 =
|
|
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
|
-
|
|
3362
|
-
|
|
3258
|
+
fs7.writeFileSync(file, content);
|
|
3259
|
+
fs7.chmodSync(file, 493);
|
|
3363
3260
|
}
|
|
3364
3261
|
function undo(root2) {
|
|
3365
|
-
const hookFile =
|
|
3366
|
-
if (
|
|
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 =
|
|
3369
|
-
if (next2.trim() === "#!/bin/sh")
|
|
3370
|
-
else
|
|
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 =
|
|
3373
|
-
if (
|
|
3374
|
-
const next2 =
|
|
3375
|
-
|
|
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
|
|
3282
|
+
if (configured) return path37.resolve(root2, configured);
|
|
3386
3283
|
} catch {
|
|
3387
3284
|
}
|
|
3388
|
-
return
|
|
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) =>
|
|
3313
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
|
|
3417
3314
|
for (const w of watchRoots) {
|
|
3418
|
-
if (!
|
|
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 =
|
|
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(
|
|
3373
|
+
const parts = filename.split(path37.sep);
|
|
3477
3374
|
if (parts.some((p) => SKIP_NAME.has(p))) return;
|
|
3478
|
-
if (filename.includes(`${
|
|
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) =>
|
|
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 =
|
|
3718
|
+
const p = path37__default.join(root2, rel);
|
|
3822
3719
|
let text;
|
|
3823
3720
|
try {
|
|
3824
|
-
text =
|
|
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
|
|
4543
|
-
const session = await acquireHostSession(lib,
|
|
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 || !
|
|
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
|
-
|
|
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 =
|
|
5908
|
-
|
|
5909
|
-
|
|
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 =
|
|
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) ||
|
|
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) =>
|
|
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
|
|
6000
|
+
return path37.join(root2, ".vibgrate", "code.json");
|
|
6104
6001
|
}
|
|
6105
6002
|
function loadCodeConfig(root2) {
|
|
6106
6003
|
try {
|
|
6107
|
-
const raw = JSON.parse(
|
|
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(
|
|
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(
|
|
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-
|
|
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-
|
|
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 =
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
|
6368
|
+
const os4 = await import('os');
|
|
6459
6369
|
const pathMod = await import('path');
|
|
6460
6370
|
const checkpointIndex = pathMod.join(
|
|
6461
|
-
|
|
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-
|
|
6525
|
-
const { runAgent: runAgent2 } = await import('./agent-
|
|
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:
|
|
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")
|
|
6574
|
-
|
|
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")
|
|
6585
|
-
|
|
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 }) =>
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
|
|
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:
|
|
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")
|
|
6632
|
-
|
|
6633
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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(
|
|
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 =
|
|
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 ?
|
|
7023
|
-
const dts = opts.dts ? readOptionalFile(
|
|
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
|
-
|
|
7156
|
-
|
|
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(
|
|
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 =
|
|
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
|
-
|
|
7106
|
+
fs7.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
|
|
7180
7107
|
let grammarCount = 0;
|
|
7181
7108
|
for (const { fileName, absPath } of grammarFiles) {
|
|
7182
|
-
|
|
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 (
|
|
7188
|
-
|
|
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
|
-
|
|
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 (
|
|
7199
|
-
|
|
7125
|
+
if (fs7.existsSync(cat)) {
|
|
7126
|
+
fs7.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
|
|
7200
7127
|
included.push("vibgrate.lib.json");
|
|
7201
|
-
if (
|
|
7202
|
-
|
|
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
|
-
|
|
7141
|
+
fs7.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
7215
7142
|
`);
|
|
7216
7143
|
if (global.json) {
|
|
7217
|
-
json({ out:
|
|
7144
|
+
json({ out: path37.relative(root2, outDir), ...manifest });
|
|
7218
7145
|
return;
|
|
7219
7146
|
}
|
|
7220
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
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 "${
|
|
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) =>
|
|
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:
|
|
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:
|
|
7273
|
-
present:
|
|
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 ${
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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-
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
7978
|
-
const vibgrateDir2 =
|
|
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 =
|
|
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-
|
|
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(
|
|
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
|
|
8026
|
+
const stat2 = await fs21.stat(absPath);
|
|
8100
8027
|
if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
|
|
8101
|
-
return await
|
|
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(
|
|
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 =
|
|
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(
|
|
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 =
|
|
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 =
|
|
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(
|
|
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 =
|
|
8699
|
+
const abs = path37.join(dir, e.name);
|
|
8773
8700
|
let mtimeMs;
|
|
8774
8701
|
try {
|
|
8775
|
-
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 =
|
|
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 =
|
|
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(
|
|
8848
|
+
walk2(path37.join(dir, entry.name), depth + 1);
|
|
8922
8849
|
continue;
|
|
8923
8850
|
}
|
|
8924
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
8851
|
+
const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
|
|
8925
8852
|
if (!fileEco || fileEco === "unknown") continue;
|
|
8926
8853
|
filesSeen++;
|
|
8927
|
-
const full =
|
|
8854
|
+
const full = path37.join(dir, entry.name);
|
|
8928
8855
|
let content;
|
|
8929
8856
|
try {
|
|
8930
|
-
if (
|
|
8931
|
-
content =
|
|
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,
|
|
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 =
|
|
9272
|
-
var CACHE_FILE =
|
|
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
|
|
9300
|
-
await
|
|
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 =
|
|
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 ?
|
|
9268
|
+
return dir ? path37.join(dir, "node_modules") : null;
|
|
9342
9269
|
}
|
|
9343
9270
|
},
|
|
9344
|
-
{ pm: "bun", root: () =>
|
|
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(
|
|
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(
|
|
9368
|
-
if (await pathExists(
|
|
9369
|
-
if (await pathExists(
|
|
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(
|
|
9300
|
+
if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
9374
9301
|
try {
|
|
9375
|
-
const pkgPath =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
10648
|
-
return !!rel && !rel.startsWith("..") && !
|
|
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 =
|
|
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(
|
|
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 ${
|
|
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 =
|
|
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(
|
|
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(
|
|
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
|
|
11192
|
+
return path37.join(root2, ".vibgrate", "evidence");
|
|
11266
11193
|
}
|
|
11267
11194
|
function orgPath(root2) {
|
|
11268
|
-
return
|
|
11195
|
+
return path37.join(evidenceDir(root2), "org.json");
|
|
11269
11196
|
}
|
|
11270
11197
|
function productsPath(root2) {
|
|
11271
|
-
return
|
|
11198
|
+
return path37.join(evidenceDir(root2), "products.json");
|
|
11272
11199
|
}
|
|
11273
11200
|
function releasesDir(root2) {
|
|
11274
|
-
return
|
|
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
|
|
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 ${
|
|
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(
|
|
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 ?
|
|
11945
|
+
const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
12019
11946
|
let minted = false;
|
|
12020
|
-
if (!
|
|
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
|
-
|
|
12024
|
-
|
|
12025
|
-
|
|
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(
|
|
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
|
-
|
|
12042
|
-
const write = (rel, data) =>
|
|
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(
|
|
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(
|
|
11975
|
+
write(path37.join("inputs", "releases", `${safe}.json`), rel);
|
|
12049
11976
|
}
|
|
12050
|
-
write(
|
|
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
|
-
|
|
11993
|
+
fs7.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
12067
11994
|
`);
|
|
12068
11995
|
}
|
|
12069
11996
|
if (input.timestampToken) {
|
|
12070
|
-
|
|
11997
|
+
fs7.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
12071
11998
|
}
|
|
12072
|
-
|
|
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 =
|
|
12134
|
-
const p =
|
|
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 =
|
|
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(
|
|
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
|
|
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:
|
|
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 ${
|
|
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 =
|
|
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 ${
|
|
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
|
-
|
|
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 =
|
|
12458
|
-
const envPath =
|
|
12459
|
-
if (!
|
|
12460
|
-
const envelope = JSON.parse(
|
|
12461
|
-
const resultPath =
|
|
12462
|
-
const result =
|
|
12463
|
-
const publicKeyPem = opts.pub ?
|
|
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 =
|
|
12469
|
-
if (
|
|
12470
|
-
const t = verifyTimestamp(
|
|
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 =
|
|
12538
|
-
await writeJsonFile(
|
|
12539
|
-
await writeJsonFile(
|
|
12540
|
-
for (const r of releases) await writeJsonFile(
|
|
12541
|
-
await writeJsonFile(
|
|
12542
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
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 =
|
|
12569
|
-
const resultPath =
|
|
12570
|
-
if (!
|
|
12571
|
-
exposure = JSON.parse(
|
|
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 (
|
|
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
|
|
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
|
|
12735
|
+
if (eq) return path37.resolve(eq.slice("--cwd=".length));
|
|
12809
12736
|
return process.cwd();
|
|
12810
12737
|
}
|
|
12811
12738
|
function handleError(err) {
|