@vibgrate/cli 2026.727.1 → 2026.727.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +21 -18
- package/README.md +2 -2
- package/dist/baseline-ATM5MXBZ.js +8 -0
- package/dist/{baseline-K7YBFKZI.js.map → baseline-ATM5MXBZ.js.map} +1 -1
- package/dist/{chunk-OXQNQW5J.js → chunk-2VFWXNS5.js} +4 -4
- package/dist/{chunk-OXQNQW5J.js.map → chunk-2VFWXNS5.js.map} +1 -1
- package/dist/{chunk-VXGV6NTD.js → chunk-3V24O47U.js} +11 -9
- package/dist/chunk-3V24O47U.js.map +1 -0
- package/dist/{chunk-C4CKTAZP.js → chunk-6JIKUDWM.js} +4 -4
- package/dist/chunk-6JIKUDWM.js.map +1 -0
- package/dist/{chunk-6IOQJGFT.js → chunk-6UK6QPTR.js} +96 -140
- package/dist/chunk-6UK6QPTR.js.map +1 -0
- package/dist/chunk-6UQMXIAG.js +122 -0
- package/dist/chunk-6UQMXIAG.js.map +1 -0
- package/dist/{chunk-SZLF66FJ.js → chunk-77LYGXBI.js} +5 -5
- package/dist/{chunk-SZLF66FJ.js.map → chunk-77LYGXBI.js.map} +1 -1
- package/dist/{chunk-KHJO4D5N.js → chunk-7N4Y3E47.js} +2 -2
- package/dist/{chunk-KHJO4D5N.js.map → chunk-7N4Y3E47.js.map} +1 -1
- package/dist/{chunk-65MEOA4E.js → chunk-AVQSHIJ5.js} +22 -18
- package/dist/chunk-AVQSHIJ5.js.map +1 -0
- package/dist/chunk-B3YUO3NW.js +469 -0
- package/dist/chunk-B3YUO3NW.js.map +1 -0
- package/dist/{chunk-YDAT7LD2.js → chunk-C66GOHYB.js} +18 -10
- package/dist/chunk-C66GOHYB.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +10 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/{chunk-HYZVHJ3Q.js → chunk-FFWGT55D.js} +4 -4
- package/dist/{chunk-HYZVHJ3Q.js.map → chunk-FFWGT55D.js.map} +1 -1
- package/dist/{chunk-4CQ3MGNN.js → chunk-HK3AWUXH.js} +3 -3
- package/dist/{chunk-4CQ3MGNN.js.map → chunk-HK3AWUXH.js.map} +1 -1
- package/dist/{chunk-S6CYDZEW.js → chunk-MAY5HLDH.js} +772 -200
- package/dist/chunk-MAY5HLDH.js.map +1 -0
- package/dist/{chunk-7JHPQ6WF.js → chunk-OFUC6RYN.js} +3 -3
- package/dist/{chunk-7JHPQ6WF.js.map → chunk-OFUC6RYN.js.map} +1 -1
- package/dist/{chunk-3Q7QBWFW.js → chunk-ON25BX6T.js} +9 -3
- package/dist/chunk-ON25BX6T.js.map +1 -0
- package/dist/{chunk-JZYGEZTU.js → chunk-XPJZTSY7.js} +3 -3
- package/dist/{chunk-JZYGEZTU.js.map → chunk-XPJZTSY7.js.map} +1 -1
- package/dist/{chunk-WLETRGAC.js → chunk-Y23HMSWU.js} +11 -11
- package/dist/{chunk-WLETRGAC.js.map → chunk-Y23HMSWU.js.map} +1 -1
- package/dist/{chunk-3BVSDMHV.js → chunk-Z7GP7XTJ.js} +8 -8
- package/dist/{chunk-3BVSDMHV.js.map → chunk-Z7GP7XTJ.js.map} +1 -1
- package/dist/{chunk-EDAAG7BL.js → chunk-ZBTY6VV4.js} +4 -3
- package/dist/chunk-ZBTY6VV4.js.map +1 -0
- package/dist/chunk-ZKNB4YH4.js +102 -0
- package/dist/chunk-ZKNB4YH4.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +475 -404
- package/dist/cli.js.map +1 -1
- package/dist/{execution-env-3BN7Z737.js → execution-env-ZU45JZ4G.js} +3 -2
- package/dist/{execution-env-3BN7Z737.js.map → execution-env-ZU45JZ4G.js.map} +1 -1
- package/dist/{federation-EPZDUWCK.js → federation-SZWZIFZ7.js} +3 -2
- package/dist/{federation-EPZDUWCK.js.map → federation-SZWZIFZ7.js.map} +1 -1
- package/dist/{fs-IPY4FJKH.js → fs-B5HZ2MIU.js} +3 -2
- package/dist/fs-B5HZ2MIU.js.map +1 -0
- package/dist/{fs-KCABDURV.js → fs-O5IQYXHO.js} +3 -2
- package/dist/fs-O5IQYXHO.js.map +1 -0
- package/dist/{git-ref-HPRLUFFW.js → git-ref-XDXB6JP5.js} +3 -2
- package/dist/{git-ref-HPRLUFFW.js.map → git-ref-XDXB6JP5.js.map} +1 -1
- package/dist/graph-backend-UTOL3SHE.js +11 -0
- package/dist/{graph-backend-ZMSYOZMW.js.map → graph-backend-UTOL3SHE.js.map} +1 -1
- package/dist/index.d.ts +53 -17
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/{interactive-ICL7D7LO.js → interactive-INGJNSON.js} +23 -22
- package/dist/interactive-INGJNSON.js.map +1 -0
- package/dist/{llm-host-2RAYQSDQ.js → llm-host-7GWDO6IX.js} +3 -2
- package/dist/{llm-host-2RAYQSDQ.js.map → llm-host-7GWDO6IX.js.map} +1 -1
- package/dist/load-QPOWQD7C.js +8 -0
- package/dist/{load-OHVKDX4R.js.map → load-QPOWQD7C.js.map} +1 -1
- package/dist/local-runtime-5O2NN3GA.js +5 -0
- package/dist/{local-runtime-OJFLX2HI.js.map → local-runtime-5O2NN3GA.js.map} +1 -1
- package/dist/mcp-tools-I7JK3S2M.js +4 -0
- package/dist/{mcp-tools-I6PME3AV.js.map → mcp-tools-I7JK3S2M.js.map} +1 -1
- package/dist/{model-execution-profile-MQ2QCP24.js → model-execution-profile-TFBKCNJG.js} +3 -2
- package/dist/{model-execution-profile-MQ2QCP24.js.map → model-execution-profile-TFBKCNJG.js.map} +1 -1
- package/dist/{model-orchestrator-FFTZI3U2.js → model-orchestrator-TVONAUPS.js} +5 -4
- package/dist/{model-orchestrator-FFTZI3U2.js.map → model-orchestrator-TVONAUPS.js.map} +1 -1
- package/dist/parse-worker.d.ts +1 -1
- package/dist/parse-worker.js +2 -1
- package/dist/parse-worker.js.map +1 -1
- package/dist/{paths-MCH75O3G.js → paths-2RAH3GME.js} +3 -2
- package/dist/{paths-MCH75O3G.js.map → paths-2RAH3GME.js.map} +1 -1
- package/dist/{resolve-gguf-4UPIGPEE.js → resolve-gguf-VPL4YQ6J.js} +3 -2
- package/dist/{resolve-gguf-4UPIGPEE.js.map → resolve-gguf-VPL4YQ6J.js.map} +1 -1
- package/dist/runtime-session-4AMZIAAG.js +18 -0
- package/dist/{runtime-session-IDU5BDUJ.js.map → runtime-session-4AMZIAAG.js.map} +1 -1
- package/dist/session-M72522AP.js +11 -0
- package/dist/{session-L2OSDRPI.js.map → session-M72522AP.js.map} +1 -1
- package/dist/session-store-WFBX7HXL.js +4 -0
- package/dist/{session-store-W5RZZHA3.js.map → session-store-WFBX7HXL.js.map} +1 -1
- package/dist/sql-extract-JELDZA6W.js +81 -0
- package/dist/sql-extract-JELDZA6W.js.map +1 -0
- package/dist/{stream-json-F74W5FCK.js → stream-json-6ZBUA2L3.js} +11 -10
- package/dist/stream-json-6ZBUA2L3.js.map +1 -0
- package/dist/{types-ZMg1mSuu.d.ts → types-DLH-Ritr.d.ts} +22 -1
- package/dist/ui-Q6DJ3GCU.js +5 -0
- package/dist/ui-Q6DJ3GCU.js.map +1 -0
- package/dist/{vgd-EGBQD7BW.js → vgd-CVLKBS7K.js} +7 -6
- package/dist/vgd-CVLKBS7K.js.map +1 -0
- package/package.json +1 -1
- package/dist/baseline-K7YBFKZI.js +0 -7
- package/dist/chunk-3Q7QBWFW.js.map +0 -1
- package/dist/chunk-5Q54GEHM.js +0 -29
- package/dist/chunk-5Q54GEHM.js.map +0 -1
- package/dist/chunk-65MEOA4E.js.map +0 -1
- package/dist/chunk-6IOQJGFT.js.map +0 -1
- package/dist/chunk-C4CKTAZP.js.map +0 -1
- package/dist/chunk-EDAAG7BL.js.map +0 -1
- package/dist/chunk-EDBV33B7.js +0 -57
- package/dist/chunk-EDBV33B7.js.map +0 -1
- package/dist/chunk-HABUT7HW.js +0 -233
- package/dist/chunk-HABUT7HW.js.map +0 -1
- package/dist/chunk-S6CYDZEW.js.map +0 -1
- package/dist/chunk-VXGV6NTD.js.map +0 -1
- package/dist/chunk-YDAT7LD2.js.map +0 -1
- package/dist/fs-IPY4FJKH.js.map +0 -1
- package/dist/fs-KCABDURV.js.map +0 -1
- package/dist/graph-backend-ZMSYOZMW.js +0 -10
- package/dist/interactive-ICL7D7LO.js.map +0 -1
- package/dist/load-OHVKDX4R.js +0 -7
- package/dist/local-runtime-OJFLX2HI.js +0 -4
- package/dist/mcp-tools-I6PME3AV.js +0 -3
- package/dist/runtime-session-IDU5BDUJ.js +0 -17
- package/dist/session-L2OSDRPI.js +0 -10
- package/dist/session-store-W5RZZHA3.js +0 -3
- package/dist/stream-json-F74W5FCK.js.map +0 -1
- package/dist/ui-HOVOPWMX.js +0 -4
- package/dist/ui-HOVOPWMX.js.map +0 -1
- package/dist/vgd-EGBQD7BW.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,45 +1,46 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { loadAdvancedScanHook, baselineCommand } from './chunk-
|
|
3
|
-
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-
|
|
4
|
-
export { runBuild } from './chunk-
|
|
5
|
-
import {
|
|
2
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-FFWGT55D.js';
|
|
3
|
+
import { sha256Hex, generateKeypair, dssePae, DSSE_PAYLOAD_TYPE, keyId, registerBuild, readGlobal, applyGlobalOptions, ProgressBar, printLogo, fetchCatalog, resolveProviders, runBuild } from './chunk-C66GOHYB.js';
|
|
4
|
+
export { runBuild } from './chunk-C66GOHYB.js';
|
|
5
|
+
import { CONTEXT_POLICY_VERSION, computeFcsReport, renderFcsReportMarkdown, createTrajectoryCollector, runAgent } from './chunk-Z7GP7XTJ.js';
|
|
6
|
+
import { disableColor, info, c, json, out } from './chunk-CT5BS56U.js';
|
|
7
|
+
import { VGD_PROTOCOL_VERSION, startVgdServer } from './chunk-77LYGXBI.js';
|
|
6
8
|
import './chunk-5I4VSBWQ.js';
|
|
7
9
|
import './chunk-IS7VTH2Q.js';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import { fmt, estimateModelBytes } from './chunk-KHJO4D5N.js';
|
|
10
|
+
import { gatherSystemMemory } from './chunk-6UQMXIAG.js';
|
|
11
|
+
import { readOrchestratorState, writeOrchestratorState, parseMode, setDefaultMode, recommendMode, activePin, resolveMode, providerForBackend, QUALIFIED_PACKS, pinPack, unpinPack, buildOrchestratorStatus } from './chunk-3V24O47U.js';
|
|
12
|
+
import { fmt, estimateModelBytes } from './chunk-7N4Y3E47.js';
|
|
12
13
|
import './chunk-IZDH67DX.js';
|
|
13
|
-
import './chunk-
|
|
14
|
+
import './chunk-HK3AWUXH.js';
|
|
14
15
|
import { vgdIsRunning, vgdRequest, vgdSocketPath } from './chunk-PMYWZRRS.js';
|
|
15
16
|
import { defaultProcessEndpoint, startProcessHostServer, resolveInferenceIsolation } from './chunk-PXHNTC6D.js';
|
|
16
17
|
import { clearHostSessionPool, acquireHostSession, generateOnSession, listHostSessions, hostSessionPoolSize } from './chunk-K7REHDQS.js';
|
|
17
18
|
import { buildIdentifierTrieFromGraph } from './chunk-JIBOJTGS.js';
|
|
18
19
|
import './chunk-NDMDSPFX.js';
|
|
19
|
-
import { runCodeSession } from './chunk-
|
|
20
|
-
import { ensurePackage, ensureUnavailableMessage, isPackageInstalled, summarizeDiffs, ScriptedProvider } from './chunk-
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-
|
|
25
|
-
import {
|
|
20
|
+
import { runCodeSession } from './chunk-2VFWXNS5.js';
|
|
21
|
+
import { ensurePackage, ensureUnavailableMessage, isPackageInstalled, summarizeDiffs, ScriptedProvider } from './chunk-OFUC6RYN.js';
|
|
22
|
+
import { serveStdio, exportGraph, GraphSource, createServer, formatForExt } from './chunk-AVQSHIJ5.js';
|
|
23
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, CliError, ExitCode, parseDsn as parseDsn$1, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, NPX_INVOCATION, refreshIfStale, driftCount, countTokens, shortestPath, pathDisconnect, testsToRun, detectRunner, ASSISTANTS, detectAssistants, usageError, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, buildGraph, writeSnapshot, probeFreshness, discover, assistantById, SMALL_REPO_FILES, publishPrivateLibrary, assessDocQuality, symbolsFromApi, fetchHostedDocsCached, selectForBudget, hostedBase, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-MAY5HLDH.js';
|
|
24
|
+
import { inventory, enrichOnline, ECOSYSTEMS, catalogPath, libDir, loadCatalog, driftFor, addLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface } from './chunk-6JIKUDWM.js';
|
|
25
|
+
import { writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols } from './chunk-Y23HMSWU.js';
|
|
26
|
+
import { ensureDir, pathExists, readJsonFile, writeTextFile, writeJsonFile } from './chunk-CRAMOEBE.js';
|
|
26
27
|
import { resolveOne } from './chunk-J7LKEB2R.js';
|
|
27
28
|
import { discoverModels, listCachedWeights, isWeightCached, lookupCatalog, ensureWeightCached, catalogIntegrityReport, weightStoreDir } from './chunk-OOIG3RUM.js';
|
|
28
|
-
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-
|
|
29
|
-
import {
|
|
30
|
-
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-
|
|
29
|
+
import { recordCliCall, CLI_TOOL_ALIASES, savingsLedgerPath, clearSavings, readSavings, readUsage, readModelSavings, CAPSULE_RANKING_VERSION, SAVINGS_TOOLS, sanitizeClient } from './chunk-ZBTY6VV4.js';
|
|
30
|
+
import { embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, indexFor, impactOf, modelCacheInfo, clearModelCache } from './chunk-6UK6QPTR.js';
|
|
31
|
+
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-ON25BX6T.js';
|
|
31
32
|
import './chunk-RXP66R2E.js';
|
|
32
|
-
import { resolveGraphPath, renderReport, loadGraph, writeArtifacts, vibgrateDir } from './chunk-
|
|
33
|
-
import {
|
|
33
|
+
import { resolveGraphPath, renderReport, loadGraph, writeArtifacts, vibgrateDir, SCHEMA_VERSION } from './chunk-B3YUO3NW.js';
|
|
34
|
+
import { cacheDir, stableStringify } from './chunk-ZKNB4YH4.js';
|
|
34
35
|
import './chunk-BWPBB45M.js';
|
|
35
36
|
import { canonicalize, hashString, hashBytes } from './chunk-JFGYT6BI.js';
|
|
36
37
|
import './chunk-BPF3YX2U.js';
|
|
37
38
|
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
38
|
-
import
|
|
39
|
+
import './chunk-DGUM43GV.js';
|
|
39
40
|
import * as fs8 from 'fs';
|
|
40
41
|
import fs8__default, { realpathSync } from 'fs';
|
|
41
|
-
import * as
|
|
42
|
-
import
|
|
42
|
+
import * as path37 from 'path';
|
|
43
|
+
import path37__default from 'path';
|
|
43
44
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
44
45
|
import { Command, CommanderError, Option } from 'commander';
|
|
45
46
|
import * as os from 'os';
|
|
@@ -58,10 +59,10 @@ function registerStatus(program) {
|
|
|
58
59
|
applyGlobalOptions(cmd);
|
|
59
60
|
}
|
|
60
61
|
async function runStatus(global) {
|
|
61
|
-
const root2 =
|
|
62
|
+
const root2 = path37.resolve(global.cwd ?? ".");
|
|
62
63
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
63
64
|
const graph = loadGraph(root2, graphPath);
|
|
64
|
-
const hasCache = fs8.existsSync(
|
|
65
|
+
const hasCache = fs8.existsSync(path37.join(cacheDir(root2), "parse-cache.json"));
|
|
65
66
|
let stale = null;
|
|
66
67
|
let staleExact = false;
|
|
67
68
|
if (graph) {
|
|
@@ -81,8 +82,8 @@ async function runStatus(global) {
|
|
|
81
82
|
}
|
|
82
83
|
if (global.json) {
|
|
83
84
|
json({
|
|
84
|
-
root:
|
|
85
|
-
graphPath:
|
|
85
|
+
root: path37.relative(process.cwd(), root2) || ".",
|
|
86
|
+
graphPath: path37.relative(root2, graphPath),
|
|
86
87
|
built: graph !== null,
|
|
87
88
|
generatedAt: graph?.generatedAt ?? null,
|
|
88
89
|
counts: graph?.meta.counts ?? null,
|
|
@@ -97,11 +98,11 @@ async function runStatus(global) {
|
|
|
97
98
|
return;
|
|
98
99
|
}
|
|
99
100
|
if (!graph) {
|
|
100
|
-
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(
|
|
101
|
+
info(`${c.cyan("vg")} \xB7 no map yet at ${c.dim(path37.relative(root2, graphPath))}`);
|
|
101
102
|
info(` run ${c.bold("vg")} to build one`);
|
|
102
103
|
return;
|
|
103
104
|
}
|
|
104
|
-
info(`${c.cyan("vg")} \xB7 ${
|
|
105
|
+
info(`${c.cyan("vg")} \xB7 ${path37.relative(root2, graphPath)}`);
|
|
105
106
|
info(` generated ${graph.generatedAt}`);
|
|
106
107
|
info(
|
|
107
108
|
` nodes ${c.bold(String(graph.meta.counts.nodes))} edges ${c.bold(
|
|
@@ -118,7 +119,7 @@ async function runStatus(global) {
|
|
|
118
119
|
if (vibgrateDir(root2)) ;
|
|
119
120
|
}
|
|
120
121
|
function rootOf(global) {
|
|
121
|
-
return
|
|
122
|
+
return path37.resolve(global.cwd ?? ".");
|
|
122
123
|
}
|
|
123
124
|
function requireGraph(global) {
|
|
124
125
|
const root2 = rootOf(global);
|
|
@@ -401,6 +402,19 @@ function registerPath(program) {
|
|
|
401
402
|
);
|
|
402
403
|
}
|
|
403
404
|
if (!result) {
|
|
405
|
+
const disc = pathDisconnect(graph, ra.node.id, rb.node.id);
|
|
406
|
+
if (global.json) {
|
|
407
|
+
json(disc);
|
|
408
|
+
throw new CliError(
|
|
409
|
+
`no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
|
|
410
|
+
ExitCode.NOT_FOUND
|
|
411
|
+
);
|
|
412
|
+
}
|
|
413
|
+
info(`${c.cyan("vg path")} \xB7 no path between ${c.bold(disc.from.name)} and ${c.bold(disc.to.name)}`);
|
|
414
|
+
printNeighborhood("from", disc.from);
|
|
415
|
+
printNeighborhood("to", disc.to);
|
|
416
|
+
info(c.dim(` ${disc.hint}`));
|
|
417
|
+
info(c.dim(` try: vg show ${disc.from.name} \xB7 vg impact ${disc.from.name} \xB7 vg show ${disc.to.name}`));
|
|
404
418
|
throw new CliError(
|
|
405
419
|
`no path between ${ra.node.qualifiedName} and ${rb.node.qualifiedName}`,
|
|
406
420
|
ExitCode.NOT_FOUND
|
|
@@ -417,6 +431,14 @@ function registerPath(program) {
|
|
|
417
431
|
});
|
|
418
432
|
applyGlobalOptions(cmd);
|
|
419
433
|
}
|
|
434
|
+
function printNeighborhood(label, n) {
|
|
435
|
+
const parts = [];
|
|
436
|
+
if (n.calls.length) parts.push(`calls ${n.calls.join(", ")}`);
|
|
437
|
+
if (n.calledBy.length) parts.push(`called by ${n.calledBy.join(", ")}`);
|
|
438
|
+
if (n.imports.length) parts.push(`imports ${n.imports.join(", ")}`);
|
|
439
|
+
if (n.importedBy.length) parts.push(`imported by ${n.importedBy.join(", ")}`);
|
|
440
|
+
info(` ${c.dim(label)} ${c.bold(n.name)}${parts.length ? c.dim(` \xB7 ${parts.join(" \xB7 ")}`) : c.dim(" \xB7 (no call/import neighbors)")}`);
|
|
441
|
+
}
|
|
420
442
|
|
|
421
443
|
// src/commands/tree.ts
|
|
422
444
|
function registerTree(program) {
|
|
@@ -530,12 +552,12 @@ function registerInsights(program) {
|
|
|
530
552
|
}
|
|
531
553
|
});
|
|
532
554
|
applyGlobalOptions(areas);
|
|
533
|
-
const oddities = program.command("oddities").description("surprising cross-area links (architectural smells)").option("-n, --limit <n>", "how many to show", "20").action(function(opts) {
|
|
555
|
+
const oddities = program.command("oddities").description("surprising cross-area links (architectural smells)").option("-n, --limit <n>", "how many to show", "20").option("--all", "include framework/runtime externals (default: filter them out)").action(function(opts) {
|
|
534
556
|
const global = readGlobal(this);
|
|
535
557
|
const { graph } = requireGraph(global);
|
|
536
558
|
const limit = Number(opts.limit) || 20;
|
|
537
559
|
const byId = new Map(graph.nodes.map((n) => [n.id, n]));
|
|
538
|
-
const list = graph.edges.filter((e) => typeof e.surprise === "number" && e.surprise > 0).sort((a, b) => (b.surprise ?? 0) - (a.surprise ?? 0) || a.id.localeCompare(b.id)).slice(0, limit);
|
|
560
|
+
const list = graph.edges.filter((e) => typeof e.surprise === "number" && e.surprise > 0).filter((e) => opts.all || !isFrameworkOddity(byId.get(e.src), byId.get(e.dst), e.kind)).sort((a, b) => (b.surprise ?? 0) - (a.surprise ?? 0) || a.id.localeCompare(b.id)).slice(0, limit);
|
|
539
561
|
if (global.json) {
|
|
540
562
|
json(
|
|
541
563
|
list.map((e) => ({
|
|
@@ -548,7 +570,9 @@ function registerInsights(program) {
|
|
|
548
570
|
return;
|
|
549
571
|
}
|
|
550
572
|
if (!list.length) {
|
|
551
|
-
info(
|
|
573
|
+
info(
|
|
574
|
+
`${c.cyan("vg oddities")} \xB7 none found` + (opts.all ? " (no cross-area links, or only one area)" : " (no app-level surprises; try --all for framework links)")
|
|
575
|
+
);
|
|
552
576
|
return;
|
|
553
577
|
}
|
|
554
578
|
info(`${c.cyan("vg oddities")} \xB7 top ${list.length} surprising links`);
|
|
@@ -560,6 +584,70 @@ function registerInsights(program) {
|
|
|
560
584
|
});
|
|
561
585
|
applyGlobalOptions(oddities);
|
|
562
586
|
}
|
|
587
|
+
var FRAMEWORK_EXTERNALS = /* @__PURE__ */ new Set([
|
|
588
|
+
"react",
|
|
589
|
+
"react-dom",
|
|
590
|
+
"react-native",
|
|
591
|
+
"vue",
|
|
592
|
+
"vue-router",
|
|
593
|
+
"svelte",
|
|
594
|
+
"svelte/store",
|
|
595
|
+
"next",
|
|
596
|
+
"next/link",
|
|
597
|
+
"next/router",
|
|
598
|
+
"next/navigation",
|
|
599
|
+
"nuxt",
|
|
600
|
+
"angular",
|
|
601
|
+
"@angular/core",
|
|
602
|
+
"@angular/common",
|
|
603
|
+
"preact",
|
|
604
|
+
"solid-js",
|
|
605
|
+
"express",
|
|
606
|
+
"fastify",
|
|
607
|
+
"koa",
|
|
608
|
+
"hono",
|
|
609
|
+
"rxjs",
|
|
610
|
+
"lodash",
|
|
611
|
+
"lodash-es",
|
|
612
|
+
"underscore",
|
|
613
|
+
"jquery",
|
|
614
|
+
"axios",
|
|
615
|
+
"node:fs",
|
|
616
|
+
"node:path",
|
|
617
|
+
"node:url",
|
|
618
|
+
"node:http",
|
|
619
|
+
"node:https",
|
|
620
|
+
"fs",
|
|
621
|
+
"path",
|
|
622
|
+
"url",
|
|
623
|
+
"http",
|
|
624
|
+
"https",
|
|
625
|
+
"crypto",
|
|
626
|
+
"util",
|
|
627
|
+
"stream",
|
|
628
|
+
"events",
|
|
629
|
+
"assert",
|
|
630
|
+
"os",
|
|
631
|
+
"child_process"
|
|
632
|
+
]);
|
|
633
|
+
function isFrameworkOddity(from, to, kind) {
|
|
634
|
+
if (kind !== "import") return false;
|
|
635
|
+
for (const n of [from, to]) {
|
|
636
|
+
if (n?.kind === "external" && isFrameworkName(n.qualifiedName || n.name)) return true;
|
|
637
|
+
}
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
function isFrameworkName(name) {
|
|
641
|
+
if (!name) return false;
|
|
642
|
+
if (FRAMEWORK_EXTERNALS.has(name)) return true;
|
|
643
|
+
const base = name.startsWith("@") ? name.split("/").slice(0, 2).join("/") : name.split("/")[0];
|
|
644
|
+
if (FRAMEWORK_EXTERNALS.has(base)) return true;
|
|
645
|
+
if (base.startsWith("react-") || base.startsWith("@types/react")) return true;
|
|
646
|
+
if (base.startsWith("@vue/") || base.startsWith("@angular/") || base.startsWith("@sveltejs/")) {
|
|
647
|
+
return true;
|
|
648
|
+
}
|
|
649
|
+
return false;
|
|
650
|
+
}
|
|
563
651
|
function nodeSummary(n) {
|
|
564
652
|
return {
|
|
565
653
|
id: n.id,
|
|
@@ -742,8 +830,8 @@ function pad2(s, n) {
|
|
|
742
830
|
}
|
|
743
831
|
var SCHEMA_VERSION2 = "1";
|
|
744
832
|
var OFFSET_FILE = "stats-share.json";
|
|
745
|
-
var INSTALL_ID_DIR =
|
|
746
|
-
var INSTALL_ID_FILE =
|
|
833
|
+
var INSTALL_ID_DIR = path37.join(os.homedir(), ".vibgrate");
|
|
834
|
+
var INSTALL_ID_FILE = path37.join(INSTALL_ID_DIR, "install-id");
|
|
747
835
|
var SEND_TIMEOUT_MS = 4e3;
|
|
748
836
|
function telemetryOptOut(env = process.env) {
|
|
749
837
|
const dnt = (env.DO_NOT_TRACK ?? "").trim().toLowerCase();
|
|
@@ -795,10 +883,10 @@ function statsEndpoint() {
|
|
|
795
883
|
return `https://${resolveIngestHost()}/v1/ingest/cli-mcp-usage`;
|
|
796
884
|
}
|
|
797
885
|
function offsetPath(root2) {
|
|
798
|
-
return
|
|
886
|
+
return path37.join(cacheDir(root2), OFFSET_FILE);
|
|
799
887
|
}
|
|
800
888
|
function ledgerFilePath(root2) {
|
|
801
|
-
return
|
|
889
|
+
return path37.join(cacheDir(root2), "savings.jsonl");
|
|
802
890
|
}
|
|
803
891
|
function readOffset(root2) {
|
|
804
892
|
try {
|
|
@@ -969,9 +1057,9 @@ var PUBLISH_INTERVAL_MS = 2e3;
|
|
|
969
1057
|
var KEEPALIVE_MS = 1e4;
|
|
970
1058
|
var STALE_MS = 6e4;
|
|
971
1059
|
function liveStatsDir(root2) {
|
|
972
|
-
return
|
|
1060
|
+
return path37.join(cacheDir(root2), "serve-live");
|
|
973
1061
|
}
|
|
974
|
-
function reapOtherVersionServers(dir, keepVersion,
|
|
1062
|
+
function reapOtherVersionServers(dir, keepVersion, now = Date.now(), kill = (pid, signal) => process.kill(pid, signal), selfPid = process.pid) {
|
|
975
1063
|
let entries;
|
|
976
1064
|
try {
|
|
977
1065
|
entries = fs8.readdirSync(dir);
|
|
@@ -983,13 +1071,13 @@ function reapOtherVersionServers(dir, keepVersion, now2 = Date.now(), kill = (pi
|
|
|
983
1071
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
984
1072
|
let parsed;
|
|
985
1073
|
try {
|
|
986
|
-
parsed = JSON.parse(fs8.readFileSync(
|
|
1074
|
+
parsed = JSON.parse(fs8.readFileSync(path37.join(dir, name), "utf8"));
|
|
987
1075
|
} catch {
|
|
988
1076
|
continue;
|
|
989
1077
|
}
|
|
990
1078
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number") continue;
|
|
991
1079
|
if (parsed.pid === selfPid) continue;
|
|
992
|
-
if (
|
|
1080
|
+
if (now - parsed.updatedAt > STALE_MS) continue;
|
|
993
1081
|
const version = typeof parsed.version === "string" ? parsed.version : "unknown";
|
|
994
1082
|
if (version === keepVersion) continue;
|
|
995
1083
|
try {
|
|
@@ -1005,7 +1093,7 @@ var LiveStatsBus = class {
|
|
|
1005
1093
|
this.dir = dir;
|
|
1006
1094
|
this.stats = stats;
|
|
1007
1095
|
this.pid = pid;
|
|
1008
|
-
this.file =
|
|
1096
|
+
this.file = path37.join(dir, `serve-${this.pid}.json`);
|
|
1009
1097
|
}
|
|
1010
1098
|
dir;
|
|
1011
1099
|
stats;
|
|
@@ -1030,12 +1118,12 @@ var LiveStatsBus = class {
|
|
|
1030
1118
|
this.unlinkOwn();
|
|
1031
1119
|
}
|
|
1032
1120
|
/** Write the current snapshot when it changed (or as a keepalive). Never throws. */
|
|
1033
|
-
publish(
|
|
1121
|
+
publish(now = Date.now()) {
|
|
1034
1122
|
const snap = this.stats.snapshot();
|
|
1035
|
-
if (snap.revision === this.lastRevision &&
|
|
1123
|
+
if (snap.revision === this.lastRevision && now - this.lastWriteAt < KEEPALIVE_MS) return;
|
|
1036
1124
|
this.lastRevision = snap.revision;
|
|
1037
|
-
this.lastWriteAt =
|
|
1038
|
-
const body = { pid: this.pid, updatedAt:
|
|
1125
|
+
this.lastWriteAt = now;
|
|
1126
|
+
const body = { pid: this.pid, updatedAt: now, version: VERSION, snapshot: snap };
|
|
1039
1127
|
try {
|
|
1040
1128
|
fs8.mkdirSync(this.dir, { recursive: true });
|
|
1041
1129
|
const tmp = `${this.file}.tmp`;
|
|
@@ -1048,7 +1136,7 @@ var LiveStatsBus = class {
|
|
|
1048
1136
|
* Fresh snapshots of the OTHER serve processes in this repo. Stale files
|
|
1049
1137
|
* (crashed processes) are swept best-effort while reading.
|
|
1050
1138
|
*/
|
|
1051
|
-
siblings(
|
|
1139
|
+
siblings(now = Date.now()) {
|
|
1052
1140
|
let entries;
|
|
1053
1141
|
try {
|
|
1054
1142
|
entries = fs8.readdirSync(this.dir);
|
|
@@ -1058,7 +1146,7 @@ var LiveStatsBus = class {
|
|
|
1058
1146
|
const out2 = [];
|
|
1059
1147
|
for (const name of entries.sort()) {
|
|
1060
1148
|
if (!/^serve-\d+\.json$/.test(name)) continue;
|
|
1061
|
-
const file =
|
|
1149
|
+
const file = path37.join(this.dir, name);
|
|
1062
1150
|
let parsed;
|
|
1063
1151
|
try {
|
|
1064
1152
|
parsed = JSON.parse(fs8.readFileSync(file, "utf8"));
|
|
@@ -1066,7 +1154,7 @@ var LiveStatsBus = class {
|
|
|
1066
1154
|
continue;
|
|
1067
1155
|
}
|
|
1068
1156
|
if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
|
|
1069
|
-
if (
|
|
1157
|
+
if (now - parsed.updatedAt > STALE_MS) {
|
|
1070
1158
|
try {
|
|
1071
1159
|
fs8.unlinkSync(file);
|
|
1072
1160
|
} catch {
|
|
@@ -1140,12 +1228,12 @@ var SessionStats = class {
|
|
|
1140
1228
|
byClient = /* @__PURE__ */ new Map();
|
|
1141
1229
|
byTool = /* @__PURE__ */ new Map();
|
|
1142
1230
|
bySource = /* @__PURE__ */ new Map();
|
|
1143
|
-
constructor(
|
|
1144
|
-
this.startedAt =
|
|
1231
|
+
constructor(now = Date.now()) {
|
|
1232
|
+
this.startedAt = now;
|
|
1145
1233
|
}
|
|
1146
|
-
record(sample,
|
|
1234
|
+
record(sample, now = Date.now()) {
|
|
1147
1235
|
this.revision++;
|
|
1148
|
-
this.lastCallAt =
|
|
1236
|
+
this.lastCallAt = now;
|
|
1149
1237
|
const rows = [
|
|
1150
1238
|
this.totals,
|
|
1151
1239
|
this.rowFor(this.byClient, sample.client),
|
|
@@ -1208,9 +1296,9 @@ var teal = (s) => c.hex("#3FB0A4")(s);
|
|
|
1208
1296
|
var mint = (s) => c.hex("#4FE3C1")(s);
|
|
1209
1297
|
var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
1210
1298
|
var MAX_TOOL_ROWS = 8;
|
|
1211
|
-
function serveStatusLines(snap,
|
|
1299
|
+
function serveStatusLines(snap, now, tick = 0, siblingServers = 0) {
|
|
1212
1300
|
const spinner = mint(SPINNER[tick % SPINNER.length]);
|
|
1213
|
-
const up = fmtUptime(
|
|
1301
|
+
const up = fmtUptime(now - snap.startedAt);
|
|
1214
1302
|
const lines = [];
|
|
1215
1303
|
const siblingNote = siblingServers > 0 ? ` ${c.dim(`incl. ${siblingServers} assistant-spawned server${siblingServers === 1 ? "" : "s"} in this repo`)}` : null;
|
|
1216
1304
|
if (snap.totals.calls === 0) {
|
|
@@ -1224,7 +1312,7 @@ function serveStatusLines(snap, now2, tick = 0, siblingServers = 0) {
|
|
|
1224
1312
|
const answered = Math.round((t.complete + t.partial) / t.calls * 100);
|
|
1225
1313
|
const cli = snap.sources.find((s) => s.key === "cli");
|
|
1226
1314
|
const via = cli ? c.dim(" \xB7 via ") + snap.sources.map((s) => `${c.white(s.key)} ${teal(String(s.calls))}`).join(c.dim(" \xB7 ")) : "";
|
|
1227
|
-
const ago = snap.lastCallAt === null ? "" : c.dim(` \xB7 last call ${fmtUptime(
|
|
1315
|
+
const ago = snap.lastCallAt === null ? "" : c.dim(` \xB7 last call ${fmtUptime(now - snap.lastCallAt)} ago`);
|
|
1228
1316
|
lines.push(
|
|
1229
1317
|
` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal(up)} ${c.dim("\xB7")} ${c.bold.white(String(t.calls))} call${t.calls === 1 ? "" : "s"} ${c.dim("\xB7")} ${mint(`${answered}%`)} answered${via}${ago}`
|
|
1230
1318
|
);
|
|
@@ -1257,8 +1345,8 @@ function serveStatusLines(snap, now2, tick = 0, siblingServers = 0) {
|
|
|
1257
1345
|
if (siblingNote) lines.push(siblingNote);
|
|
1258
1346
|
return lines;
|
|
1259
1347
|
}
|
|
1260
|
-
function serveHeartbeatLine(snap,
|
|
1261
|
-
const up = fmtUptime(
|
|
1348
|
+
function serveHeartbeatLine(snap, now) {
|
|
1349
|
+
const up = fmtUptime(now - snap.startedAt);
|
|
1262
1350
|
const t = snap.totals;
|
|
1263
1351
|
if (t.calls === 0) return c.dim(`vg \xB7 serving for ${up} \u2014 no tool calls yet`);
|
|
1264
1352
|
const clients = snap.clients.map((cl) => `${cl.key} ${cl.calls}`).join(", ");
|
|
@@ -1382,7 +1470,7 @@ var LedgerTail = class {
|
|
|
1382
1470
|
}
|
|
1383
1471
|
}
|
|
1384
1472
|
/** One poll cycle — exposed for tests (deterministic, no timers needed). */
|
|
1385
|
-
poll(
|
|
1473
|
+
poll(now = Date.now()) {
|
|
1386
1474
|
let size;
|
|
1387
1475
|
try {
|
|
1388
1476
|
size = this.sizeOf();
|
|
@@ -1407,7 +1495,7 @@ var LedgerTail = class {
|
|
|
1407
1495
|
if (lastNewline < 0) return;
|
|
1408
1496
|
const text = chunk.subarray(0, lastNewline).toString("utf8");
|
|
1409
1497
|
this.offset += lastNewline + 1;
|
|
1410
|
-
for (const line of text.split("\n")) ingestLedgerLine(this.stats, line,
|
|
1498
|
+
for (const line of text.split("\n")) ingestLedgerLine(this.stats, line, now);
|
|
1411
1499
|
}
|
|
1412
1500
|
sizeOf() {
|
|
1413
1501
|
try {
|
|
@@ -1417,7 +1505,7 @@ var LedgerTail = class {
|
|
|
1417
1505
|
}
|
|
1418
1506
|
}
|
|
1419
1507
|
};
|
|
1420
|
-
function ingestLedgerLine(stats, line,
|
|
1508
|
+
function ingestLedgerLine(stats, line, now) {
|
|
1421
1509
|
if (!line.trim()) return;
|
|
1422
1510
|
let e;
|
|
1423
1511
|
try {
|
|
@@ -1436,7 +1524,7 @@ function ingestLedgerLine(stats, line, now2) {
|
|
|
1436
1524
|
vgTokens: e.vgTokens ?? 0,
|
|
1437
1525
|
baselineTokens: e.baselineTokens ?? 0
|
|
1438
1526
|
},
|
|
1439
|
-
|
|
1527
|
+
now
|
|
1440
1528
|
);
|
|
1441
1529
|
}
|
|
1442
1530
|
|
|
@@ -1486,8 +1574,8 @@ function registerServe(program) {
|
|
|
1486
1574
|
await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
|
|
1487
1575
|
} else {
|
|
1488
1576
|
info(c.dim(`vg \xB7 MCP server on stdio (read-only, ${freshness}). Connect your assistant to this process.`));
|
|
1489
|
-
await serveStdio(graphPath, serveOpts);
|
|
1490
1577
|
display?.start();
|
|
1578
|
+
await serveStdio(graphPath, serveOpts);
|
|
1491
1579
|
}
|
|
1492
1580
|
});
|
|
1493
1581
|
applyGlobalOptions(cmd);
|
|
@@ -1502,13 +1590,22 @@ async function ensureServableGraph(root2, graphPath, global, refresh, opts = {})
|
|
|
1502
1590
|
{ ...global, json: false }
|
|
1503
1591
|
);
|
|
1504
1592
|
} else {
|
|
1505
|
-
const
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1593
|
+
const kick = refreshIfStale(root2, { inline: opts.inline, graphPath }).then((refreshed) => {
|
|
1594
|
+
if (refreshed.status === "refreshed") {
|
|
1595
|
+
const n = driftCount(refreshed.drift);
|
|
1596
|
+
info(
|
|
1597
|
+
c.dim(
|
|
1598
|
+
`vg \xB7 map refreshed in background \u2014 ${n} file(s) drifted (${(refreshed.ms / 1e3).toFixed(2)}s)`
|
|
1599
|
+
)
|
|
1600
|
+
);
|
|
1601
|
+
} else if (refreshed.status === "error") {
|
|
1602
|
+
info(c.yellow(`vg \xB7 map refresh failed (${refreshed.message}) \u2014 serving the last built map`));
|
|
1603
|
+
}
|
|
1604
|
+
}).catch((err) => {
|
|
1605
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1606
|
+
info(c.yellow(`vg \xB7 map refresh failed (${msg}) \u2014 serving the last built map`));
|
|
1607
|
+
});
|
|
1608
|
+
if (opts.awaitStaleRefresh) await kick;
|
|
1512
1609
|
}
|
|
1513
1610
|
}
|
|
1514
1611
|
if (!fs8.existsSync(graphPath)) {
|
|
@@ -1573,7 +1670,7 @@ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
|
|
|
1573
1670
|
info(c.red(`vg serve: request error: ${err.message}`));
|
|
1574
1671
|
}
|
|
1575
1672
|
});
|
|
1576
|
-
await new Promise((
|
|
1673
|
+
await new Promise((resolve20) => httpServer.listen(port, host, resolve20));
|
|
1577
1674
|
info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
|
|
1578
1675
|
onReady?.();
|
|
1579
1676
|
await new Promise(() => {
|
|
@@ -1787,7 +1884,7 @@ function endOfLine(text, line) {
|
|
|
1787
1884
|
}
|
|
1788
1885
|
var CACHE_VERSION = "vg-lsp-scan-cache/2";
|
|
1789
1886
|
function cachePath(root2) {
|
|
1790
|
-
return
|
|
1887
|
+
return path37.join(cacheDir(root2), "lsp-scan.json");
|
|
1791
1888
|
}
|
|
1792
1889
|
function manifestHash(root2) {
|
|
1793
1890
|
const files = [];
|
|
@@ -1799,7 +1896,7 @@ function manifestHash(root2) {
|
|
|
1799
1896
|
return;
|
|
1800
1897
|
}
|
|
1801
1898
|
for (const entry of entries) {
|
|
1802
|
-
const abs =
|
|
1899
|
+
const abs = path37.join(dir, entry.name);
|
|
1803
1900
|
if (entry.isDirectory()) {
|
|
1804
1901
|
if (SKIP_DIRS.has(entry.name)) continue;
|
|
1805
1902
|
walk2(abs);
|
|
@@ -1809,7 +1906,7 @@ function manifestHash(root2) {
|
|
|
1809
1906
|
const base = entry.name.toLowerCase();
|
|
1810
1907
|
if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
|
|
1811
1908
|
try {
|
|
1812
|
-
const rel =
|
|
1909
|
+
const rel = path37.relative(root2, abs).split(path37.sep).join("/");
|
|
1813
1910
|
files.push({ rel, hash: hashBytes(fs8.readFileSync(abs)) });
|
|
1814
1911
|
} catch {
|
|
1815
1912
|
}
|
|
@@ -2455,12 +2552,12 @@ function uriToPath(uri) {
|
|
|
2455
2552
|
}
|
|
2456
2553
|
}
|
|
2457
2554
|
function projectForFile(root2, a, filePath) {
|
|
2458
|
-
const dir =
|
|
2555
|
+
const dir = path37.dirname(path37.resolve(filePath));
|
|
2459
2556
|
let best;
|
|
2460
2557
|
let bestLen = -1;
|
|
2461
2558
|
for (const proj of a.projects ?? []) {
|
|
2462
|
-
const projDir =
|
|
2463
|
-
if ((dir === projDir || dir.startsWith(projDir +
|
|
2559
|
+
const projDir = path37.resolve(root2, proj.path);
|
|
2560
|
+
if ((dir === projDir || dir.startsWith(projDir + path37.sep)) && projDir.length > bestLen) {
|
|
2464
2561
|
best = proj;
|
|
2465
2562
|
bestLen = projDir.length;
|
|
2466
2563
|
}
|
|
@@ -2468,7 +2565,7 @@ function projectForFile(root2, a, filePath) {
|
|
|
2468
2565
|
return best;
|
|
2469
2566
|
}
|
|
2470
2567
|
function sameProject(location, projectPath) {
|
|
2471
|
-
return
|
|
2568
|
+
return path37.normalize(location) === path37.normalize(projectPath);
|
|
2472
2569
|
}
|
|
2473
2570
|
function hasReleaseDates(a) {
|
|
2474
2571
|
for (const proj of a.projects ?? []) {
|
|
@@ -2714,9 +2811,9 @@ function registerInstall(program) {
|
|
|
2714
2811
|
info(`${c.cyan("vg install")} \xB7 no AI assistants detected here`);
|
|
2715
2812
|
} else {
|
|
2716
2813
|
info(`${c.cyan("vg install")} \xB7 detected assistants`);
|
|
2717
|
-
const
|
|
2814
|
+
const pad4 = Math.max(...detected.map((d) => d.assistant.id.length)) + 2;
|
|
2718
2815
|
for (const d of detected) {
|
|
2719
|
-
info(` ${c.bold(d.assistant.id.padEnd(
|
|
2816
|
+
info(` ${c.bold(d.assistant.id.padEnd(pad4))} ${d.assistant.label} ${c.dim(`via ${d.via}: ${d.marker}`)}`);
|
|
2720
2817
|
}
|
|
2721
2818
|
}
|
|
2722
2819
|
return;
|
|
@@ -2725,9 +2822,9 @@ function registerInstall(program) {
|
|
|
2725
2822
|
json(ASSISTANTS.map((a) => ({ id: a.id, label: a.label, mcp: !!a.mcp, skill: !!a.skill, nudge: !!a.nudge })));
|
|
2726
2823
|
} else {
|
|
2727
2824
|
info(`${c.cyan("vg install")} \xB7 supported assistants`);
|
|
2728
|
-
const
|
|
2825
|
+
const pad4 = Math.max(...ASSISTANTS.map((a) => a.id.length)) + 2;
|
|
2729
2826
|
for (const a of ASSISTANTS) {
|
|
2730
|
-
info(` ${c.bold(a.id.padEnd(
|
|
2827
|
+
info(` ${c.bold(a.id.padEnd(pad4))} ${a.label} ${c.dim(`mcp:${a.mcp ? "\u2713" : "\u2014"} skill:${a.skill ? "\u2713" : "\u2014"} nudge:${a.nudge ? "\u2713" : "\u2014"}`)}`);
|
|
2731
2828
|
}
|
|
2732
2829
|
}
|
|
2733
2830
|
return;
|
|
@@ -2794,7 +2891,7 @@ function registerShare(program) {
|
|
|
2794
2891
|
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) {
|
|
2795
2892
|
const global = readGlobal(this);
|
|
2796
2893
|
const root2 = rootOf(global);
|
|
2797
|
-
const gitDir =
|
|
2894
|
+
const gitDir = path37.join(root2, ".git");
|
|
2798
2895
|
if (!fs8.existsSync(gitDir)) {
|
|
2799
2896
|
throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
|
|
2800
2897
|
}
|
|
@@ -2816,15 +2913,15 @@ function registerShare(program) {
|
|
|
2816
2913
|
applyGlobalOptions(cmd);
|
|
2817
2914
|
}
|
|
2818
2915
|
function writeVibgrateGitignore(root2, reports) {
|
|
2819
|
-
const dir =
|
|
2916
|
+
const dir = path37.join(root2, ".vibgrate");
|
|
2820
2917
|
fs8.mkdirSync(dir, { recursive: true });
|
|
2821
2918
|
const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl"];
|
|
2822
2919
|
if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
|
|
2823
|
-
fs8.writeFileSync(
|
|
2920
|
+
fs8.writeFileSync(path37.join(dir, ".gitignore"), `${lines.join("\n")}
|
|
2824
2921
|
`);
|
|
2825
2922
|
}
|
|
2826
2923
|
function writeGitAttributes(root2) {
|
|
2827
|
-
const file =
|
|
2924
|
+
const file = path37.join(root2, ".gitattributes");
|
|
2828
2925
|
const line = ".vibgrate/graph.json merge=vg";
|
|
2829
2926
|
let content = fs8.existsSync(file) ? fs8.readFileSync(file, "utf8") : "";
|
|
2830
2927
|
if (!content.split("\n").some((l) => l.trim() === line)) {
|
|
@@ -2842,7 +2939,7 @@ function configureMergeDriver(root2) {
|
|
|
2842
2939
|
function installPreCommitHook(root2) {
|
|
2843
2940
|
const hooksDir = hookDir(root2);
|
|
2844
2941
|
fs8.mkdirSync(hooksDir, { recursive: true });
|
|
2845
|
-
const file =
|
|
2942
|
+
const file = path37.join(hooksDir, "pre-commit");
|
|
2846
2943
|
const block = [
|
|
2847
2944
|
HOOK_BEGIN,
|
|
2848
2945
|
"if command -v vg >/dev/null 2>&1; then",
|
|
@@ -2864,14 +2961,14 @@ ${content}`;
|
|
|
2864
2961
|
fs8.chmodSync(file, 493);
|
|
2865
2962
|
}
|
|
2866
2963
|
function undo(root2) {
|
|
2867
|
-
const hookFile =
|
|
2964
|
+
const hookFile = path37.join(hookDir(root2), "pre-commit");
|
|
2868
2965
|
if (fs8.existsSync(hookFile)) {
|
|
2869
2966
|
const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
|
|
2870
2967
|
const next2 = fs8.readFileSync(hookFile, "utf8").replace(re, "\n");
|
|
2871
2968
|
if (next2.trim() === "#!/bin/sh") fs8.rmSync(hookFile);
|
|
2872
2969
|
else fs8.writeFileSync(hookFile, next2);
|
|
2873
2970
|
}
|
|
2874
|
-
const attr =
|
|
2971
|
+
const attr = path37.join(root2, ".gitattributes");
|
|
2875
2972
|
if (fs8.existsSync(attr)) {
|
|
2876
2973
|
const next2 = fs8.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
|
|
2877
2974
|
fs8.writeFileSync(attr, next2);
|
|
@@ -2884,10 +2981,10 @@ function undo(root2) {
|
|
|
2884
2981
|
function hookDir(root2) {
|
|
2885
2982
|
try {
|
|
2886
2983
|
const configured = git(root2, ["config", "--get", "core.hooksPath"]).trim();
|
|
2887
|
-
if (configured) return
|
|
2984
|
+
if (configured) return path37.resolve(root2, configured);
|
|
2888
2985
|
} catch {
|
|
2889
2986
|
}
|
|
2890
|
-
return
|
|
2987
|
+
return path37.join(root2, ".git", "hooks");
|
|
2891
2988
|
}
|
|
2892
2989
|
function git(root2, args) {
|
|
2893
2990
|
return execFileSync("git", args, { cwd: root2, encoding: "utf8" });
|
|
@@ -2895,148 +2992,111 @@ function git(root2, args) {
|
|
|
2895
2992
|
function escapeRe(s) {
|
|
2896
2993
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2897
2994
|
}
|
|
2898
|
-
var
|
|
2899
|
-
|
|
2900
|
-
|
|
2995
|
+
var DEFAULT_DEBOUNCE_MS = 400;
|
|
2996
|
+
var SKIP_NAME = /* @__PURE__ */ new Set([
|
|
2997
|
+
".git",
|
|
2998
|
+
"node_modules",
|
|
2999
|
+
".vibgrate",
|
|
3000
|
+
"dist",
|
|
3001
|
+
"build",
|
|
3002
|
+
"out",
|
|
3003
|
+
"coverage",
|
|
3004
|
+
".next",
|
|
3005
|
+
"target",
|
|
3006
|
+
"__pycache__",
|
|
3007
|
+
".venv",
|
|
3008
|
+
"venv"
|
|
3009
|
+
]);
|
|
3010
|
+
function registerWatch(program) {
|
|
3011
|
+
const cmd = program.command("watch").description("rebuild the code map when files change (debounced)").argument("[paths...]", "folders to watch (default: current folder)").option("--debounce <ms>", "settle time after a change before rebuild", String(DEFAULT_DEBOUNCE_MS)).option("--no-html", "do not write graph.html on each rebuild").option("--no-report", "do not write GRAPH_REPORT.md on each rebuild").option("--fast", "skip precise tsc resolve on rebuilds (heuristic only)").action(async function(paths, opts) {
|
|
2901
3012
|
const global = readGlobal(this);
|
|
2902
3013
|
const root2 = rootOf(global);
|
|
2903
|
-
const
|
|
2904
|
-
const
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
|
|
2909
|
-
|
|
2910
|
-
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
2914
|
-
|
|
2915
|
-
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2920
|
-
|
|
2921
|
-
|
|
3014
|
+
const debounceMs = Math.max(50, Number(opts.debounce) || DEFAULT_DEBOUNCE_MS);
|
|
3015
|
+
const watchRoots = (paths.length ? paths : ["."]).map((p) => path37.resolve(root2, p));
|
|
3016
|
+
for (const w of watchRoots) {
|
|
3017
|
+
if (!fs8.existsSync(w)) {
|
|
3018
|
+
throw new CliError(`watch path not found: ${w}`, ExitCode.USAGE_ERROR);
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
let building = false;
|
|
3022
|
+
let pending = false;
|
|
3023
|
+
let timer = null;
|
|
3024
|
+
const rebuild = async (reason) => {
|
|
3025
|
+
if (building) {
|
|
3026
|
+
pending = true;
|
|
3027
|
+
return;
|
|
3028
|
+
}
|
|
3029
|
+
building = true;
|
|
3030
|
+
try {
|
|
3031
|
+
info(c.dim(`vg watch \xB7 rebuild (${reason})`));
|
|
3032
|
+
const result = await buildGraph({
|
|
3033
|
+
root: root2,
|
|
3034
|
+
paths: paths.length ? paths : void 0,
|
|
3035
|
+
fast: opts.fast === true,
|
|
3036
|
+
noGround: false
|
|
3037
|
+
});
|
|
3038
|
+
writeArtifacts(result.graph, {
|
|
3039
|
+
root: root2,
|
|
3040
|
+
html: opts.html !== false,
|
|
3041
|
+
report: opts.report !== false,
|
|
3042
|
+
graphPath: global.graph
|
|
3043
|
+
});
|
|
3044
|
+
writeSnapshot(root2, result.graph.provenance.corpusHash, result.fileStats);
|
|
3045
|
+
const { counts } = result.graph.meta;
|
|
3046
|
+
info(
|
|
3047
|
+
`${c.cyan("vg watch")} \xB7 ${counts.nodes} nodes \xB7 ${counts.edges} edges \xB7 ${(result.timing.totalMs / 1e3).toFixed(2)}s` + (result.statHits ? c.dim(` \xB7 ${result.statHits} mtime hits`) : "")
|
|
3048
|
+
);
|
|
3049
|
+
} catch (err) {
|
|
3050
|
+
info(c.yellow(`vg watch \xB7 rebuild failed: ${err.message}`));
|
|
3051
|
+
} finally {
|
|
3052
|
+
building = false;
|
|
3053
|
+
if (pending) {
|
|
3054
|
+
pending = false;
|
|
3055
|
+
void rebuild("queued changes");
|
|
3056
|
+
}
|
|
3057
|
+
}
|
|
3058
|
+
};
|
|
3059
|
+
const schedule = (label) => {
|
|
3060
|
+
if (timer) clearTimeout(timer);
|
|
3061
|
+
timer = setTimeout(() => {
|
|
3062
|
+
timer = null;
|
|
3063
|
+
void rebuild(label);
|
|
3064
|
+
}, debounceMs);
|
|
3065
|
+
};
|
|
3066
|
+
await rebuild("initial");
|
|
3067
|
+
const watchers = [];
|
|
3068
|
+
for (const w of watchRoots) {
|
|
3069
|
+
try {
|
|
3070
|
+
const watcher = fs8.watch(w, { recursive: true }, (_event, filename) => {
|
|
3071
|
+
if (!filename) {
|
|
3072
|
+
schedule("change");
|
|
3073
|
+
return;
|
|
3074
|
+
}
|
|
3075
|
+
const parts = filename.split(path37.sep);
|
|
3076
|
+
if (parts.some((p) => SKIP_NAME.has(p))) return;
|
|
3077
|
+
if (filename.includes(`${path37.sep}.vibgrate${path37.sep}`) || filename.startsWith(".vibgrate")) {
|
|
3078
|
+
return;
|
|
3079
|
+
}
|
|
3080
|
+
schedule(filename);
|
|
3081
|
+
});
|
|
3082
|
+
watchers.push(watcher);
|
|
3083
|
+
} catch (err) {
|
|
3084
|
+
throw new CliError(`cannot watch ${w}: ${err.message}`, ExitCode.ERROR);
|
|
2922
3085
|
}
|
|
2923
|
-
info(` ${c.bold(`aggregate \u2248 ${tokenReduction.aggregateRatio.toFixed(1)}\xD7 fewer tokens`)} ${c.dim("(honest estimate, scales with repo size)")}`);
|
|
2924
3086
|
}
|
|
3087
|
+
info(c.dim(`vg watch \xB7 watching ${watchRoots.map((p) => path37.relative(root2, p) || ".").join(", ")} (debounce ${debounceMs}ms) \xB7 Ctrl+C to stop`));
|
|
3088
|
+
await new Promise((resolve20) => {
|
|
3089
|
+
const stop = () => {
|
|
3090
|
+
for (const w of watchers) w.close();
|
|
3091
|
+
if (timer) clearTimeout(timer);
|
|
3092
|
+
resolve20();
|
|
3093
|
+
};
|
|
3094
|
+
process.once("SIGINT", stop);
|
|
3095
|
+
process.once("SIGTERM", stop);
|
|
3096
|
+
});
|
|
2925
3097
|
});
|
|
2926
3098
|
applyGlobalOptions(cmd);
|
|
2927
3099
|
}
|
|
2928
|
-
async function runBenchmarkSuite(root2, budget) {
|
|
2929
|
-
const baseline = process.memoryUsage();
|
|
2930
|
-
const sampler = startMemorySampler();
|
|
2931
|
-
const t0 = now();
|
|
2932
|
-
const cold = await buildGraph({ root: root2, generatedAt: PIN, noCache: true });
|
|
2933
|
-
const coldMs = now() - t0;
|
|
2934
|
-
const t1 = now();
|
|
2935
|
-
const warm = await buildGraph({ root: root2, generatedAt: PIN });
|
|
2936
|
-
const warmMs = now() - t1;
|
|
2937
|
-
const a = serializeGraph(cold.graph);
|
|
2938
|
-
const b = serializeGraph((await buildGraph({ root: root2, generatedAt: PIN, noCache: true })).graph);
|
|
2939
|
-
const peak = sampler.stop();
|
|
2940
|
-
const deterministic = a === b;
|
|
2941
|
-
const after = process.memoryUsage();
|
|
2942
|
-
const corpusBytes = cold.fileStats.reduce((s, f) => s + f.size, 0);
|
|
2943
|
-
const graphJsonBytes = Buffer.byteLength(a, "utf8");
|
|
2944
|
-
const nodes = cold.graph.meta.counts.nodes;
|
|
2945
|
-
const questions = deriveQuestions(cold.graph);
|
|
2946
|
-
const fileSizes = fileSizeIndex(root2);
|
|
2947
|
-
const perQuestion = questions.map((q) => {
|
|
2948
|
-
const vgTokens = queryGraph(cold.graph, q, { budget }).tokensEstimate;
|
|
2949
|
-
const baseTokens = grepBaselineTokens(q, fileSizes);
|
|
2950
|
-
return { question: q, vgTokens, baselineTokens: baseTokens, ratio: baseTokens > 0 ? round(baseTokens / Math.max(vgTokens, 1)) : 1 };
|
|
2951
|
-
});
|
|
2952
|
-
const totalVg = perQuestion.reduce((s, x) => s + x.vgTokens, 0);
|
|
2953
|
-
const totalBase = perQuestion.reduce((s, x) => s + x.baselineTokens, 0);
|
|
2954
|
-
const aggregateRatio = totalVg > 0 ? round(totalBase / totalVg) : 0;
|
|
2955
|
-
return {
|
|
2956
|
-
repo: { files: cold.totalFiles, nodes, edges: cold.graph.meta.counts.edges },
|
|
2957
|
-
build: { coldMs: round(coldMs), incrementalMs: round(warmMs), reusedOnWarm: warm.reused },
|
|
2958
|
-
throughput: {
|
|
2959
|
-
corpusBytes,
|
|
2960
|
-
filesPerSec: coldMs > 0 ? round(cold.totalFiles / coldMs * 1e3) : 0,
|
|
2961
|
-
// 6-decimal precision: a small corpus at 3 decimals would round to 0.
|
|
2962
|
-
mbPerSec: coldMs > 0 ? round6(mb2(corpusBytes) / coldMs * 1e3) : 0
|
|
2963
|
-
},
|
|
2964
|
-
memory: {
|
|
2965
|
-
baselineRssMb: round(mb2(baseline.rss)),
|
|
2966
|
-
peakRssMb: round(mb2(Math.max(peak.rss, baseline.rss))),
|
|
2967
|
-
peakHeapMb: round(mb2(Math.max(peak.heapUsed, baseline.heapUsed))),
|
|
2968
|
-
// Heap growth across the run ≈ what the loaded graphs + caches retain.
|
|
2969
|
-
retainedHeapMb: round(Math.max(0, mb2(after.heapUsed - baseline.heapUsed))),
|
|
2970
|
-
graphJsonBytes,
|
|
2971
|
-
bytesPerNode: nodes > 0 ? round(graphJsonBytes / nodes) : 0,
|
|
2972
|
-
note: "sampled at 25ms + phase boundaries; GC timing makes these approximate"
|
|
2973
|
-
},
|
|
2974
|
-
limits: resolveLimits(),
|
|
2975
|
-
determinism: { byteIdentical: deterministic },
|
|
2976
|
-
tokenReduction: { questions: perQuestion, aggregateRatio, note: "estimates (~4 chars/token); scales with repo size" }
|
|
2977
|
-
};
|
|
2978
|
-
}
|
|
2979
|
-
function startMemorySampler() {
|
|
2980
|
-
let rss = 0;
|
|
2981
|
-
let heapUsed = 0;
|
|
2982
|
-
const sample = () => {
|
|
2983
|
-
const m = process.memoryUsage();
|
|
2984
|
-
if (m.rss > rss) rss = m.rss;
|
|
2985
|
-
if (m.heapUsed > heapUsed) heapUsed = m.heapUsed;
|
|
2986
|
-
};
|
|
2987
|
-
const timer = setInterval(sample, 25);
|
|
2988
|
-
timer.unref?.();
|
|
2989
|
-
return {
|
|
2990
|
-
stop: () => {
|
|
2991
|
-
clearInterval(timer);
|
|
2992
|
-
sample();
|
|
2993
|
-
return { rss, heapUsed };
|
|
2994
|
-
}
|
|
2995
|
-
};
|
|
2996
|
-
}
|
|
2997
|
-
function deriveQuestions(graph) {
|
|
2998
|
-
return graph.nodes.filter((n) => n.kind !== "file" && n.kind !== "external").sort((a, b) => b.importance - a.importance || a.qualifiedName.localeCompare(b.qualifiedName)).slice(0, 5).map((n) => n.name);
|
|
2999
|
-
}
|
|
3000
|
-
function fileSizeIndex(root2) {
|
|
3001
|
-
return discover({ root: root2 }).map((f) => ({ rel: f.rel, abs: f.abs, size: safeSize(f.abs) }));
|
|
3002
|
-
}
|
|
3003
|
-
function grepBaselineTokens(term, files) {
|
|
3004
|
-
const lower = term.toLowerCase();
|
|
3005
|
-
let bytes = 0;
|
|
3006
|
-
for (const f of files) {
|
|
3007
|
-
if (f.size > 512 * 1024) continue;
|
|
3008
|
-
let content = "";
|
|
3009
|
-
try {
|
|
3010
|
-
content = fs8.readFileSync(f.abs, "utf8");
|
|
3011
|
-
} catch {
|
|
3012
|
-
continue;
|
|
3013
|
-
}
|
|
3014
|
-
if (content.toLowerCase().includes(lower)) bytes += content.length;
|
|
3015
|
-
}
|
|
3016
|
-
return Math.ceil(bytes / 4);
|
|
3017
|
-
}
|
|
3018
|
-
function safeSize(abs) {
|
|
3019
|
-
try {
|
|
3020
|
-
return fs8.statSync(abs).size;
|
|
3021
|
-
} catch {
|
|
3022
|
-
return 0;
|
|
3023
|
-
}
|
|
3024
|
-
}
|
|
3025
|
-
function mb2(bytes) {
|
|
3026
|
-
return bytes / (1024 * 1024);
|
|
3027
|
-
}
|
|
3028
|
-
function now() {
|
|
3029
|
-
return Number(process.hrtime.bigint() / 1000n) / 1e3;
|
|
3030
|
-
}
|
|
3031
|
-
function round(x) {
|
|
3032
|
-
return Math.round(x * 1e3) / 1e3;
|
|
3033
|
-
}
|
|
3034
|
-
function round6(x) {
|
|
3035
|
-
return Math.round(x * 1e6) / 1e6;
|
|
3036
|
-
}
|
|
3037
|
-
function pad3(s, n) {
|
|
3038
|
-
return s.padStart(n, " ");
|
|
3039
|
-
}
|
|
3040
3100
|
function registerTests(program) {
|
|
3041
3101
|
const cmd = program.command("tests").description("which tests cover a node (call/coverage linkage)").argument("<name>", "node to inspect").option("--missing", "show untested nodes nearby instead").option("--run", "print the command to run exactly these tests").option("--exec", "run that command").option("--pick <n>", "pick the nth candidate when ambiguous").action(function(name, opts) {
|
|
3042
3102
|
const global = readGlobal(this);
|
|
@@ -3092,8 +3152,17 @@ function registerFacts(program) {
|
|
|
3092
3152
|
const { node: node2, candidates } = resolveOne(graph, name, opts.pick ? Number(opts.pick) : void 0);
|
|
3093
3153
|
if (!node2) throw ambiguityError(`"${name}" ${candidates.length ? "is ambiguous" : "not found"}`, candidates);
|
|
3094
3154
|
if (!graph.facts) {
|
|
3095
|
-
if (global.json)
|
|
3096
|
-
|
|
3155
|
+
if (global.json) {
|
|
3156
|
+
json({
|
|
3157
|
+
node: node2.qualifiedName,
|
|
3158
|
+
facts: [],
|
|
3159
|
+
note: "map has no facts \u2014 rebuild with a current vg (facts ship on every build)"
|
|
3160
|
+
});
|
|
3161
|
+
} else {
|
|
3162
|
+
info(
|
|
3163
|
+
`${c.cyan("vg facts")} \xB7 none in this map \u2014 rebuild with ${c.bold("vg")} (facts ship on every build)`
|
|
3164
|
+
);
|
|
3165
|
+
}
|
|
3097
3166
|
return;
|
|
3098
3167
|
}
|
|
3099
3168
|
const facts = graph.facts.filter((f) => f.subjectIds.includes(node2.id));
|
|
@@ -3348,7 +3417,7 @@ function normalizeStandards(raw) {
|
|
|
3348
3417
|
}
|
|
3349
3418
|
function loadStandards(root2) {
|
|
3350
3419
|
for (const rel of STANDARDS_FILES) {
|
|
3351
|
-
const p =
|
|
3420
|
+
const p = path37__default.join(root2, rel);
|
|
3352
3421
|
let text;
|
|
3353
3422
|
try {
|
|
3354
3423
|
text = fs8__default.readFileSync(p, "utf8");
|
|
@@ -4224,8 +4293,8 @@ async function runHostBench(options = {}) {
|
|
|
4224
4293
|
}
|
|
4225
4294
|
async function runArmSimulate(input) {
|
|
4226
4295
|
const { arm, lib, modelPath, turns, trie, env, live } = input;
|
|
4227
|
-
const
|
|
4228
|
-
const session = await acquireHostSession(lib,
|
|
4296
|
+
const path39 = `${modelPath}#${arm.id}`;
|
|
4297
|
+
const session = await acquireHostSession(lib, path39);
|
|
4229
4298
|
const system = "You are a coding agent with a Task Capsule.";
|
|
4230
4299
|
const capsule = "function readConfig(): Config { return load(); }";
|
|
4231
4300
|
let last = null;
|
|
@@ -5167,7 +5236,7 @@ function registerModels(program) {
|
|
|
5167
5236
|
);
|
|
5168
5237
|
});
|
|
5169
5238
|
applyGlobalOptions(modeCmd);
|
|
5170
|
-
const
|
|
5239
|
+
const resolve20 = cmd.command("resolve").description("resolve a Code Mode to pack + underlying model + fit (no download)").argument("[mode]", "spark | flow | forge (default: auto-fit or configured default)").action(function(modeArg) {
|
|
5171
5240
|
const global = readGlobal(this);
|
|
5172
5241
|
const root2 = rootOf(global);
|
|
5173
5242
|
const sys = gatherSystemMemory();
|
|
@@ -5199,7 +5268,7 @@ function registerModels(program) {
|
|
|
5199
5268
|
info(c.yellow(" will not fit \u2014 choose a lower mode or free memory before loading"));
|
|
5200
5269
|
}
|
|
5201
5270
|
});
|
|
5202
|
-
applyGlobalOptions(
|
|
5271
|
+
applyGlobalOptions(resolve20);
|
|
5203
5272
|
const installCmd = cmd.command("install").description("resolve the best Code Mode for this machine and install the pack").argument("[mode]", "spark | flow | forge (default: auto-fit)").option("--dry-run", "print the install plan only \u2014 do not download").option("--yes", "skip prompts (install already runs by default)").action(async function(modeArg, opts) {
|
|
5204
5273
|
const global = readGlobal(this);
|
|
5205
5274
|
const root2 = rootOf(global);
|
|
@@ -5537,8 +5606,8 @@ function registerModels(program) {
|
|
|
5537
5606
|
}
|
|
5538
5607
|
});
|
|
5539
5608
|
if (opts.out) {
|
|
5540
|
-
const outPath =
|
|
5541
|
-
fs8.mkdirSync(
|
|
5609
|
+
const outPath = path37.resolve(opts.out);
|
|
5610
|
+
fs8.mkdirSync(path37.dirname(outPath), { recursive: true });
|
|
5542
5611
|
fs8.writeFileSync(outPath, `${JSON.stringify(report, null, 2)}
|
|
5543
5612
|
`);
|
|
5544
5613
|
if (!global.json) info(c.dim(` wrote ${outPath}`));
|
|
@@ -5649,11 +5718,11 @@ function fitColor(label) {
|
|
|
5649
5718
|
return label;
|
|
5650
5719
|
}
|
|
5651
5720
|
function confirmYesNo(question) {
|
|
5652
|
-
return new Promise((
|
|
5721
|
+
return new Promise((resolve20) => {
|
|
5653
5722
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
5654
5723
|
rl.question(`${question} [y/N] `, (answer) => {
|
|
5655
5724
|
rl.close();
|
|
5656
|
-
|
|
5725
|
+
resolve20(/^y(es)?$/i.test(answer.trim()));
|
|
5657
5726
|
});
|
|
5658
5727
|
});
|
|
5659
5728
|
}
|
|
@@ -5679,7 +5748,7 @@ function printBackends(backends) {
|
|
|
5679
5748
|
}
|
|
5680
5749
|
}
|
|
5681
5750
|
function codeConfigPath(root2) {
|
|
5682
|
-
return
|
|
5751
|
+
return path37.join(root2, ".vibgrate", "code.json");
|
|
5683
5752
|
}
|
|
5684
5753
|
function loadCodeConfig(root2) {
|
|
5685
5754
|
try {
|
|
@@ -5761,7 +5830,7 @@ function discoverMcpServers(root2, ownServers) {
|
|
|
5761
5830
|
const servers = {};
|
|
5762
5831
|
const sources = [];
|
|
5763
5832
|
for (const rel of MCP_CONFIG_FILES) {
|
|
5764
|
-
const found = readMcpServersFile(
|
|
5833
|
+
const found = readMcpServersFile(path37.join(root2, rel));
|
|
5765
5834
|
const names = Object.keys(found);
|
|
5766
5835
|
if (names.length) {
|
|
5767
5836
|
sources.push(rel);
|
|
@@ -5786,9 +5855,9 @@ function registerCode(program) {
|
|
|
5786
5855
|
const modeFlag = opts.mode ?? config.modelProfile?.mode;
|
|
5787
5856
|
if (!opts.model && !opts.modelPath && (modeFlag || !provider && !model)) {
|
|
5788
5857
|
try {
|
|
5789
|
-
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2, providerForBackend: providerForBackend2 } = await import('./model-orchestrator-
|
|
5790
|
-
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-
|
|
5791
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
5858
|
+
const { parseMode: parseMode2, resolveMode: resolveMode2, readOrchestratorState: readOrchestratorState2, activePin: activePin2, providerForBackend: providerForBackend2 } = await import('./model-orchestrator-TVONAUPS.js');
|
|
5859
|
+
const { gatherSystemMemory: gatherSystemMemory2 } = await import('./local-runtime-5O2NN3GA.js');
|
|
5860
|
+
const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
|
|
5792
5861
|
const state = readOrchestratorState2();
|
|
5793
5862
|
const mode = parseMode2(modeFlag) ?? state.defaultMode ?? void 0;
|
|
5794
5863
|
const pin = mode ? activePin2(mode, state) : null;
|
|
@@ -5817,7 +5886,7 @@ function registerCode(program) {
|
|
|
5817
5886
|
ExitCode.ERROR
|
|
5818
5887
|
);
|
|
5819
5888
|
}
|
|
5820
|
-
const { resolveGgufPath } = await import('./resolve-gguf-
|
|
5889
|
+
const { resolveGgufPath } = await import('./resolve-gguf-VPL4YQ6J.js');
|
|
5821
5890
|
const gguf = resolveGgufPath({
|
|
5822
5891
|
modelRef: resolved.underlying.weightsRef,
|
|
5823
5892
|
modelPath: opts.modelPath
|
|
@@ -5872,7 +5941,7 @@ function registerCode(program) {
|
|
|
5872
5941
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) {
|
|
5873
5942
|
throw usageError('say what to change, e.g. `vg code "add a --timeout flag to the scan command"` (guided mode needs an interactive terminal)');
|
|
5874
5943
|
}
|
|
5875
|
-
const { runInteractive } = await import('./interactive-
|
|
5944
|
+
const { runInteractive } = await import('./interactive-INGJNSON.js');
|
|
5876
5945
|
await runInteractive(
|
|
5877
5946
|
rootOf(global),
|
|
5878
5947
|
global,
|
|
@@ -5926,18 +5995,18 @@ function registerCode(program) {
|
|
|
5926
5995
|
}
|
|
5927
5996
|
if (opts.streamJson && !opts.mock) {
|
|
5928
5997
|
const primarySlug = route.providers[0]?.model.includes("/") ? route.providers[0].model.split("/")[0] : route.providers[0]?.id;
|
|
5929
|
-
const { runCodeStreamJson } = await import('./stream-json-
|
|
5930
|
-
const { nodeCodeFs } = await import('./session-
|
|
5998
|
+
const { runCodeStreamJson } = await import('./stream-json-6ZBUA2L3.js');
|
|
5999
|
+
const { nodeCodeFs } = await import('./session-M72522AP.js');
|
|
5931
6000
|
const readline5 = await import('readline');
|
|
5932
6001
|
const child = await import('child_process');
|
|
5933
|
-
const { loadOrDiscoverFederation } = await import('./federation-
|
|
5934
|
-
const { resolveExecutionEnv } = await import('./execution-env-
|
|
5935
|
-
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-
|
|
5936
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
5937
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
5938
|
-
const { detectGitRef } = await import('./git-ref-
|
|
5939
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
5940
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6002
|
+
const { loadOrDiscoverFederation } = await import('./federation-SZWZIFZ7.js');
|
|
6003
|
+
const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
|
|
6004
|
+
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-TFBKCNJG.js');
|
|
6005
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
|
|
6006
|
+
const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
|
|
6007
|
+
const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
|
|
6008
|
+
const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
|
|
6009
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
|
|
5941
6010
|
const federation = loadOrDiscoverFederation(root2);
|
|
5942
6011
|
const modelProfile = mergeModelExecutionProfile(
|
|
5943
6012
|
resolveModelExecutionProfile({
|
|
@@ -6026,12 +6095,12 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
|
|
|
6026
6095
|
if (!autonomous && !tty) {
|
|
6027
6096
|
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).");
|
|
6028
6097
|
}
|
|
6029
|
-
const { agentTask } = await import('./interactive-
|
|
6030
|
-
const { nodeCodeFs } = await import('./session-
|
|
6031
|
-
const { TtyPrompter } = await import('./ui-
|
|
6098
|
+
const { agentTask } = await import('./interactive-INGJNSON.js');
|
|
6099
|
+
const { nodeCodeFs } = await import('./session-M72522AP.js');
|
|
6100
|
+
const { TtyPrompter } = await import('./ui-Q6DJ3GCU.js');
|
|
6032
6101
|
let priorSummary;
|
|
6033
6102
|
if (opts.continue) {
|
|
6034
|
-
const { loadLatestSession, summarizeSession } = await import('./session-store-
|
|
6103
|
+
const { loadLatestSession, summarizeSession } = await import('./session-store-WFBX7HXL.js');
|
|
6035
6104
|
const prev = loadLatestSession(root2);
|
|
6036
6105
|
if (prev) priorSummary = summarizeSession(prev);
|
|
6037
6106
|
}
|
|
@@ -6039,21 +6108,21 @@ ${res.stderr}` : ""), exitCode: res.status ?? 1 };
|
|
|
6039
6108
|
let mcpTools;
|
|
6040
6109
|
let disposeMcp;
|
|
6041
6110
|
if (Object.keys(mcp.servers).length) {
|
|
6042
|
-
const { McpToolset, defaultMcpConnect } = await import('./mcp-tools-
|
|
6111
|
+
const { McpToolset, defaultMcpConnect } = await import('./mcp-tools-I7JK3S2M.js');
|
|
6043
6112
|
const { toolset } = await McpToolset.connect(mcp.servers, defaultMcpConnect);
|
|
6044
6113
|
disposeMcp = () => toolset.dispose();
|
|
6045
6114
|
const approve = async (a) => autonomous || !!(prompter && a.kind === "tool" && await prompter.confirm("Call an external tool?", false));
|
|
6046
6115
|
mcpTools = { specs: toolset.specs(), owns: (n) => toolset.owns(n), execute: (call) => toolset.execute(call, approve) };
|
|
6047
6116
|
}
|
|
6048
6117
|
try {
|
|
6049
|
-
const { loadFederation } = await import('./federation-
|
|
6050
|
-
const { resolveExecutionEnv } = await import('./execution-env-
|
|
6051
|
-
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-
|
|
6052
|
-
const { startCodeRuntimeSession } = await import('./runtime-session-
|
|
6053
|
-
const { resolveGraphBackend } = await import('./graph-backend-
|
|
6054
|
-
const { detectGitRef } = await import('./git-ref-
|
|
6055
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
6056
|
-
const { vgdRequest: vgdRequest2 } = await import('./vgd-
|
|
6118
|
+
const { loadFederation } = await import('./federation-SZWZIFZ7.js');
|
|
6119
|
+
const { resolveExecutionEnv } = await import('./execution-env-ZU45JZ4G.js');
|
|
6120
|
+
const { resolveModelExecutionProfile, mergeModelExecutionProfile } = await import('./model-execution-profile-TFBKCNJG.js');
|
|
6121
|
+
const { startCodeRuntimeSession } = await import('./runtime-session-4AMZIAAG.js');
|
|
6122
|
+
const { resolveGraphBackend } = await import('./graph-backend-UTOL3SHE.js');
|
|
6123
|
+
const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
|
|
6124
|
+
const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
|
|
6125
|
+
const { vgdRequest: vgdRequest2 } = await import('./vgd-CVLKBS7K.js');
|
|
6057
6126
|
const federation = loadFederation(root2);
|
|
6058
6127
|
const modelProfile = mergeModelExecutionProfile(
|
|
6059
6128
|
resolveModelExecutionProfile({
|
|
@@ -6197,11 +6266,11 @@ function resolveSecurityTierFlag(flag, fromConfig, auto) {
|
|
|
6197
6266
|
return auto ? "L1" : "L0";
|
|
6198
6267
|
}
|
|
6199
6268
|
function confirm(question) {
|
|
6200
|
-
return new Promise((
|
|
6269
|
+
return new Promise((resolve20) => {
|
|
6201
6270
|
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
6202
6271
|
rl.question(`${question} [y/N] `, (answer) => {
|
|
6203
6272
|
rl.close();
|
|
6204
|
-
|
|
6273
|
+
resolve20(/^y(es)?$/i.test(answer.trim()));
|
|
6205
6274
|
});
|
|
6206
6275
|
});
|
|
6207
6276
|
}
|
|
@@ -6223,10 +6292,10 @@ function registerSavings(program) {
|
|
|
6223
6292
|
);
|
|
6224
6293
|
return;
|
|
6225
6294
|
}
|
|
6226
|
-
const
|
|
6227
|
-
const report = readSavings(root2, days,
|
|
6228
|
-
const usage = readUsage(root2, days,
|
|
6229
|
-
const models = readModelSavings(root2, days,
|
|
6295
|
+
const now = Date.now();
|
|
6296
|
+
const report = readSavings(root2, days, now);
|
|
6297
|
+
const usage = readUsage(root2, days, now);
|
|
6298
|
+
const models = readModelSavings(root2, days, now);
|
|
6230
6299
|
if (global.json) {
|
|
6231
6300
|
json({ ...report, usage, models });
|
|
6232
6301
|
return;
|
|
@@ -6358,7 +6427,7 @@ async function addCmd(root2, rest, opts, asJson) {
|
|
|
6358
6427
|
}
|
|
6359
6428
|
function readPackageVersion(root2) {
|
|
6360
6429
|
try {
|
|
6361
|
-
const pkg = JSON.parse(fs8__default.readFileSync(
|
|
6430
|
+
const pkg = JSON.parse(fs8__default.readFileSync(path37__default.join(root2, "package.json"), "utf8"));
|
|
6362
6431
|
return typeof pkg.version === "string" ? pkg.version : void 0;
|
|
6363
6432
|
} catch {
|
|
6364
6433
|
return void 0;
|
|
@@ -6381,8 +6450,8 @@ async function publishCmd(root2, rest, opts, global, asJson) {
|
|
|
6381
6450
|
if (!parsed) throw new CliError("publishing a private library requires a DSN \u2014 run `vibgrate login` or set VIBGRATE_DSN", ExitCode.USAGE_ERROR);
|
|
6382
6451
|
const version = (opts.version || readPackageVersion(root2) || "").trim();
|
|
6383
6452
|
if (!version) throw usageError("a --version is required (or run from a package whose package.json has a version)");
|
|
6384
|
-
const readme = readOptionalFile(opts.readme ?
|
|
6385
|
-
const dts = opts.dts ? readOptionalFile(
|
|
6453
|
+
const readme = readOptionalFile(opts.readme ? path37__default.resolve(opts.readme) : path37__default.join(root2, "README.md"));
|
|
6454
|
+
const dts = opts.dts ? readOptionalFile(path37__default.resolve(opts.dts)) : void 0;
|
|
6386
6455
|
if (!readme && !dts) throw usageError("nothing to publish \u2014 no README.md found and no --dts given");
|
|
6387
6456
|
const result = await publishPrivateLibrary(
|
|
6388
6457
|
{ name, version, readme, dts, language: opts.language },
|
|
@@ -6495,7 +6564,7 @@ async function showCmd(root2, name, budget, asJson, opts = {}) {
|
|
|
6495
6564
|
out(doc);
|
|
6496
6565
|
}
|
|
6497
6566
|
function registerExport(program) {
|
|
6498
|
-
const cmd = program.command("export").description("export the map (format inferred: json|ndjson|graphml|dot|cypher|sql|md|html|cdx.json|spdx.json)").argument("[file]", "target file (or - for stdout)", "map.json").action(function(file) {
|
|
6567
|
+
const cmd = program.command("export").description("export the map (format inferred: json|ndjson|graphml|dot|cypher|sql|md|html|cdx.json|spdx.json)").argument("[file]", "target file (or - for stdout)", "map.json").option("--compact", "compact JSON (no pretty-print; auto for large maps)").option("--slim", "drop heavy fields (area member lists, grounding) for smaller exports").action(function(file, opts) {
|
|
6499
6568
|
const global = readGlobal(this);
|
|
6500
6569
|
const { graph } = requireGraph(global);
|
|
6501
6570
|
const root2 = rootOf(global);
|
|
@@ -6506,13 +6575,15 @@ function registerExport(program) {
|
|
|
6506
6575
|
graph,
|
|
6507
6576
|
deps: needsDeps ? inventory(root2).records : void 0,
|
|
6508
6577
|
models: needsDeps && !global.local ? discoverModels() : void 0,
|
|
6509
|
-
generatedAt: graph.generatedAt
|
|
6578
|
+
generatedAt: graph.generatedAt,
|
|
6579
|
+
compact: opts.compact === true ? true : opts.compact === false ? false : void 0,
|
|
6580
|
+
slim: opts.slim === true
|
|
6510
6581
|
});
|
|
6511
6582
|
if (file === "-") {
|
|
6512
6583
|
out(content.trimEnd());
|
|
6513
6584
|
return;
|
|
6514
6585
|
}
|
|
6515
|
-
fs8.mkdirSync(
|
|
6586
|
+
fs8.mkdirSync(path37.dirname(path37.resolve(file)), { recursive: true });
|
|
6516
6587
|
fs8.writeFileSync(file, content);
|
|
6517
6588
|
info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
|
|
6518
6589
|
});
|
|
@@ -6523,37 +6594,37 @@ function detectFormat(file) {
|
|
|
6523
6594
|
if (lower.endsWith(".cdx.json")) return "cyclonedx";
|
|
6524
6595
|
if (lower.endsWith(".spdx.json")) return "spdx";
|
|
6525
6596
|
if (file === "-") return "json";
|
|
6526
|
-
return formatForExt(
|
|
6597
|
+
return formatForExt(path37.extname(file));
|
|
6527
6598
|
}
|
|
6528
6599
|
function registerBundle(program) {
|
|
6529
6600
|
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) {
|
|
6530
6601
|
const global = readGlobal(this);
|
|
6531
6602
|
const root2 = rootOf(global);
|
|
6532
|
-
const outDir =
|
|
6603
|
+
const outDir = path37.resolve(root2, opts.out ?? "vg-bundle");
|
|
6533
6604
|
let grammarFiles;
|
|
6534
6605
|
try {
|
|
6535
6606
|
grammarFiles = resolvedGrammarFiles();
|
|
6536
6607
|
} catch {
|
|
6537
6608
|
throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
|
|
6538
6609
|
}
|
|
6539
|
-
fs8.mkdirSync(
|
|
6610
|
+
fs8.mkdirSync(path37.join(outDir, "grammars"), { recursive: true });
|
|
6540
6611
|
let grammarCount = 0;
|
|
6541
6612
|
for (const { fileName, absPath } of grammarFiles) {
|
|
6542
|
-
fs8.copyFileSync(absPath,
|
|
6613
|
+
fs8.copyFileSync(absPath, path37.join(outDir, "grammars", fileName));
|
|
6543
6614
|
grammarCount++;
|
|
6544
6615
|
}
|
|
6545
6616
|
const included = [`grammars/ (${grammarCount} .wasm)`];
|
|
6546
6617
|
const graphSrc = resolveGraphPath(root2, global.graph);
|
|
6547
6618
|
if (fs8.existsSync(graphSrc)) {
|
|
6548
|
-
fs8.copyFileSync(graphSrc,
|
|
6619
|
+
fs8.copyFileSync(graphSrc, path37.join(outDir, "graph.json"));
|
|
6549
6620
|
included.push("graph.json");
|
|
6550
6621
|
}
|
|
6551
6622
|
const cat = catalogPath(root2);
|
|
6552
6623
|
if (fs8.existsSync(cat)) {
|
|
6553
|
-
fs8.copyFileSync(cat,
|
|
6624
|
+
fs8.copyFileSync(cat, path37.join(outDir, "vibgrate.lib.json"));
|
|
6554
6625
|
included.push("vibgrate.lib.json");
|
|
6555
6626
|
if (fs8.existsSync(libDir(root2))) {
|
|
6556
|
-
fs8.cpSync(libDir(root2),
|
|
6627
|
+
fs8.cpSync(libDir(root2), path37.join(outDir, "lib"), { recursive: true });
|
|
6557
6628
|
included.push("lib/");
|
|
6558
6629
|
}
|
|
6559
6630
|
}
|
|
@@ -6565,15 +6636,15 @@ function registerBundle(program) {
|
|
|
6565
6636
|
included,
|
|
6566
6637
|
usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
|
|
6567
6638
|
};
|
|
6568
|
-
fs8.writeFileSync(
|
|
6639
|
+
fs8.writeFileSync(path37.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
|
|
6569
6640
|
`);
|
|
6570
6641
|
if (global.json) {
|
|
6571
|
-
json({ out:
|
|
6642
|
+
json({ out: path37.relative(root2, outDir), ...manifest });
|
|
6572
6643
|
return;
|
|
6573
6644
|
}
|
|
6574
|
-
info(`${c.cyan("vg bundle")} \xB7 wrote ${
|
|
6645
|
+
info(`${c.cyan("vg bundle")} \xB7 wrote ${path37.relative(root2, outDir)}/`);
|
|
6575
6646
|
for (const i of included) info(` ${c.green("\u2714")} ${i}`);
|
|
6576
|
-
info(c.dim(` offline: vg build --grammars "${
|
|
6647
|
+
info(c.dim(` offline: vg build --grammars "${path37.relative(root2, outDir)}/grammars"`));
|
|
6577
6648
|
});
|
|
6578
6649
|
applyGlobalOptions(cmd);
|
|
6579
6650
|
}
|
|
@@ -6591,7 +6662,7 @@ async function runDoctor(global) {
|
|
|
6591
6662
|
const root2 = rootOf(global);
|
|
6592
6663
|
const local = global.local === true;
|
|
6593
6664
|
const graphPath = resolveGraphPath(root2, global.graph);
|
|
6594
|
-
const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(
|
|
6665
|
+
const configFile = CONFIG_BASENAMES.find((f) => fs8.existsSync(path37.join(root2, f))) ?? null;
|
|
6595
6666
|
const graph = loadGraph(root2, graphPath);
|
|
6596
6667
|
let staleFiles = null;
|
|
6597
6668
|
if (graph) {
|
|
@@ -6617,13 +6688,13 @@ async function runDoctor(global) {
|
|
|
6617
6688
|
root: root2,
|
|
6618
6689
|
configFile,
|
|
6619
6690
|
map: {
|
|
6620
|
-
path:
|
|
6691
|
+
path: path37.relative(root2, graphPath),
|
|
6621
6692
|
built: graph !== null,
|
|
6622
6693
|
generatedAt: graph?.generatedAt ?? null,
|
|
6623
6694
|
staleFiles
|
|
6624
6695
|
},
|
|
6625
6696
|
libCatalog: {
|
|
6626
|
-
path:
|
|
6697
|
+
path: path37.relative(root2, catalogPath(root2)),
|
|
6627
6698
|
present: fs8.existsSync(catalogPath(root2)),
|
|
6628
6699
|
libraries: libCount
|
|
6629
6700
|
},
|
|
@@ -6681,7 +6752,7 @@ async function runDoctor(global) {
|
|
|
6681
6752
|
);
|
|
6682
6753
|
info(
|
|
6683
6754
|
` host pool ${li.hostPool.size} warm session(s)` + (li.hostPool.sessions[0] ? c.dim(
|
|
6684
|
-
` \xB7 last ${
|
|
6755
|
+
` \xB7 last ${path37.basename(li.hostPool.sessions[0].modelPath)} kv=${li.hostPool.sessions[0].kvBlocks}`
|
|
6685
6756
|
) : c.dim(" \xB7 none (load via vg code / vgd host-load)"))
|
|
6686
6757
|
);
|
|
6687
6758
|
if (li.dynamicOnToken || li.dynamicCustomSampler) {
|
|
@@ -6817,7 +6888,7 @@ function registerDaemon(program) {
|
|
|
6817
6888
|
const register = cmd.command("register").description("register the current repository with a running vgd").argument("[root]", "repository root (default: cwd)").action(async function(rootArg) {
|
|
6818
6889
|
const global = readGlobal(this);
|
|
6819
6890
|
const socketPath = socketOf(this);
|
|
6820
|
-
const root2 =
|
|
6891
|
+
const root2 = path37.resolve(rootArg ?? rootOf(global));
|
|
6821
6892
|
if (!await vgdIsRunning({ socketPath })) {
|
|
6822
6893
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
6823
6894
|
}
|
|
@@ -6853,11 +6924,11 @@ function registerDaemon(program) {
|
|
|
6853
6924
|
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) {
|
|
6854
6925
|
const global = readGlobal(this);
|
|
6855
6926
|
const socketPath = socketOf(this);
|
|
6856
|
-
const primary =
|
|
6927
|
+
const primary = path37.resolve(rootArg ?? rootOf(global));
|
|
6857
6928
|
if (!await vgdIsRunning({ socketPath })) {
|
|
6858
6929
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon start\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
6859
6930
|
}
|
|
6860
|
-
const { loadFederation } = await import('./federation-
|
|
6931
|
+
const { loadFederation } = await import('./federation-SZWZIFZ7.js');
|
|
6861
6932
|
const fed = loadFederation(primary);
|
|
6862
6933
|
if (!fed) throw new CliError(`could not load federation for ${primary}`, ExitCode.ERROR);
|
|
6863
6934
|
const res = await vgdRequest(
|
|
@@ -6881,13 +6952,13 @@ function registerDaemon(program) {
|
|
|
6881
6952
|
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) {
|
|
6882
6953
|
const global = readGlobal(this);
|
|
6883
6954
|
const socketPath = socketOf(this);
|
|
6884
|
-
const root2 =
|
|
6955
|
+
const root2 = path37.resolve(rootArg ?? rootOf(global));
|
|
6885
6956
|
if (!await vgdIsRunning({ socketPath })) {
|
|
6886
6957
|
throw new CliError(`vgd is not running \u2014 start it with \`vg daemon ensure\` (${socketPath})`, ExitCode.NOT_FOUND);
|
|
6887
6958
|
}
|
|
6888
|
-
const { loadGraph: loadGraph2 } = await import('./load-
|
|
6889
|
-
const { detectGitRef } = await import('./git-ref-
|
|
6890
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
6959
|
+
const { loadGraph: loadGraph2 } = await import('./load-QPOWQD7C.js');
|
|
6960
|
+
const { detectGitRef } = await import('./git-ref-XDXB6JP5.js');
|
|
6961
|
+
const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
|
|
6891
6962
|
const opts = this.opts();
|
|
6892
6963
|
const graph = loadGraph2(root2, global.graph);
|
|
6893
6964
|
if (!graph) {
|
|
@@ -7001,7 +7072,7 @@ function socketOf(cmd) {
|
|
|
7001
7072
|
let c2 = cmd;
|
|
7002
7073
|
while (c2) {
|
|
7003
7074
|
const opts = c2.opts();
|
|
7004
|
-
if (opts.socket) return
|
|
7075
|
+
if (opts.socket) return path37.resolve(opts.socket);
|
|
7005
7076
|
c2 = c2.parent;
|
|
7006
7077
|
}
|
|
7007
7078
|
return vgdSocketPath();
|
|
@@ -7025,7 +7096,7 @@ function sleep(ms) {
|
|
|
7025
7096
|
return new Promise((r) => setTimeout(r, ms));
|
|
7026
7097
|
}
|
|
7027
7098
|
async function repositoryIdForCwd(socketPath, root2) {
|
|
7028
|
-
const { repositoryIdFromRoot } = await import('./paths-
|
|
7099
|
+
const { repositoryIdFromRoot } = await import('./paths-2RAH3GME.js');
|
|
7029
7100
|
const reg = await vgdRequest({ op: "register", root: root2 }, { socketPath });
|
|
7030
7101
|
if (reg.ok && "workspace" in reg) return reg.workspace.id;
|
|
7031
7102
|
return repositoryIdFromRoot(root2);
|
|
@@ -7218,11 +7289,11 @@ function registerLlmHost(program) {
|
|
|
7218
7289
|
applyGlobalOptions(cmd);
|
|
7219
7290
|
}
|
|
7220
7291
|
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) => {
|
|
7221
|
-
const rootDir =
|
|
7222
|
-
const vibgrateDir2 =
|
|
7292
|
+
const rootDir = path37.resolve(targetPath);
|
|
7293
|
+
const vibgrateDir2 = path37.join(rootDir, ".vibgrate");
|
|
7223
7294
|
await ensureDir(vibgrateDir2);
|
|
7224
7295
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold(".vibgrate/")} directory`);
|
|
7225
|
-
const configPath =
|
|
7296
|
+
const configPath = path37.join(rootDir, "vibgrate.config.ts");
|
|
7226
7297
|
if (await pathExists(configPath)) {
|
|
7227
7298
|
console.log(chalk7.dim(" vibgrate.config.ts already exists, skipping"));
|
|
7228
7299
|
} else {
|
|
@@ -7230,7 +7301,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
7230
7301
|
console.log(chalk7.green("\u2714") + ` Created ${chalk7.bold("vibgrate.config.ts")}`);
|
|
7231
7302
|
}
|
|
7232
7303
|
if (opts.baseline) {
|
|
7233
|
-
const { runBaseline } = await import('./baseline-
|
|
7304
|
+
const { runBaseline } = await import('./baseline-ATM5MXBZ.js');
|
|
7234
7305
|
await runBaseline(rootDir);
|
|
7235
7306
|
}
|
|
7236
7307
|
console.log("");
|
|
@@ -7333,7 +7404,7 @@ function collectPackageImports(graph, ecosystem, pkg) {
|
|
|
7333
7404
|
};
|
|
7334
7405
|
}
|
|
7335
7406
|
async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3) {
|
|
7336
|
-
const content = await readFile3(
|
|
7407
|
+
const content = await readFile3(path37.join(rootDir, relFile));
|
|
7337
7408
|
if (!content) return false;
|
|
7338
7409
|
const escaped = identifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7339
7410
|
return new RegExp(`\\b${escaped}\\b`).test(content);
|
|
@@ -7527,7 +7598,7 @@ var AI_ASSISTANT_DETECTORS = [
|
|
|
7527
7598
|
async function detectAiAssistant(rootDir) {
|
|
7528
7599
|
for (const detector of AI_ASSISTANT_DETECTORS) {
|
|
7529
7600
|
for (const file of detector.files) {
|
|
7530
|
-
if (await pathExists$1(
|
|
7601
|
+
if (await pathExists$1(path37.join(rootDir, file))) {
|
|
7531
7602
|
return detector.name;
|
|
7532
7603
|
}
|
|
7533
7604
|
}
|
|
@@ -7720,7 +7791,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
7720
7791
|
collectExcludes,
|
|
7721
7792
|
[]
|
|
7722
7793
|
).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) => {
|
|
7723
|
-
const rootDir =
|
|
7794
|
+
const rootDir = path37.resolve(targetPath);
|
|
7724
7795
|
if (!await pathExists$1(rootDir)) {
|
|
7725
7796
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
7726
7797
|
process.exit(1);
|
|
@@ -7728,7 +7799,7 @@ var scanCommand = new Command("scan").description("Scan a project for upgrade dr
|
|
|
7728
7799
|
const hasDsn = !!resolveDsn(opts.dsn);
|
|
7729
7800
|
const willPush = !opts.offline && (opts.push || hasDsn);
|
|
7730
7801
|
const noLocalArtifacts = opts.localArtifacts === false;
|
|
7731
|
-
const isFirstRun = !await pathExists$1(
|
|
7802
|
+
const isFirstRun = !await pathExists$1(path37.join(rootDir, ".vibgrate", "scan_result.json"));
|
|
7732
7803
|
let pinnedRegion;
|
|
7733
7804
|
let planTier;
|
|
7734
7805
|
let upgradeUrl;
|
|
@@ -8007,11 +8078,11 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
8007
8078
|
scanned++;
|
|
8008
8079
|
if (scanned > MAX_ENTRIES) break;
|
|
8009
8080
|
if (e.isDirectory()) {
|
|
8010
|
-
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(
|
|
8081
|
+
if (!SKIP_DIRS2.has(e.name) && !e.name.startsWith(".")) walk2(path37.join(dir, e.name), depth + 1);
|
|
8011
8082
|
continue;
|
|
8012
8083
|
}
|
|
8013
8084
|
if (!WATCHED_FILES.has(e.name) && !WATCHED_EXT.test(e.name)) continue;
|
|
8014
|
-
const abs =
|
|
8085
|
+
const abs = path37.join(dir, e.name);
|
|
8015
8086
|
let mtimeMs;
|
|
8016
8087
|
try {
|
|
8017
8088
|
mtimeMs = fs8.statSync(abs).mtimeMs;
|
|
@@ -8020,7 +8091,7 @@ function scanStaleness(rootDir, artifactPath) {
|
|
|
8020
8091
|
}
|
|
8021
8092
|
if (mtimeMs > newest) {
|
|
8022
8093
|
newest = mtimeMs;
|
|
8023
|
-
newestChanged =
|
|
8094
|
+
newestChanged = path37.relative(rootDir, abs) || e.name;
|
|
8024
8095
|
}
|
|
8025
8096
|
}
|
|
8026
8097
|
};
|
|
@@ -8157,13 +8228,13 @@ function analyzeTree(root2, packages) {
|
|
|
8157
8228
|
if (filesSeen >= MAX_FILES) return;
|
|
8158
8229
|
if (entry.isDirectory()) {
|
|
8159
8230
|
if (SKIP_DIRS3.has(entry.name) || entry.name.startsWith(".")) continue;
|
|
8160
|
-
walk2(
|
|
8231
|
+
walk2(path37.join(dir, entry.name), depth + 1);
|
|
8161
8232
|
continue;
|
|
8162
8233
|
}
|
|
8163
|
-
const fileEco = EXT_ECOSYSTEM[
|
|
8234
|
+
const fileEco = EXT_ECOSYSTEM[path37.extname(entry.name)];
|
|
8164
8235
|
if (!fileEco || fileEco === "unknown") continue;
|
|
8165
8236
|
filesSeen++;
|
|
8166
|
-
const full =
|
|
8237
|
+
const full = path37.join(dir, entry.name);
|
|
8167
8238
|
let content;
|
|
8168
8239
|
try {
|
|
8169
8240
|
if (fs8.statSync(full).size > MAX_FILE_BYTES2) continue;
|
|
@@ -8386,16 +8457,16 @@ function estimateDriftScore(artifact, upgraded) {
|
|
|
8386
8457
|
const buckets = p.dependencyAgeBuckets;
|
|
8387
8458
|
for (const dep of p.dependencies ?? []) {
|
|
8388
8459
|
if (!upgraded.has(dep.package)) continue;
|
|
8389
|
-
const
|
|
8460
|
+
const mb2 = dep.majorsBehind ?? 0;
|
|
8390
8461
|
dep.majorsBehind = 0;
|
|
8391
8462
|
dep.drift = "current";
|
|
8392
8463
|
if (dep.libyears != null) dep.libyears = 0;
|
|
8393
8464
|
if (dep.ageDays != null) dep.ageDays = 0;
|
|
8394
8465
|
if (dep.latestStable) dep.resolvedVersion = dep.latestStable;
|
|
8395
|
-
if (
|
|
8466
|
+
if (mb2 >= 2 && buckets.twoPlusBehind > 0) {
|
|
8396
8467
|
buckets.twoPlusBehind--;
|
|
8397
8468
|
buckets.current++;
|
|
8398
|
-
} else if (
|
|
8469
|
+
} else if (mb2 === 1 && buckets.oneBehind > 0) {
|
|
8399
8470
|
buckets.oneBehind--;
|
|
8400
8471
|
buckets.current++;
|
|
8401
8472
|
}
|
|
@@ -8478,7 +8549,7 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8478
8549
|
}
|
|
8479
8550
|
const outcomes = effective.map((t) => {
|
|
8480
8551
|
const c2 = pmCommandFor(u.ecosystem, u.package, u.to, opts.packageManager, { workspaceRoot: t.isWorkspaceRoot });
|
|
8481
|
-
return { t, res: run(c2,
|
|
8552
|
+
return { t, res: run(c2, path37.join(rootDir, t.dir)) };
|
|
8482
8553
|
});
|
|
8483
8554
|
const failures = outcomes.filter((o) => !o.res.ok);
|
|
8484
8555
|
if (failures.length === 0) {
|
|
@@ -8507,8 +8578,8 @@ function applyPlan(rootDir, upgrades, opts = {}) {
|
|
|
8507
8578
|
return results;
|
|
8508
8579
|
}
|
|
8509
8580
|
var REGISTRY_URL = "https://registry.npmjs.org/@vibgrate%2fcli/latest";
|
|
8510
|
-
var CACHE_DIR =
|
|
8511
|
-
var CACHE_FILE =
|
|
8581
|
+
var CACHE_DIR = path37.join(os.homedir(), ".vibgrate");
|
|
8582
|
+
var CACHE_FILE = path37.join(CACHE_DIR, "update-check.json");
|
|
8512
8583
|
async function fetchLatestVersion() {
|
|
8513
8584
|
try {
|
|
8514
8585
|
const controller = new AbortController();
|
|
@@ -8577,14 +8648,14 @@ async function findGlobalInstall(pkg = PACKAGE_NAME, run = defaultRunner) {
|
|
|
8577
8648
|
pm: "yarn",
|
|
8578
8649
|
root: () => {
|
|
8579
8650
|
const dir = tryRun("yarn global dir");
|
|
8580
|
-
return dir ?
|
|
8651
|
+
return dir ? path37.join(dir, "node_modules") : null;
|
|
8581
8652
|
}
|
|
8582
8653
|
},
|
|
8583
|
-
{ pm: "bun", root: () =>
|
|
8654
|
+
{ pm: "bun", root: () => path37.join(os.homedir(), ".bun", "install", "global", "node_modules") }
|
|
8584
8655
|
];
|
|
8585
8656
|
for (const probe of probes) {
|
|
8586
8657
|
const root2 = probe.root();
|
|
8587
|
-
if (root2 && await pathExists(
|
|
8658
|
+
if (root2 && await pathExists(path37.join(root2, pkg))) return probe.pm;
|
|
8588
8659
|
}
|
|
8589
8660
|
return null;
|
|
8590
8661
|
}
|
|
@@ -8603,15 +8674,15 @@ function getGlobalUpdateCommand(pm, pkg, version) {
|
|
|
8603
8674
|
}
|
|
8604
8675
|
}
|
|
8605
8676
|
async function detectPackageManager(cwd) {
|
|
8606
|
-
if (await pathExists(
|
|
8607
|
-
if (await pathExists(
|
|
8608
|
-
if (await pathExists(
|
|
8677
|
+
if (await pathExists(path37.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
8678
|
+
if (await pathExists(path37.join(cwd, "bun.lockb"))) return "bun";
|
|
8679
|
+
if (await pathExists(path37.join(cwd, "yarn.lock"))) return "yarn";
|
|
8609
8680
|
return "npm";
|
|
8610
8681
|
}
|
|
8611
8682
|
async function detectWorkspaceRoot(cwd) {
|
|
8612
|
-
if (await pathExists(
|
|
8683
|
+
if (await pathExists(path37.join(cwd, "pnpm-workspace.yaml"))) return true;
|
|
8613
8684
|
try {
|
|
8614
|
-
const pkgPath =
|
|
8685
|
+
const pkgPath = path37.join(cwd, "package.json");
|
|
8615
8686
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
8616
8687
|
const pkg = JSON.parse(raw);
|
|
8617
8688
|
return pkg.workspaces != null;
|
|
@@ -8636,7 +8707,7 @@ function getInstallCommand(pm, pkg, version, isDev, opts = {}) {
|
|
|
8636
8707
|
}
|
|
8637
8708
|
async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
8638
8709
|
try {
|
|
8639
|
-
const pkgPath =
|
|
8710
|
+
const pkgPath = path37.join(cwd, "package.json");
|
|
8640
8711
|
const raw = await (await import('fs/promises')).readFile(pkgPath, "utf-8");
|
|
8641
8712
|
const parsed = JSON.parse(raw);
|
|
8642
8713
|
if (parsed.devDependencies?.[pkg]) return "dev";
|
|
@@ -8648,11 +8719,11 @@ async function getLocalDependencyState(cwd, pkg = PACKAGE_NAME) {
|
|
|
8648
8719
|
async function confirmWorkspaceRoot(pm) {
|
|
8649
8720
|
if (!(process.stdin.isTTY && process.stdout.isTTY)) return false;
|
|
8650
8721
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
8651
|
-
return new Promise((
|
|
8722
|
+
return new Promise((resolve20) => {
|
|
8652
8723
|
rl.question(chalk7.yellow(`Update the ${pm} workspace root with -w? [y/N]: `), (ans) => {
|
|
8653
8724
|
rl.close();
|
|
8654
8725
|
const t = ans.trim().toLowerCase();
|
|
8655
|
-
|
|
8726
|
+
resolve20(t === "y" || t === "yes");
|
|
8656
8727
|
});
|
|
8657
8728
|
});
|
|
8658
8729
|
}
|
|
@@ -8784,13 +8855,13 @@ function collectCandidates(artifact) {
|
|
|
8784
8855
|
return out2;
|
|
8785
8856
|
}
|
|
8786
8857
|
var defaultFixScanner = async (rootDir) => {
|
|
8787
|
-
const scratch =
|
|
8858
|
+
const scratch = path37.join(os.tmpdir(), `vg-fix-scan-${process.pid}.json`);
|
|
8788
8859
|
const scanOpts = { vibgrateVersion: VERSION, format: "json", out: scratch, quiet: true, concurrency: 8 };
|
|
8789
8860
|
const advanced = await loadAdvancedScanHook();
|
|
8790
8861
|
return runCoreScan(rootDir, scanOpts, advanced);
|
|
8791
8862
|
};
|
|
8792
8863
|
async function loadArtifact(rootDir, inFile, scan = defaultFixScanner) {
|
|
8793
|
-
const artifactPath =
|
|
8864
|
+
const artifactPath = path37.isAbsolute(inFile) ? inFile : path37.join(rootDir, inFile);
|
|
8794
8865
|
if (await pathExists(artifactPath)) {
|
|
8795
8866
|
const staleness = scanStaleness(rootDir, artifactPath);
|
|
8796
8867
|
if (!staleness.stale) {
|
|
@@ -8817,7 +8888,7 @@ async function repositoryIdentity(rootDir, override) {
|
|
|
8817
8888
|
}
|
|
8818
8889
|
}
|
|
8819
8890
|
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) => {
|
|
8820
|
-
const rootDir =
|
|
8891
|
+
const rootDir = path37.resolve(targetPath);
|
|
8821
8892
|
if (!await pathExists(rootDir)) {
|
|
8822
8893
|
console.error(chalk7.red(`Path does not exist: ${rootDir}`));
|
|
8823
8894
|
process.exit(1);
|
|
@@ -8978,7 +9049,7 @@ function emit(report, format) {
|
|
|
8978
9049
|
}
|
|
8979
9050
|
}
|
|
8980
9051
|
function relProjectDir(rootDir, projectPath) {
|
|
8981
|
-
const rel =
|
|
9052
|
+
const rel = path37.isAbsolute(projectPath) ? path37.relative(rootDir, projectPath) : projectPath;
|
|
8982
9053
|
return rel === "" ? "." : rel;
|
|
8983
9054
|
}
|
|
8984
9055
|
async function buildTargetResolver(rootDir, artifact) {
|
|
@@ -9019,14 +9090,14 @@ function promptPlanSelection(response) {
|
|
|
9019
9090
|
const defaultIdx = plans.findIndex((p) => p.tier === response.recommended);
|
|
9020
9091
|
const def = defaultIdx >= 0 ? defaultIdx + 1 : 1;
|
|
9021
9092
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
9022
|
-
return new Promise((
|
|
9093
|
+
return new Promise((resolve20) => {
|
|
9023
9094
|
rl.question(`Plan [1-${plans.length}, default ${def}, q to cancel]: `, (ans) => {
|
|
9024
9095
|
rl.close();
|
|
9025
9096
|
const t = ans.trim().toLowerCase();
|
|
9026
|
-
if (t === "q" || t === "quit") return
|
|
9097
|
+
if (t === "q" || t === "quit") return resolve20(null);
|
|
9027
9098
|
const n = t === "" ? def : Number.parseInt(t, 10);
|
|
9028
|
-
if (!Number.isInteger(n) || n < 1 || n > plans.length) return
|
|
9029
|
-
|
|
9099
|
+
if (!Number.isInteger(n) || n < 1 || n > plans.length) return resolve20(null);
|
|
9100
|
+
resolve20(plans[n - 1].tier);
|
|
9030
9101
|
});
|
|
9031
9102
|
});
|
|
9032
9103
|
}
|
|
@@ -9813,7 +9884,7 @@ function formatMarkdown(artifact) {
|
|
|
9813
9884
|
|
|
9814
9885
|
// src/reporting/commands/report.ts
|
|
9815
9886
|
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) => {
|
|
9816
|
-
const artifactPath =
|
|
9887
|
+
const artifactPath = path37.resolve(opts.in);
|
|
9817
9888
|
if (!await pathExists(artifactPath)) {
|
|
9818
9889
|
console.error(chalk7.red(`Artifact not found: ${artifactPath}`));
|
|
9819
9890
|
console.error(chalk7.dim('Run "vibgrate scan" first to generate a scan artifact.'));
|
|
@@ -9859,10 +9930,10 @@ function openUrl(url) {
|
|
|
9859
9930
|
}
|
|
9860
9931
|
|
|
9861
9932
|
// src/reporting/commands/login.ts
|
|
9862
|
-
var delay = (ms) => new Promise((
|
|
9933
|
+
var delay = (ms) => new Promise((resolve20) => setTimeout(resolve20, ms));
|
|
9863
9934
|
function isInside(dir, file) {
|
|
9864
|
-
const rel =
|
|
9865
|
-
return !!rel && !rel.startsWith("..") && !
|
|
9935
|
+
const rel = path37.relative(dir, file);
|
|
9936
|
+
return !!rel && !rel.startsWith("..") && !path37.isAbsolute(rel);
|
|
9866
9937
|
}
|
|
9867
9938
|
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(
|
|
9868
9939
|
"--local",
|
|
@@ -10117,7 +10188,7 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10117
10188
|
try {
|
|
10118
10189
|
const statements = [];
|
|
10119
10190
|
if (opts.from) {
|
|
10120
|
-
const fromPath =
|
|
10191
|
+
const fromPath = path37.resolve(opts.from);
|
|
10121
10192
|
if (!await pathExists(fromPath)) {
|
|
10122
10193
|
process.stderr.write(chalk7.red(`Statements file not found: ${fromPath}
|
|
10123
10194
|
`));
|
|
@@ -10135,9 +10206,9 @@ var vexCommand = new Command("vex").description("Generate an OpenVEX document (e
|
|
|
10135
10206
|
});
|
|
10136
10207
|
const json2 = JSON.stringify(doc, null, 2);
|
|
10137
10208
|
if (opts.out) {
|
|
10138
|
-
await writeTextFile(
|
|
10209
|
+
await writeTextFile(path37.resolve(opts.out), json2 + "\n");
|
|
10139
10210
|
process.stderr.write(
|
|
10140
|
-
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${
|
|
10211
|
+
chalk7.green("\u2714") + ` Wrote OpenVEX document (${doc.statements.length} statement(s)) to ${path37.resolve(opts.out)}
|
|
10141
10212
|
`
|
|
10142
10213
|
);
|
|
10143
10214
|
} else {
|
|
@@ -10320,7 +10391,7 @@ function formatDeltaText(base, current) {
|
|
|
10320
10391
|
return lines.join("\n");
|
|
10321
10392
|
}
|
|
10322
10393
|
async function readArtifactOrExit(filePath) {
|
|
10323
|
-
const absolutePath =
|
|
10394
|
+
const absolutePath = path37.resolve(filePath);
|
|
10324
10395
|
if (!await pathExists(absolutePath)) {
|
|
10325
10396
|
console.error(chalk7.red(`Artifact not found: ${absolutePath}`));
|
|
10326
10397
|
process.exit(1);
|
|
@@ -10337,7 +10408,7 @@ var exportCommand = new Command("export").description("Export scan artifact as S
|
|
|
10337
10408
|
const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
|
|
10338
10409
|
const body = JSON.stringify(sbom, null, 2);
|
|
10339
10410
|
if (opts.out) {
|
|
10340
|
-
await writeTextFile(
|
|
10411
|
+
await writeTextFile(path37.resolve(opts.out), body);
|
|
10341
10412
|
console.log(chalk7.green("\u2714") + ` SBOM written to ${opts.out}`);
|
|
10342
10413
|
} else {
|
|
10343
10414
|
console.log(body);
|
|
@@ -10348,7 +10419,7 @@ var deltaCommand = new Command("delta").description("Show SBOM delta between two
|
|
|
10348
10419
|
const current = await readArtifactOrExit(opts.to);
|
|
10349
10420
|
const report = formatDeltaText(base, current);
|
|
10350
10421
|
if (opts.out) {
|
|
10351
|
-
await writeTextFile(
|
|
10422
|
+
await writeTextFile(path37.resolve(opts.out), report);
|
|
10352
10423
|
console.log(chalk7.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
|
|
10353
10424
|
} else {
|
|
10354
10425
|
console.log(report);
|
|
@@ -10479,20 +10550,20 @@ function resolveRegime(id) {
|
|
|
10479
10550
|
return regime;
|
|
10480
10551
|
}
|
|
10481
10552
|
function evidenceDir(root2) {
|
|
10482
|
-
return
|
|
10553
|
+
return path37.join(root2, ".vibgrate", "evidence");
|
|
10483
10554
|
}
|
|
10484
10555
|
function orgPath(root2) {
|
|
10485
|
-
return
|
|
10556
|
+
return path37.join(evidenceDir(root2), "org.json");
|
|
10486
10557
|
}
|
|
10487
10558
|
function productsPath(root2) {
|
|
10488
|
-
return
|
|
10559
|
+
return path37.join(evidenceDir(root2), "products.json");
|
|
10489
10560
|
}
|
|
10490
10561
|
function releasesDir(root2) {
|
|
10491
|
-
return
|
|
10562
|
+
return path37.join(evidenceDir(root2), "releases");
|
|
10492
10563
|
}
|
|
10493
10564
|
function releasePath(root2, productId, version) {
|
|
10494
10565
|
const safe = `${productId}@${version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
10495
|
-
return
|
|
10566
|
+
return path37.join(releasesDir(root2), `${safe}.json`);
|
|
10496
10567
|
}
|
|
10497
10568
|
var DEFAULT_ORG = {
|
|
10498
10569
|
responsiblePersons: [],
|
|
@@ -10523,7 +10594,7 @@ async function freezeRelease(root2, release) {
|
|
|
10523
10594
|
const p = releasePath(root2, release.productId, release.version);
|
|
10524
10595
|
if (await pathExists(p)) {
|
|
10525
10596
|
throw new CliError(
|
|
10526
|
-
`release ${release.productId}@${release.version} is already frozen and manifests are immutable \u2014 delete ${
|
|
10597
|
+
`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`,
|
|
10527
10598
|
ExitCode.USAGE_ERROR
|
|
10528
10599
|
);
|
|
10529
10600
|
}
|
|
@@ -10537,7 +10608,7 @@ async function loadReleases(root2, productId) {
|
|
|
10537
10608
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json")).sort();
|
|
10538
10609
|
const releases = [];
|
|
10539
10610
|
for (const f of files) {
|
|
10540
|
-
const rel = await readJsonFile(
|
|
10611
|
+
const rel = await readJsonFile(path37.join(dir, f));
|
|
10541
10612
|
if (!productId || rel.productId === productId) releases.push(rel);
|
|
10542
10613
|
}
|
|
10543
10614
|
return releases;
|
|
@@ -11232,12 +11303,12 @@ function verifyEvidenceEnvelope(env, opts = {}) {
|
|
|
11232
11303
|
var DEFAULT_KEY = "attest-key.pem";
|
|
11233
11304
|
function resolveSigningKey(root2, explicit) {
|
|
11234
11305
|
const chosen = process.env.VG_ATTEST_KEY;
|
|
11235
|
-
const keyPath = chosen ?
|
|
11306
|
+
const keyPath = chosen ? path37.resolve(chosen) : path37.join(root2, ".vibgrate", DEFAULT_KEY);
|
|
11236
11307
|
let minted = false;
|
|
11237
11308
|
if (!fs8.existsSync(keyPath)) {
|
|
11238
11309
|
if (chosen) throw new CliError(`signing key not found: ${chosen}`, ExitCode.USAGE_ERROR);
|
|
11239
11310
|
const kp = generateKeypair();
|
|
11240
|
-
fs8.mkdirSync(
|
|
11311
|
+
fs8.mkdirSync(path37.dirname(keyPath), { recursive: true });
|
|
11241
11312
|
fs8.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
|
|
11242
11313
|
fs8.writeFileSync(`${keyPath}.pub`, kp.publicPem);
|
|
11243
11314
|
minted = true;
|
|
@@ -11255,16 +11326,16 @@ function resolveSigningKey(root2, explicit) {
|
|
|
11255
11326
|
}
|
|
11256
11327
|
function writeBundle(input) {
|
|
11257
11328
|
const dir = input.outDir;
|
|
11258
|
-
fs8.mkdirSync(
|
|
11259
|
-
const write = (rel, data) => fs8.writeFileSync(
|
|
11329
|
+
fs8.mkdirSync(path37.join(dir, "inputs", "releases"), { recursive: true });
|
|
11330
|
+
const write = (rel, data) => fs8.writeFileSync(path37.join(dir, rel), `${JSON.stringify(data, null, 2)}
|
|
11260
11331
|
`);
|
|
11261
11332
|
write("result.json", input.result);
|
|
11262
|
-
write(
|
|
11333
|
+
write(path37.join("inputs", "advisory.json"), input.advisory);
|
|
11263
11334
|
for (const rel of input.releases) {
|
|
11264
11335
|
const safe = `${rel.productId}@${rel.version}`.replace(/[^A-Za-z0-9._@-]/g, "_");
|
|
11265
|
-
write(
|
|
11336
|
+
write(path37.join("inputs", "releases", `${safe}.json`), rel);
|
|
11266
11337
|
}
|
|
11267
|
-
write(
|
|
11338
|
+
write(path37.join("inputs", "datapack.lock"), { dataPackVersion: input.result.meta.dataPackVersion, kernelVersion: input.result.meta.kernelVersion });
|
|
11268
11339
|
write("provenance.json", {
|
|
11269
11340
|
method: "deterministic",
|
|
11270
11341
|
modelDrafted: [],
|
|
@@ -11280,13 +11351,13 @@ function writeBundle(input) {
|
|
|
11280
11351
|
disclaimer: input.regime.disclaimer
|
|
11281
11352
|
});
|
|
11282
11353
|
if (input.envelope) {
|
|
11283
|
-
fs8.writeFileSync(
|
|
11354
|
+
fs8.writeFileSync(path37.join(dir, "evidence.intoto.jsonl"), `${JSON.stringify(input.envelope)}
|
|
11284
11355
|
`);
|
|
11285
11356
|
}
|
|
11286
11357
|
if (input.timestampToken) {
|
|
11287
|
-
fs8.writeFileSync(
|
|
11358
|
+
fs8.writeFileSync(path37.join(dir, "timestamp.tsr"), input.timestampToken);
|
|
11288
11359
|
}
|
|
11289
|
-
fs8.writeFileSync(
|
|
11360
|
+
fs8.writeFileSync(path37.join(dir, "VERIFY.md"), verifyDoc(input));
|
|
11290
11361
|
return dir;
|
|
11291
11362
|
}
|
|
11292
11363
|
function verifyDoc(input) {
|
|
@@ -11347,26 +11418,26 @@ function undeterminedFields(result, regime) {
|
|
|
11347
11418
|
return gaps.filter((g) => regime.submission.requires.some((r) => g.startsWith(r)) || g.startsWith("exposure") || g.startsWith("member"));
|
|
11348
11419
|
}
|
|
11349
11420
|
async function recordDrill(root2, record) {
|
|
11350
|
-
const dir =
|
|
11351
|
-
const p =
|
|
11421
|
+
const dir = path37.join(evidenceDir(root2), "drills");
|
|
11422
|
+
const p = path37.join(dir, `${record.drillId}.json`);
|
|
11352
11423
|
await writeJsonFile(p, record);
|
|
11353
11424
|
return p;
|
|
11354
11425
|
}
|
|
11355
11426
|
async function hasRecentDrill(root2, asOf) {
|
|
11356
|
-
const dir =
|
|
11427
|
+
const dir = path37.join(evidenceDir(root2), "drills");
|
|
11357
11428
|
if (!await pathExists(dir)) return void 0;
|
|
11358
11429
|
const { readdir } = await import('fs/promises');
|
|
11359
|
-
const { readJsonFile: readJsonFile2 } = await import('./fs-
|
|
11430
|
+
const { readJsonFile: readJsonFile2 } = await import('./fs-O5IQYXHO.js');
|
|
11360
11431
|
const files = (await readdir(dir)).filter((f) => f.endsWith(".json"));
|
|
11361
11432
|
if (files.length === 0) return void 0;
|
|
11362
11433
|
const cutoff = new Date(new Date(asOf).getTime() - 90 * 24 * 3600 * 1e3).toISOString();
|
|
11363
11434
|
for (const f of files) {
|
|
11364
|
-
const rec = await readJsonFile2(
|
|
11435
|
+
const rec = await readJsonFile2(path37.join(dir, f));
|
|
11365
11436
|
if (rec.ranAt >= cutoff) return true;
|
|
11366
11437
|
}
|
|
11367
11438
|
return false;
|
|
11368
11439
|
}
|
|
11369
|
-
function
|
|
11440
|
+
function pad3(s, n) {
|
|
11370
11441
|
return s.length >= n ? s : s + " ".repeat(n - s.length);
|
|
11371
11442
|
}
|
|
11372
11443
|
function formatExposure(result, regime) {
|
|
@@ -11383,13 +11454,13 @@ function formatExposure(result, regime) {
|
|
|
11383
11454
|
}
|
|
11384
11455
|
lines.push("");
|
|
11385
11456
|
if (affected.length) {
|
|
11386
|
-
lines.push(" " + chalk7.dim(
|
|
11457
|
+
lines.push(" " + chalk7.dim(pad3("Product", 22) + pad3("Shipped versions", 24) + pad3("Markets", 16) + "Support"));
|
|
11387
11458
|
lines.push(" " + chalk7.dim("\u2500".repeat(74)));
|
|
11388
11459
|
for (const p of affected) {
|
|
11389
11460
|
const versions = p.affectedVersions.join(", ") || "\u2014";
|
|
11390
11461
|
const markets = p.memberStates.join(" ") || "\u2014";
|
|
11391
11462
|
const support = p.supportStatus === "in_support" ? chalk7.green("in support") : p.supportStatus === "expired" ? chalk7.yellow(p.supportDetail ?? "expired") : chalk7.dim("not declared");
|
|
11392
|
-
lines.push(" " +
|
|
11463
|
+
lines.push(" " + pad3(p.productName, 22) + pad3(versions, 24) + pad3(markets, 16) + support);
|
|
11393
11464
|
}
|
|
11394
11465
|
lines.push("");
|
|
11395
11466
|
}
|
|
@@ -11420,7 +11491,7 @@ function formatReadiness(report, regime) {
|
|
|
11420
11491
|
lines.push(" " + chalk7.bold(`Readiness \u2014 ${regime.name}`) + ` ${chalk7.bold(String(report.score))}% (${report.ready}/${report.assessable} ready)`);
|
|
11421
11492
|
lines.push("");
|
|
11422
11493
|
for (const item of report.items) {
|
|
11423
|
-
lines.push(" " + mark(item) + " " +
|
|
11494
|
+
lines.push(" " + mark(item) + " " + pad3(item.label, 52) + " " + chalk7.dim(item.detail));
|
|
11424
11495
|
if (item.status === "gap" && item.fix) lines.push(" " + chalk7.dim("fix: ") + chalk7.cyan(item.fix));
|
|
11425
11496
|
}
|
|
11426
11497
|
lines.push("");
|
|
@@ -11431,7 +11502,7 @@ function formatRegimeList() {
|
|
|
11431
11502
|
const lines = [" " + chalk7.bold("Available regimes")];
|
|
11432
11503
|
lines.push("");
|
|
11433
11504
|
for (const r of listRegimes()) {
|
|
11434
|
-
lines.push(" " + chalk7.cyan(
|
|
11505
|
+
lines.push(" " + chalk7.cyan(pad3(r.id, 16)) + r.name + chalk7.dim(` (${r.jurisdiction})`));
|
|
11435
11506
|
const clocks = r.clocks.map((c2) => `${c2.stage} ${c2.within}`).join(" \xB7 ");
|
|
11436
11507
|
lines.push(" " + chalk7.dim(clocks));
|
|
11437
11508
|
lines.push(" " + chalk7.dim(`submission: ${r.submission.target}${r.submission.api ? "" : " \u2014 manual (no API)"}`));
|
|
@@ -11441,7 +11512,7 @@ function formatRegimeList() {
|
|
|
11441
11512
|
|
|
11442
11513
|
// src/reporting/commands/evidence/index.ts
|
|
11443
11514
|
function root(opts) {
|
|
11444
|
-
return
|
|
11515
|
+
return path37.resolve(opts.cwd ?? process.cwd());
|
|
11445
11516
|
}
|
|
11446
11517
|
function slug(name) {
|
|
11447
11518
|
return name.trim().toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "product";
|
|
@@ -11529,7 +11600,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11529
11600
|
const release = await buildRelease({
|
|
11530
11601
|
productId: product.id,
|
|
11531
11602
|
version,
|
|
11532
|
-
from:
|
|
11603
|
+
from: path37.resolve(rootDir, opts.from),
|
|
11533
11604
|
shipDate: opts.shipDate,
|
|
11534
11605
|
buildId: opts.buildId,
|
|
11535
11606
|
artefactDigest: opts.digest,
|
|
@@ -11537,7 +11608,7 @@ var releaseCmd = new Command("release").description("Freeze a shipped release in
|
|
|
11537
11608
|
frozenAt: nowIso()
|
|
11538
11609
|
});
|
|
11539
11610
|
const p = await freezeRelease(rootDir, release);
|
|
11540
|
-
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${
|
|
11611
|
+
console.log(chalk7.green("\u2714") + ` froze ${chalk7.bold(`${product.id}@${version}`)} \u2014 ${release.components.length} components, immutable at ${path37.relative(rootDir, p)}`);
|
|
11541
11612
|
});
|
|
11542
11613
|
async function runExposure(rootDir, vuln, opts) {
|
|
11543
11614
|
const org = await loadOrg(rootDir);
|
|
@@ -11589,7 +11660,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
11589
11660
|
console.log("\n" + buildPack(result, regime, org, stage));
|
|
11590
11661
|
}
|
|
11591
11662
|
if (opts.bundle) {
|
|
11592
|
-
const dir =
|
|
11663
|
+
const dir = path37.resolve(rootDir, opts.bundle, `evidence-${result.meta.evidenceId}`);
|
|
11593
11664
|
let envelope;
|
|
11594
11665
|
if (opts.sign !== false) {
|
|
11595
11666
|
const { key: key2, minted } = resolveSigningKey(rootDir);
|
|
@@ -11597,7 +11668,7 @@ var exposureCmd = new Command("exposure").description("Which shipped products co
|
|
|
11597
11668
|
envelope = signEvidenceStatement(buildEvidenceStatement(result, VERSION), key2);
|
|
11598
11669
|
}
|
|
11599
11670
|
writeBundle({ outDir: dir, result, advisory, releases, regime, envelope, timestampToken, cliVersion: VERSION });
|
|
11600
|
-
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${
|
|
11671
|
+
console.error(chalk7.green("\u2714") + ` evidence bundle written to ${path37.relative(rootDir, dir)}${envelope ? " (signed)" : " (unsigned)"}${timestampToken ? " \xB7 RFC 3161" : ""}`);
|
|
11601
11672
|
}
|
|
11602
11673
|
process.exitCode = exposureExit(result.overallStatus);
|
|
11603
11674
|
});
|
|
@@ -11629,7 +11700,7 @@ var packCmd = new Command("pack").description("Build the submission pack a human
|
|
|
11629
11700
|
const stage = opts.stage ?? regime.clocks[0]?.stage ?? "early-warning";
|
|
11630
11701
|
const md = buildPack(result, regime, org, stage);
|
|
11631
11702
|
if (opts.out) {
|
|
11632
|
-
fs8.writeFileSync(
|
|
11703
|
+
fs8.writeFileSync(path37.resolve(rootDir, opts.out), md);
|
|
11633
11704
|
console.error(chalk7.green("\u2714") + ` pack written to ${opts.out}`);
|
|
11634
11705
|
} else {
|
|
11635
11706
|
console.log(md);
|
|
@@ -11671,18 +11742,18 @@ var drillCmd = new Command("drill").description("Timed dry-run of the determinat
|
|
|
11671
11742
|
}
|
|
11672
11743
|
});
|
|
11673
11744
|
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) => {
|
|
11674
|
-
const abs =
|
|
11675
|
-
const envPath = fs8.statSync(abs).isDirectory() ?
|
|
11745
|
+
const abs = path37.resolve(bundlePath);
|
|
11746
|
+
const envPath = fs8.statSync(abs).isDirectory() ? path37.join(abs, "evidence.intoto.jsonl") : abs;
|
|
11676
11747
|
if (!fs8.existsSync(envPath)) throw new CliError(`no evidence.intoto.jsonl at ${bundlePath}`, ExitCode.NOT_FOUND);
|
|
11677
11748
|
const envelope = JSON.parse(fs8.readFileSync(envPath, "utf8").trim().split("\n")[0]);
|
|
11678
|
-
const resultPath =
|
|
11749
|
+
const resultPath = path37.join(path37.dirname(envPath), "result.json");
|
|
11679
11750
|
const result = fs8.existsSync(resultPath) ? JSON.parse(fs8.readFileSync(resultPath, "utf8")) : void 0;
|
|
11680
|
-
const publicKeyPem = opts.pub ? fs8.readFileSync(
|
|
11751
|
+
const publicKeyPem = opts.pub ? fs8.readFileSync(path37.resolve(opts.pub), "utf8") : void 0;
|
|
11681
11752
|
const v = verifyEvidenceEnvelope(envelope, { publicKeyPem, result });
|
|
11682
11753
|
const color = v.status === "verified" ? chalk7.green : v.status === "failed" ? chalk7.red : chalk7.yellow;
|
|
11683
11754
|
console.log(" " + color(v.status.toUpperCase()) + ` ${v.reason}`);
|
|
11684
11755
|
if (v.evidenceId) console.log(" " + chalk7.dim(`evidence ${v.evidenceId} \xB7 regime ${v.regime} \xB7 advisory ${v.advisoryId} \xB7 ${v.overallStatus}`));
|
|
11685
|
-
const tsrPath =
|
|
11756
|
+
const tsrPath = path37.join(path37.dirname(envPath), "timestamp.tsr");
|
|
11686
11757
|
if (fs8.existsSync(tsrPath) && result) {
|
|
11687
11758
|
const t = verifyTimestamp(fs8.readFileSync(tsrPath), exposureSubjectDigest(result));
|
|
11688
11759
|
const tcolor = t.imprintMatches ? chalk7.green : chalk7.red;
|
|
@@ -11751,12 +11822,12 @@ var exportCmd = new Command("export").description("Air-gap bundle of all evidenc
|
|
|
11751
11822
|
const releases = [];
|
|
11752
11823
|
for (const list of releasesByProduct.values()) releases.push(...list);
|
|
11753
11824
|
const report = computeReadiness({ regime, org, products, releasesByProduct, recentDrill: await hasRecentDrill(rootDir, today()) });
|
|
11754
|
-
const dir =
|
|
11755
|
-
await writeJsonFile(
|
|
11756
|
-
await writeJsonFile(
|
|
11757
|
-
for (const r of releases) await writeJsonFile(
|
|
11758
|
-
await writeJsonFile(
|
|
11759
|
-
console.error(chalk7.green("\u2714") + ` exported evidence state to ${
|
|
11825
|
+
const dir = path37.resolve(rootDir, opts.out);
|
|
11826
|
+
await writeJsonFile(path37.join(dir, "org.json"), org);
|
|
11827
|
+
await writeJsonFile(path37.join(dir, "products.json"), products);
|
|
11828
|
+
for (const r of releases) await writeJsonFile(path37.join(dir, "releases", `${r.productId}@${r.version}.json`.replace(/[^A-Za-z0-9._@-]/g, "_")), r);
|
|
11829
|
+
await writeJsonFile(path37.join(dir, "readiness.json"), report);
|
|
11830
|
+
console.error(chalk7.green("\u2714") + ` exported evidence state to ${path37.relative(rootDir, dir)} (${products.length} products, ${releases.length} frozen releases)`);
|
|
11760
11831
|
});
|
|
11761
11832
|
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) => {
|
|
11762
11833
|
const rootDir = root(opts);
|
|
@@ -11782,8 +11853,8 @@ var pushCmd = new Command("push").description("Push the product registry (and an
|
|
|
11782
11853
|
}));
|
|
11783
11854
|
let exposure;
|
|
11784
11855
|
if (opts.result) {
|
|
11785
|
-
const raw =
|
|
11786
|
-
const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ?
|
|
11856
|
+
const raw = path37.resolve(rootDir, opts.result);
|
|
11857
|
+
const resultPath = fs8.existsSync(raw) && fs8.statSync(raw).isDirectory() ? path37.join(raw, "result.json") : raw;
|
|
11787
11858
|
if (!fs8.existsSync(resultPath)) throw new CliError(`no result.json at ${opts.result}`, ExitCode.NOT_FOUND);
|
|
11788
11859
|
exposure = JSON.parse(fs8.readFileSync(resultPath, "utf8"));
|
|
11789
11860
|
}
|
|
@@ -11849,7 +11920,7 @@ var KNOWN_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
11849
11920
|
"install",
|
|
11850
11921
|
"uninstall",
|
|
11851
11922
|
"share",
|
|
11852
|
-
"
|
|
11923
|
+
"watch",
|
|
11853
11924
|
"help",
|
|
11854
11925
|
// Drift-reporting verbs (merged from the Vibgrate CLI).
|
|
11855
11926
|
"init",
|
|
@@ -11890,7 +11961,7 @@ ${aliasNote}Docs: https://vibgrate.com/help`;
|
|
|
11890
11961
|
registerLsp(program);
|
|
11891
11962
|
registerInstall(program);
|
|
11892
11963
|
registerShare(program);
|
|
11893
|
-
|
|
11964
|
+
registerWatch(program);
|
|
11894
11965
|
registerTests(program);
|
|
11895
11966
|
registerFacts(program);
|
|
11896
11967
|
registerGuide(program);
|
|
@@ -11975,7 +12046,7 @@ function dispatch(argv, cwd) {
|
|
|
11975
12046
|
}
|
|
11976
12047
|
const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
|
|
11977
12048
|
if (looksLikeQuestion) return ["ask", ...args];
|
|
11978
|
-
if (fs8.existsSync(
|
|
12049
|
+
if (fs8.existsSync(path37.resolve(cwd, first))) {
|
|
11979
12050
|
return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
|
|
11980
12051
|
}
|
|
11981
12052
|
const moved = MOVED_COMMANDS[first];
|
|
@@ -12020,9 +12091,9 @@ async function main(argv = process.argv) {
|
|
|
12020
12091
|
}
|
|
12021
12092
|
function readCwd(raw) {
|
|
12022
12093
|
const i = raw.findIndex((a) => a === "-C" || a === "--cwd");
|
|
12023
|
-
if (i >= 0 && raw[i + 1]) return
|
|
12094
|
+
if (i >= 0 && raw[i + 1]) return path37.resolve(raw[i + 1]);
|
|
12024
12095
|
const eq = raw.find((a) => a.startsWith("--cwd="));
|
|
12025
|
-
if (eq) return
|
|
12096
|
+
if (eq) return path37.resolve(eq.slice("--cwd=".length));
|
|
12026
12097
|
return process.cwd();
|
|
12027
12098
|
}
|
|
12028
12099
|
function handleError(err) {
|