@vibgrate/cli 2026.703.7 → 2026.704.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DOCS.md +22 -0
- package/dist/baseline-FESLZK5O.js +6 -0
- package/dist/{baseline-HBRBXJHJ.js.map → baseline-FESLZK5O.js.map} +1 -1
- package/dist/{chunk-UPPWLMVD.js → chunk-GI6W53LM.js} +3 -3
- package/dist/chunk-GI6W53LM.js.map +1 -0
- package/dist/{chunk-QWS7M7DG.js → chunk-RJHYTD62.js} +12 -12
- package/dist/{chunk-QWS7M7DG.js.map → chunk-RJHYTD62.js.map} +1 -1
- package/dist/{chunk-ZNVLRKWK.js → chunk-W4ANUENJ.js} +3 -3
- package/dist/{chunk-ZNVLRKWK.js.map → chunk-W4ANUENJ.js.map} +1 -1
- package/dist/{chunk-WGXDYBAN.js → chunk-YODVLV37.js} +271 -35
- package/dist/chunk-YODVLV37.js.map +1 -0
- package/dist/cli.js +97 -38
- package/dist/cli.js.map +1 -1
- package/dist/fs-IPY4FJKH.js +3 -0
- package/dist/fs-IPY4FJKH.js.map +1 -0
- package/dist/index.d.ts +48 -2
- package/dist/index.js +3 -3
- package/package.json +1 -1
- package/dist/baseline-HBRBXJHJ.js +0 -6
- package/dist/chunk-UPPWLMVD.js.map +0 -1
- package/dist/chunk-WGXDYBAN.js.map +0 -1
- package/dist/fs-DSQZWBO5.js +0 -3
- package/dist/fs-DSQZWBO5.js.map +0 -1
package/dist/cli.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, dsnCommand, pushCommand, ExitCode, CliError, NPX_INVOCATION, verifyDeterminism, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, resolveOne, GraphIndex, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, usageError, loadGraph, detectServeLaunch, installAssistant, uninstallAssistant,
|
|
2
|
+
import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, dsnCommand, pushCommand, ExitCode, CliError, NPX_INVOCATION, verifyDeterminism, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, countPending, resolveOne, GraphIndex, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, serveStdio, ASSISTANTS, usageError, loadGraph, detectServeLaunch, installAssistant, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, cacheDir, probeFreshness, discover, vibgrateDir, modelCacheInfo, clearModelCache, GraphSource, createServer, assistantById, serializeGraph, resolveLimits, loadCatalog, driftFor, addLibrary, parseDsn as parseDsn$1, publishPrivateLibrary, resolveLib, libId, resolveVersion, readDoc, localPackageDocs, localApiSurface, assessDocQuality, symbolsFromApi, fetchHostedDocs, selectForBudget, formatForExt, renderHtml, isModelReady } from './chunk-YODVLV37.js';
|
|
3
3
|
import { resolvedGrammarFiles, grammarSetVersion } from './chunk-X5YT263H.js';
|
|
4
|
-
import { loadAdvancedScanHook, baselineCommand } from './chunk-
|
|
5
|
-
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, prepareCompressedUpload, titleBox, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, brandProgressBar } from './chunk-
|
|
4
|
+
import { loadAdvancedScanHook, baselineCommand } from './chunk-W4ANUENJ.js';
|
|
5
|
+
import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, prepareCompressedUpload, titleBox, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, brandProgressBar } from './chunk-RJHYTD62.js';
|
|
6
6
|
import './chunk-RXP66R2E.js';
|
|
7
|
-
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-
|
|
7
|
+
import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
|
|
8
8
|
import * as fs4 from 'fs';
|
|
9
9
|
import fs4__default, { realpathSync } from 'fs';
|
|
10
10
|
import * as path9 from 'path';
|
|
@@ -156,6 +156,7 @@ async function runBuild(paths, opts, global) {
|
|
|
156
156
|
} catch (err) {
|
|
157
157
|
bar?.done();
|
|
158
158
|
if (err instanceof UsageError) throw usageError(err.message);
|
|
159
|
+
if (err instanceof ResourceLimitError) throw new CliError(err.message, ExitCode.ERROR);
|
|
159
160
|
throw err;
|
|
160
161
|
}
|
|
161
162
|
bar?.done();
|
|
@@ -192,7 +193,8 @@ async function runBuild(paths, opts, global) {
|
|
|
192
193
|
scip: result.scip,
|
|
193
194
|
artifacts: written,
|
|
194
195
|
corpusHash: result.graph.provenance.corpusHash,
|
|
195
|
-
timingMs: result.timing.totalMs
|
|
196
|
+
timingMs: result.timing.totalMs,
|
|
197
|
+
warnings: result.warnings
|
|
196
198
|
});
|
|
197
199
|
return;
|
|
198
200
|
}
|
|
@@ -1059,52 +1061,103 @@ function escapeRe(s) {
|
|
|
1059
1061
|
}
|
|
1060
1062
|
var PIN = "2020-01-01T00:00:00.000Z";
|
|
1061
1063
|
function registerBenchmark(program) {
|
|
1062
|
-
const cmd = program.command("benchmark").description("reproducible build + token-reduction benchmark (honest estimates)").option("--budget <n>", "token budget for vg answers", "2000").action(async function(opts) {
|
|
1064
|
+
const cmd = program.command("benchmark").description("reproducible build + memory + token-reduction benchmark (honest estimates)").option("--budget <n>", "token budget for vg answers", "2000").action(async function(opts) {
|
|
1063
1065
|
const global = readGlobal(this);
|
|
1064
1066
|
const root = rootOf(global);
|
|
1065
1067
|
const budget = Number(opts.budget) || 2e3;
|
|
1066
|
-
const
|
|
1067
|
-
const cold = await buildGraph({ root, generatedAt: PIN, noCache: true });
|
|
1068
|
-
const coldMs = now() - t0;
|
|
1069
|
-
const t1 = now();
|
|
1070
|
-
const warm = await buildGraph({ root, generatedAt: PIN });
|
|
1071
|
-
const warmMs = now() - t1;
|
|
1072
|
-
const a = serializeGraph(cold.graph);
|
|
1073
|
-
const b = serializeGraph((await buildGraph({ root, generatedAt: PIN, noCache: true })).graph);
|
|
1074
|
-
const deterministic = a === b;
|
|
1075
|
-
const questions = deriveQuestions(cold.graph);
|
|
1076
|
-
const fileSizes = fileSizeIndex(root);
|
|
1077
|
-
const perQuestion = questions.map((q) => {
|
|
1078
|
-
const vgTokens = queryGraph(cold.graph, q, { budget }).tokensEstimate;
|
|
1079
|
-
const baseTokens = grepBaselineTokens(q, fileSizes);
|
|
1080
|
-
return { question: q, vgTokens, baselineTokens: baseTokens, ratio: baseTokens > 0 ? round(baseTokens / Math.max(vgTokens, 1)) : 1 };
|
|
1081
|
-
});
|
|
1082
|
-
const totalVg = perQuestion.reduce((s, x) => s + x.vgTokens, 0);
|
|
1083
|
-
const totalBase = perQuestion.reduce((s, x) => s + x.baselineTokens, 0);
|
|
1084
|
-
const aggregateRatio = totalVg > 0 ? round(totalBase / totalVg) : 0;
|
|
1085
|
-
const result = {
|
|
1086
|
-
repo: { files: cold.totalFiles, nodes: cold.graph.meta.counts.nodes, edges: cold.graph.meta.counts.edges },
|
|
1087
|
-
build: { coldMs: round(coldMs), incrementalMs: round(warmMs), reusedOnWarm: warm.reused },
|
|
1088
|
-
determinism: { byteIdentical: deterministic },
|
|
1089
|
-
tokenReduction: { questions: perQuestion, aggregateRatio, note: "estimates (~4 chars/token); scales with repo size" }
|
|
1090
|
-
};
|
|
1068
|
+
const result = await runBenchmarkSuite(root, budget);
|
|
1091
1069
|
if (global.json) {
|
|
1092
1070
|
json(result);
|
|
1093
1071
|
return;
|
|
1094
1072
|
}
|
|
1095
|
-
|
|
1096
|
-
info(
|
|
1097
|
-
info(`
|
|
1098
|
-
|
|
1073
|
+
const { repo, build, throughput, memory, determinism, tokenReduction } = result;
|
|
1074
|
+
info(`${c.cyan("vg benchmark")} \xB7 ${repo.files} files \xB7 ${repo.nodes} nodes`);
|
|
1075
|
+
info(` build cold ${build.coldMs.toFixed(0)}ms \xB7 incremental ${build.incrementalMs.toFixed(0)}ms (reused ${build.reusedOnWarm})`);
|
|
1076
|
+
info(` speed ${throughput.filesPerSec.toFixed(0)} files/s \xB7 ${throughput.mbPerSec.toFixed(1)} MB/s (cold, ${mb2(throughput.corpusBytes).toFixed(1)} MB corpus)`);
|
|
1077
|
+
info(
|
|
1078
|
+
` memory peak rss ${memory.peakRssMb.toFixed(0)} MB (baseline ${memory.baselineRssMb.toFixed(0)} MB) \xB7 peak heap ${memory.peakHeapMb.toFixed(0)} MB \xB7 graph retains ~${memory.retainedHeapMb.toFixed(0)} MB ${c.dim("(approximate)")}`
|
|
1079
|
+
);
|
|
1080
|
+
info(` graph ${mb2(memory.graphJsonBytes).toFixed(1)} MB serialized \xB7 ${memory.bytesPerNode.toFixed(0)} B/node`);
|
|
1081
|
+
info(` determinism ${determinism.byteIdentical ? c.green("byte-identical \u2713") : c.red("NON-DETERMINISTIC \u2717")}`);
|
|
1082
|
+
if (tokenReduction.questions.length) {
|
|
1099
1083
|
info(` token reduction vs grep/read baseline (${c.dim("estimates")}):`);
|
|
1100
|
-
for (const q of
|
|
1084
|
+
for (const q of tokenReduction.questions) {
|
|
1101
1085
|
info(` ${pad2(`${q.ratio.toFixed(1)}\xD7`, 6)} ${c.dim(`vg ${q.vgTokens} vs ~${q.baselineTokens}`)} "${q.question}"`);
|
|
1102
1086
|
}
|
|
1103
|
-
info(` ${c.bold(`aggregate \u2248 ${aggregateRatio.toFixed(1)}\xD7 fewer tokens`)} ${c.dim("(honest estimate, scales with repo size)")}`);
|
|
1087
|
+
info(` ${c.bold(`aggregate \u2248 ${tokenReduction.aggregateRatio.toFixed(1)}\xD7 fewer tokens`)} ${c.dim("(honest estimate, scales with repo size)")}`);
|
|
1104
1088
|
}
|
|
1105
1089
|
});
|
|
1106
1090
|
applyGlobalOptions(cmd);
|
|
1107
1091
|
}
|
|
1092
|
+
async function runBenchmarkSuite(root, budget) {
|
|
1093
|
+
const baseline = process.memoryUsage();
|
|
1094
|
+
const sampler = startMemorySampler();
|
|
1095
|
+
const t0 = now();
|
|
1096
|
+
const cold = await buildGraph({ root, generatedAt: PIN, noCache: true });
|
|
1097
|
+
const coldMs = now() - t0;
|
|
1098
|
+
const t1 = now();
|
|
1099
|
+
const warm = await buildGraph({ root, generatedAt: PIN });
|
|
1100
|
+
const warmMs = now() - t1;
|
|
1101
|
+
const a = serializeGraph(cold.graph);
|
|
1102
|
+
const b = serializeGraph((await buildGraph({ root, generatedAt: PIN, noCache: true })).graph);
|
|
1103
|
+
const peak = sampler.stop();
|
|
1104
|
+
const deterministic = a === b;
|
|
1105
|
+
const after = process.memoryUsage();
|
|
1106
|
+
const corpusBytes = cold.fileStats.reduce((s, f) => s + f.size, 0);
|
|
1107
|
+
const graphJsonBytes = Buffer.byteLength(a, "utf8");
|
|
1108
|
+
const nodes = cold.graph.meta.counts.nodes;
|
|
1109
|
+
const questions = deriveQuestions(cold.graph);
|
|
1110
|
+
const fileSizes = fileSizeIndex(root);
|
|
1111
|
+
const perQuestion = questions.map((q) => {
|
|
1112
|
+
const vgTokens = queryGraph(cold.graph, q, { budget }).tokensEstimate;
|
|
1113
|
+
const baseTokens = grepBaselineTokens(q, fileSizes);
|
|
1114
|
+
return { question: q, vgTokens, baselineTokens: baseTokens, ratio: baseTokens > 0 ? round(baseTokens / Math.max(vgTokens, 1)) : 1 };
|
|
1115
|
+
});
|
|
1116
|
+
const totalVg = perQuestion.reduce((s, x) => s + x.vgTokens, 0);
|
|
1117
|
+
const totalBase = perQuestion.reduce((s, x) => s + x.baselineTokens, 0);
|
|
1118
|
+
const aggregateRatio = totalVg > 0 ? round(totalBase / totalVg) : 0;
|
|
1119
|
+
return {
|
|
1120
|
+
repo: { files: cold.totalFiles, nodes, edges: cold.graph.meta.counts.edges },
|
|
1121
|
+
build: { coldMs: round(coldMs), incrementalMs: round(warmMs), reusedOnWarm: warm.reused },
|
|
1122
|
+
throughput: {
|
|
1123
|
+
corpusBytes,
|
|
1124
|
+
filesPerSec: coldMs > 0 ? round(cold.totalFiles / coldMs * 1e3) : 0,
|
|
1125
|
+
// 6-decimal precision: a small corpus at 3 decimals would round to 0.
|
|
1126
|
+
mbPerSec: coldMs > 0 ? round6(mb2(corpusBytes) / coldMs * 1e3) : 0
|
|
1127
|
+
},
|
|
1128
|
+
memory: {
|
|
1129
|
+
baselineRssMb: round(mb2(baseline.rss)),
|
|
1130
|
+
peakRssMb: round(mb2(Math.max(peak.rss, baseline.rss))),
|
|
1131
|
+
peakHeapMb: round(mb2(Math.max(peak.heapUsed, baseline.heapUsed))),
|
|
1132
|
+
// Heap growth across the run ≈ what the loaded graphs + caches retain.
|
|
1133
|
+
retainedHeapMb: round(Math.max(0, mb2(after.heapUsed - baseline.heapUsed))),
|
|
1134
|
+
graphJsonBytes,
|
|
1135
|
+
bytesPerNode: nodes > 0 ? round(graphJsonBytes / nodes) : 0,
|
|
1136
|
+
note: "sampled at 25ms + phase boundaries; GC timing makes these approximate"
|
|
1137
|
+
},
|
|
1138
|
+
limits: resolveLimits(),
|
|
1139
|
+
determinism: { byteIdentical: deterministic },
|
|
1140
|
+
tokenReduction: { questions: perQuestion, aggregateRatio, note: "estimates (~4 chars/token); scales with repo size" }
|
|
1141
|
+
};
|
|
1142
|
+
}
|
|
1143
|
+
function startMemorySampler() {
|
|
1144
|
+
let rss = 0;
|
|
1145
|
+
let heapUsed = 0;
|
|
1146
|
+
const sample = () => {
|
|
1147
|
+
const m = process.memoryUsage();
|
|
1148
|
+
if (m.rss > rss) rss = m.rss;
|
|
1149
|
+
if (m.heapUsed > heapUsed) heapUsed = m.heapUsed;
|
|
1150
|
+
};
|
|
1151
|
+
const timer = setInterval(sample, 25);
|
|
1152
|
+
timer.unref?.();
|
|
1153
|
+
return {
|
|
1154
|
+
stop: () => {
|
|
1155
|
+
clearInterval(timer);
|
|
1156
|
+
sample();
|
|
1157
|
+
return { rss, heapUsed };
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1108
1161
|
function deriveQuestions(graph) {
|
|
1109
1162
|
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);
|
|
1110
1163
|
}
|
|
@@ -1133,12 +1186,18 @@ function safeSize(abs) {
|
|
|
1133
1186
|
return 0;
|
|
1134
1187
|
}
|
|
1135
1188
|
}
|
|
1189
|
+
function mb2(bytes) {
|
|
1190
|
+
return bytes / (1024 * 1024);
|
|
1191
|
+
}
|
|
1136
1192
|
function now() {
|
|
1137
1193
|
return Number(process.hrtime.bigint() / 1000n) / 1e3;
|
|
1138
1194
|
}
|
|
1139
1195
|
function round(x) {
|
|
1140
1196
|
return Math.round(x * 1e3) / 1e3;
|
|
1141
1197
|
}
|
|
1198
|
+
function round6(x) {
|
|
1199
|
+
return Math.round(x * 1e6) / 1e6;
|
|
1200
|
+
}
|
|
1142
1201
|
function pad2(s, n) {
|
|
1143
1202
|
return s.padStart(n, " ");
|
|
1144
1203
|
}
|
|
@@ -1882,7 +1941,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
|
|
|
1882
1941
|
console.log(chalk5.green("\u2714") + ` Created ${chalk5.bold("vibgrate.config.ts")}`);
|
|
1883
1942
|
}
|
|
1884
1943
|
if (opts.baseline) {
|
|
1885
|
-
const { runBaseline } = await import('./baseline-
|
|
1944
|
+
const { runBaseline } = await import('./baseline-FESLZK5O.js');
|
|
1886
1945
|
await runBaseline(rootDir);
|
|
1887
1946
|
}
|
|
1888
1947
|
console.log("");
|