@vibgrate/cli 2026.720.2 → 2026.720.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -1,12 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, savingsLedgerPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, epistemicBreakdown, 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, fetchHostedDocsCached, selectForBudget, formatForExt, hostedBase, verifyDeterminism, renderHtml, isModelReady, SAVINGS_TOOLS, sanitizeClient, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-7R4O5CZD.js';
2
+ import { resolveDsn, resolveIngestHost, dashHostForIngestHost, resolveCliInvocation, availableRegionIds, createWorkspaceDsn, writeStoredCredentials, credentialsPath, findGitRoot, ensureGitignored, gitignoreEntryForCredentials, clearStoredCredentials, inventory, uploadScanArtifact, ingestHostForRegionId, dsnCommand, pushCommand, CliError, ExitCode, NPX_INVOCATION, refreshIfStale, driftCount, embeddingsCached, resolveEmbedModel, loadEmbedder, getNodeEmbeddings, queryGraphSemantic, queryGraph, unavailableMessage, recordCliCall, CLI_TOOL_ALIASES, countPending, resolveOne, indexFor, countTokens, shortestPath, renderReport, impactOf, testsToRun, detectRunner, defaultGraphPath, savingsLedgerPath, serveStdio, ASSISTANTS, detectAssistants, usageError, loadGraph, detectServeLaunch, installAssistant, writeNavigationConfig, uninstallAssistant, coveringTests, FREE_PACK, readScanArtifact, enrichOnline, ECOSYSTEMS, discoverModels, readSavings, readUsage, exportGraph, catalogPath, libDir, stableStringify, buildGraph, writeArtifacts, writeSnapshot, UsageError, ResourceLimitError, refreshInstalledInstructions, SMALL_REPO_FILES, epistemicBreakdown, 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, fetchHostedDocsCached, selectForBudget, formatForExt, hostedBase, verifyDeterminism, renderHtml, isModelReady, SAVINGS_TOOLS, sanitizeClient, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-AS7DIHZZ.js';
3
3
  import { resolvedGrammarFiles, grammarSetVersion, hashString, canonicalize, hashBytes } from './chunk-BHA7QIPD.js';
4
- import { loadAdvancedScanHook, baselineCommand } from './chunk-DDQ5JGBV.js';
5
- import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-OD5654VF.js';
4
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-ULAYELSU.js';
5
+ import { ensureDir, pathExists, writeDefaultConfig, parseDsn, detectVcs, computeRepoFingerprint, resolveRepositoryName, fetchScanPreflight, runCoreScan, VERSION, readJsonFile, writeTextFile, loadConfig, prepareCompressedUpload, computeDriftScore, titleBox, projectTypeToVulnEcosystem, driftBar, gitHistoryAvailable, buildVersionTimelines, findPackageAnyEcosystem, normalizeConstraint, findVersionCrossings, versionSatisfies, PROJECT_TYPE_TO_OSV_ECOSYSTEM, fetchRiskySymbols, brandProgressBar, resolveHead, workingTreeDirty } from './chunk-RAQBGOP5.js';
6
6
  import './chunk-RXP66R2E.js';
7
7
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
8
- import * as fs9 from 'fs';
9
- import fs9__default, { realpathSync } from 'fs';
8
+ import * as fs10 from 'fs';
9
+ import fs10__default, { realpathSync } from 'fs';
10
10
  import * as path from 'path';
11
11
  import path__default from 'path';
12
12
  import { fileURLToPath, pathToFileURL } from 'url';
@@ -16,7 +16,7 @@ import * as crypto from 'crypto';
16
16
  import { randomUUID } from 'crypto';
17
17
  import chalk8 from 'chalk';
18
18
  import * as os from 'os';
19
- import * as fs16 from 'fs/promises';
19
+ import * as fs17 from 'fs/promises';
20
20
  import * as readline from 'readline';
21
21
  import semver from 'semver';
22
22
 
@@ -178,14 +178,14 @@ async function signGraphAttestation(root, graph, opts) {
178
178
  const explicitKey = opts.key ?? process.env.VG_ATTEST_KEY;
179
179
  const keyPath = explicitKey ? path.resolve(explicitKey) : path.join(root, ".vibgrate", DEFAULT_KEY);
180
180
  let keyGeneratedAt;
181
- if (!fs9.existsSync(keyPath)) {
181
+ if (!fs10.existsSync(keyPath)) {
182
182
  if (explicitKey) {
183
183
  throw new CliError(`signing key not found: ${explicitKey}`, ExitCode.USAGE_ERROR);
184
184
  }
185
185
  const kp = generateKeypair();
186
- fs9.mkdirSync(path.dirname(keyPath), { recursive: true });
187
- fs9.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
188
- fs9.writeFileSync(`${keyPath}.pub`, kp.publicPem);
186
+ fs10.mkdirSync(path.dirname(keyPath), { recursive: true });
187
+ fs10.writeFileSync(keyPath, kp.privatePem, { mode: 384 });
188
+ fs10.writeFileSync(`${keyPath}.pub`, kp.publicPem);
189
189
  keyGeneratedAt = keyPath;
190
190
  notices.push(
191
191
  `minted a new Ed25519 signing key at ${rel(root, keyPath)} (keyid ${kp.keyid}) \u2014 keep it, add it to .gitignore, and reuse it to re-sign reproducibly`
@@ -193,7 +193,7 @@ async function signGraphAttestation(root, graph, opts) {
193
193
  }
194
194
  let privateKey;
195
195
  try {
196
- privateKey = crypto.createPrivateKey(fs9.readFileSync(keyPath, "utf8"));
196
+ privateKey = crypto.createPrivateKey(fs10.readFileSync(keyPath, "utf8"));
197
197
  } catch {
198
198
  throw new CliError(`could not read an Ed25519 private key from ${rel(root, keyPath)}`, ExitCode.USAGE_ERROR);
199
199
  }
@@ -207,8 +207,8 @@ async function signGraphAttestation(root, graph, opts) {
207
207
  const statement = buildStatement(graph, { commit });
208
208
  const envelope = signStatement(statement, privateKey);
209
209
  const outPath = opts.attestation ? path.resolve(opts.attestation) : path.join(root, ".vibgrate", DEFAULT_ATTESTATION);
210
- fs9.mkdirSync(path.dirname(outPath), { recursive: true });
211
- fs9.writeFileSync(outPath, serializeEnvelope(envelope));
210
+ fs10.mkdirSync(path.dirname(outPath), { recursive: true });
211
+ fs10.writeFileSync(outPath, serializeEnvelope(envelope));
212
212
  return {
213
213
  summary: {
214
214
  keyid: envelope.signatures[0]?.keyid ?? "",
@@ -223,7 +223,7 @@ async function signGraphAttestation(root, graph, opts) {
223
223
  }
224
224
  function verifyGraphAttestation(root, opts) {
225
225
  const bundlePath = opts.attestation ? path.resolve(opts.attestation) : path.join(root, ".vibgrate", DEFAULT_ATTESTATION);
226
- if (!fs9.existsSync(bundlePath)) {
226
+ if (!fs10.existsSync(bundlePath)) {
227
227
  if (opts.attestation || opts.pub) {
228
228
  throw new CliError(
229
229
  `no attestation at ${rel(root, bundlePath)} \u2014 sign one with \`vg build --attest\``,
@@ -232,8 +232,8 @@ function verifyGraphAttestation(root, opts) {
232
232
  }
233
233
  return { bundlePath, missing: true };
234
234
  }
235
- const envelope = parseEnvelope(fs9.readFileSync(bundlePath, "utf8"));
236
- const publicKeyPem = opts.pub ? fs9.readFileSync(path.resolve(opts.pub), "utf8") : void 0;
235
+ const envelope = parseEnvelope(fs10.readFileSync(bundlePath, "utf8"));
236
+ const publicKeyPem = opts.pub ? fs10.readFileSync(path.resolve(opts.pub), "utf8") : void 0;
237
237
  const graph = loadGraph(root) ?? void 0;
238
238
  return { bundlePath, missing: false, result: verifyEnvelope(envelope, { publicKeyPem, graph }) };
239
239
  }
@@ -431,6 +431,15 @@ async function runBuild(paths, opts, global) {
431
431
  });
432
432
  }
433
433
  if (opts.export) writeExport(result.graph, opts.export);
434
+ if (!global.graph) {
435
+ const fileCount = result.graph.nodes.filter((n) => n.kind === "file").length;
436
+ const refreshed = refreshInstalledInstructions(root, fileCount > 0 && fileCount < SMALL_REPO_FILES);
437
+ if (interactive) {
438
+ for (const r of refreshed) {
439
+ info(c.dim(`vg \xB7 refreshed assistant instructions ${r.file} (v${r.from} \u2192 v${r.to})`));
440
+ }
441
+ }
442
+ }
434
443
  let attestation;
435
444
  const attestNotices = [];
436
445
  if (opts.attest) {
@@ -586,8 +595,8 @@ function writeExport(graph, target) {
586
595
  ExitCode.USAGE_ERROR
587
596
  );
588
597
  }
589
- fs9.mkdirSync(path.dirname(path.resolve(target)), { recursive: true });
590
- fs9.writeFileSync(target, content);
598
+ fs10.mkdirSync(path.dirname(path.resolve(target)), { recursive: true });
599
+ fs10.writeFileSync(target, content);
591
600
  }
592
601
  function collect(value, prev) {
593
602
  return [...prev, value];
@@ -606,7 +615,7 @@ async function runStatus(global) {
606
615
  const root = path.resolve(global.cwd ?? ".");
607
616
  const graphPath = global.graph ?? defaultGraphPath(root);
608
617
  const graph = loadGraph(root, graphPath);
609
- const hasCache = fs9.existsSync(path.join(cacheDir(root), "parse-cache.json"));
618
+ const hasCache = fs10.existsSync(path.join(cacheDir(root), "parse-cache.json"));
610
619
  let stale = null;
611
620
  let staleExact = false;
612
621
  if (graph) {
@@ -1315,14 +1324,14 @@ function isCI(env = process.env) {
1315
1324
  function installId(env = process.env) {
1316
1325
  if (telemetryOptOut(env) !== null || isCI(env)) return randomUuid();
1317
1326
  try {
1318
- const existing = fs9.readFileSync(INSTALL_ID_FILE, "utf8").trim();
1327
+ const existing = fs10.readFileSync(INSTALL_ID_FILE, "utf8").trim();
1319
1328
  if (isUuid(existing)) return existing;
1320
1329
  } catch {
1321
1330
  }
1322
1331
  const id = randomUuid();
1323
1332
  try {
1324
- fs9.mkdirSync(INSTALL_ID_DIR, { recursive: true });
1325
- fs9.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
1333
+ fs10.mkdirSync(INSTALL_ID_DIR, { recursive: true });
1334
+ fs10.writeFileSync(INSTALL_ID_FILE, id + "\n", { mode: 384 });
1326
1335
  } catch {
1327
1336
  }
1328
1337
  return id;
@@ -1346,7 +1355,7 @@ function ledgerFilePath(root) {
1346
1355
  }
1347
1356
  function readOffset(root) {
1348
1357
  try {
1349
- const raw = JSON.parse(fs9.readFileSync(offsetPath(root), "utf8"));
1358
+ const raw = JSON.parse(fs10.readFileSync(offsetPath(root), "utf8"));
1350
1359
  return typeof raw.offset === "number" && raw.offset >= 0 ? raw.offset : 0;
1351
1360
  } catch {
1352
1361
  return 0;
@@ -1354,8 +1363,8 @@ function readOffset(root) {
1354
1363
  }
1355
1364
  function writeOffset(root, offset) {
1356
1365
  try {
1357
- fs9.mkdirSync(cacheDir(root), { recursive: true });
1358
- fs9.writeFileSync(offsetPath(root), JSON.stringify({ offset }) + "\n");
1366
+ fs10.mkdirSync(cacheDir(root), { recursive: true });
1367
+ fs10.writeFileSync(offsetPath(root), JSON.stringify({ offset }) + "\n");
1359
1368
  } catch {
1360
1369
  }
1361
1370
  }
@@ -1363,7 +1372,7 @@ function buildBatch(root, fromOffset, id = installId()) {
1363
1372
  const file = ledgerFilePath(root);
1364
1373
  let size = 0;
1365
1374
  try {
1366
- size = fs9.statSync(file).size;
1375
+ size = fs10.statSync(file).size;
1367
1376
  } catch {
1368
1377
  return { batch: null, newOffset: 0 };
1369
1378
  }
@@ -1371,13 +1380,13 @@ function buildBatch(root, fromOffset, id = installId()) {
1371
1380
  if (start >= size) return { batch: null, newOffset: size };
1372
1381
  let text = "";
1373
1382
  try {
1374
- const fd = fs9.openSync(file, "r");
1383
+ const fd = fs10.openSync(file, "r");
1375
1384
  try {
1376
1385
  const buf = Buffer.alloc(size - start);
1377
- fs9.readSync(fd, buf, 0, buf.length, start);
1386
+ fs10.readSync(fd, buf, 0, buf.length, start);
1378
1387
  text = buf.toString("utf8");
1379
1388
  } finally {
1380
- fs9.closeSync(fd);
1389
+ fs10.closeSync(fd);
1381
1390
  }
1382
1391
  } catch {
1383
1392
  return { batch: null, newOffset: fromOffset };
@@ -1509,6 +1518,139 @@ function isLoopbackOrigin(origin) {
1509
1518
  if (host === "localhost" || host === "[::1]" || host === "::1") return true;
1510
1519
  return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
1511
1520
  }
1521
+ var PUBLISH_INTERVAL_MS = 2e3;
1522
+ var KEEPALIVE_MS = 1e4;
1523
+ var STALE_MS = 6e4;
1524
+ function liveStatsDir(root) {
1525
+ return path.join(cacheDir(root), "serve-live");
1526
+ }
1527
+ var LiveStatsBus = class {
1528
+ constructor(dir, stats, pid = process.pid) {
1529
+ this.dir = dir;
1530
+ this.stats = stats;
1531
+ this.pid = pid;
1532
+ this.file = path.join(dir, `serve-${this.pid}.json`);
1533
+ }
1534
+ dir;
1535
+ stats;
1536
+ pid;
1537
+ timer = null;
1538
+ lastRevision = -1;
1539
+ lastWriteAt = 0;
1540
+ file;
1541
+ start() {
1542
+ if (this.timer) return;
1543
+ this.publish();
1544
+ this.timer = setInterval(() => this.publish(), PUBLISH_INTERVAL_MS);
1545
+ this.timer.unref?.();
1546
+ process.on("exit", this.unlinkOwn);
1547
+ }
1548
+ stop() {
1549
+ if (this.timer) {
1550
+ clearInterval(this.timer);
1551
+ this.timer = null;
1552
+ }
1553
+ process.removeListener("exit", this.unlinkOwn);
1554
+ this.unlinkOwn();
1555
+ }
1556
+ /** Write the current snapshot when it changed (or as a keepalive). Never throws. */
1557
+ publish(now2 = Date.now()) {
1558
+ const snap = this.stats.snapshot();
1559
+ if (snap.revision === this.lastRevision && now2 - this.lastWriteAt < KEEPALIVE_MS) return;
1560
+ this.lastRevision = snap.revision;
1561
+ this.lastWriteAt = now2;
1562
+ const body = { pid: this.pid, updatedAt: now2, snapshot: snap };
1563
+ try {
1564
+ fs10.mkdirSync(this.dir, { recursive: true });
1565
+ const tmp = `${this.file}.tmp`;
1566
+ fs10.writeFileSync(tmp, JSON.stringify(body));
1567
+ fs10.renameSync(tmp, this.file);
1568
+ } catch {
1569
+ }
1570
+ }
1571
+ /**
1572
+ * Fresh snapshots of the OTHER serve processes in this repo. Stale files
1573
+ * (crashed processes) are swept best-effort while reading.
1574
+ */
1575
+ siblings(now2 = Date.now()) {
1576
+ let entries;
1577
+ try {
1578
+ entries = fs10.readdirSync(this.dir);
1579
+ } catch {
1580
+ return [];
1581
+ }
1582
+ const out2 = [];
1583
+ for (const name of entries.sort()) {
1584
+ if (!/^serve-\d+\.json$/.test(name)) continue;
1585
+ const file = path.join(this.dir, name);
1586
+ let parsed;
1587
+ try {
1588
+ parsed = JSON.parse(fs10.readFileSync(file, "utf8"));
1589
+ } catch {
1590
+ continue;
1591
+ }
1592
+ if (typeof parsed?.pid !== "number" || typeof parsed.updatedAt !== "number" || !parsed.snapshot?.totals) continue;
1593
+ if (now2 - parsed.updatedAt > STALE_MS) {
1594
+ try {
1595
+ fs10.unlinkSync(file);
1596
+ } catch {
1597
+ }
1598
+ continue;
1599
+ }
1600
+ if (parsed.pid === this.pid) continue;
1601
+ out2.push(parsed.snapshot);
1602
+ }
1603
+ return out2;
1604
+ }
1605
+ unlinkOwn = () => {
1606
+ try {
1607
+ fs10.unlinkSync(this.file);
1608
+ } catch {
1609
+ }
1610
+ };
1611
+ };
1612
+ function addInto(target, add) {
1613
+ target.calls += add.calls;
1614
+ target.complete += add.complete;
1615
+ target.partial += add.partial;
1616
+ target.miss += add.miss;
1617
+ target.timed += add.timed;
1618
+ target.totalMs += add.totalMs;
1619
+ target.vgTokens += add.vgTokens;
1620
+ target.baselineTokens += add.baselineTokens;
1621
+ }
1622
+ function mergeRows(base, extra) {
1623
+ const byKey = new Map(base.map((r) => [r.key, { ...r }]));
1624
+ for (const row of extra) {
1625
+ const hit = byKey.get(row.key);
1626
+ if (hit) addInto(hit, row);
1627
+ else byKey.set(row.key, { ...row });
1628
+ }
1629
+ return [...byKey.values()].sort((a, b) => b.calls - a.calls || a.key.localeCompare(b.key));
1630
+ }
1631
+ function mergeSnapshots(own, siblings) {
1632
+ if (!siblings.length) return own;
1633
+ const merged = {
1634
+ startedAt: own.startedAt,
1635
+ revision: own.revision,
1636
+ lastCallAt: own.lastCallAt,
1637
+ totals: { ...own.totals },
1638
+ clients: [...own.clients.map((r) => ({ ...r }))],
1639
+ tools: [...own.tools.map((r) => ({ ...r }))],
1640
+ sources: [...own.sources.map((r) => ({ ...r }))]
1641
+ };
1642
+ for (const s of siblings) {
1643
+ merged.revision += s.revision;
1644
+ if (s.lastCallAt !== null && (merged.lastCallAt === null || s.lastCallAt > merged.lastCallAt)) {
1645
+ merged.lastCallAt = s.lastCallAt;
1646
+ }
1647
+ addInto(merged.totals, s.totals);
1648
+ merged.clients = mergeRows(merged.clients, s.clients);
1649
+ merged.tools = mergeRows(merged.tools, s.tools);
1650
+ merged.sources = mergeRows(merged.sources, s.sources);
1651
+ }
1652
+ return merged;
1653
+ }
1512
1654
 
1513
1655
  // src/mcp/serve-stats.ts
1514
1656
  function zeroRow(key2) {
@@ -1590,14 +1732,16 @@ var teal2 = (s) => c.hex("#3FB0A4")(s);
1590
1732
  var mint2 = (s) => c.hex("#4FE3C1")(s);
1591
1733
  var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1592
1734
  var MAX_TOOL_ROWS = 8;
1593
- function serveStatusLines(snap, now2, tick = 0) {
1735
+ function serveStatusLines(snap, now2, tick = 0, siblingServers = 0) {
1594
1736
  const spinner = mint2(SPINNER[tick % SPINNER.length]);
1595
1737
  const up = fmtUptime(now2 - snap.startedAt);
1596
1738
  const lines = [];
1739
+ const siblingNote = siblingServers > 0 ? ` ${c.dim(`incl. ${siblingServers} assistant-spawned server${siblingServers === 1 ? "" : "s"} in this repo`)}` : null;
1597
1740
  if (snap.totals.calls === 0) {
1598
1741
  lines.push(
1599
1742
  ` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal2(up)} ${c.dim("\xB7 waiting for your assistant\u2019s first call (MCP tool call, or `vg \u2026 --client=<ai>` CLI)\u2026")}`
1600
1743
  );
1744
+ if (siblingNote) lines.push(siblingNote);
1601
1745
  return lines;
1602
1746
  }
1603
1747
  const t = snap.totals;
@@ -1634,6 +1778,7 @@ function serveStatusLines(snap, now2, tick = 0) {
1634
1778
  ` ${c.dim("est. saved \u2248")} ${mint2(`${fmtTokens(savedTokens)} context tokens`)} ${c.dim("(estimate)")}`
1635
1779
  );
1636
1780
  }
1781
+ if (siblingNote) lines.push(siblingNote);
1637
1782
  return lines;
1638
1783
  }
1639
1784
  function serveHeartbeatLine(snap, now2) {
@@ -1653,13 +1798,15 @@ function serveHeartbeatLine(snap, now2) {
1653
1798
  var TTY_INTERVAL_MS = 1e3;
1654
1799
  var HEARTBEAT_INTERVAL_MS = 15 * 60 * 1e3;
1655
1800
  var ServeStatusDisplay = class {
1656
- constructor(stats, stream = process.stderr) {
1801
+ constructor(stats, stream = process.stderr, siblings) {
1657
1802
  this.stats = stats;
1658
1803
  this.stream = stream;
1804
+ this.siblings = siblings;
1659
1805
  this.isTTY = (stream.isTTY ?? false) && process.env.VIBGRATE_PROGRESS_MODE !== "plain";
1660
1806
  }
1661
1807
  stats;
1662
1808
  stream;
1809
+ siblings;
1663
1810
  timer = null;
1664
1811
  tick = 0;
1665
1812
  lastRowCount = 0;
@@ -1702,7 +1849,9 @@ var ServeStatusDisplay = class {
1702
1849
  }
1703
1850
  renderTTY() {
1704
1851
  this.tick++;
1705
- const lines = serveStatusLines(this.stats.snapshot(), Date.now(), this.tick);
1852
+ const sibs = this.siblings?.() ?? [];
1853
+ const snap = mergeSnapshots(this.stats.snapshot(), sibs);
1854
+ const lines = serveStatusLines(snap, Date.now(), this.tick, sibs.length);
1706
1855
  const content = lines.join("\n") + "\n";
1707
1856
  if (content === this.lastFrame) return;
1708
1857
  this.lastFrame = content;
@@ -1774,12 +1923,12 @@ var LedgerTail = class {
1774
1923
  if (size === this.offset) return;
1775
1924
  let chunk;
1776
1925
  try {
1777
- const fd = fs9.openSync(this.file, "r");
1926
+ const fd = fs10.openSync(this.file, "r");
1778
1927
  try {
1779
1928
  chunk = Buffer.alloc(size - this.offset);
1780
- fs9.readSync(fd, chunk, 0, chunk.length, this.offset);
1929
+ fs10.readSync(fd, chunk, 0, chunk.length, this.offset);
1781
1930
  } finally {
1782
- fs9.closeSync(fd);
1931
+ fs10.closeSync(fd);
1783
1932
  }
1784
1933
  } catch {
1785
1934
  return;
@@ -1792,7 +1941,7 @@ var LedgerTail = class {
1792
1941
  }
1793
1942
  sizeOf() {
1794
1943
  try {
1795
- return fs9.statSync(this.file).size;
1944
+ return fs10.statSync(this.file).size;
1796
1945
  } catch {
1797
1946
  return 0;
1798
1947
  }
@@ -1856,8 +2005,11 @@ function registerServe(program) {
1856
2005
  info(c.dim(`vg \xB7 --share-stats disabled by ${optOut}: recording locally, not uploading.`));
1857
2006
  }
1858
2007
  if (shareStats) startSharing(root);
1859
- const display = stats ? new ServeStatusDisplay(stats) : void 0;
1860
- if (stats) new LedgerTail(savingsLedgerPath(root), stats).start();
2008
+ const interactive = process.stderr.isTTY === true;
2009
+ const bus = stats ? new LiveStatsBus(liveStatsDir(root), stats) : void 0;
2010
+ if (bus && !interactive) bus.start();
2011
+ const display = stats ? new ServeStatusDisplay(stats, process.stderr, bus && interactive ? () => bus.siblings() : void 0) : void 0;
2012
+ if (stats && interactive) new LedgerTail(savingsLedgerPath(root), stats).start();
1861
2013
  const freshness = refresh ? "auto-refresh" : "as built";
1862
2014
  if (opts.http) {
1863
2015
  await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
@@ -1871,7 +2023,7 @@ function registerServe(program) {
1871
2023
  }
1872
2024
  async function ensureServableGraph(root, graphPath, global, refresh, opts = {}) {
1873
2025
  if (refresh) {
1874
- if (!fs9.existsSync(graphPath)) {
2026
+ if (!fs10.existsSync(graphPath)) {
1875
2027
  info(c.dim("vg \xB7 no map found \u2014 building it before serving\u2026"));
1876
2028
  await runBuild(
1877
2029
  [],
@@ -1888,7 +2040,7 @@ async function ensureServableGraph(root, graphPath, global, refresh, opts = {})
1888
2040
  }
1889
2041
  }
1890
2042
  }
1891
- if (!fs9.existsSync(graphPath)) {
2043
+ if (!fs10.existsSync(graphPath)) {
1892
2044
  throw new CliError(
1893
2045
  `no map found at ${graphPath} \u2014 run \`vg\` to build one first`,
1894
2046
  ExitCode.NOT_FOUND
@@ -2171,7 +2323,7 @@ function manifestHash(root) {
2171
2323
  const walk2 = (dir) => {
2172
2324
  let entries;
2173
2325
  try {
2174
- entries = fs9.readdirSync(dir, { withFileTypes: true });
2326
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
2175
2327
  } catch {
2176
2328
  return;
2177
2329
  }
@@ -2187,7 +2339,7 @@ function manifestHash(root) {
2187
2339
  if (!isManifest(abs) && !SKIP_FILES.has(base)) continue;
2188
2340
  try {
2189
2341
  const rel3 = path.relative(root, abs).split(path.sep).join("/");
2190
- files.push({ rel: rel3, hash: hashBytes(fs9.readFileSync(abs)) });
2342
+ files.push({ rel: rel3, hash: hashBytes(fs10.readFileSync(abs)) });
2191
2343
  } catch {
2192
2344
  }
2193
2345
  }
@@ -2198,7 +2350,7 @@ function manifestHash(root) {
2198
2350
  }
2199
2351
  function loadScanCache(root, key2) {
2200
2352
  try {
2201
- const raw = JSON.parse(fs9.readFileSync(cachePath(root), "utf8"));
2353
+ const raw = JSON.parse(fs10.readFileSync(cachePath(root), "utf8"));
2202
2354
  if (raw.version === CACHE_VERSION && raw.manifestHash === key2.manifestHash && raw.toolVersion === key2.toolVersion && raw.offline === key2.offline && raw.artifact) {
2203
2355
  return { manifestHash: raw.manifestHash, artifact: raw.artifact };
2204
2356
  }
@@ -2208,8 +2360,8 @@ function loadScanCache(root, key2) {
2208
2360
  }
2209
2361
  function writeScanCache(root, key2, artifact) {
2210
2362
  try {
2211
- fs9.mkdirSync(cacheDir(root), { recursive: true });
2212
- fs9.writeFileSync(
2363
+ fs10.mkdirSync(cacheDir(root), { recursive: true });
2364
+ fs10.writeFileSync(
2213
2365
  cachePath(root),
2214
2366
  stableStringify(
2215
2367
  { version: CACHE_VERSION, manifestHash: key2.manifestHash, toolVersion: key2.toolVersion, offline: key2.offline, artifact },
@@ -3033,7 +3185,7 @@ function hoverMarkdown(dep, contribution) {
3033
3185
  return lines.join("\n");
3034
3186
  }
3035
3187
  function startLanguageServer(opts) {
3036
- if (!fs9.existsSync(opts.root)) {
3188
+ if (!fs10.existsSync(opts.root)) {
3037
3189
  process.stderr.write(`vg lsp: root does not exist: ${opts.root}
3038
3190
  `);
3039
3191
  process.exit(1);
@@ -3077,7 +3229,6 @@ function registerLsp(program) {
3077
3229
  }
3078
3230
 
3079
3231
  // src/commands/install.ts
3080
- var SMALL_REPO_FILES = 150;
3081
3232
  function registerInstall(program) {
3082
3233
  const install = program.command("install").description("add vg to your AI assistant(s): skill + MCP + advisory nudge").argument("[tools...]", `assistant ids: ${ASSISTANTS.map((a) => a.id).join(", ")}`).option("--all", "install for every supported assistant").option("--detect", "detect assistants in use (repo footprint, home config, PATH) and install for those; with --list, only report what was detected").option("--list", "show the support matrix and exit").option("--no-hook", "skip the advisory nudge").action(function(tools, opts) {
3083
3234
  const global = readGlobal(this);
@@ -3172,7 +3323,7 @@ function registerShare(program) {
3172
3323
  const global = readGlobal(this);
3173
3324
  const root = rootOf(global);
3174
3325
  const gitDir = path.join(root, ".git");
3175
- if (!fs9.existsSync(gitDir)) {
3326
+ if (!fs10.existsSync(gitDir)) {
3176
3327
  throw new CliError("not a git repository \u2014 run `vg share` inside a git repo", ExitCode.USAGE_ERROR);
3177
3328
  }
3178
3329
  if (opts.undo) {
@@ -3194,22 +3345,22 @@ function registerShare(program) {
3194
3345
  }
3195
3346
  function writeVibgrateGitignore(root, reports) {
3196
3347
  const dir = path.join(root, ".vibgrate");
3197
- fs9.mkdirSync(dir, { recursive: true });
3348
+ fs10.mkdirSync(dir, { recursive: true });
3198
3349
  const lines = ["# Managed by `vg share` \u2014 keep graph.json committed, ignore the rest", "cache/", "facts.jsonl"];
3199
3350
  if (!reports) lines.push("graph.html", "GRAPH_REPORT.md");
3200
- fs9.writeFileSync(path.join(dir, ".gitignore"), `${lines.join("\n")}
3351
+ fs10.writeFileSync(path.join(dir, ".gitignore"), `${lines.join("\n")}
3201
3352
  `);
3202
3353
  }
3203
3354
  function writeGitAttributes(root) {
3204
3355
  const file = path.join(root, ".gitattributes");
3205
3356
  const line = ".vibgrate/graph.json merge=vg";
3206
- let content = fs9.existsSync(file) ? fs9.readFileSync(file, "utf8") : "";
3357
+ let content = fs10.existsSync(file) ? fs10.readFileSync(file, "utf8") : "";
3207
3358
  if (!content.split("\n").some((l) => l.trim() === line)) {
3208
3359
  content = content.length ? `${content.replace(/\s*$/, "")}
3209
3360
  ${line}
3210
3361
  ` : `${line}
3211
3362
  `;
3212
- fs9.writeFileSync(file, content);
3363
+ fs10.writeFileSync(file, content);
3213
3364
  }
3214
3365
  }
3215
3366
  function configureMergeDriver(root) {
@@ -3218,7 +3369,7 @@ function configureMergeDriver(root) {
3218
3369
  }
3219
3370
  function installPreCommitHook(root) {
3220
3371
  const hooksDir = hookDir(root);
3221
- fs9.mkdirSync(hooksDir, { recursive: true });
3372
+ fs10.mkdirSync(hooksDir, { recursive: true });
3222
3373
  const file = path.join(hooksDir, "pre-commit");
3223
3374
  const block = [
3224
3375
  HOOK_BEGIN,
@@ -3228,7 +3379,7 @@ function installPreCommitHook(root) {
3228
3379
  "fi",
3229
3380
  HOOK_END
3230
3381
  ].join("\n");
3231
- let content = fs9.existsSync(file) ? fs9.readFileSync(file, "utf8") : "#!/bin/sh\n";
3382
+ let content = fs10.existsSync(file) ? fs10.readFileSync(file, "utf8") : "#!/bin/sh\n";
3232
3383
  const re = new RegExp(`${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}`);
3233
3384
  if (re.test(content)) content = content.replace(re, block);
3234
3385
  else content = `${content.replace(/\s*$/, "")}
@@ -3237,21 +3388,21 @@ ${block}
3237
3388
  `;
3238
3389
  if (!content.startsWith("#!")) content = `#!/bin/sh
3239
3390
  ${content}`;
3240
- fs9.writeFileSync(file, content);
3241
- fs9.chmodSync(file, 493);
3391
+ fs10.writeFileSync(file, content);
3392
+ fs10.chmodSync(file, 493);
3242
3393
  }
3243
3394
  function undo(root) {
3244
3395
  const hookFile = path.join(hookDir(root), "pre-commit");
3245
- if (fs9.existsSync(hookFile)) {
3396
+ if (fs10.existsSync(hookFile)) {
3246
3397
  const re = new RegExp(`\\n*${escapeRe(HOOK_BEGIN)}[\\s\\S]*?${escapeRe(HOOK_END)}\\n*`);
3247
- const next2 = fs9.readFileSync(hookFile, "utf8").replace(re, "\n");
3248
- if (next2.trim() === "#!/bin/sh") fs9.rmSync(hookFile);
3249
- else fs9.writeFileSync(hookFile, next2);
3398
+ const next2 = fs10.readFileSync(hookFile, "utf8").replace(re, "\n");
3399
+ if (next2.trim() === "#!/bin/sh") fs10.rmSync(hookFile);
3400
+ else fs10.writeFileSync(hookFile, next2);
3250
3401
  }
3251
3402
  const attr = path.join(root, ".gitattributes");
3252
- if (fs9.existsSync(attr)) {
3253
- const next2 = fs9.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3254
- fs9.writeFileSync(attr, next2);
3403
+ if (fs10.existsSync(attr)) {
3404
+ const next2 = fs10.readFileSync(attr, "utf8").split("\n").filter((l) => l.trim() !== ".vibgrate/graph.json merge=vg").join("\n");
3405
+ fs10.writeFileSync(attr, next2);
3255
3406
  }
3256
3407
  try {
3257
3408
  git(root, ["config", "--remove-section", "merge.vg"]);
@@ -3384,7 +3535,7 @@ function grepBaselineTokens(term, files) {
3384
3535
  if (f.size > 512 * 1024) continue;
3385
3536
  let content = "";
3386
3537
  try {
3387
- content = fs9.readFileSync(f.abs, "utf8");
3538
+ content = fs10.readFileSync(f.abs, "utf8");
3388
3539
  } catch {
3389
3540
  continue;
3390
3541
  }
@@ -3394,7 +3545,7 @@ function grepBaselineTokens(term, files) {
3394
3545
  }
3395
3546
  function safeSize(abs) {
3396
3547
  try {
3397
- return fs9.statSync(abs).size;
3548
+ return fs10.statSync(abs).size;
3398
3549
  } catch {
3399
3550
  return 0;
3400
3551
  }
@@ -3728,7 +3879,7 @@ function loadStandards(root) {
3728
3879
  const p = path__default.join(root, rel3);
3729
3880
  let text;
3730
3881
  try {
3731
- text = fs9__default.readFileSync(p, "utf8");
3882
+ text = fs10__default.readFileSync(p, "utf8");
3732
3883
  } catch {
3733
3884
  continue;
3734
3885
  }
@@ -3967,7 +4118,7 @@ async function addCmd(root, rest, opts, asJson) {
3967
4118
  }
3968
4119
  function readPackageVersion(root) {
3969
4120
  try {
3970
- const pkg = JSON.parse(fs9__default.readFileSync(path__default.join(root, "package.json"), "utf8"));
4121
+ const pkg = JSON.parse(fs10__default.readFileSync(path__default.join(root, "package.json"), "utf8"));
3971
4122
  return typeof pkg.version === "string" ? pkg.version : void 0;
3972
4123
  } catch {
3973
4124
  return void 0;
@@ -3975,7 +4126,7 @@ function readPackageVersion(root) {
3975
4126
  }
3976
4127
  function readOptionalFile(p) {
3977
4128
  try {
3978
- const t = fs9__default.readFileSync(p, "utf8");
4129
+ const t = fs10__default.readFileSync(p, "utf8");
3979
4130
  return t.trim() ? t : void 0;
3980
4131
  } catch {
3981
4132
  return void 0;
@@ -4121,8 +4272,8 @@ function registerExport(program) {
4121
4272
  out(content.trimEnd());
4122
4273
  return;
4123
4274
  }
4124
- fs9.mkdirSync(path.dirname(path.resolve(file)), { recursive: true });
4125
- fs9.writeFileSync(file, content);
4275
+ fs10.mkdirSync(path.dirname(path.resolve(file)), { recursive: true });
4276
+ fs10.writeFileSync(file, content);
4126
4277
  info(`${c.green("\u2714")} wrote ${file} ${c.dim(`(${format})`)}`);
4127
4278
  });
4128
4279
  applyGlobalOptions(cmd);
@@ -4145,24 +4296,24 @@ function registerBundle(program) {
4145
4296
  } catch {
4146
4297
  throw new CliError("no grammars found to bundle (run a build first)", ExitCode.ERROR);
4147
4298
  }
4148
- fs9.mkdirSync(path.join(outDir, "grammars"), { recursive: true });
4299
+ fs10.mkdirSync(path.join(outDir, "grammars"), { recursive: true });
4149
4300
  let grammarCount = 0;
4150
4301
  for (const { fileName, absPath } of grammarFiles) {
4151
- fs9.copyFileSync(absPath, path.join(outDir, "grammars", fileName));
4302
+ fs10.copyFileSync(absPath, path.join(outDir, "grammars", fileName));
4152
4303
  grammarCount++;
4153
4304
  }
4154
4305
  const included = [`grammars/ (${grammarCount} .wasm)`];
4155
4306
  const graphSrc = global.graph ?? defaultGraphPath(root);
4156
- if (fs9.existsSync(graphSrc)) {
4157
- fs9.copyFileSync(graphSrc, path.join(outDir, "graph.json"));
4307
+ if (fs10.existsSync(graphSrc)) {
4308
+ fs10.copyFileSync(graphSrc, path.join(outDir, "graph.json"));
4158
4309
  included.push("graph.json");
4159
4310
  }
4160
4311
  const cat = catalogPath(root);
4161
- if (fs9.existsSync(cat)) {
4162
- fs9.copyFileSync(cat, path.join(outDir, "vibgrate.lib.json"));
4312
+ if (fs10.existsSync(cat)) {
4313
+ fs10.copyFileSync(cat, path.join(outDir, "vibgrate.lib.json"));
4163
4314
  included.push("vibgrate.lib.json");
4164
- if (fs9.existsSync(libDir(root))) {
4165
- fs9.cpSync(libDir(root), path.join(outDir, "lib"), { recursive: true });
4315
+ if (fs10.existsSync(libDir(root))) {
4316
+ fs10.cpSync(libDir(root), path.join(outDir, "lib"), { recursive: true });
4166
4317
  included.push("lib/");
4167
4318
  }
4168
4319
  }
@@ -4174,7 +4325,7 @@ function registerBundle(program) {
4174
4325
  included,
4175
4326
  usage: "Run `vg build --grammars <this dir>/grammars` to build fully offline."
4176
4327
  };
4177
- fs9.writeFileSync(path.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
4328
+ fs10.writeFileSync(path.join(outDir, "MANIFEST.json"), `${stableStringify(manifest, 2)}
4178
4329
  `);
4179
4330
  if (global.json) {
4180
4331
  json({ out: path.relative(root, outDir), ...manifest });
@@ -4198,7 +4349,7 @@ async function runDoctor(global) {
4198
4349
  const root = rootOf(global);
4199
4350
  const local = global.local === true;
4200
4351
  const graphPath = global.graph ?? defaultGraphPath(root);
4201
- const configFile = CONFIG_BASENAMES.find((f) => fs9.existsSync(path.join(root, f))) ?? null;
4352
+ const configFile = CONFIG_BASENAMES.find((f) => fs10.existsSync(path.join(root, f))) ?? null;
4202
4353
  const graph = loadGraph(root, graphPath);
4203
4354
  let staleFiles = null;
4204
4355
  if (graph) {
@@ -4226,7 +4377,7 @@ async function runDoctor(global) {
4226
4377
  },
4227
4378
  libCatalog: {
4228
4379
  path: path.relative(root, catalogPath(root)),
4229
- present: fs9.existsSync(catalogPath(root)),
4380
+ present: fs10.existsSync(catalogPath(root)),
4230
4381
  libraries: libCount
4231
4382
  },
4232
4383
  credentials: creds,
@@ -4318,7 +4469,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
4318
4469
  console.log(chalk8.green("\u2714") + ` Created ${chalk8.bold("vibgrate.config.ts")}`);
4319
4470
  }
4320
4471
  if (opts.baseline) {
4321
- const { runBaseline } = await import('./baseline-WIZAFIJS.js');
4472
+ const { runBaseline } = await import('./baseline-YJT32DP2.js');
4322
4473
  await runBaseline(rootDir);
4323
4474
  }
4324
4475
  console.log("");
@@ -4428,9 +4579,9 @@ async function fileReferencesIdentifier(rootDir, relFile, identifier, readFile3)
4428
4579
  }
4429
4580
  async function defaultReadFile(absPath) {
4430
4581
  try {
4431
- const stat2 = await fs16.stat(absPath);
4582
+ const stat2 = await fs17.stat(absPath);
4432
4583
  if (!stat2.isFile() || stat2.size > MAX_FILE_BYTES) return null;
4433
- return await fs16.readFile(absPath, "utf8");
4584
+ return await fs17.readFile(absPath, "utf8");
4434
4585
  } catch {
4435
4586
  return null;
4436
4587
  }
@@ -5075,7 +5226,7 @@ var SKIP_DIRS2 = /* @__PURE__ */ new Set([
5075
5226
  function scanStaleness(rootDir, artifactPath) {
5076
5227
  let ref;
5077
5228
  try {
5078
- ref = fs9.statSync(artifactPath).mtimeMs;
5229
+ ref = fs10.statSync(artifactPath).mtimeMs;
5079
5230
  } catch {
5080
5231
  return { stale: false };
5081
5232
  }
@@ -5087,7 +5238,7 @@ function scanStaleness(rootDir, artifactPath) {
5087
5238
  if (depth > 8 || scanned > MAX_ENTRIES) return;
5088
5239
  let entries;
5089
5240
  try {
5090
- entries = fs9.readdirSync(dir, { withFileTypes: true });
5241
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
5091
5242
  } catch {
5092
5243
  return;
5093
5244
  }
@@ -5102,7 +5253,7 @@ function scanStaleness(rootDir, artifactPath) {
5102
5253
  const abs = path.join(dir, e.name);
5103
5254
  let mtimeMs;
5104
5255
  try {
5105
- mtimeMs = fs9.statSync(abs).mtimeMs;
5256
+ mtimeMs = fs10.statSync(abs).mtimeMs;
5106
5257
  } catch {
5107
5258
  continue;
5108
5259
  }
@@ -5236,7 +5387,7 @@ function analyzeTree(root, packages) {
5236
5387
  if (depth > MAX_DEPTH || filesSeen >= MAX_FILES) return;
5237
5388
  let entries;
5238
5389
  try {
5239
- entries = fs9.readdirSync(dir, { withFileTypes: true });
5390
+ entries = fs10.readdirSync(dir, { withFileTypes: true });
5240
5391
  } catch {
5241
5392
  return;
5242
5393
  }
@@ -5254,8 +5405,8 @@ function analyzeTree(root, packages) {
5254
5405
  const full = path.join(dir, entry.name);
5255
5406
  let content;
5256
5407
  try {
5257
- if (fs9.statSync(full).size > MAX_FILE_BYTES2) continue;
5258
- content = fs9.readFileSync(full, "utf8");
5408
+ if (fs10.statSync(full).size > MAX_FILE_BYTES2) continue;
5409
+ content = fs10.readFileSync(full, "utf8");
5259
5410
  } catch {
5260
5411
  continue;
5261
5412
  }
@@ -5623,8 +5774,8 @@ async function fetchLatestVersion() {
5623
5774
  }
5624
5775
  async function writeCache(data) {
5625
5776
  try {
5626
- await fs16.mkdir(CACHE_DIR, { recursive: true });
5627
- await fs16.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
5777
+ await fs17.mkdir(CACHE_DIR, { recursive: true });
5778
+ await fs17.writeFile(CACHE_FILE, JSON.stringify(data), "utf-8");
5628
5779
  } catch {
5629
5780
  }
5630
5781
  }
@@ -5635,7 +5786,7 @@ function detectGlobalInstall(execPath = process.argv[1] || "", cwd = process.cwd
5635
5786
  if (!execPath) return null;
5636
5787
  let resolved = execPath;
5637
5788
  try {
5638
- resolved = fs9.realpathSync(execPath);
5789
+ resolved = fs10.realpathSync(execPath);
5639
5790
  } catch {
5640
5791
  }
5641
5792
  const p = resolved.replace(/\\/g, "/");
@@ -7575,7 +7726,7 @@ function dispatch(argv, cwd) {
7575
7726
  }
7576
7727
  const looksLikeQuestion = /\s/.test(first) || first.endsWith("?");
7577
7728
  if (looksLikeQuestion) return ["ask", ...args];
7578
- if (fs9.existsSync(path.resolve(cwd, first))) {
7729
+ if (fs10.existsSync(path.resolve(cwd, first))) {
7579
7730
  return [hasBuildOnlyFlag(args) ? "build" : "scan", ...args];
7580
7731
  }
7581
7732
  const moved = MOVED_COMMANDS[first];