@vibgrate/cli 2026.718.2 → 2026.720.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/dist/cli.js CHANGED
@@ -1,8 +1,8 @@
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, 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, readStoredCredentials, projectCredentialsPath, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-H5M7CXE6.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, 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, DEFAULT_RATE_LABEL, readStoredCredentials, projectCredentialsPath, DEFAULT_RATE_PER_M, homeCredentialsPath, SKIP_DIRS, SKIP_FILES } from './chunk-VQLOVQZP.js';
3
3
  import { resolvedGrammarFiles, grammarSetVersion, hashString, canonicalize, hashBytes } from './chunk-VFO5UDAT.js';
4
- import { loadAdvancedScanHook, baselineCommand } from './chunk-BFXDF6ZE.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-RME7BFMU.js';
4
+ import { loadAdvancedScanHook, baselineCommand } from './chunk-VYSTOEAK.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-AJDUMRVI.js';
6
6
  import './chunk-RXP66R2E.js';
7
7
  import { pathExists as pathExists$1, parseExcludePatterns } from './chunk-GI6W53LM.js';
8
8
  import * as fs8 from 'fs';
@@ -288,21 +288,23 @@ var ROBOT = [
288
288
  " " + c.dim("\u2524") + teal("\u2502") + " " + c.dim("\u2581\u2581") + " " + teal("\u2502") + c.dim("\u251C"),
289
289
  " " + teal("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F")
290
290
  ];
291
- function logoLines(root) {
291
+ function logoLines(root, opts = {}) {
292
+ const product = opts.product ?? "Graph";
293
+ const tagline = opts.tagline ?? "Code Intelligence Engine";
292
294
  return [
293
295
  "",
294
296
  ` ${ROBOT[0]}`,
295
297
  ` ${ROBOT[1]}`,
296
298
  ` ${ROBOT[2]}`,
297
299
  ` ${ROBOT[3]}`,
298
- ` ${c.bold.white("Vibgrate")} ${teal("Graph")} ${c.dim(`\xB7 Code Intelligence Engine \xB7 v${VERSION}`)}`,
300
+ ` ${c.bold.white("Vibgrate")} ${teal(product)} ${c.dim(`\xB7 ${tagline} \xB7 v${VERSION}`)}`,
299
301
  ...root ? [` ${c.dim(root)}`] : [],
300
302
  ""
301
303
  ];
302
304
  }
303
- function printLogo(root) {
305
+ function printLogo(root, opts = {}) {
304
306
  if (!process.stderr.isTTY) return;
305
- process.stderr.write(`${logoLines(root).join("\n")}
307
+ process.stderr.write(`${logoLines(root, opts).join("\n")}
306
308
  `);
307
309
  }
308
310
 
@@ -1508,6 +1510,220 @@ function isLoopbackOrigin(origin) {
1508
1510
  return /^127\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(host);
1509
1511
  }
1510
1512
 
1513
+ // src/mcp/serve-stats.ts
1514
+ function zeroRow(key2) {
1515
+ return { key: key2, calls: 0, complete: 0, partial: 0, miss: 0, totalMs: 0, vgTokens: 0, baselineTokens: 0 };
1516
+ }
1517
+ var SessionStats = class {
1518
+ startedAt;
1519
+ revision = 0;
1520
+ lastCallAt = null;
1521
+ totals = zeroRow("total");
1522
+ byClient = /* @__PURE__ */ new Map();
1523
+ byTool = /* @__PURE__ */ new Map();
1524
+ constructor(now2 = Date.now()) {
1525
+ this.startedAt = now2;
1526
+ }
1527
+ record(sample, now2 = Date.now()) {
1528
+ this.revision++;
1529
+ this.lastCallAt = now2;
1530
+ for (const row of [this.totals, this.rowFor(this.byClient, sample.client), this.rowFor(this.byTool, sample.tool)]) {
1531
+ row.calls++;
1532
+ row[sample.outcome]++;
1533
+ row.totalMs += sample.ms;
1534
+ row.vgTokens += sample.vgTokens;
1535
+ row.baselineTokens += sample.baselineTokens;
1536
+ }
1537
+ }
1538
+ snapshot() {
1539
+ const sorted = (m) => [...m.values()].map((r) => ({ ...r })).sort((a, b) => b.calls - a.calls || a.key.localeCompare(b.key));
1540
+ return {
1541
+ startedAt: this.startedAt,
1542
+ revision: this.revision,
1543
+ lastCallAt: this.lastCallAt,
1544
+ totals: { ...this.totals },
1545
+ clients: sorted(this.byClient),
1546
+ tools: sorted(this.byTool)
1547
+ };
1548
+ }
1549
+ rowFor(m, key2) {
1550
+ let row = m.get(key2);
1551
+ if (!row) {
1552
+ row = zeroRow(key2);
1553
+ m.set(key2, row);
1554
+ }
1555
+ return row;
1556
+ }
1557
+ };
1558
+ function fmtUptime(ms) {
1559
+ const s = Math.max(0, Math.floor(ms / 1e3));
1560
+ if (s < 60) return `${s}s`;
1561
+ const m = Math.floor(s / 60);
1562
+ if (m < 60) return `${m}m ${String(s % 60).padStart(2, "0")}s`;
1563
+ const h = Math.floor(m / 60);
1564
+ if (h < 24) return `${h}h ${String(m % 60).padStart(2, "0")}m`;
1565
+ const d = Math.floor(h / 24);
1566
+ return `${d}d ${String(h % 24).padStart(2, "0")}h`;
1567
+ }
1568
+ function fmtTokens(n) {
1569
+ if (n >= 1e6) return `${(n / 1e6).toFixed(2)}M`;
1570
+ if (n >= 1e3) return `${(n / 1e3).toFixed(1)}k`;
1571
+ return String(n);
1572
+ }
1573
+ function fmtAvgMs(row) {
1574
+ if (row.calls === 0) return "\u2014";
1575
+ const avg = row.totalMs / row.calls;
1576
+ return avg >= 1e3 ? `${(avg / 1e3).toFixed(1)}s` : `${Math.round(avg)}ms`;
1577
+ }
1578
+ var teal2 = (s) => c.hex("#3FB0A4")(s);
1579
+ var mint2 = (s) => c.hex("#4FE3C1")(s);
1580
+ var SPINNER = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
1581
+ var MAX_TOOL_ROWS = 8;
1582
+ function serveStatusLines(snap, now2, tick = 0) {
1583
+ const spinner = mint2(SPINNER[tick % SPINNER.length]);
1584
+ const up = fmtUptime(now2 - snap.startedAt);
1585
+ const lines = [];
1586
+ if (snap.totals.calls === 0) {
1587
+ lines.push(
1588
+ ` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal2(up)} ${c.dim("\xB7 waiting for your assistant\u2019s first tool call\u2026")}`
1589
+ );
1590
+ return lines;
1591
+ }
1592
+ const t = snap.totals;
1593
+ const answered = Math.round((t.complete + t.partial) / t.calls * 100);
1594
+ const ago = snap.lastCallAt === null ? "" : c.dim(` \xB7 last call ${fmtUptime(now2 - snap.lastCallAt)} ago`);
1595
+ lines.push(
1596
+ ` ${spinner} ${c.bold.white("vg serve")} ${c.dim("\xB7")} up ${teal2(up)} ${c.dim("\xB7")} ${c.bold.white(String(t.calls))} call${t.calls === 1 ? "" : "s"} ${c.dim("\xB7")} ${mint2(`${answered}%`)} answered${ago}`
1597
+ );
1598
+ lines.push(
1599
+ ` ${c.dim("clients")} ` + snap.clients.map((cl) => `${c.white(cl.key)} ${teal2(String(cl.calls))}${c.dim(` (avg ${fmtAvgMs(cl)})`)}`).join(c.dim(" \xB7 "))
1600
+ );
1601
+ const shown = snap.tools.slice(0, MAX_TOOL_ROWS);
1602
+ const nameW = Math.max(...shown.map((r) => r.key.length));
1603
+ for (const row of shown) {
1604
+ let line = ` ${c.white(row.key.padEnd(nameW))} ${teal2(String(row.calls).padStart(4))} ${c.dim("\xB7")} ` + c.dim(`avg ${fmtAvgMs(row)}`);
1605
+ if (SAVINGS_TOOLS.has(row.key) && row.baselineTokens > 0) {
1606
+ line += c.dim(" \xB7 ctx ") + c.white(fmtTokens(row.vgTokens)) + c.dim(` vs \u2248${fmtTokens(row.baselineTokens)} grep/read`);
1607
+ }
1608
+ if (row.miss > 0) line += c.dim(" \xB7 ") + c.yellow(`${row.miss} miss`);
1609
+ lines.push(line);
1610
+ }
1611
+ if (snap.tools.length > shown.length) {
1612
+ lines.push(` ${c.dim(`\u2026 +${snap.tools.length - shown.length} more tools`)}`);
1613
+ }
1614
+ if (t.baselineTokens > 0) {
1615
+ const savedTokens = Math.max(0, t.baselineTokens - t.vgTokens);
1616
+ const savedUsd = savedTokens / 1e6 * DEFAULT_RATE_PER_M;
1617
+ const ratio = t.vgTokens > 0 ? (t.baselineTokens / t.vgTokens).toFixed(1) : "\u2014";
1618
+ lines.push(
1619
+ ` ${c.dim("session")} ctx ${c.bold.white(fmtTokens(t.vgTokens))} ` + c.dim(`vs grep/read \u2248${fmtTokens(t.baselineTokens)} \u2192 `) + mint2(`${ratio}\xD7 fewer`)
1620
+ );
1621
+ lines.push(
1622
+ ` ${c.dim("est. saved \u2248")} ${mint2(`${fmtTokens(savedTokens)} tokens ($${savedUsd.toFixed(2)})`)} ` + c.dim(`(${DEFAULT_RATE_LABEL}; estimate)`)
1623
+ );
1624
+ }
1625
+ return lines;
1626
+ }
1627
+ function serveHeartbeatLine(snap, now2) {
1628
+ const up = fmtUptime(now2 - snap.startedAt);
1629
+ const t = snap.totals;
1630
+ if (t.calls === 0) return c.dim(`vg \xB7 serving for ${up} \u2014 no tool calls yet`);
1631
+ const clients = snap.clients.map((cl) => `${cl.key} ${cl.calls}`).join(", ");
1632
+ let line = `vg \xB7 serving for ${up} \u2014 ${t.calls} call${t.calls === 1 ? "" : "s"} (${clients})`;
1633
+ if (t.baselineTokens > 0) {
1634
+ const savedTokens = Math.max(0, t.baselineTokens - t.vgTokens);
1635
+ line += ` \xB7 ctx ${fmtTokens(t.vgTokens)} vs \u2248${fmtTokens(t.baselineTokens)} grep/read \xB7 est. saved \u2248 ${fmtTokens(savedTokens)} tokens`;
1636
+ }
1637
+ return c.dim(line);
1638
+ }
1639
+ var TTY_INTERVAL_MS = 1e3;
1640
+ var HEARTBEAT_INTERVAL_MS = 15 * 60 * 1e3;
1641
+ var ServeStatusDisplay = class {
1642
+ constructor(stats, stream = process.stderr) {
1643
+ this.stats = stats;
1644
+ this.stream = stream;
1645
+ this.isTTY = (stream.isTTY ?? false) && process.env.VIBGRATE_PROGRESS_MODE !== "plain";
1646
+ }
1647
+ stats;
1648
+ stream;
1649
+ timer = null;
1650
+ tick = 0;
1651
+ lastRowCount = 0;
1652
+ lastFrame = "";
1653
+ lastHeartbeatRevision = -1;
1654
+ cursorHidden = false;
1655
+ isTTY;
1656
+ start() {
1657
+ if (this.timer) return;
1658
+ if (this.isTTY) {
1659
+ this.hideCursor();
1660
+ process.on("exit", this.restoreCursor);
1661
+ process.once("SIGINT", () => {
1662
+ this.restoreCursor();
1663
+ process.exit(130);
1664
+ });
1665
+ process.once("SIGTERM", () => {
1666
+ this.restoreCursor();
1667
+ process.exit(143);
1668
+ });
1669
+ this.timer = setInterval(() => this.renderTTY(), TTY_INTERVAL_MS);
1670
+ this.renderTTY();
1671
+ } else {
1672
+ this.timer = setInterval(() => this.renderHeartbeat(), HEARTBEAT_INTERVAL_MS);
1673
+ }
1674
+ this.timer.unref?.();
1675
+ }
1676
+ stop() {
1677
+ if (this.timer) {
1678
+ clearInterval(this.timer);
1679
+ this.timer = null;
1680
+ }
1681
+ if (this.isTTY) {
1682
+ let buf = "";
1683
+ if (this.lastRowCount > 0) buf += `\x1B[${this.lastRowCount}A\x1B[J`;
1684
+ this.stream.write(buf);
1685
+ this.lastRowCount = 0;
1686
+ this.restoreCursor();
1687
+ }
1688
+ }
1689
+ renderTTY() {
1690
+ this.tick++;
1691
+ const lines = serveStatusLines(this.stats.snapshot(), Date.now(), this.tick);
1692
+ const content = lines.join("\n") + "\n";
1693
+ if (content === this.lastFrame) return;
1694
+ this.lastFrame = content;
1695
+ let buf = "";
1696
+ if (this.lastRowCount > 0) buf += `\x1B[${this.lastRowCount}A\x1B[J`;
1697
+ buf += content;
1698
+ this.stream.write(buf);
1699
+ this.lastRowCount = this.countRows(lines);
1700
+ }
1701
+ renderHeartbeat() {
1702
+ const snap = this.stats.snapshot();
1703
+ if (snap.revision === this.lastHeartbeatRevision) return;
1704
+ this.lastHeartbeatRevision = snap.revision;
1705
+ this.stream.write(serveHeartbeatLine(snap, Date.now()) + "\n");
1706
+ }
1707
+ /** Terminal rows the frame occupies, accounting for line wrap. */
1708
+ countRows(lines) {
1709
+ const columns = Math.max(this.stream.columns ?? 80, 20);
1710
+ return lines.reduce((total, line) => {
1711
+ const visible = line.replace(/\x1b\[[0-9;]*m/g, "").length;
1712
+ return total + Math.max(1, Math.ceil(visible / columns));
1713
+ }, 0);
1714
+ }
1715
+ hideCursor() {
1716
+ if (this.cursorHidden) return;
1717
+ this.stream.write("\x1B[?25l");
1718
+ this.cursorHidden = true;
1719
+ }
1720
+ restoreCursor = () => {
1721
+ if (!this.cursorHidden) return;
1722
+ this.stream.write("\x1B[?25h");
1723
+ this.cursorHidden = false;
1724
+ };
1725
+ };
1726
+
1511
1727
  // src/commands/serve.ts
1512
1728
  var SHARE_FLUSH_INTERVAL_MS = 5 * 60 * 1e3;
1513
1729
  function registerServe(program) {
@@ -1519,6 +1735,11 @@ function registerServe(program) {
1519
1735
  const local = global.local === true;
1520
1736
  const optOut = telemetryOptOut();
1521
1737
  const shareStats = opts.shareStats === true && !local && optOut === null;
1738
+ const quiet = global.quiet === true;
1739
+ const stats = quiet ? void 0 : new SessionStats();
1740
+ if (!quiet) {
1741
+ printLogo(root, { product: "AI Context", tagline: "Local-first MCP for your AI" });
1742
+ }
1522
1743
  const serveOpts = {
1523
1744
  // A *requested* --share-stats always implies local recording, even when
1524
1745
  // the upload itself is suppressed (--local / env opt-out) — the local
@@ -1528,7 +1749,8 @@ function registerServe(program) {
1528
1749
  shareStats,
1529
1750
  local,
1530
1751
  dedup: opts.dedup === true,
1531
- refresh
1752
+ refresh,
1753
+ stats
1532
1754
  };
1533
1755
  await ensureServableGraph(root, graphPath, global, refresh);
1534
1756
  if (opts.shareStats === true && local) {
@@ -1537,12 +1759,14 @@ function registerServe(program) {
1537
1759
  info(c.dim(`vg \xB7 --share-stats disabled by ${optOut}: recording locally, not uploading.`));
1538
1760
  }
1539
1761
  if (shareStats) startSharing(root);
1762
+ const display = stats ? new ServeStatusDisplay(stats) : void 0;
1540
1763
  const freshness = refresh ? "auto-refresh" : "as built";
1541
1764
  if (opts.http) {
1542
- await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness);
1765
+ await serveHttp(graphPath, opts.host ?? "127.0.0.1", Number(opts.port) || 7437, serveOpts, freshness, () => display?.start());
1543
1766
  } else {
1544
1767
  info(c.dim(`vg \xB7 MCP server on stdio (read-only, ${freshness}). Connect your assistant to this process.`));
1545
1768
  await serveStdio(graphPath, serveOpts);
1769
+ display?.start();
1546
1770
  }
1547
1771
  });
1548
1772
  applyGlobalOptions(cmd);
@@ -1598,7 +1822,7 @@ function startSharing(root) {
1598
1822
  });
1599
1823
  process.once("beforeExit", finalFlush);
1600
1824
  }
1601
- async function serveHttp(graphPath, host, port, opts, freshness) {
1825
+ async function serveHttp(graphPath, host, port, opts, freshness, onReady) {
1602
1826
  const { createServer: createHttp } = await import('http');
1603
1827
  const { StreamableHTTPServerTransport } = await import('@modelcontextprotocol/sdk/server/streamableHttp.js');
1604
1828
  const source = new GraphSource(graphPath, opts.refresh !== false);
@@ -1630,6 +1854,7 @@ async function serveHttp(graphPath, host, port, opts, freshness) {
1630
1854
  });
1631
1855
  await new Promise((resolve17) => httpServer.listen(port, host, resolve17));
1632
1856
  info(c.dim(`vg \xB7 MCP server on http://${host}:${port}/mcp (read-only, local, ${freshness})`));
1857
+ onReady?.();
1633
1858
  await new Promise(() => {
1634
1859
  });
1635
1860
  }
@@ -3558,17 +3783,18 @@ function printBreakdown(usage) {
3558
3783
  info("");
3559
3784
  info(c.bold(" by command") + c.dim(" (complete = full result \xB7 partial = capped/paginated \xB7 miss = no result)"));
3560
3785
  const nameW = Math.max(7, ...usage.commands.map((cmd) => cmd.tool.length));
3561
- const header = " " + "command".padEnd(nameW) + ["calls", "complete", "partial", "miss", "success%"].map((h) => h.padStart(9)).join("");
3786
+ const header = " " + "command".padEnd(nameW) + ["calls", "complete", "partial", "miss", "success%", "avg ms"].map((h) => h.padStart(9)).join("");
3562
3787
  info(c.dim(header));
3563
3788
  for (const cmd of usage.commands) {
3564
3789
  info(
3565
- " " + cmd.tool.padEnd(nameW) + String(cmd.calls).padStart(9) + String(cmd.complete).padStart(9) + String(cmd.partial).padStart(9) + String(cmd.miss).padStart(9) + `${cmd.successPct}%`.padStart(9)
3790
+ " " + cmd.tool.padEnd(nameW) + String(cmd.calls).padStart(9) + String(cmd.complete).padStart(9) + String(cmd.partial).padStart(9) + String(cmd.miss).padStart(9) + `${cmd.successPct}%`.padStart(9) + // Absent ≠ zero: calls recorded before timing existed show '—'.
3791
+ (cmd.avgMs === null ? "\u2014" : String(cmd.avgMs)).padStart(9)
3566
3792
  );
3567
3793
  }
3568
3794
  const t = usage.totals;
3569
- info(c.dim(" " + "\u2500".repeat(nameW + 45)));
3795
+ info(c.dim(" " + "\u2500".repeat(nameW + 54)));
3570
3796
  info(
3571
- " " + c.bold("total".padEnd(nameW)) + String(t.calls).padStart(9) + String(t.complete).padStart(9) + String(t.partial).padStart(9) + String(t.miss).padStart(9) + "".padStart(9)
3797
+ " " + c.bold("total".padEnd(nameW)) + String(t.calls).padStart(9) + String(t.complete).padStart(9) + String(t.partial).padStart(9) + String(t.miss).padStart(9) + "".padStart(9) + "".padStart(9)
3572
3798
  );
3573
3799
  info(c.dim(` avg success across commands: ${usage.avgSuccessPct}%`));
3574
3800
  }
@@ -3994,7 +4220,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
3994
4220
  console.log(chalk8.green("\u2714") + ` Created ${chalk8.bold("vibgrate.config.ts")}`);
3995
4221
  }
3996
4222
  if (opts.baseline) {
3997
- const { runBaseline } = await import('./baseline-DKPQWOQ6.js');
4223
+ const { runBaseline } = await import('./baseline-5QPV6API.js');
3998
4224
  await runBaseline(rootDir);
3999
4225
  }
4000
4226
  console.log("");
@@ -4299,22 +4525,22 @@ async function detectAiAssistant(rootDir) {
4299
4525
  return null;
4300
4526
  }
4301
4527
  function printAiContextPrompt(detectedAssistant) {
4302
- const teal2 = chalk8.hex("#3FB0A4");
4303
- const mint2 = chalk8.hex("#4FE3C1");
4528
+ const teal3 = chalk8.hex("#3FB0A4");
4529
+ const mint3 = chalk8.hex("#4FE3C1");
4304
4530
  const cli = resolveCliInvocation();
4305
4531
  const installArgs = detectedAssistant ? `install ${detectedAssistant}` : "install --all";
4306
4532
  const installCmd = `${cli} ${installArgs}`;
4307
4533
  const detectedNote = detectedAssistant ? chalk8.dim(` (${detectedAssistant} config detected)`) : "";
4308
4534
  console.log("");
4309
- console.log(teal2(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
4310
- console.log(teal2(" \u2502") + " " + mint2("\u25C6") + " " + chalk8.bold.white("Get AI-aware answers in your editor") + " " + teal2("\u2502"));
4311
- console.log(teal2(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
4535
+ console.log(teal3(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E"));
4536
+ console.log(teal3(" \u2502") + " " + mint3("\u25C6") + " " + chalk8.bold.white("Get AI-aware answers in your editor") + " " + teal3("\u2502"));
4537
+ console.log(teal3(" \u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
4312
4538
  console.log("");
4313
4539
  console.log(" " + chalk8.bold.white(installCmd) + detectedNote);
4314
4540
  console.log("");
4315
- console.log(" " + teal2("\xB7") + " " + chalk8.white("Code map in your assistant") + chalk8.dim(" \u2014 call trees, impact surfaces, import paths"));
4316
- console.log(" " + teal2("\xB7") + " " + chalk8.white("Offline drift") + chalk8.dim(" \u2014 DriftScore and upgrade priorities, right inside your editor"));
4317
- console.log(" " + teal2("\xB7") + " " + chalk8.white("Version-correct library docs") + chalk8.dim(" \u2014 pinned to your lockfile, no hallucinated APIs"));
4541
+ console.log(" " + teal3("\xB7") + " " + chalk8.white("Code map in your assistant") + chalk8.dim(" \u2014 call trees, impact surfaces, import paths"));
4542
+ console.log(" " + teal3("\xB7") + " " + chalk8.white("Offline drift") + chalk8.dim(" \u2014 DriftScore and upgrade priorities, right inside your editor"));
4543
+ console.log(" " + teal3("\xB7") + " " + chalk8.white("Version-correct library docs") + chalk8.dim(" \u2014 pinned to your lockfile, no hallucinated APIs"));
4318
4544
  console.log("");
4319
4545
  }
4320
4546
 
@@ -5840,15 +6066,15 @@ Applied the ${chosen.label} plan:`));
5840
6066
  }
5841
6067
  function formatText(artifact) {
5842
6068
  const lines = [];
5843
- const teal2 = chalk8.hex("#3FB0A4");
5844
- const mint2 = chalk8.hex("#4FE3C1");
6069
+ const teal3 = chalk8.hex("#3FB0A4");
6070
+ const mint3 = chalk8.hex("#4FE3C1");
5845
6071
  lines.push("");
5846
- lines.push(" " + teal2("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u256E") + mint2("\u279C"));
5847
- lines.push(" " + chalk8.dim("\u2524") + teal2("\u2502") + " " + mint2("\u25FC") + " " + mint2("\u25FC") + " " + teal2("\u2502") + chalk8.dim("\u251C") + " " + chalk8.bold.white("vibgrate"));
5848
- lines.push(" " + chalk8.dim("\u2524") + teal2("\u2502") + " " + chalk8.dim("\u2581\u2581") + " " + teal2("\u2502") + chalk8.dim("\u251C") + " " + chalk8.dim(`Code Intelligence Engine v${VERSION}`));
5849
- lines.push(" " + teal2("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
6072
+ lines.push(" " + teal3("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u256E") + mint3("\u279C"));
6073
+ lines.push(" " + chalk8.dim("\u2524") + teal3("\u2502") + " " + mint3("\u25FC") + " " + mint3("\u25FC") + " " + teal3("\u2502") + chalk8.dim("\u251C") + " " + chalk8.bold.white("vibgrate"));
6074
+ lines.push(" " + chalk8.dim("\u2524") + teal3("\u2502") + " " + chalk8.dim("\u2581\u2581") + " " + teal3("\u2502") + chalk8.dim("\u251C") + " " + chalk8.dim(`Code Intelligence Engine v${VERSION}`));
6075
+ lines.push(" " + teal3("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
5850
6076
  lines.push("");
5851
- lines.push(...titleBox("Vibgrate Drift Report", teal2));
6077
+ lines.push(...titleBox("Vibgrate Drift Report", teal3));
5852
6078
  lines.push("");
5853
6079
  for (const project of artifact.projects) {
5854
6080
  lines.push(chalk8.bold(` \u2500\u2500 ${project.name} `) + chalk8.dim(`(${project.type}) ${project.path}`));