@vibgrate/cli 2026.617.1 → 2026.618.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.
Files changed (2) hide show
  1. package/dist/cli.js +432 -387
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
 
31
31
  // src/cli.ts
32
32
  import { Command as Command13 } from "commander";
33
- import chalk14 from "chalk";
33
+ import chalk15 from "chalk";
34
34
 
35
35
  // src/commands/init.ts
36
36
  import * as path from "path";
@@ -62,7 +62,7 @@ var initCommand = new Command("init").description("Initialize vibgrate in a proj
62
62
  // src/commands/scan.ts
63
63
  import * as path4 from "path";
64
64
  import { Command as Command3 } from "commander";
65
- import chalk3 from "chalk";
65
+ import chalk4 from "chalk";
66
66
 
67
67
  // src/version.ts
68
68
  import { createRequire } from "module";
@@ -129,6 +129,9 @@ function dashHostForIngestHost(ingestHost) {
129
129
  const match = REGIONS.find((r) => r.ingestHost === ingestHost);
130
130
  return match?.dashHost ?? "dash.vibgrate.com";
131
131
  }
132
+ function ingestHostForRegionId(region) {
133
+ return findRegion(region.toLowerCase())?.ingestHost;
134
+ }
132
135
 
133
136
  // src/commands/dsn.ts
134
137
  async function provisionDsn(keyId, secret, workspaceId, ingestHost, region) {
@@ -261,18 +264,62 @@ function emitIngestIdLine(ingestId, options) {
261
264
  }
262
265
  }
263
266
 
267
+ // src/utils/upload.ts
268
+ import chalk3 from "chalk";
269
+ function postOnce(input, host) {
270
+ const url = `${input.scheme}://${host}/v1/ingest/scan`;
271
+ return fetch(url, {
272
+ method: "POST",
273
+ headers: {
274
+ "Content-Type": "application/json",
275
+ "Content-Encoding": input.contentEncoding,
276
+ "X-Vibgrate-Timestamp": input.timestamp,
277
+ "Authorization": `VibgrateDSN ${input.keyId}:${input.secret}`,
278
+ "Connection": "close"
279
+ // Prevent keep-alive delays on exit
280
+ },
281
+ body: input.body
282
+ });
283
+ }
284
+ async function regionRedirectHost(response) {
285
+ try {
286
+ const payload = await response.clone().json();
287
+ if (payload?.code !== "REGION_MISMATCH" || !payload.region) return void 0;
288
+ return ingestHostForRegionId(payload.region);
289
+ } catch {
290
+ return void 0;
291
+ }
292
+ }
293
+ async function uploadScanArtifact(input) {
294
+ let host = input.host;
295
+ let response = await postOnce(input, host);
296
+ if (response.status === 409) {
297
+ const target = await regionRedirectHost(response);
298
+ if (target && target !== host) {
299
+ console.log(
300
+ chalk3.yellow(
301
+ `\u21BB Workspace is pinned to a different region \u2014 retrying upload to ${target}...`
302
+ )
303
+ );
304
+ host = target;
305
+ response = await postOnce(input, host);
306
+ }
307
+ }
308
+ return { response, host };
309
+ }
310
+
264
311
  // src/commands/scan.ts
265
312
  async function autoPush(artifact, rootDir, opts) {
266
313
  const dsn = resolveDsn(opts.dsn);
267
314
  if (!dsn) {
268
- console.error(chalk3.red("No DSN provided for push."));
269
- console.error(chalk3.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.'));
315
+ console.error(chalk4.red("No DSN provided for push."));
316
+ console.error(chalk4.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.'));
270
317
  if (opts.strict) process.exit(1);
271
318
  return;
272
319
  }
273
320
  const parsed = parseDsn(dsn);
274
321
  if (!parsed) {
275
- console.error(chalk3.red("Invalid DSN format."));
322
+ console.error(chalk4.red("Invalid DSN format."));
276
323
  if (opts.strict) process.exit(1);
277
324
  return;
278
325
  }
@@ -283,29 +330,26 @@ async function autoPush(artifact, rootDir, opts) {
283
330
  try {
284
331
  host = resolveIngestHost(opts.region);
285
332
  } catch (e) {
286
- console.error(chalk3.red(e instanceof Error ? e.message : String(e)));
333
+ console.error(chalk4.red(e instanceof Error ? e.message : String(e)));
287
334
  if (opts.strict) process.exit(1);
288
335
  return;
289
336
  }
290
337
  }
291
- const url = `${parsed.scheme}://${host}/v1/ingest/scan`;
292
338
  const originalSize = JSON.stringify(artifact).length;
293
339
  const compressedSize = body.length;
294
340
  const ratio = ((1 - compressedSize / originalSize) * 100).toFixed(0);
295
- console.log(chalk3.dim(`Uploading to ${host}... (${(compressedSize / 1024).toFixed(0)} KB, ${ratio}% smaller)`));
341
+ console.log(chalk4.dim(`Uploading to ${host}... (${(compressedSize / 1024).toFixed(0)} KB, ${ratio}% smaller)`));
296
342
  try {
297
- const response = await fetch(url, {
298
- method: "POST",
299
- headers: {
300
- "Content-Type": "application/json",
301
- "Content-Encoding": contentEncoding,
302
- "X-Vibgrate-Timestamp": timestamp,
303
- "Authorization": `VibgrateDSN ${parsed.keyId}:${parsed.secret}`,
304
- "Connection": "close"
305
- // Prevent keep-alive delays on exit
306
- },
307
- body
343
+ const { response, host: uploadedHost } = await uploadScanArtifact({
344
+ scheme: parsed.scheme,
345
+ host,
346
+ keyId: parsed.keyId,
347
+ secret: parsed.secret,
348
+ body,
349
+ contentEncoding,
350
+ timestamp
308
351
  });
352
+ host = uploadedHost;
309
353
  if (!response.ok) {
310
354
  const text = await response.text();
311
355
  throw new Error(`HTTP ${response.status}: ${text}`);
@@ -313,36 +357,36 @@ async function autoPush(artifact, rootDir, opts) {
313
357
  const result = await response.json();
314
358
  if (result.unchanged) {
315
359
  console.log(
316
- chalk3.green("\u2714") + ` Repository unchanged since ${result.lastScannedAt ?? "last scan"} \u2014 skipped upload (no credit used).`
360
+ chalk4.green("\u2714") + ` Repository unchanged since ${result.lastScannedAt ?? "last scan"} \u2014 skipped upload (no credit used).`
317
361
  );
318
362
  if (result.previousIngestId) {
319
363
  emitIngestIdLine(result.previousIngestId, { unchanged: true });
320
- const dashUrl = `https://dash.vibgrate.com/${parsed.workspaceId}/scan/${result.previousIngestId}`;
321
- console.log(chalk3.dim(` Previous report: ${dashUrl}`));
364
+ const dashUrl = `https://${dashHostForIngestHost(host)}/${parsed.workspaceId}/scan/${result.previousIngestId}`;
365
+ console.log(chalk4.dim(` Previous report: ${dashUrl}`));
322
366
  } else if (opts.strict) {
323
- console.error(chalk3.red("Repository unchanged but no previous ingest id returned."));
367
+ console.error(chalk4.red("Repository unchanged but no previous ingest id returned."));
324
368
  process.exit(1);
325
369
  }
326
370
  return;
327
371
  }
328
- console.log(chalk3.green("\u2714") + ` Scan queued for processing (${result.ingestId ?? "ok"})`);
372
+ console.log(chalk4.green("\u2714") + ` Scan queued for processing (${result.ingestId ?? "ok"})`);
329
373
  if (result.ingestId) {
330
374
  emitIngestIdLine(result.ingestId);
331
- const dashUrl = `https://dash.vibgrate.com/${parsed.workspaceId}/scan/${result.ingestId}`;
375
+ const dashUrl = `https://${dashHostForIngestHost(host)}/${parsed.workspaceId}/scan/${result.ingestId}`;
332
376
  const CLEAR_LINE = process.platform === "win32" ? "\x1B[0G\x1B[2K" : "";
333
377
  console.log("");
334
- console.log(CLEAR_LINE + chalk3.dim(" Processing continues in the background. Results available shortly."));
378
+ console.log(CLEAR_LINE + chalk4.dim(" Processing continues in the background. Results available shortly."));
335
379
  console.log("");
336
- console.log(CLEAR_LINE + chalk3.cyan("\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\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"));
337
- console.log(CLEAR_LINE + chalk3.bold(" \u{1F4CA} View Scan Report"));
338
- console.log(CLEAR_LINE + " " + chalk3.underline.cyan(dashUrl));
339
- console.log(CLEAR_LINE + chalk3.cyan("\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\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"));
380
+ console.log(CLEAR_LINE + chalk4.cyan("\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\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"));
381
+ console.log(CLEAR_LINE + chalk4.bold(" \u{1F4CA} View Scan Report"));
382
+ console.log(CLEAR_LINE + " " + chalk4.underline.cyan(dashUrl));
383
+ console.log(CLEAR_LINE + chalk4.cyan("\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\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"));
340
384
  console.log("");
341
385
  console.log("");
342
386
  }
343
387
  } catch (e) {
344
388
  const msg = e instanceof Error ? e.message : String(e);
345
- console.error(chalk3.red(`Upload failed: ${msg}`));
389
+ console.error(chalk4.red(`Upload failed: ${msg}`));
346
390
  if (opts.strict) process.exit(1);
347
391
  }
348
392
  }
@@ -365,11 +409,12 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
365
409
  ).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("--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 drift score is above budget (0-100)").option("--drift-worsening <percent>", "Fail if drift worsens by more than % since baseline").action(async (targetPath, opts) => {
366
410
  const rootDir = path4.resolve(targetPath);
367
411
  if (!await pathExists2(rootDir)) {
368
- console.error(chalk3.red(`Path does not exist: ${rootDir}`));
412
+ console.error(chalk4.red(`Path does not exist: ${rootDir}`));
369
413
  process.exit(1);
370
414
  }
371
415
  const hasDsn = !!resolveDsn(opts.dsn);
372
416
  const willPush = !opts.offline && (opts.push || hasDsn);
417
+ let pinnedRegion;
373
418
  if (willPush && hasDsn) {
374
419
  const dsn = resolveDsn(opts.dsn);
375
420
  const parsed = parseDsn(dsn);
@@ -383,19 +428,20 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
383
428
  repositoryName,
384
429
  vcsSha: fingerprint.vcsSha
385
430
  });
431
+ pinnedRegion = preflight.region;
386
432
  if (preflight.vm && !preflight.vm.allowed) {
387
- console.error(chalk3.red(preflight.error ?? "VM meter usage exhausted"));
433
+ console.error(chalk4.red(preflight.error ?? "VM meter usage exhausted"));
388
434
  console.error(
389
- chalk3.dim(
435
+ chalk4.dim(
390
436
  `VM minutes: ${preflight.vm.used}/${preflight.vm.limit} (${preflight.plan.label} plan) \u2014 enable overages or upgrade your plan.`
391
437
  )
392
438
  );
393
439
  process.exit(1);
394
440
  }
395
441
  if (preflight.status === "error" || !preflight.scans.allowed) {
396
- console.error(chalk3.red(preflight.error ?? "Scan ingestion not allowed for this workspace."));
442
+ console.error(chalk4.red(preflight.error ?? "Scan ingestion not allowed for this workspace."));
397
443
  console.error(
398
- chalk3.dim(
444
+ chalk4.dim(
399
445
  `Credits: ${preflight.scans.used}/${preflight.scans.limit} (${preflight.plan.label} plan)`
400
446
  )
401
447
  );
@@ -403,27 +449,27 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
403
449
  process.exit(1);
404
450
  }
405
451
  console.log(
406
- chalk3.dim(
452
+ chalk4.dim(
407
453
  `Plan: ${preflight.plan.label} \u2014 scan credits ${preflight.scans.used}/${preflight.scans.limit} this month`
408
454
  )
409
455
  );
410
456
  if (preflight.repository?.unchanged) {
411
457
  console.log(
412
- chalk3.green("\u2714") + ` Repository unchanged at ${preflight.repository.lastVcsSha?.slice(0, 7) ?? "same revision"} \u2014 skipping scan.`
458
+ chalk4.green("\u2714") + ` Repository unchanged at ${preflight.repository.lastVcsSha?.slice(0, 7) ?? "same revision"} \u2014 skipping scan.`
413
459
  );
414
460
  if (preflight.repository.lastIngestId) {
415
461
  emitIngestIdLine(preflight.repository.lastIngestId, { unchanged: true });
416
- const dashUrl = `https://dash.vibgrate.com/${parsed.workspaceId}/scan/${preflight.repository.lastIngestId}`;
417
- console.log(chalk3.dim(` Latest report: ${dashUrl}`));
462
+ const dashUrl = `https://${dashHostForIngestHost(ingestHost)}/${parsed.workspaceId}/scan/${preflight.repository.lastIngestId}`;
463
+ console.log(chalk4.dim(` Latest report: ${dashUrl}`));
418
464
  } else if (opts.strict) {
419
- console.error(chalk3.red("Repository unchanged but no previous ingest id available."));
465
+ console.error(chalk4.red("Repository unchanged but no previous ingest id available."));
420
466
  process.exit(1);
421
467
  }
422
468
  return;
423
469
  }
424
470
  } catch (e) {
425
471
  const msg = e instanceof Error ? e.message : String(e);
426
- console.error(chalk3.yellow(`Preflight check failed: ${msg}`));
472
+ console.error(chalk4.yellow(`Preflight check failed: ${msg}`));
427
473
  if (opts.strict) process.exit(1);
428
474
  }
429
475
  }
@@ -439,7 +485,9 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
439
485
  concurrency: parseInt(opts.concurrency, 10) || 8,
440
486
  push: opts.push,
441
487
  dsn: opts.dsn,
442
- region: opts.region,
488
+ // An explicit --region wins; otherwise route to the workspace's pinned
489
+ // region as reported by preflight.
490
+ region: opts.region ?? pinnedRegion,
443
491
  strict: opts.strict,
444
492
  uiPurpose: opts.uiPurpose,
445
493
  noLocalArtifacts: opts.noLocalArtifacts,
@@ -455,24 +503,24 @@ var scanCommand = new Command3("scan").description("Scan a project for upgrade d
455
503
  const hasErrors = artifact.findings.some((f) => f.level === "error");
456
504
  const hasWarnings = artifact.findings.some((f) => f.level === "warning");
457
505
  if (opts.failOn === "error" && hasErrors) {
458
- console.error(chalk3.red(`
506
+ console.error(chalk4.red(`
459
507
  Failing: ${artifact.findings.filter((f) => f.level === "error").length} error finding(s) detected.`));
460
508
  process.exit(2);
461
509
  }
462
510
  if (opts.failOn === "warn" && (hasErrors || hasWarnings)) {
463
- console.error(chalk3.red(`
511
+ console.error(chalk4.red(`
464
512
  Failing: findings detected at warn level or above.`));
465
513
  process.exit(2);
466
514
  }
467
515
  }
468
516
  if (scanOpts.driftBudget !== void 0 && artifact.drift.score > scanOpts.driftBudget) {
469
- console.error(chalk3.red(`
517
+ console.error(chalk4.red(`
470
518
  Failing fitness function: drift score ${artifact.drift.score}/100 exceeds budget ${scanOpts.driftBudget}.`));
471
519
  process.exit(2);
472
520
  }
473
521
  if (scanOpts.driftWorseningPercent !== void 0) {
474
522
  if (artifact.delta === void 0) {
475
- console.error(chalk3.red("\nFailing fitness function: --drift-worsening requires --baseline to compare against previous drift."));
523
+ console.error(chalk4.red("\nFailing fitness function: --drift-worsening requires --baseline to compare against previous drift."));
476
524
  process.exit(2);
477
525
  }
478
526
  if (artifact.delta > 0) {
@@ -480,7 +528,7 @@ Failing fitness function: drift score ${artifact.drift.score}/100 exceeds budget
480
528
  const denominator = Math.max(Math.abs(baselineScore), 1e-4);
481
529
  const worseningPercent = artifact.delta / denominator * 100;
482
530
  if (worseningPercent > scanOpts.driftWorseningPercent) {
483
- console.error(chalk3.red(`
531
+ console.error(chalk4.red(`
484
532
  Failing fitness function: drift worsened by ${worseningPercent.toFixed(2)}% (threshold ${scanOpts.driftWorseningPercent}%).`));
485
533
  process.exit(2);
486
534
  }
@@ -494,28 +542,28 @@ Failing fitness function: drift worsened by ${worseningPercent.toFixed(2)}% (thr
494
542
  // src/commands/report.ts
495
543
  import * as path5 from "path";
496
544
  import { Command as Command4 } from "commander";
497
- import chalk5 from "chalk";
545
+ import chalk6 from "chalk";
498
546
 
499
547
  // src/formatters/text.ts
500
- import chalk4 from "chalk";
548
+ import chalk5 from "chalk";
501
549
  function formatText(artifact) {
502
550
  const lines = [];
503
- const teal = chalk4.hex("#3FB0A4");
504
- const mint = chalk4.hex("#4FE3C1");
551
+ const teal = chalk5.hex("#3FB0A4");
552
+ const mint = chalk5.hex("#4FE3C1");
505
553
  lines.push("");
506
554
  lines.push(" " + teal("\u256D\u2500\u2500\u2500\u2500\u2500\u2500\u256E") + mint("\u279C"));
507
- lines.push(" " + chalk4.dim("\u2524") + teal("\u2502") + " " + mint("\u25FC") + " " + mint("\u25FC") + " " + teal("\u2502") + chalk4.dim("\u251C") + " " + chalk4.bold.white("vibgrate"));
508
- lines.push(" " + chalk4.dim("\u2524") + teal("\u2502") + " " + chalk4.dim("\u2581\u2581") + " " + teal("\u2502") + chalk4.dim("\u251C") + " " + chalk4.dim(`Drift Intelligence Engine v${VERSION}`));
555
+ lines.push(" " + chalk5.dim("\u2524") + teal("\u2502") + " " + mint("\u25FC") + " " + mint("\u25FC") + " " + teal("\u2502") + chalk5.dim("\u251C") + " " + chalk5.bold.white("vibgrate"));
556
+ lines.push(" " + chalk5.dim("\u2524") + teal("\u2502") + " " + chalk5.dim("\u2581\u2581") + " " + teal("\u2502") + chalk5.dim("\u251C") + " " + chalk5.dim(`Drift Intelligence Engine v${VERSION}`));
509
557
  lines.push(" " + teal("\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u256F"));
510
558
  lines.push("");
511
559
  lines.push(teal("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
512
- lines.push(teal("\u2551 ") + chalk4.bold.white("Vibgrate Drift Report") + teal(" \u2551"));
560
+ lines.push(teal("\u2551 ") + chalk5.bold.white("Vibgrate Drift Report") + teal(" \u2551"));
513
561
  lines.push(teal("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
514
562
  lines.push("");
515
563
  for (const project of artifact.projects) {
516
- lines.push(chalk4.bold(` \u2500\u2500 ${project.name} `) + chalk4.dim(`(${project.type}) ${project.path}`));
564
+ lines.push(chalk5.bold(` \u2500\u2500 ${project.name} `) + chalk5.dim(`(${project.type}) ${project.path}`));
517
565
  if (project.runtime) {
518
- const behindStr = project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind > 0 ? chalk4.yellow(` (${project.runtimeMajorsBehind} major${project.runtimeMajorsBehind > 1 ? "s" : ""} behind)`) : chalk4.green(" (current)");
566
+ const behindStr = project.runtimeMajorsBehind !== void 0 && project.runtimeMajorsBehind > 0 ? chalk5.yellow(` (${project.runtimeMajorsBehind} major${project.runtimeMajorsBehind > 1 ? "s" : ""} behind)`) : chalk5.green(" (current)");
519
567
  lines.push(` Runtime: ${project.runtime}${behindStr}`);
520
568
  }
521
569
  if (project.targetFramework) {
@@ -524,7 +572,7 @@ function formatText(artifact) {
524
572
  if (project.frameworks.length > 0) {
525
573
  lines.push(" Frameworks:");
526
574
  for (const fw of project.frameworks) {
527
- const lag = fw.majorsBehind !== null ? fw.majorsBehind === 0 ? chalk4.green("current") : chalk4.yellow(`${fw.majorsBehind} behind`) : chalk4.dim("unknown");
575
+ const lag = fw.majorsBehind !== null ? fw.majorsBehind === 0 ? chalk5.green("current") : chalk5.yellow(`${fw.majorsBehind} behind`) : chalk5.dim("unknown");
528
576
  lines.push(` ${fw.name}: ${fw.currentVersion ?? "?"} \u2192 ${fw.latestVersion ?? "?"} (${lag})`);
529
577
  }
530
578
  }
@@ -532,13 +580,13 @@ function formatText(artifact) {
532
580
  const total = b.current + b.oneBehind + b.twoPlusBehind + b.unknown;
533
581
  if (total > 0) {
534
582
  lines.push(" Dependencies:");
535
- lines.push(` ${chalk4.green(`${b.current} current`)} ${chalk4.yellow(`${b.oneBehind} 1-behind`)} ${chalk4.red(`${b.twoPlusBehind} 2+ behind`)} ${chalk4.dim(`${b.unknown} unknown`)}`);
583
+ lines.push(` ${chalk5.green(`${b.current} current`)} ${chalk5.yellow(`${b.oneBehind} 1-behind`)} ${chalk5.red(`${b.twoPlusBehind} 2+ behind`)} ${chalk5.dim(`${b.unknown} unknown`)}`);
536
584
  }
537
585
  lines.push("");
538
586
  }
539
587
  if (artifact.delta !== void 0) {
540
- const deltaStr = artifact.delta > 0 ? chalk4.green(`+${artifact.delta}`) : artifact.delta < 0 ? chalk4.red(`${artifact.delta}`) : chalk4.dim("0");
541
- lines.push(chalk4.bold(" Drift Delta: ") + deltaStr + " (vs baseline)");
588
+ const deltaStr = artifact.delta > 0 ? chalk5.green(`+${artifact.delta}`) : artifact.delta < 0 ? chalk5.red(`${artifact.delta}`) : chalk5.dim("0");
589
+ lines.push(chalk5.bold(" Drift Delta: ") + deltaStr + " (vs baseline)");
542
590
  lines.push("");
543
591
  }
544
592
  if (artifact.extended) {
@@ -549,30 +597,30 @@ function formatText(artifact) {
549
597
  const warnings = artifact.findings.filter((f) => f.level === "warning");
550
598
  const notes = artifact.findings.filter((f) => f.level === "note");
551
599
  const summary = [
552
- errors.length > 0 ? chalk4.red(`${errors.length} error${errors.length !== 1 ? "s" : ""}`) : "",
553
- warnings.length > 0 ? chalk4.yellow(`${warnings.length} warning${warnings.length !== 1 ? "s" : ""}`) : "",
554
- notes.length > 0 ? chalk4.blue(`${notes.length} note${notes.length !== 1 ? "s" : ""}`) : ""
555
- ].filter(Boolean).join(chalk4.dim(", "));
556
- lines.push(chalk4.bold.underline(` Findings`) + chalk4.dim(` (${summary})`));
600
+ errors.length > 0 ? chalk5.red(`${errors.length} error${errors.length !== 1 ? "s" : ""}`) : "",
601
+ warnings.length > 0 ? chalk5.yellow(`${warnings.length} warning${warnings.length !== 1 ? "s" : ""}`) : "",
602
+ notes.length > 0 ? chalk5.blue(`${notes.length} note${notes.length !== 1 ? "s" : ""}`) : ""
603
+ ].filter(Boolean).join(chalk5.dim(", "));
604
+ lines.push(chalk5.bold.underline(` Findings`) + chalk5.dim(` (${summary})`));
557
605
  for (const f of artifact.findings) {
558
- const icon = f.level === "error" ? chalk4.red("\u2716") : f.level === "warning" ? chalk4.yellow("\u26A0") : chalk4.blue("\u2139");
606
+ const icon = f.level === "error" ? chalk5.red("\u2716") : f.level === "warning" ? chalk5.yellow("\u26A0") : chalk5.blue("\u2139");
559
607
  lines.push(` ${icon} ${f.message}`);
560
- lines.push(chalk4.dim(` ${f.ruleId} in ${f.location}`));
608
+ lines.push(chalk5.dim(` ${f.ruleId} in ${f.location}`));
561
609
  }
562
610
  lines.push("");
563
611
  }
564
612
  const actions = generatePriorityActions(artifact);
565
613
  if (actions.length > 0) {
566
- lines.push(chalk4.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
567
- lines.push(chalk4.bold.cyan("\u2551 Top Priority Actions \u2551"));
568
- lines.push(chalk4.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
614
+ lines.push(chalk5.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
615
+ lines.push(chalk5.bold.cyan("\u2551 Top Priority Actions \u2551"));
616
+ lines.push(chalk5.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
569
617
  lines.push("");
570
618
  for (let i = 0; i < actions.length; i++) {
571
619
  const a = actions[i];
572
- const num = chalk4.bold.cyan(` ${i + 1}.`);
573
- lines.push(`${num} ${chalk4.bold(a.title)}`);
574
- lines.push(chalk4.dim(` ${a.explanation}`));
575
- if (a.impact) lines.push(` Impact: ${chalk4.green(a.impact)}`);
620
+ const num = chalk5.bold.cyan(` ${i + 1}.`);
621
+ lines.push(`${num} ${chalk5.bold(a.title)}`);
622
+ lines.push(chalk5.dim(` ${a.explanation}`));
623
+ if (a.impact) lines.push(` Impact: ${chalk5.green(a.impact)}`);
576
624
  lines.push("");
577
625
  }
578
626
  }
@@ -580,38 +628,38 @@ function formatText(artifact) {
580
628
  lines.push(...formatArchitectureDiagram(artifact.extended.architecture));
581
629
  }
582
630
  if (artifact.solutions && artifact.solutions.length > 0) {
583
- lines.push(chalk4.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
584
- lines.push(chalk4.bold.cyan("\u2551 Solution Drift Summary \u2551"));
585
- lines.push(chalk4.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
631
+ lines.push(chalk5.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
632
+ lines.push(chalk5.bold.cyan("\u2551 Solution Drift Summary \u2551"));
633
+ lines.push(chalk5.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
586
634
  lines.push("");
587
635
  for (const solution of artifact.solutions) {
588
636
  const solScore = solution.drift?.score;
589
- const color = typeof solScore === "number" ? solScore >= 70 ? chalk4.green : solScore >= 40 ? chalk4.yellow : chalk4.red : chalk4.dim;
590
- lines.push(` \u2022 ${solution.name} (${solution.projectPaths.length} projects) \u2014 ${typeof solScore === "number" ? color(`${solScore}/100`) : chalk4.dim("n/a")}`);
637
+ const color = typeof solScore === "number" ? solScore >= 70 ? chalk5.green : solScore >= 40 ? chalk5.yellow : chalk5.red : chalk5.dim;
638
+ lines.push(` \u2022 ${solution.name} (${solution.projectPaths.length} projects) \u2014 ${typeof solScore === "number" ? color(`${solScore}/100`) : chalk5.dim("n/a")}`);
591
639
  }
592
640
  lines.push("");
593
641
  }
594
- const scoreColor = artifact.drift.score >= 70 ? chalk4.green : artifact.drift.score >= 40 ? chalk4.yellow : chalk4.red;
595
- lines.push(chalk4.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
596
- lines.push(chalk4.bold.cyan("\u2551 Drift Score Summary \u2551"));
597
- lines.push(chalk4.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
642
+ const scoreColor = artifact.drift.score >= 70 ? chalk5.green : artifact.drift.score >= 40 ? chalk5.yellow : chalk5.red;
643
+ lines.push(chalk5.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
644
+ lines.push(chalk5.bold.cyan("\u2551 Drift Score Summary \u2551"));
645
+ lines.push(chalk5.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
598
646
  lines.push("");
599
- lines.push(chalk4.bold(" Drift Score: ") + scoreColor.bold(`${artifact.drift.score}/100`));
600
- lines.push(chalk4.bold(" Risk Level: ") + riskBadge(artifact.drift.riskLevel));
601
- lines.push(chalk4.bold(" Projects: ") + `${artifact.projects.length}`);
647
+ lines.push(chalk5.bold(" Drift Score: ") + scoreColor.bold(`${artifact.drift.score}/100`));
648
+ lines.push(chalk5.bold(" Risk Level: ") + riskBadge(artifact.drift.riskLevel));
649
+ lines.push(chalk5.bold(" Projects: ") + `${artifact.projects.length}`);
602
650
  if (artifact.vcs) {
603
651
  const vcsParts = [artifact.vcs.type];
604
652
  if (artifact.vcs.branch) vcsParts.push(artifact.vcs.branch);
605
- if (artifact.vcs.shortSha) vcsParts.push(chalk4.dim(artifact.vcs.shortSha));
606
- lines.push(chalk4.bold(" VCS: ") + vcsParts.join(" "));
653
+ if (artifact.vcs.shortSha) vcsParts.push(chalk5.dim(artifact.vcs.shortSha));
654
+ lines.push(chalk5.bold(" VCS: ") + vcsParts.join(" "));
607
655
  }
608
656
  lines.push("");
609
657
  const m = new Set(artifact.drift.measured ?? ["runtime", "framework", "dependency", "eol"]);
610
- lines.push(" " + chalk4.bold.underline("Score Breakdown"));
611
- lines.push(` Runtime: ${m.has("runtime") ? scoreBar(artifact.drift.components.runtimeScore) : chalk4.dim("n/a")}`);
612
- lines.push(` Frameworks: ${m.has("framework") ? scoreBar(artifact.drift.components.frameworkScore) : chalk4.dim("n/a")}`);
613
- lines.push(` Dependencies: ${m.has("dependency") ? scoreBar(artifact.drift.components.dependencyScore) : chalk4.dim("n/a")}`);
614
- lines.push(` EOL Risk: ${m.has("eol") ? scoreBar(artifact.drift.components.eolScore) : chalk4.dim("n/a")}`);
658
+ lines.push(" " + chalk5.bold.underline("Score Breakdown"));
659
+ lines.push(` Runtime: ${m.has("runtime") ? scoreBar(artifact.drift.components.runtimeScore) : chalk5.dim("n/a")}`);
660
+ lines.push(` Frameworks: ${m.has("framework") ? scoreBar(artifact.drift.components.frameworkScore) : chalk5.dim("n/a")}`);
661
+ lines.push(` Dependencies: ${m.has("dependency") ? scoreBar(artifact.drift.components.dependencyScore) : chalk5.dim("n/a")}`);
662
+ lines.push(` EOL Risk: ${m.has("eol") ? scoreBar(artifact.drift.components.eolScore) : chalk5.dim("n/a")}`);
615
663
  lines.push("");
616
664
  const scannedParts = [`Scanned at ${artifact.timestamp}`];
617
665
  if (artifact.durationMs !== void 0) {
@@ -625,18 +673,18 @@ function formatText(artifact) {
625
673
  scannedParts.push(`${artifact.treeSummary.totalFiles.toLocaleString()} workspace files`);
626
674
  scannedParts.push(`${artifact.treeSummary.totalDirs.toLocaleString()} dirs`);
627
675
  }
628
- lines.push(chalk4.dim(` ${scannedParts.join(" \xB7 ")}`));
676
+ lines.push(chalk5.dim(` ${scannedParts.join(" \xB7 ")}`));
629
677
  lines.push("");
630
678
  return lines.join("\n");
631
679
  }
632
680
  function riskBadge(level) {
633
681
  switch (level) {
634
682
  case "low":
635
- return chalk4.bgGreen.black(" LOW ");
683
+ return chalk5.bgGreen.black(" LOW ");
636
684
  case "moderate":
637
- return chalk4.bgYellow.black(" MODERATE ");
685
+ return chalk5.bgYellow.black(" MODERATE ");
638
686
  case "high":
639
- return chalk4.bgRed.white(" HIGH ");
687
+ return chalk5.bgRed.white(" HIGH ");
640
688
  default:
641
689
  return level;
642
690
  }
@@ -645,8 +693,8 @@ function scoreBar(score) {
645
693
  const width = 20;
646
694
  const filled = Math.round(score / 100 * width);
647
695
  const empty = width - filled;
648
- const color = score >= 70 ? chalk4.green : score >= 40 ? chalk4.yellow : chalk4.red;
649
- return color("\u2588".repeat(filled)) + chalk4.dim("\u2591".repeat(empty)) + ` ${Math.round(score)}`;
696
+ const color = score >= 70 ? chalk5.green : score >= 40 ? chalk5.yellow : chalk5.red;
697
+ return color("\u2588".repeat(filled)) + chalk5.dim("\u2591".repeat(empty)) + ` ${Math.round(score)}`;
650
698
  }
651
699
  var CATEGORY_LABELS = {
652
700
  frontend: "Frontend",
@@ -675,11 +723,11 @@ function formatExtended(ext) {
675
723
  const inv = ext.toolingInventory;
676
724
  const categories = Object.entries(inv).filter(([, items]) => items.length > 0);
677
725
  if (categories.length > 0) {
678
- lines.push(chalk4.bold.underline(" Tech Stack"));
726
+ lines.push(chalk5.bold.underline(" Tech Stack"));
679
727
  for (const [cat, items] of categories) {
680
728
  const label = CATEGORY_LABELS[cat] ?? cat;
681
- const names = items.map((i) => chalk4.white(i.name)).join(chalk4.dim(", "));
682
- lines.push(` ${chalk4.cyan(label)}: ${names}`);
729
+ const names = items.map((i) => chalk5.white(i.name)).join(chalk5.dim(", "));
730
+ lines.push(` ${chalk5.cyan(label)}: ${names}`);
683
731
  }
684
732
  lines.push("");
685
733
  }
@@ -688,14 +736,14 @@ function formatExtended(ext) {
688
736
  const svc = ext.serviceDependencies;
689
737
  const categories = Object.entries(svc).filter(([, items]) => items.length > 0);
690
738
  if (categories.length > 0) {
691
- lines.push(chalk4.bold.underline(" Services & Integrations"));
739
+ lines.push(chalk5.bold.underline(" Services & Integrations"));
692
740
  for (const [cat, items] of categories) {
693
741
  const label = CATEGORY_LABELS[cat] ?? cat;
694
742
  const names = items.map((i) => {
695
- const ver = i.version ? chalk4.dim(` ${i.version}`) : "";
696
- return chalk4.white(i.name) + ver;
697
- }).join(chalk4.dim(", "));
698
- lines.push(` ${chalk4.cyan(label)}: ${names}`);
743
+ const ver = i.version ? chalk5.dim(` ${i.version}`) : "";
744
+ return chalk5.white(i.name) + ver;
745
+ }).join(chalk5.dim(", "));
746
+ lines.push(` ${chalk5.cyan(label)}: ${names}`);
699
747
  }
700
748
  lines.push("");
701
749
  }
@@ -703,19 +751,19 @@ function formatExtended(ext) {
703
751
  if (ext.breakingChangeExposure) {
704
752
  const bc = ext.breakingChangeExposure;
705
753
  if (bc.deprecatedPackages.length > 0 || bc.legacyPolyfills.length > 0) {
706
- lines.push(chalk4.bold.underline(" Breaking Change Exposure"));
707
- const exposureColor = bc.exposureScore >= 40 ? chalk4.red : bc.exposureScore >= 20 ? chalk4.yellow : chalk4.green;
754
+ lines.push(chalk5.bold.underline(" Breaking Change Exposure"));
755
+ const exposureColor = bc.exposureScore >= 40 ? chalk5.red : bc.exposureScore >= 20 ? chalk5.yellow : chalk5.green;
708
756
  lines.push(` Exposure Score: ${exposureColor.bold(`${bc.exposureScore}/100`)}`);
709
757
  if (bc.deprecatedPackages.length > 0) {
710
- lines.push(` ${chalk4.red("Deprecated")}: ${bc.deprecatedPackages.map((p) => chalk4.dim(p)).join(", ")}`);
758
+ lines.push(` ${chalk5.red("Deprecated")}: ${bc.deprecatedPackages.map((p) => chalk5.dim(p)).join(", ")}`);
711
759
  }
712
760
  if (bc.legacyPolyfills.length > 0) {
713
- lines.push(` ${chalk4.yellow("Polyfills")}: ${bc.legacyPolyfills.map((p) => chalk4.dim(p)).join(", ")}`);
761
+ lines.push(` ${chalk5.yellow("Polyfills")}: ${bc.legacyPolyfills.map((p) => chalk5.dim(p)).join(", ")}`);
714
762
  }
715
763
  if (bc.peerConflictsDetected) {
716
- lines.push(` ${chalk4.red("\u26A0")} Peer dependency conflicts detected`);
764
+ lines.push(` ${chalk5.red("\u26A0")} Peer dependency conflicts detected`);
717
765
  }
718
- lines.push(` Recommendation: ${chalk4.bold(bc.overallRecommendation)}`);
766
+ lines.push(` Recommendation: ${chalk5.bold(bc.overallRecommendation)}`);
719
767
  const projectsWithPlans = bc.projectIntelligence.filter((p) => p.packages.length > 0).slice(0, 3);
720
768
  if (projectsWithPlans.length > 0) {
721
769
  lines.push(" Major Upgrade Intelligence:");
@@ -731,21 +779,21 @@ function formatExtended(ext) {
731
779
  }
732
780
  if (ext.tsModernity && ext.tsModernity.typescriptVersion) {
733
781
  const ts = ext.tsModernity;
734
- lines.push(chalk4.bold.underline(" TypeScript"));
782
+ lines.push(chalk5.bold.underline(" TypeScript"));
735
783
  const parts = [];
736
784
  parts.push(`v${ts.typescriptVersion}`);
737
- if (ts.strict === true) parts.push(chalk4.green("strict \u2714"));
738
- else if (ts.strict === false) parts.push(chalk4.yellow("strict \u2716"));
785
+ if (ts.strict === true) parts.push(chalk5.green("strict \u2714"));
786
+ else if (ts.strict === false) parts.push(chalk5.yellow("strict \u2716"));
739
787
  if (ts.moduleType) parts.push(ts.moduleType.toUpperCase());
740
788
  if (ts.target) parts.push(`target: ${ts.target}`);
741
- lines.push(` ${parts.join(chalk4.dim(" \xB7 "))}`);
789
+ lines.push(` ${parts.join(chalk5.dim(" \xB7 "))}`);
742
790
  lines.push("");
743
791
  }
744
792
  if (ext.buildDeploy) {
745
793
  const bd = ext.buildDeploy;
746
794
  const hasSomething = bd.ci.length > 0 || bd.docker.dockerfileCount > 0 || bd.packageManagers.length > 0;
747
795
  if (hasSomething) {
748
- lines.push(chalk4.bold.underline(" Build & Deploy"));
796
+ lines.push(chalk5.bold.underline(" Build & Deploy"));
749
797
  if (bd.ci.length > 0) lines.push(` CI: ${bd.ci.join(", ")}`);
750
798
  if (bd.docker.dockerfileCount > 0) {
751
799
  lines.push(` Docker: ${bd.docker.dockerfileCount} Dockerfile${bd.docker.dockerfileCount !== 1 ? "s" : ""} (${bd.docker.baseImages.join(", ")})`);
@@ -758,42 +806,42 @@ function formatExtended(ext) {
758
806
  }
759
807
  if (ext.uiPurpose) {
760
808
  const up = ext.uiPurpose;
761
- lines.push(chalk4.bold.underline(" Product Purpose Signals"));
762
- lines.push(` Frameworks: ${up.detectedFrameworks.length > 0 ? up.detectedFrameworks.join(", ") : chalk4.dim("unknown")}`);
763
- lines.push(` Evidence: ${up.topEvidence.length}${up.capped ? chalk4.dim(` of ${up.evidenceCount} (capped)`) : ""}`);
809
+ lines.push(chalk5.bold.underline(" Product Purpose Signals"));
810
+ lines.push(` Frameworks: ${up.detectedFrameworks.length > 0 ? up.detectedFrameworks.join(", ") : chalk5.dim("unknown")}`);
811
+ lines.push(` Evidence: ${up.topEvidence.length}${up.capped ? chalk5.dim(` of ${up.evidenceCount} (capped)`) : ""}`);
764
812
  const top = up.topEvidence.slice(0, 8);
765
813
  if (top.length > 0) {
766
814
  lines.push(" Top Signals:");
767
815
  for (const item of top) {
768
- lines.push(` - [${item.kind}] ${item.value} ${chalk4.dim(`(${item.file})`)}`);
816
+ lines.push(` - [${item.kind}] ${item.value} ${chalk5.dim(`(${item.file})`)}`);
769
817
  }
770
818
  }
771
819
  if (up.unknownSignals.length > 0) {
772
820
  lines.push(" Unknowns:");
773
821
  for (const u of up.unknownSignals.slice(0, 4)) {
774
- lines.push(` - ${chalk4.yellow(u)}`);
822
+ lines.push(` - ${chalk5.yellow(u)}`);
775
823
  }
776
824
  }
777
825
  lines.push("");
778
826
  }
779
827
  if (ext.securityPosture) {
780
828
  const sec = ext.securityPosture;
781
- lines.push(chalk4.bold.underline(" Security Posture"));
829
+ lines.push(chalk5.bold.underline(" Security Posture"));
782
830
  const checks = [];
783
- checks.push(sec.lockfilePresent ? chalk4.green("Lockfile \u2714") : chalk4.red("Lockfile \u2716"));
784
- checks.push(sec.gitignoreCoversEnv ? chalk4.green(".env \u2714") : chalk4.red(".env \u2716"));
785
- checks.push(sec.gitignoreCoversNodeModules ? chalk4.green("node_modules \u2714") : chalk4.yellow("node_modules \u2716"));
786
- if (sec.multipleLockfileTypes) checks.push(chalk4.yellow("Multiple lockfiles \u26A0"));
787
- if (sec.envFilesTracked) checks.push(chalk4.red("Env files tracked \u2716"));
788
- lines.push(` ${checks.join(chalk4.dim(" \xB7 "))}`);
831
+ checks.push(sec.lockfilePresent ? chalk5.green("Lockfile \u2714") : chalk5.red("Lockfile \u2716"));
832
+ checks.push(sec.gitignoreCoversEnv ? chalk5.green(".env \u2714") : chalk5.red(".env \u2716"));
833
+ checks.push(sec.gitignoreCoversNodeModules ? chalk5.green("node_modules \u2714") : chalk5.yellow("node_modules \u2716"));
834
+ if (sec.multipleLockfileTypes) checks.push(chalk5.yellow("Multiple lockfiles \u26A0"));
835
+ if (sec.envFilesTracked) checks.push(chalk5.red("Env files tracked \u2716"));
836
+ lines.push(` ${checks.join(chalk5.dim(" \xB7 "))}`);
789
837
  lines.push("");
790
838
  }
791
839
  if (ext.platformMatrix) {
792
840
  const pm = ext.platformMatrix;
793
841
  if (pm.nativeModules.length > 0 || pm.dockerBaseImages.length > 0) {
794
- lines.push(chalk4.bold.underline(" Platform"));
842
+ lines.push(chalk5.bold.underline(" Platform"));
795
843
  if (pm.nativeModules.length > 0) {
796
- lines.push(` Native modules: ${pm.nativeModules.map((m) => chalk4.dim(m)).join(", ")}`);
844
+ lines.push(` Native modules: ${pm.nativeModules.map((m) => chalk5.dim(m)).join(", ")}`);
797
845
  }
798
846
  if (pm.osAssumptions.length > 0) {
799
847
  lines.push(` OS assumptions: ${pm.osAssumptions.join(", ")}`);
@@ -803,25 +851,25 @@ function formatExtended(ext) {
803
851
  }
804
852
  if (ext.codeQuality) {
805
853
  const cq = ext.codeQuality;
806
- lines.push(chalk4.bold.underline(" Code Quality"));
807
- lines.push(` Files: ${chalk4.white(`${cq.filesAnalyzed}`)} \xB7 Functions: ${chalk4.white(`${cq.functionsAnalyzed}`)} \xB7 Avg complexity: ${chalk4.white(`${cq.avgCyclomaticComplexity}`)} \xB7 Avg length: ${chalk4.white(`${cq.avgFunctionLength}`)} lines`);
854
+ lines.push(chalk5.bold.underline(" Code Quality"));
855
+ lines.push(` Files: ${chalk5.white(`${cq.filesAnalyzed}`)} \xB7 Functions: ${chalk5.white(`${cq.functionsAnalyzed}`)} \xB7 Avg complexity: ${chalk5.white(`${cq.avgCyclomaticComplexity}`)} \xB7 Avg length: ${chalk5.white(`${cq.avgFunctionLength}`)} lines`);
808
856
  lines.push(` Max nesting: ${cq.maxNestingDepth} \xB7 Circular deps: ${cq.circularDependencies} \xB7 Dead code: ${cq.deadCodePercent}%`);
809
857
  if (cq.godFiles.length > 0) {
810
858
  const preview = cq.godFiles.slice(0, 3).map((f) => `${f.path} (${f.lines} lines)`).join(", ");
811
- lines.push(` ${chalk4.yellow("God files")}: ${preview}`);
859
+ lines.push(` ${chalk5.yellow("God files")}: ${preview}`);
812
860
  }
813
861
  lines.push("");
814
862
  }
815
863
  if (ext.dependencyGraph) {
816
864
  const dg = ext.dependencyGraph;
817
865
  if (dg.lockfileType) {
818
- lines.push(chalk4.bold.underline(" Dependency Graph"));
819
- lines.push(` ${dg.lockfileType}: ${chalk4.white(`${dg.totalUnique}`)} unique, ${chalk4.white(`${dg.totalInstalled}`)} installed`);
866
+ lines.push(chalk5.bold.underline(" Dependency Graph"));
867
+ lines.push(` ${dg.lockfileType}: ${chalk5.white(`${dg.totalUnique}`)} unique, ${chalk5.white(`${dg.totalInstalled}`)} installed`);
820
868
  if (dg.duplicatedPackages.length > 0) {
821
- lines.push(` ${chalk4.yellow(`${dg.duplicatedPackages.length} duplicated`)} packages`);
869
+ lines.push(` ${chalk5.yellow(`${dg.duplicatedPackages.length} duplicated`)} packages`);
822
870
  }
823
871
  if (dg.phantomDependencies.length > 0) {
824
- lines.push(` ${chalk4.red(`${dg.phantomDependencies.length} phantom`)} dependencies`);
872
+ lines.push(` ${chalk5.red(`${dg.phantomDependencies.length} phantom`)} dependencies`);
825
873
  }
826
874
  lines.push("");
827
875
  }
@@ -830,17 +878,17 @@ function formatExtended(ext) {
830
878
  }
831
879
  function formatArchitectureDiagram(arch) {
832
880
  const lines = [];
833
- lines.push(chalk4.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
834
- lines.push(chalk4.bold.cyan("\u2551 Architecture Layers \u2551"));
835
- lines.push(chalk4.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
881
+ lines.push(chalk5.bold.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
882
+ lines.push(chalk5.bold.cyan("\u2551 Architecture Layers \u2551"));
883
+ lines.push(chalk5.bold.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
836
884
  lines.push("");
837
- lines.push(chalk4.bold(" Archetype: ") + `${arch.archetype}` + chalk4.dim(` (${Math.round(arch.archetypeConfidence * 100)}% confidence)`));
838
- lines.push(` Files classified: ${arch.totalClassified}` + (arch.unclassified > 0 ? chalk4.dim(` (${arch.unclassified} unclassified)`) : ""));
885
+ lines.push(chalk5.bold(" Archetype: ") + `${arch.archetype}` + chalk5.dim(` (${Math.round(arch.archetypeConfidence * 100)}% confidence)`));
886
+ lines.push(` Files classified: ${arch.totalClassified}` + (arch.unclassified > 0 ? chalk5.dim(` (${arch.unclassified} unclassified)`) : ""));
839
887
  lines.push("");
840
888
  if (arch.layers.length > 0) {
841
889
  for (const layer of arch.layers) {
842
- const risk = layer.riskLevel === "none" ? chalk4.dim("none") : layer.riskLevel === "low" ? chalk4.green("low") : layer.riskLevel === "moderate" ? chalk4.yellow("moderate") : chalk4.red("high");
843
- lines.push(` ${chalk4.bold(layer.layer)} ${layer.fileCount} file${layer.fileCount !== 1 ? "s" : ""} drift ${scoreBar(layer.driftScore)} risk ${risk}`);
890
+ const risk = layer.riskLevel === "none" ? chalk5.dim("none") : layer.riskLevel === "low" ? chalk5.green("low") : layer.riskLevel === "moderate" ? chalk5.yellow("moderate") : chalk5.red("high");
891
+ lines.push(` ${chalk5.bold(layer.layer)} ${layer.fileCount} file${layer.fileCount !== 1 ? "s" : ""} drift ${scoreBar(layer.driftScore)} risk ${risk}`);
844
892
  }
845
893
  lines.push("");
846
894
  }
@@ -1211,8 +1259,8 @@ function formatMarkdown(artifact) {
1211
1259
  var reportCommand = new Command4("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) => {
1212
1260
  const artifactPath = path5.resolve(opts.in);
1213
1261
  if (!await pathExists(artifactPath)) {
1214
- console.error(chalk5.red(`Artifact not found: ${artifactPath}`));
1215
- console.error(chalk5.dim('Run "vibgrate scan" first to generate a scan artifact.'));
1262
+ console.error(chalk6.red(`Artifact not found: ${artifactPath}`));
1263
+ console.error(chalk6.dim('Run "vibgrate scan" first to generate a scan artifact.'));
1216
1264
  process.exit(1);
1217
1265
  }
1218
1266
  const artifact = await readJsonFile(artifactPath);
@@ -1232,7 +1280,7 @@ var reportCommand = new Command4("report").description("Generate a drift report
1232
1280
 
1233
1281
  // src/commands/login.ts
1234
1282
  import { Command as Command5 } from "commander";
1235
- import chalk6 from "chalk";
1283
+ import chalk7 from "chalk";
1236
1284
 
1237
1285
  // src/utils/open-url.ts
1238
1286
  import { spawn } from "child_process";
@@ -1268,7 +1316,7 @@ var loginCommand = new Command5("login").description("Authenticate the CLI with
1268
1316
  try {
1269
1317
  ingestHost = resolveIngestHost(opts.region, opts.ingest);
1270
1318
  } catch (e) {
1271
- console.error(chalk6.red(e instanceof Error ? e.message : String(e)));
1319
+ console.error(chalk7.red(e instanceof Error ? e.message : String(e)));
1272
1320
  process.exit(1);
1273
1321
  }
1274
1322
  const base = `https://${ingestHost}/v1/auth/device`;
@@ -1280,28 +1328,28 @@ var loginCommand = new Command5("login").description("Authenticate the CLI with
1280
1328
  body: "{}"
1281
1329
  });
1282
1330
  if (!res.ok) {
1283
- console.error(chalk6.red(`Failed to start login (HTTP ${res.status}).`));
1331
+ console.error(chalk7.red(`Failed to start login (HTTP ${res.status}).`));
1284
1332
  process.exit(1);
1285
1333
  }
1286
1334
  start = await res.json();
1287
1335
  } catch (e) {
1288
- console.error(chalk6.red(`Could not reach ${ingestHost}: ${e instanceof Error ? e.message : String(e)}`));
1336
+ console.error(chalk7.red(`Could not reach ${ingestHost}: ${e instanceof Error ? e.message : String(e)}`));
1289
1337
  process.exit(1);
1290
1338
  }
1291
1339
  console.log("");
1292
1340
  console.log("To finish signing in, open this URL and approve the request:");
1293
1341
  console.log("");
1294
- console.log(" " + chalk6.cyan(start.verificationUri));
1342
+ console.log(" " + chalk7.cyan(start.verificationUri));
1295
1343
  console.log("");
1296
- console.log(" Your code: " + chalk6.bold(start.userCode));
1344
+ console.log(" Your code: " + chalk7.bold(start.userCode));
1297
1345
  console.log("");
1298
1346
  if (opts.browser) {
1299
1347
  const opened = openUrl(start.verificationUriComplete);
1300
1348
  if (opened) {
1301
- console.log(chalk6.dim("Opening your browser\u2026 (if it does not open, use the URL above)"));
1349
+ console.log(chalk7.dim("Opening your browser\u2026 (if it does not open, use the URL above)"));
1302
1350
  }
1303
1351
  }
1304
- console.log(chalk6.dim("Waiting for approval\u2026"));
1352
+ console.log(chalk7.dim("Waiting for approval\u2026"));
1305
1353
  const intervalMs = Math.max(2, start.interval || 5) * 1e3;
1306
1354
  const deadline = Date.now() + (start.expiresIn || 900) * 1e3;
1307
1355
  while (Date.now() < deadline) {
@@ -1327,40 +1375,40 @@ var loginCommand = new Command5("login").description("Authenticate the CLI with
1327
1375
  savedAt: (/* @__PURE__ */ new Date()).toISOString()
1328
1376
  });
1329
1377
  console.log("");
1330
- console.log(chalk6.green("\u2714") + " Logged in.");
1378
+ console.log(chalk7.green("\u2714") + " Logged in.");
1331
1379
  if (token.workspaceId) {
1332
- console.log(" Workspace: " + chalk6.bold(token.workspaceId));
1380
+ console.log(" Workspace: " + chalk7.bold(token.workspaceId));
1333
1381
  }
1334
- console.log(chalk6.dim(` Credentials saved to ${credentialsPath()}`));
1335
- console.log(chalk6.dim(' You can now run "vibgrate scan --push".'));
1382
+ console.log(chalk7.dim(` Credentials saved to ${credentialsPath()}`));
1383
+ console.log(chalk7.dim(' You can now run "vibgrate scan --push".'));
1336
1384
  return;
1337
1385
  }
1338
1386
  if (token.status === "access_denied") {
1339
- console.error(chalk6.red("\u2716 Login was denied in the browser."));
1387
+ console.error(chalk7.red("\u2716 Login was denied in the browser."));
1340
1388
  process.exit(1);
1341
1389
  }
1342
1390
  if (token.status === "expired" || token.status === "invalid") {
1343
- console.error(chalk6.red('\u2716 Login request expired. Run "vibgrate login" again.'));
1391
+ console.error(chalk7.red('\u2716 Login request expired. Run "vibgrate login" again.'));
1344
1392
  process.exit(1);
1345
1393
  }
1346
1394
  if (token.status === "error") {
1347
- console.error(chalk6.red(`\u2716 ${token.error ?? "Login failed."}`));
1395
+ console.error(chalk7.red(`\u2716 ${token.error ?? "Login failed."}`));
1348
1396
  process.exit(1);
1349
1397
  }
1350
1398
  }
1351
- console.error(chalk6.red('\u2716 Timed out waiting for approval. Run "vibgrate login" again.'));
1399
+ console.error(chalk7.red('\u2716 Timed out waiting for approval. Run "vibgrate login" again.'));
1352
1400
  process.exit(1);
1353
1401
  });
1354
1402
 
1355
1403
  // src/commands/logout.ts
1356
1404
  import { Command as Command6 } from "commander";
1357
- import chalk7 from "chalk";
1405
+ import chalk8 from "chalk";
1358
1406
  var logoutCommand = new Command6("logout").description("Clear stored Vibgrate login credentials").action(() => {
1359
1407
  const cleared = clearStoredCredentials();
1360
1408
  if (cleared) {
1361
- console.log(chalk7.green("\u2714") + " Logged out. Stored credentials removed.");
1409
+ console.log(chalk8.green("\u2714") + " Logged out. Stored credentials removed.");
1362
1410
  } else {
1363
- console.log(chalk7.dim(`No stored credentials found at ${credentialsPath()}.`));
1411
+ console.log(chalk8.dim(`No stored credentials found at ${credentialsPath()}.`));
1364
1412
  }
1365
1413
  });
1366
1414
 
@@ -1368,7 +1416,7 @@ var logoutCommand = new Command6("logout").description("Clear stored Vibgrate lo
1368
1416
  import * as crypto2 from "crypto";
1369
1417
  import * as path6 from "path";
1370
1418
  import { Command as Command7 } from "commander";
1371
- import chalk8 from "chalk";
1419
+ import chalk9 from "chalk";
1372
1420
 
1373
1421
  // src/utils/compact-artifact.ts
1374
1422
  import * as zlib from "zlib";
@@ -1643,22 +1691,22 @@ function computeHmac(body, secret) {
1643
1691
  var pushCommand = new Command7("push").description("Push scan results to Vibgrate API").option("--dsn <dsn>", "DSN token (or use VIBGRATE_DSN env)").option("--region <region>", `Override data residency region (${availableRegionIds().join(", ")})`).option("--file <file>", "Scan artifact file", ".vibgrate/scan_result.json").option("--strict", "Fail on upload errors").action(async (opts) => {
1644
1692
  const dsn = resolveDsn(opts.dsn);
1645
1693
  if (!dsn) {
1646
- console.error(chalk8.red("No DSN provided."));
1647
- console.error(chalk8.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.'));
1694
+ console.error(chalk9.red("No DSN provided."));
1695
+ console.error(chalk9.dim('Run "vibgrate login", set VIBGRATE_DSN, or use the --dsn flag.'));
1648
1696
  if (opts.strict) process.exit(1);
1649
1697
  return;
1650
1698
  }
1651
1699
  const parsed = parseDsn2(dsn);
1652
1700
  if (!parsed) {
1653
- console.error(chalk8.red("Invalid DSN format."));
1654
- console.error(chalk8.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>"));
1701
+ console.error(chalk9.red("Invalid DSN format."));
1702
+ console.error(chalk9.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>"));
1655
1703
  if (opts.strict) process.exit(1);
1656
1704
  return;
1657
1705
  }
1658
1706
  const filePath = path6.resolve(opts.file);
1659
1707
  if (!await pathExists(filePath)) {
1660
- console.error(chalk8.red(`Scan artifact not found: ${filePath}`));
1661
- console.error(chalk8.dim('Run "vibgrate scan" first.'));
1708
+ console.error(chalk9.red(`Scan artifact not found: ${filePath}`));
1709
+ console.error(chalk9.dim('Run "vibgrate scan" first.'));
1662
1710
  if (opts.strict) process.exit(1);
1663
1711
  return;
1664
1712
  }
@@ -1670,46 +1718,43 @@ var pushCommand = new Command7("push").description("Push scan results to Vibgrat
1670
1718
  try {
1671
1719
  host = resolveIngestHost(opts.region);
1672
1720
  } catch (e) {
1673
- console.error(chalk8.red(e instanceof Error ? e.message : String(e)));
1721
+ console.error(chalk9.red(e instanceof Error ? e.message : String(e)));
1674
1722
  if (opts.strict) process.exit(1);
1675
1723
  return;
1676
1724
  }
1677
1725
  }
1678
- const url = `${parsed.scheme}://${host}/v1/ingest/scan`;
1679
1726
  const originalSize = JSON.stringify(artifact).length;
1680
1727
  const compressedSize = body.length;
1681
1728
  const ratio = ((1 - compressedSize / originalSize) * 100).toFixed(0);
1682
- console.log(chalk8.dim(`Uploading to ${host}... (${(compressedSize / 1024).toFixed(0)} KB, ${ratio}% smaller)`));
1729
+ console.log(chalk9.dim(`Uploading to ${host}... (${(compressedSize / 1024).toFixed(0)} KB, ${ratio}% smaller)`));
1683
1730
  try {
1684
- const response = await fetch(url, {
1685
- method: "POST",
1686
- headers: {
1687
- "Content-Type": "application/json",
1688
- "Content-Encoding": contentEncoding,
1689
- "X-Vibgrate-Timestamp": timestamp,
1690
- "Authorization": `VibgrateDSN ${parsed.keyId}:${parsed.secret}`,
1691
- "Connection": "close"
1692
- // Prevent keep-alive delays on exit
1693
- },
1694
- body
1731
+ const { response, host: uploadedHost } = await uploadScanArtifact({
1732
+ scheme: parsed.scheme,
1733
+ host,
1734
+ keyId: parsed.keyId,
1735
+ secret: parsed.secret,
1736
+ body,
1737
+ contentEncoding,
1738
+ timestamp
1695
1739
  });
1740
+ host = uploadedHost;
1696
1741
  if (!response.ok) {
1697
1742
  const text = await response.text();
1698
1743
  throw new Error(`HTTP ${response.status}: ${text}`);
1699
1744
  }
1700
1745
  const result = await response.json();
1701
- console.log(chalk8.green("\u2714") + ` Scan queued for processing (${result.ingestId ?? "ok"})`);
1746
+ console.log(chalk9.green("\u2714") + ` Scan queued for processing (${result.ingestId ?? "ok"})`);
1702
1747
  console.log();
1703
- console.log(chalk8.dim("Processing continues in the background. Results available shortly."));
1748
+ console.log(chalk9.dim("Processing continues in the background. Results available shortly."));
1704
1749
  console.log();
1705
1750
  if (result.ingestId) {
1706
1751
  const dashHost = dashHostForIngestHost(host);
1707
1752
  const reportUrl = `https://${dashHost}/${parsed.workspaceId}/scan/${result.ingestId}`;
1708
- console.log(chalk8.dim("View report: ") + chalk8.underline(reportUrl));
1753
+ console.log(chalk9.dim("View report: ") + chalk9.underline(reportUrl));
1709
1754
  }
1710
1755
  } catch (e) {
1711
1756
  const msg = e instanceof Error ? e.message : String(e);
1712
- console.error(chalk8.red(`Upload failed: ${msg}`));
1757
+ console.error(chalk9.red(`Upload failed: ${msg}`));
1713
1758
  if (opts.strict) process.exit(1);
1714
1759
  }
1715
1760
  });
@@ -1718,7 +1763,7 @@ var pushCommand = new Command7("push").description("Push scan results to Vibgrat
1718
1763
  import { execSync } from "child_process";
1719
1764
  import * as path8 from "path";
1720
1765
  import { Command as Command8 } from "commander";
1721
- import chalk9 from "chalk";
1766
+ import chalk10 from "chalk";
1722
1767
 
1723
1768
  // src/utils/update-check.ts
1724
1769
  var import_semver = __toESM(require_semver(), 1);
@@ -1865,21 +1910,21 @@ async function isDevDependency(cwd) {
1865
1910
  }
1866
1911
  }
1867
1912
  var updateCommand = new Command8("update").description("Update vibgrate to the latest version").option("--check", "Only check for updates, do not install").option("--pm <manager>", "Package manager to use (npm, pnpm, yarn, bun)").option("--global", "Update global installation").action(async (opts) => {
1868
- console.log(chalk9.dim(`Current version: ${VERSION}`));
1869
- console.log(chalk9.dim("Checking npm registry..."));
1913
+ console.log(chalk10.dim(`Current version: ${VERSION}`));
1914
+ console.log(chalk10.dim("Checking npm registry..."));
1870
1915
  const latest = await fetchLatestVersion();
1871
1916
  if (!latest) {
1872
- console.error(chalk9.red("Could not reach the npm registry. Check your network connection."));
1917
+ console.error(chalk10.red("Could not reach the npm registry. Check your network connection."));
1873
1918
  process.exit(1);
1874
1919
  }
1875
1920
  const semver2 = await import("./semver-2FJFIYVN.js");
1876
1921
  if (!semver2.gt(latest, VERSION)) {
1877
- console.log(chalk9.green("\u2714") + ` You are on the latest version (${VERSION}).`);
1922
+ console.log(chalk10.green("\u2714") + ` You are on the latest version (${VERSION}).`);
1878
1923
  return;
1879
1924
  }
1880
- console.log(chalk9.yellow(`Update available: ${VERSION} \u2192 ${latest}`));
1925
+ console.log(chalk10.yellow(`Update available: ${VERSION} \u2192 ${latest}`));
1881
1926
  if (opts.check) {
1882
- console.log(chalk9.dim('Run "vibgrate update" to install.'));
1927
+ console.log(chalk10.dim('Run "vibgrate update" to install.'));
1883
1928
  return;
1884
1929
  }
1885
1930
  const cwd = process.cwd();
@@ -1889,17 +1934,17 @@ var updateCommand = new Command8("update").description("Update vibgrate to the l
1889
1934
  let cmd;
1890
1935
  if (isGlobal) {
1891
1936
  cmd = getGlobalUpdateCommand(pm, "@vibgrate/cli", latest);
1892
- console.log(chalk9.dim(`Updating global installation with ${pm}: ${cmd}`));
1937
+ console.log(chalk10.dim(`Updating global installation with ${pm}: ${cmd}`));
1893
1938
  } else {
1894
1939
  const isDev = await isDevDependency(cwd);
1895
1940
  cmd = getInstallCommand(pm, "@vibgrate/cli", latest, isDev);
1896
- console.log(chalk9.dim(`Using ${pm}: ${cmd}`));
1941
+ console.log(chalk10.dim(`Using ${pm}: ${cmd}`));
1897
1942
  }
1898
1943
  try {
1899
1944
  execSync(cmd, { cwd, stdio: "inherit" });
1900
- console.log(chalk9.green("\u2714") + ` Updated to @vibgrate/cli@${latest}`);
1945
+ console.log(chalk10.green("\u2714") + ` Updated to @vibgrate/cli@${latest}`);
1901
1946
  } catch {
1902
- console.error(chalk9.red(`Update failed. Run manually: ${cmd}`));
1947
+ console.error(chalk10.red(`Update failed. Run manually: ${cmd}`));
1903
1948
  process.exit(1);
1904
1949
  }
1905
1950
  });
@@ -1908,7 +1953,7 @@ var updateCommand = new Command8("update").description("Update vibgrate to the l
1908
1953
  import * as path9 from "path";
1909
1954
  import { randomUUID } from "crypto";
1910
1955
  import { Command as Command9 } from "commander";
1911
- import chalk10 from "chalk";
1956
+ import chalk11 from "chalk";
1912
1957
  function flattenDependencies(artifact) {
1913
1958
  const rows = [];
1914
1959
  for (const project of artifact.projects) {
@@ -2048,7 +2093,7 @@ function formatDeltaText(base, current) {
2048
2093
  async function readArtifactOrExit(filePath) {
2049
2094
  const absolutePath = path9.resolve(filePath);
2050
2095
  if (!await pathExists(absolutePath)) {
2051
- console.error(chalk10.red(`Artifact not found: ${absolutePath}`));
2096
+ console.error(chalk11.red(`Artifact not found: ${absolutePath}`));
2052
2097
  process.exit(1);
2053
2098
  }
2054
2099
  return readJsonFile(absolutePath);
@@ -2057,14 +2102,14 @@ var exportCommand = new Command9("export").description("Export scan artifact as
2057
2102
  const artifact = await readArtifactOrExit(opts.in);
2058
2103
  const format = opts.format.toLowerCase();
2059
2104
  if (format !== "cyclonedx" && format !== "spdx") {
2060
- console.error(chalk10.red("Invalid SBOM format. Use cyclonedx or spdx."));
2105
+ console.error(chalk11.red("Invalid SBOM format. Use cyclonedx or spdx."));
2061
2106
  process.exit(1);
2062
2107
  }
2063
2108
  const sbom = format === "cyclonedx" ? toCycloneDx(artifact) : toSpdx(artifact);
2064
2109
  const body = JSON.stringify(sbom, null, 2);
2065
2110
  if (opts.out) {
2066
2111
  await writeTextFile(path9.resolve(opts.out), body);
2067
- console.log(chalk10.green("\u2714") + ` SBOM written to ${opts.out}`);
2112
+ console.log(chalk11.green("\u2714") + ` SBOM written to ${opts.out}`);
2068
2113
  } else {
2069
2114
  console.log(body);
2070
2115
  }
@@ -2075,7 +2120,7 @@ var deltaCommand = new Command9("delta").description("Show SBOM delta between tw
2075
2120
  const report = formatDeltaText(base, current);
2076
2121
  if (opts.out) {
2077
2122
  await writeTextFile(path9.resolve(opts.out), report);
2078
- console.log(chalk10.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
2123
+ console.log(chalk11.green("\u2714") + ` SBOM delta report written to ${opts.out}`);
2079
2124
  } else {
2080
2125
  console.log(report);
2081
2126
  }
@@ -2089,7 +2134,7 @@ import * as fs4 from "fs/promises";
2089
2134
  import { existsSync, rmSync as rmSync2 } from "fs";
2090
2135
  import { spawn as spawn3, spawnSync as spawnSync2 } from "child_process";
2091
2136
  import { Command as Command10 } from "commander";
2092
- import chalk11 from "chalk";
2137
+ import chalk12 from "chalk";
2093
2138
 
2094
2139
  // src/behavioural/derive.ts
2095
2140
  import { createHash as createHash2 } from "crypto";
@@ -3577,7 +3622,7 @@ async function runNodeWorker(rootDir, language, opts) {
3577
3622
  continue;
3578
3623
  }
3579
3624
  if (opts.verbose) {
3580
- process.stderr.write(chalk11.dim(`[${language}] ${trimmed}
3625
+ process.stderr.write(chalk12.dim(`[${language}] ${trimmed}
3581
3626
  `));
3582
3627
  }
3583
3628
  if (trimmed.startsWith("[error]")) {
@@ -3718,7 +3763,7 @@ async function runNativeWorker(rootDir, language, opts) {
3718
3763
  let stdoutBuf = "";
3719
3764
  let killed = false;
3720
3765
  if (opts.verbose) {
3721
- process.stderr.write(chalk11.dim(`[${language}] Spawning: ${spec.cmd} ${spec.args.join(" ")}
3766
+ process.stderr.write(chalk12.dim(`[${language}] Spawning: ${spec.cmd} ${spec.args.join(" ")}
3722
3767
  `));
3723
3768
  }
3724
3769
  const runtimeReq = NATIVE_RUNTIME_REQUIREMENTS[language];
@@ -3759,7 +3804,7 @@ async function runNativeWorker(rootDir, language, opts) {
3759
3804
  const trimmed = line.trim();
3760
3805
  if (!trimmed) continue;
3761
3806
  if (opts.verbose) {
3762
- process.stderr.write(chalk11.dim(`[${language}] ${trimmed}
3807
+ process.stderr.write(chalk12.dim(`[${language}] ${trimmed}
3763
3808
  `));
3764
3809
  }
3765
3810
  if (trimmed.startsWith("[error]")) {
@@ -3789,14 +3834,14 @@ async function runNativeWorker(rootDir, language, opts) {
3789
3834
  async function pushFacts(facts, dsn, verbose) {
3790
3835
  const parsed = parseDsn2(dsn);
3791
3836
  if (!parsed) {
3792
- process.stderr.write(chalk11.red("Invalid DSN format.\n"));
3793
- process.stderr.write(chalk11.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>\n"));
3837
+ process.stderr.write(chalk12.red("Invalid DSN format.\n"));
3838
+ process.stderr.write(chalk12.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>\n"));
3794
3839
  return false;
3795
3840
  }
3796
3841
  const body = facts.join("\n") + "\n";
3797
3842
  const url = `${parsed.scheme}://${parsed.host}/v1/ingest/hcs`;
3798
3843
  if (verbose) {
3799
- process.stderr.write(chalk11.dim(`Pushing ${facts.length} facts to ${parsed.host}...
3844
+ process.stderr.write(chalk12.dim(`Pushing ${facts.length} facts to ${parsed.host}...
3800
3845
  `));
3801
3846
  }
3802
3847
  try {
@@ -3814,17 +3859,17 @@ async function pushFacts(facts, dsn, verbose) {
3814
3859
  });
3815
3860
  if (!response.ok) {
3816
3861
  const text = await response.text().catch(() => "");
3817
- process.stderr.write(chalk11.red(`Push failed: HTTP ${response.status} ${text}
3862
+ process.stderr.write(chalk12.red(`Push failed: HTTP ${response.status} ${text}
3818
3863
  `));
3819
3864
  return false;
3820
3865
  }
3821
3866
  if (verbose) {
3822
- process.stderr.write(chalk11.green(`\u2714 Pushed ${facts.length} facts successfully
3867
+ process.stderr.write(chalk12.green(`\u2714 Pushed ${facts.length} facts successfully
3823
3868
  `));
3824
3869
  }
3825
3870
  return true;
3826
3871
  } catch (err) {
3827
- process.stderr.write(chalk11.red(`Push failed: ${err instanceof Error ? err.message : String(err)}
3872
+ process.stderr.write(chalk12.red(`Push failed: ${err instanceof Error ? err.message : String(err)}
3828
3873
  `));
3829
3874
  return false;
3830
3875
  }
@@ -3891,21 +3936,21 @@ var ProgressTracker = class {
3891
3936
  const parts = [];
3892
3937
  for (const [lang, st] of this.langStatus) {
3893
3938
  if (st.done) {
3894
- parts.push(chalk11.green(`${lang} \u2713`));
3939
+ parts.push(chalk12.green(`${lang} \u2713`));
3895
3940
  } else if (st.phase === "waiting") {
3896
- parts.push(chalk11.dim(`${lang} \xB7`));
3941
+ parts.push(chalk12.dim(`${lang} \xB7`));
3897
3942
  } else if (st.phase === "discovering") {
3898
- parts.push(chalk11.yellow(`${lang} \u2026`));
3943
+ parts.push(chalk12.yellow(`${lang} \u2026`));
3899
3944
  } else if (st.phase === "scanning" && st.fileCount > 0) {
3900
3945
  const pct = Math.round(st.fileIndex / st.fileCount * 100);
3901
- parts.push(chalk11.cyan(`${lang} ${st.fileIndex}/${st.fileCount} ${pct}%`));
3946
+ parts.push(chalk12.cyan(`${lang} ${st.fileIndex}/${st.fileCount} ${pct}%`));
3902
3947
  } else if (st.phase === "extracting") {
3903
- parts.push(chalk11.cyan(`${lang} extracting`));
3948
+ parts.push(chalk12.cyan(`${lang} extracting`));
3904
3949
  } else {
3905
- parts.push(chalk11.dim(`${lang} ${st.phase}`));
3950
+ parts.push(chalk12.dim(`${lang} ${st.phase}`));
3906
3951
  }
3907
3952
  }
3908
- const line = ` ${parts.join(" ")} ${chalk11.dim(`${this.totalFacts} facts`)}`;
3953
+ const line = ` ${parts.join(" ")} ${chalk12.dim(`${this.totalFacts} facts`)}`;
3909
3954
  const padding = Math.max(0, this.lastLineLen - line.length);
3910
3955
  process.stderr.write(`\r${line}${" ".repeat(padding)}`);
3911
3956
  this.lastLineLen = line.length;
@@ -3925,7 +3970,7 @@ var extractCommand = new Command10("extract").description("Analyze source code a
3925
3970
  if (urlArg) {
3926
3971
  const cloneTimeoutMins = parseInt(opts.cloneTimeoutMins, 10);
3927
3972
  if (isNaN(cloneTimeoutMins) || cloneTimeoutMins < 1) {
3928
- process.stderr.write(chalk11.red("--clone-timeout-mins must be >= 1\n"));
3973
+ process.stderr.write(chalk12.red("--clone-timeout-mins must be >= 1\n"));
3929
3974
  process.exit(EXIT_USAGE_ERROR);
3930
3975
  }
3931
3976
  manifestRemoteUrl = redactRemoteUrl(urlArg);
@@ -3937,7 +3982,7 @@ var extractCommand = new Command10("extract").description("Analyze source code a
3937
3982
  });
3938
3983
  rootDir = cloned.dir;
3939
3984
  if (opts.keepClone) {
3940
- process.stderr.write(chalk11.dim(`Clone retained at: ${cloned.dir}
3985
+ process.stderr.write(chalk12.dim(`Clone retained at: ${cloned.dir}
3941
3986
  `));
3942
3987
  } else {
3943
3988
  process.once("exit", () => {
@@ -3949,14 +3994,14 @@ var extractCommand = new Command10("extract").description("Analyze source code a
3949
3994
  }
3950
3995
  } catch (err) {
3951
3996
  const msg = err instanceof CloneError ? err.message : err instanceof Error ? err.message : String(err);
3952
- process.stderr.write(chalk11.red(`Clone failed: ${msg}
3997
+ process.stderr.write(chalk12.red(`Clone failed: ${msg}
3953
3998
  `));
3954
3999
  process.exit(EXIT_USAGE_ERROR);
3955
4000
  }
3956
4001
  } else {
3957
4002
  rootDir = path12.resolve(targetPath);
3958
4003
  if (!await pathExists(rootDir)) {
3959
- process.stderr.write(chalk11.red(`Path does not exist: ${rootDir}
4004
+ process.stderr.write(chalk12.red(`Path does not exist: ${rootDir}
3960
4005
  `));
3961
4006
  process.exit(EXIT_USAGE_ERROR);
3962
4007
  }
@@ -3964,48 +4009,48 @@ var extractCommand = new Command10("extract").description("Analyze source code a
3964
4009
  try {
3965
4010
  stat4 = await fs4.stat(rootDir);
3966
4011
  } catch {
3967
- process.stderr.write(chalk11.red(`Cannot read path: ${rootDir}
4012
+ process.stderr.write(chalk12.red(`Cannot read path: ${rootDir}
3968
4013
  `));
3969
4014
  process.exit(EXIT_USAGE_ERROR);
3970
4015
  }
3971
4016
  if (!stat4.isDirectory()) {
3972
- process.stderr.write(chalk11.red(`Path must be a directory: ${rootDir}
4017
+ process.stderr.write(chalk12.red(`Path must be a directory: ${rootDir}
3973
4018
  `));
3974
4019
  process.exit(EXIT_USAGE_ERROR);
3975
4020
  }
3976
4021
  }
3977
4022
  const dsn = opts.dsn || process.env.VIBGRATE_DSN;
3978
4023
  if (opts.push && !dsn) {
3979
- process.stderr.write(chalk11.red("--push requires --dsn or VIBGRATE_DSN environment variable\n"));
4024
+ process.stderr.write(chalk12.red("--push requires --dsn or VIBGRATE_DSN environment variable\n"));
3980
4025
  process.exit(EXIT_USAGE_ERROR);
3981
4026
  }
3982
4027
  if (dsn && !parseDsn2(dsn)) {
3983
- process.stderr.write(chalk11.red("Invalid DSN format.\n"));
3984
- process.stderr.write(chalk11.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>\n"));
4028
+ process.stderr.write(chalk12.red("Invalid DSN format.\n"));
4029
+ process.stderr.write(chalk12.dim("Expected: vibgrate+https://<key_id>:<secret>@<host>/<workspace_id>\n"));
3985
4030
  process.exit(EXIT_USAGE_ERROR);
3986
4031
  }
3987
4032
  const concurrency = opts.concurrency ? parseInt(opts.concurrency, 10) : os4.cpus().length;
3988
4033
  if (isNaN(concurrency) || concurrency < 1) {
3989
- process.stderr.write(chalk11.red("--concurrency must be >= 1\n"));
4034
+ process.stderr.write(chalk12.red("--concurrency must be >= 1\n"));
3990
4035
  process.exit(EXIT_USAGE_ERROR);
3991
4036
  }
3992
4037
  const timeoutMins = parseInt(opts.timeoutMins, 10);
3993
4038
  if (isNaN(timeoutMins) || timeoutMins < 1) {
3994
- process.stderr.write(chalk11.red("--timeout-mins must be >= 1\n"));
4039
+ process.stderr.write(chalk12.red("--timeout-mins must be >= 1\n"));
3995
4040
  process.exit(EXIT_USAGE_ERROR);
3996
4041
  }
3997
4042
  const timeoutMs = timeoutMins * 60 * 1e3;
3998
4043
  if (opts.out) {
3999
4044
  const outDir = path12.dirname(path12.resolve(opts.out));
4000
4045
  if (!await pathExists(outDir)) {
4001
- process.stderr.write(chalk11.red(`Output directory does not exist: ${outDir}
4046
+ process.stderr.write(chalk12.red(`Output directory does not exist: ${outDir}
4002
4047
  `));
4003
4048
  process.exit(EXIT_USAGE_ERROR);
4004
4049
  }
4005
4050
  try {
4006
4051
  const outStat = await fs4.stat(path12.resolve(opts.out));
4007
4052
  if (outStat.isDirectory()) {
4008
- process.stderr.write(chalk11.red(`--out cannot be a directory: ${opts.out}
4053
+ process.stderr.write(chalk12.red(`--out cannot be a directory: ${opts.out}
4009
4054
  `));
4010
4055
  process.exit(EXIT_USAGE_ERROR);
4011
4056
  }
@@ -4016,14 +4061,14 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4016
4061
  if (opts.feedback) {
4017
4062
  const feedbackPath = path12.resolve(opts.feedback);
4018
4063
  if (!await pathExists(feedbackPath)) {
4019
- process.stderr.write(chalk11.red(`Feedback file not found: ${feedbackPath}
4064
+ process.stderr.write(chalk12.red(`Feedback file not found: ${feedbackPath}
4020
4065
  `));
4021
4066
  process.exit(EXIT_USAGE_ERROR);
4022
4067
  }
4023
4068
  try {
4024
4069
  feedbackLines = await loadFeedback(feedbackPath);
4025
4070
  } catch (err) {
4026
- process.stderr.write(chalk11.red(`Invalid feedback file: ${err instanceof Error ? err.message : String(err)}
4071
+ process.stderr.write(chalk12.red(`Invalid feedback file: ${err instanceof Error ? err.message : String(err)}
4027
4072
  `));
4028
4073
  process.exit(EXIT_USAGE_ERROR);
4029
4074
  }
@@ -4033,9 +4078,9 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4033
4078
  targetLanguages = opts.language.split(",").map((l) => normalizeLanguageToken(l)).filter(Boolean);
4034
4079
  for (const lang of targetLanguages) {
4035
4080
  if (!SUPPORTED_LANGUAGES.has(lang)) {
4036
- process.stderr.write(chalk11.red(`Unknown language: "${lang}"
4081
+ process.stderr.write(chalk12.red(`Unknown language: "${lang}"
4037
4082
  `));
4038
- process.stderr.write(chalk11.dim(`Supported: ${[...SUPPORTED_LANGUAGES].sort().join(", ")}
4083
+ process.stderr.write(chalk12.dim(`Supported: ${[...SUPPORTED_LANGUAGES].sort().join(", ")}
4039
4084
  `));
4040
4085
  process.exit(EXIT_USAGE_ERROR);
4041
4086
  }
@@ -4043,14 +4088,14 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4043
4088
  } else {
4044
4089
  const detected = await detectLanguages(rootDir, opts.includeTests ?? false);
4045
4090
  if (detected.length === 0) {
4046
- process.stderr.write(chalk11.yellow("No supported source files detected.\n"));
4091
+ process.stderr.write(chalk12.yellow("No supported source files detected.\n"));
4047
4092
  process.exit(EXIT_SUCCESS);
4048
4093
  }
4049
4094
  targetLanguages = detected.map((d) => d.language);
4050
4095
  if (opts.verbose) {
4051
- process.stderr.write(chalk11.dim("Detected languages:\n"));
4096
+ process.stderr.write(chalk12.dim("Detected languages:\n"));
4052
4097
  for (const d of detected) {
4053
- process.stderr.write(chalk11.dim(` ${d.language}: ${d.fileCount} files
4098
+ process.stderr.write(chalk12.dim(` ${d.language}: ${d.fileCount} files
4054
4099
  `));
4055
4100
  }
4056
4101
  }
@@ -4058,20 +4103,20 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4058
4103
  const runnableLanguages = targetLanguages.filter((l) => ALL_WORKER_LANGS.has(l));
4059
4104
  const unknownWorkerLangs = targetLanguages.filter((l) => !ALL_WORKER_LANGS.has(l));
4060
4105
  if (unknownWorkerLangs.length > 0 && opts.verbose) {
4061
- process.stderr.write(chalk11.dim(
4106
+ process.stderr.write(chalk12.dim(
4062
4107
  `No worker registered for: ${unknownWorkerLangs.join(", ")} \u2014 skipping.
4063
4108
  `
4064
4109
  ));
4065
4110
  }
4066
4111
  if (runnableLanguages.length === 0) {
4067
- process.stderr.write(chalk11.yellow("No languages with available HCS workers found.\n"));
4112
+ process.stderr.write(chalk12.yellow("No languages with available HCS workers found.\n"));
4068
4113
  process.exit(EXIT_SUCCESS);
4069
4114
  }
4070
4115
  const startTime = Date.now();
4071
4116
  const globalDeadline = startTime + timeoutMs;
4072
4117
  process.stderr.write(
4073
- chalk11.bold(`Extracting HCS facts from ${rootDir}
4074
- `) + chalk11.dim(`Languages: ${runnableLanguages.join(", ")} Concurrency: ${concurrency} Timeout: ${timeoutMins}m
4118
+ chalk12.bold(`Extracting HCS facts from ${rootDir}
4119
+ `) + chalk12.dim(`Languages: ${runnableLanguages.join(", ")} Concurrency: ${concurrency} Timeout: ${timeoutMins}m
4075
4120
  `)
4076
4121
  );
4077
4122
  const progress = new ProgressTracker(runnableLanguages);
@@ -4118,7 +4163,7 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4118
4163
  hasSchemaFailure = true;
4119
4164
  allErrors.push(`[${language}] Schema validation: ${validation.error}`);
4120
4165
  if (opts.verbose) {
4121
- process.stderr.write(chalk11.red(`[${language}] Invalid fact: ${validation.error}
4166
+ process.stderr.write(chalk12.red(`[${language}] Invalid fact: ${validation.error}
4122
4167
  `));
4123
4168
  }
4124
4169
  }
@@ -4155,7 +4200,7 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4155
4200
  allErrors.push("[behavioural] derived fact failed schema validation");
4156
4201
  }
4157
4202
  }
4158
- process.stderr.write(chalk11.dim(
4203
+ process.stderr.write(chalk12.dim(
4159
4204
  `Derived ${summary.assertions} behavioural assertion(s) \xB7 confidence ${summary.behaviouralConfidence} (${summary.assertedFacts}/${summary.surfaceFacts} surface facts)
4160
4205
  `
4161
4206
  ));
@@ -4190,7 +4235,7 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4190
4235
  if (opts.out) {
4191
4236
  const outPath = path12.resolve(opts.out);
4192
4237
  await fs4.writeFile(outPath, ndjsonOutput, "utf-8");
4193
- process.stderr.write(chalk11.green(`\u2714 Wrote ${allFacts.length} facts to ${outPath}
4238
+ process.stderr.write(chalk12.green(`\u2714 Wrote ${allFacts.length} facts to ${outPath}
4194
4239
  `));
4195
4240
  } else {
4196
4241
  process.stdout.write(ndjsonOutput);
@@ -4202,38 +4247,38 @@ var extractCommand = new Command10("extract").description("Analyze source code a
4202
4247
  }
4203
4248
  }
4204
4249
  if (opts.verbose) {
4205
- process.stderr.write(chalk11.dim("\n\u2500\u2500 Summary \u2500\u2500\n"));
4206
- process.stderr.write(chalk11.dim(` Facts emitted : ${allFacts.length}
4250
+ process.stderr.write(chalk12.dim("\n\u2500\u2500 Summary \u2500\u2500\n"));
4251
+ process.stderr.write(chalk12.dim(` Facts emitted : ${allFacts.length}
4207
4252
  `));
4208
- process.stderr.write(chalk11.dim(` Languages : ${runnableLanguages.join(", ")}
4253
+ process.stderr.write(chalk12.dim(` Languages : ${runnableLanguages.join(", ")}
4209
4254
  `));
4210
- process.stderr.write(chalk11.dim(` Elapsed : ${elapsed}s
4255
+ process.stderr.write(chalk12.dim(` Elapsed : ${elapsed}s
4211
4256
  `));
4212
4257
  if (allErrors.length > 0) {
4213
- process.stderr.write(chalk11.dim(` Errors : ${allErrors.length}
4258
+ process.stderr.write(chalk12.dim(` Errors : ${allErrors.length}
4214
4259
  `));
4215
4260
  for (const err of allErrors.slice(0, 10)) {
4216
- process.stderr.write(chalk11.dim(` ${err}
4261
+ process.stderr.write(chalk12.dim(` ${err}
4217
4262
  `));
4218
4263
  }
4219
4264
  if (allErrors.length > 10) {
4220
- process.stderr.write(chalk11.dim(` ... and ${allErrors.length - 10} more
4265
+ process.stderr.write(chalk12.dim(` ... and ${allErrors.length - 10} more
4221
4266
  `));
4222
4267
  }
4223
4268
  }
4224
- process.stderr.write(chalk11.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n"));
4269
+ process.stderr.write(chalk12.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n"));
4225
4270
  }
4226
4271
  if (hasTimeout) {
4227
- process.stderr.write(chalk11.red(`Timeout exceeded (${timeoutMins} minutes)
4272
+ process.stderr.write(chalk12.red(`Timeout exceeded (${timeoutMins} minutes)
4228
4273
  `));
4229
4274
  process.exit(EXIT_TIMEOUT);
4230
4275
  }
4231
4276
  if (hasSchemaFailure) {
4232
- process.stderr.write(chalk11.red("Fact schema validation failures detected\n"));
4277
+ process.stderr.write(chalk12.red("Fact schema validation failures detected\n"));
4233
4278
  process.exit(EXIT_SCHEMA_FAILURE);
4234
4279
  }
4235
4280
  if (hasParseFailure) {
4236
- process.stderr.write(chalk11.red("Parsing failures detected\n"));
4281
+ process.stderr.write(chalk12.red("Parsing failures detected\n"));
4237
4282
  process.exit(EXIT_PARSE_FAILURE);
4238
4283
  }
4239
4284
  });
@@ -4243,7 +4288,7 @@ import * as path13 from "path";
4243
4288
  import * as fs5 from "fs/promises";
4244
4289
  import * as crypto4 from "crypto";
4245
4290
  import { Command as Command11 } from "commander";
4246
- import chalk12 from "chalk";
4291
+ import chalk13 from "chalk";
4247
4292
  var EXIT_INVALID_PATH = 2;
4248
4293
  var EXIT_USAGE_ERROR2 = 5;
4249
4294
  var VALID_FORMATS = /* @__PURE__ */ new Set(["ndjson", "json", "patch"]);
@@ -4476,7 +4521,7 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4476
4521
  const genDir = path13.resolve(generatedPath);
4477
4522
  for (const [label, dir] of [["original_path", origDir], ["generated_path", genDir]]) {
4478
4523
  if (!await pathExists(dir)) {
4479
- process.stderr.write(chalk12.red(`${label} does not exist: ${dir}
4524
+ process.stderr.write(chalk13.red(`${label} does not exist: ${dir}
4480
4525
  `));
4481
4526
  process.exit(EXIT_INVALID_PATH);
4482
4527
  }
@@ -4484,25 +4529,25 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4484
4529
  try {
4485
4530
  stat4 = await fs5.stat(dir);
4486
4531
  } catch {
4487
- process.stderr.write(chalk12.red(`Cannot read ${label}: ${dir}
4532
+ process.stderr.write(chalk13.red(`Cannot read ${label}: ${dir}
4488
4533
  `));
4489
4534
  process.exit(EXIT_INVALID_PATH);
4490
4535
  }
4491
4536
  if (!stat4.isDirectory()) {
4492
- process.stderr.write(chalk12.red(`${label} must be a directory: ${dir}
4537
+ process.stderr.write(chalk13.red(`${label} must be a directory: ${dir}
4493
4538
  `));
4494
4539
  process.exit(EXIT_INVALID_PATH);
4495
4540
  }
4496
4541
  }
4497
4542
  const format = opts.format.toLowerCase();
4498
4543
  if (!VALID_FORMATS.has(format)) {
4499
- process.stderr.write(chalk12.red(`Invalid format: "${opts.format}". Allowed: ndjson, json, patch
4544
+ process.stderr.write(chalk13.red(`Invalid format: "${opts.format}". Allowed: ndjson, json, patch
4500
4545
  `));
4501
4546
  process.exit(EXIT_USAGE_ERROR2);
4502
4547
  }
4503
4548
  const contextLines = parseInt(opts.context, 10);
4504
4549
  if (isNaN(contextLines) || contextLines < 0) {
4505
- process.stderr.write(chalk12.red("--context must be >= 0\n"));
4550
+ process.stderr.write(chalk13.red("--context must be >= 0\n"));
4506
4551
  process.exit(EXIT_USAGE_ERROR2);
4507
4552
  }
4508
4553
  const includeGlobs = opts.include ? opts.include.split(",").map((g) => g.trim()).filter(Boolean) : void 0;
@@ -4514,9 +4559,9 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4514
4559
  const origMap = new Map(origFiles.map((f) => [f.relPath, f]));
4515
4560
  const genMap = new Map(genFiles.map((f) => [f.relPath, f]));
4516
4561
  if (opts.verbose) {
4517
- process.stderr.write(chalk12.dim(`Original: ${origFiles.length} files
4562
+ process.stderr.write(chalk13.dim(`Original: ${origFiles.length} files
4518
4563
  `));
4519
- process.stderr.write(chalk12.dim(`Generated: ${genFiles.length} files
4564
+ process.stderr.write(chalk13.dim(`Generated: ${genFiles.length} files
4520
4565
  `));
4521
4566
  }
4522
4567
  const deltas = [];
@@ -4550,7 +4595,7 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4550
4595
  }
4551
4596
  deltas.push(delta);
4552
4597
  if (opts.verbose) {
4553
- process.stderr.write(chalk12.dim(` modified: ${relPath} (+${diffResult.insertions} -${diffResult.deletions})
4598
+ process.stderr.write(chalk13.dim(` modified: ${relPath} (+${diffResult.insertions} -${diffResult.deletions})
4554
4599
  `));
4555
4600
  }
4556
4601
  }
@@ -4614,7 +4659,7 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4614
4659
  }
4615
4660
  deltas.push(delta);
4616
4661
  if (opts.verbose) {
4617
- process.stderr.write(chalk12.dim(
4662
+ process.stderr.write(chalk13.dim(
4618
4663
  ` renamed: ${pair.origPath} \u2192 ${pair.genPath} (${(pair.similarity * 100).toFixed(0)}% similar)
4619
4664
  `
4620
4665
  ));
@@ -4639,7 +4684,7 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4639
4684
  }
4640
4685
  deltas.push(delta);
4641
4686
  if (opts.verbose) {
4642
- process.stderr.write(chalk12.dim(` removed: ${file.relPath}
4687
+ process.stderr.write(chalk13.dim(` removed: ${file.relPath}
4643
4688
  `));
4644
4689
  }
4645
4690
  }
@@ -4661,7 +4706,7 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4661
4706
  }
4662
4707
  deltas.push(delta);
4663
4708
  if (opts.verbose) {
4664
- process.stderr.write(chalk12.dim(` added: ${file.relPath}
4709
+ process.stderr.write(chalk13.dim(` added: ${file.relPath}
4665
4710
  `));
4666
4711
  }
4667
4712
  }
@@ -4689,9 +4734,9 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4689
4734
  const modified = deltas.filter((d) => d.changeKind === "modified").length;
4690
4735
  const renamed = deltas.filter((d) => d.changeKind === "renamed").length;
4691
4736
  process.stderr.write(
4692
- chalk12.green(`\u2714 `) + `${deltas.length} changes: ` + chalk12.green(`+${added} added`) + ", " + chalk12.red(`-${removed} removed`) + ", " + chalk12.yellow(`~${modified} modified`) + ", " + chalk12.blue(`\u2192${renamed} renamed`) + "\n"
4737
+ chalk13.green(`\u2714 `) + `${deltas.length} changes: ` + chalk13.green(`+${added} added`) + ", " + chalk13.red(`-${removed} removed`) + ", " + chalk13.yellow(`~${modified} modified`) + ", " + chalk13.blue(`\u2192${renamed} renamed`) + "\n"
4693
4738
  );
4694
- process.stderr.write(chalk12.dim(` Written to ${outPath}
4739
+ process.stderr.write(chalk13.dim(` Written to ${outPath}
4695
4740
  `));
4696
4741
  if (opts.verbose && opts.stats) {
4697
4742
  let totalIns = 0;
@@ -4702,193 +4747,193 @@ var diffCommand = new Command11("diff").description("Compare two directory trees
4702
4747
  totalDel += d.stats.deletions;
4703
4748
  }
4704
4749
  }
4705
- process.stderr.write(chalk12.dim(` Total: +${totalIns} insertions, -${totalDel} deletions
4750
+ process.stderr.write(chalk13.dim(` Total: +${totalIns} insertions, -${totalDel} deletions
4706
4751
  `));
4707
4752
  }
4708
4753
  });
4709
4754
 
4710
4755
  // src/commands/help.ts
4711
4756
  import { Command as Command12 } from "commander";
4712
- import chalk13 from "chalk";
4757
+ import chalk14 from "chalk";
4713
4758
  var HELP_URL = "https://vibgrate.com/help";
4714
4759
  function printFooter() {
4715
4760
  console.log("");
4716
- console.log(chalk13.dim(`See ${HELP_URL} for more guidance`));
4761
+ console.log(chalk14.dim(`See ${HELP_URL} for more guidance`));
4717
4762
  }
4718
4763
  var detailedHelp = {
4719
4764
  scan: () => {
4720
4765
  console.log("");
4721
- console.log(chalk13.bold.underline("vibgrate scan") + chalk13.dim(" \u2014 Scan a project for upgrade drift"));
4766
+ console.log(chalk14.bold.underline("vibgrate scan") + chalk14.dim(" \u2014 Scan a project for upgrade drift"));
4722
4767
  console.log("");
4723
- console.log(chalk13.bold("Usage:"));
4768
+ console.log(chalk14.bold("Usage:"));
4724
4769
  console.log(" vibgrate scan [path] [options]");
4725
4770
  console.log("");
4726
- console.log(chalk13.bold("Arguments:"));
4727
- console.log(` ${chalk13.cyan("[path]")} Path to scan (default: current directory)`);
4771
+ console.log(chalk14.bold("Arguments:"));
4772
+ console.log(` ${chalk14.cyan("[path]")} Path to scan (default: current directory)`);
4728
4773
  console.log("");
4729
- console.log(chalk13.bold("Output options:"));
4730
- console.log(` ${chalk13.cyan("--format <format>")} Output format: ${chalk13.white("text")} | json | sarif | md (default: text)`);
4731
- console.log(` ${chalk13.cyan("--out <file>")} Write output to a file instead of stdout`);
4774
+ console.log(chalk14.bold("Output options:"));
4775
+ console.log(` ${chalk14.cyan("--format <format>")} Output format: ${chalk14.white("text")} | json | sarif | md (default: text)`);
4776
+ console.log(` ${chalk14.cyan("--out <file>")} Write output to a file instead of stdout`);
4732
4777
  console.log("");
4733
- console.log(chalk13.bold("Baseline & gating:"));
4734
- console.log(` ${chalk13.cyan("--baseline <file>")} Compare results against a saved baseline`);
4735
- console.log(` ${chalk13.cyan("--drift-budget <score>")} Fail if drift score exceeds this value (0\u2013100)`);
4736
- console.log(` ${chalk13.cyan("--drift-worsening <percent>")} Fail if drift worsens by more than % since baseline`);
4737
- console.log(` ${chalk13.cyan("--fail-on <level>")} Fail exit code on warn or error findings`);
4778
+ console.log(chalk14.bold("Baseline & gating:"));
4779
+ console.log(` ${chalk14.cyan("--baseline <file>")} Compare results against a saved baseline`);
4780
+ console.log(` ${chalk14.cyan("--drift-budget <score>")} Fail if drift score exceeds this value (0\u2013100)`);
4781
+ console.log(` ${chalk14.cyan("--drift-worsening <percent>")} Fail if drift worsens by more than % since baseline`);
4782
+ console.log(` ${chalk14.cyan("--fail-on <level>")} Fail exit code on warn or error findings`);
4738
4783
  console.log("");
4739
- console.log(chalk13.bold("Performance:"));
4740
- console.log(` ${chalk13.cyan("--concurrency <n>")} Max concurrent registry calls (default: 8)`);
4741
- console.log(` ${chalk13.cyan("--changed-only")} Only scan files changed since last git commit`);
4784
+ console.log(chalk14.bold("Performance:"));
4785
+ console.log(` ${chalk14.cyan("--concurrency <n>")} Max concurrent registry calls (default: 8)`);
4786
+ console.log(` ${chalk14.cyan("--changed-only")} Only scan files changed since last git commit`);
4742
4787
  console.log("");
4743
- console.log(chalk13.bold("Privacy & offline:"));
4744
- console.log(` ${chalk13.cyan("--offline")} Run without any network calls; skip result upload`);
4745
- console.log(` ${chalk13.cyan("--package-manifest <file>")} Use a local package-version manifest (JSON or ZIP) for offline mode`);
4746
- console.log(` ${chalk13.cyan("--no-local-artifacts")} Do not write .vibgrate JSON artifacts to disk`);
4747
- console.log(` ${chalk13.cyan("--max-privacy")} Strongest privacy mode: minimal scanners + no local artifacts`);
4788
+ console.log(chalk14.bold("Privacy & offline:"));
4789
+ console.log(` ${chalk14.cyan("--offline")} Run without any network calls; skip result upload`);
4790
+ console.log(` ${chalk14.cyan("--package-manifest <file>")} Use a local package-version manifest (JSON or ZIP) for offline mode`);
4791
+ console.log(` ${chalk14.cyan("--no-local-artifacts")} Do not write .vibgrate JSON artifacts to disk`);
4792
+ console.log(` ${chalk14.cyan("--max-privacy")} Strongest privacy mode: minimal scanners + no local artifacts`);
4748
4793
  console.log("");
4749
- console.log(chalk13.bold("Tooling:"));
4750
- console.log(` ${chalk13.cyan("--install-tools")} Auto-install missing security scanners via Homebrew`);
4751
- console.log(` ${chalk13.cyan("--ui-purpose")} Enable UI purpose evidence extraction (slower)`);
4794
+ console.log(chalk14.bold("Tooling:"));
4795
+ console.log(` ${chalk14.cyan("--install-tools")} Auto-install missing security scanners via Homebrew`);
4796
+ console.log(` ${chalk14.cyan("--ui-purpose")} Enable UI purpose evidence extraction (slower)`);
4752
4797
  console.log("");
4753
- console.log(chalk13.bold("Uploading results:"));
4754
- console.log(` ${chalk13.cyan("--push")} Auto-push results to Vibgrate API after scan`);
4755
- console.log(` ${chalk13.cyan("--dsn <dsn>")} DSN token for push (or set VIBGRATE_DSN env var)`);
4756
- console.log(` ${chalk13.cyan("--region <region>")} Data residency region: us | eu (default: us)`);
4757
- console.log(` ${chalk13.cyan("--strict")} Fail if the upload to Vibgrate API fails`);
4798
+ console.log(chalk14.bold("Uploading results:"));
4799
+ console.log(` ${chalk14.cyan("--push")} Auto-push results to Vibgrate API after scan`);
4800
+ console.log(` ${chalk14.cyan("--dsn <dsn>")} DSN token for push (or set VIBGRATE_DSN env var)`);
4801
+ console.log(` ${chalk14.cyan("--region <region>")} Data residency region: us | eu (default: us)`);
4802
+ console.log(` ${chalk14.cyan("--strict")} Fail if the upload to Vibgrate API fails`);
4758
4803
  console.log("");
4759
- console.log(chalk13.bold("Examples:"));
4760
- console.log(` ${chalk13.dim("# Scan the current directory and display a text report")}`);
4804
+ console.log(chalk14.bold("Examples:"));
4805
+ console.log(` ${chalk14.dim("# Scan the current directory and display a text report")}`);
4761
4806
  console.log(" vibgrate scan .");
4762
4807
  console.log("");
4763
- console.log(` ${chalk13.dim("# Scan, fail if drift score > 40, and write SARIF for GitHub Actions")}`);
4808
+ console.log(` ${chalk14.dim("# Scan, fail if drift score > 40, and write SARIF for GitHub Actions")}`);
4764
4809
  console.log(" vibgrate scan . --drift-budget 40 --format sarif --out drift.sarif");
4765
4810
  console.log("");
4766
- console.log(` ${chalk13.dim("# Scan and automatically upload results via a DSN")}`);
4811
+ console.log(` ${chalk14.dim("# Scan and automatically upload results via a DSN")}`);
4767
4812
  console.log(" vibgrate scan . --push --dsn $VIBGRATE_DSN");
4768
4813
  console.log("");
4769
- console.log(` ${chalk13.dim("# Offline scan using a pre-downloaded package manifest")}`);
4814
+ console.log(` ${chalk14.dim("# Offline scan using a pre-downloaded package manifest")}`);
4770
4815
  console.log(" vibgrate scan . --offline --package-manifest ./manifest.zip");
4771
4816
  },
4772
4817
  init: () => {
4773
4818
  console.log("");
4774
- console.log(chalk13.bold.underline("vibgrate init") + chalk13.dim(" \u2014 Initialise vibgrate in a project directory"));
4819
+ console.log(chalk14.bold.underline("vibgrate init") + chalk14.dim(" \u2014 Initialise vibgrate in a project directory"));
4775
4820
  console.log("");
4776
- console.log(chalk13.bold("Usage:"));
4821
+ console.log(chalk14.bold("Usage:"));
4777
4822
  console.log(" vibgrate init [path] [options]");
4778
4823
  console.log("");
4779
- console.log(chalk13.bold("Arguments:"));
4780
- console.log(` ${chalk13.cyan("[path]")} Directory to initialise (default: current directory)`);
4824
+ console.log(chalk14.bold("Arguments:"));
4825
+ console.log(` ${chalk14.cyan("[path]")} Directory to initialise (default: current directory)`);
4781
4826
  console.log("");
4782
- console.log(chalk13.bold("Options:"));
4783
- console.log(` ${chalk13.cyan("--baseline")} Create an initial drift baseline after init`);
4784
- console.log(` ${chalk13.cyan("--yes")} Skip all confirmation prompts`);
4827
+ console.log(chalk14.bold("Options:"));
4828
+ console.log(` ${chalk14.cyan("--baseline")} Create an initial drift baseline after init`);
4829
+ console.log(` ${chalk14.cyan("--yes")} Skip all confirmation prompts`);
4785
4830
  console.log("");
4786
- console.log(chalk13.bold("What it does:"));
4831
+ console.log(chalk14.bold("What it does:"));
4787
4832
  console.log(" \u2022 Creates a .vibgrate/ directory");
4788
4833
  console.log(" \u2022 Writes a vibgrate.config.ts starter config");
4789
4834
  console.log(" \u2022 Optionally runs an initial baseline scan (--baseline)");
4790
4835
  console.log("");
4791
- console.log(chalk13.bold("Examples:"));
4836
+ console.log(chalk14.bold("Examples:"));
4792
4837
  console.log(" vibgrate init");
4793
4838
  console.log(" vibgrate init ./my-project --baseline");
4794
4839
  },
4795
4840
  baseline: () => {
4796
4841
  console.log("");
4797
- console.log(chalk13.bold.underline("vibgrate baseline") + chalk13.dim(" \u2014 Save a drift baseline snapshot"));
4842
+ console.log(chalk14.bold.underline("vibgrate baseline") + chalk14.dim(" \u2014 Save a drift baseline snapshot"));
4798
4843
  console.log("");
4799
- console.log(chalk13.bold("Usage:"));
4844
+ console.log(chalk14.bold("Usage:"));
4800
4845
  console.log(" vibgrate baseline [path]");
4801
4846
  console.log("");
4802
- console.log(chalk13.bold("Arguments:"));
4803
- console.log(` ${chalk13.cyan("[path]")} Path to baseline (default: current directory)`);
4847
+ console.log(chalk14.bold("Arguments:"));
4848
+ console.log(` ${chalk14.cyan("[path]")} Path to baseline (default: current directory)`);
4804
4849
  console.log("");
4805
- console.log(chalk13.bold("What it does:"));
4850
+ console.log(chalk14.bold("What it does:"));
4806
4851
  console.log(" Runs a full scan and saves the result as .vibgrate/baseline.json.");
4807
4852
  console.log(" Future scans can compare against this file using --baseline.");
4808
4853
  console.log("");
4809
- console.log(chalk13.bold("Examples:"));
4854
+ console.log(chalk14.bold("Examples:"));
4810
4855
  console.log(" vibgrate baseline .");
4811
4856
  console.log(" vibgrate scan . --baseline .vibgrate/baseline.json --drift-worsening 10");
4812
4857
  },
4813
4858
  report: () => {
4814
4859
  console.log("");
4815
- console.log(chalk13.bold.underline("vibgrate report") + chalk13.dim(" \u2014 Generate a report from a saved scan artifact"));
4860
+ console.log(chalk14.bold.underline("vibgrate report") + chalk14.dim(" \u2014 Generate a report from a saved scan artifact"));
4816
4861
  console.log("");
4817
- console.log(chalk13.bold("Usage:"));
4862
+ console.log(chalk14.bold("Usage:"));
4818
4863
  console.log(" vibgrate report [options]");
4819
4864
  console.log("");
4820
- console.log(chalk13.bold("Options:"));
4821
- console.log(` ${chalk13.cyan("--in <file>")} Input artifact file (default: .vibgrate/scan_result.json)`);
4822
- console.log(` ${chalk13.cyan("--format <format>")} Output format: ${chalk13.white("text")} | md | json (default: text)`);
4865
+ console.log(chalk14.bold("Options:"));
4866
+ console.log(` ${chalk14.cyan("--in <file>")} Input artifact file (default: .vibgrate/scan_result.json)`);
4867
+ console.log(` ${chalk14.cyan("--format <format>")} Output format: ${chalk14.white("text")} | md | json (default: text)`);
4823
4868
  console.log("");
4824
- console.log(chalk13.bold("Examples:"));
4869
+ console.log(chalk14.bold("Examples:"));
4825
4870
  console.log(" vibgrate report");
4826
4871
  console.log(" vibgrate report --format md > DRIFT-REPORT.md");
4827
4872
  console.log(" vibgrate report --in ./ci/scan_result.json --format json");
4828
4873
  },
4829
4874
  sbom: () => {
4830
4875
  console.log("");
4831
- console.log(chalk13.bold.underline("vibgrate sbom") + chalk13.dim(" \u2014 Export a Software Bill of Materials from a scan artifact"));
4876
+ console.log(chalk14.bold.underline("vibgrate sbom") + chalk14.dim(" \u2014 Export a Software Bill of Materials from a scan artifact"));
4832
4877
  console.log("");
4833
- console.log(chalk13.bold("Usage:"));
4878
+ console.log(chalk14.bold("Usage:"));
4834
4879
  console.log(" vibgrate sbom [options]");
4835
4880
  console.log("");
4836
- console.log(chalk13.bold("Options:"));
4837
- console.log(` ${chalk13.cyan("--in <file>")} Input artifact (default: .vibgrate/scan_result.json)`);
4838
- console.log(` ${chalk13.cyan("--format <format>")} SBOM format: ${chalk13.white("cyclonedx")} | spdx (default: cyclonedx)`);
4839
- console.log(` ${chalk13.cyan("--out <file>")} Write SBOM to file instead of stdout`);
4881
+ console.log(chalk14.bold("Options:"));
4882
+ console.log(` ${chalk14.cyan("--in <file>")} Input artifact (default: .vibgrate/scan_result.json)`);
4883
+ console.log(` ${chalk14.cyan("--format <format>")} SBOM format: ${chalk14.white("cyclonedx")} | spdx (default: cyclonedx)`);
4884
+ console.log(` ${chalk14.cyan("--out <file>")} Write SBOM to file instead of stdout`);
4840
4885
  console.log("");
4841
- console.log(chalk13.bold("Examples:"));
4886
+ console.log(chalk14.bold("Examples:"));
4842
4887
  console.log(" vibgrate sbom --format cyclonedx --out sbom.json");
4843
4888
  console.log(" vibgrate sbom --format spdx --out sbom.spdx.json");
4844
4889
  },
4845
4890
  push: () => {
4846
4891
  console.log("");
4847
- console.log(chalk13.bold.underline("vibgrate push") + chalk13.dim(" \u2014 Upload a scan artifact to the Vibgrate API"));
4892
+ console.log(chalk14.bold.underline("vibgrate push") + chalk14.dim(" \u2014 Upload a scan artifact to the Vibgrate API"));
4848
4893
  console.log("");
4849
- console.log(chalk13.bold("Usage:"));
4894
+ console.log(chalk14.bold("Usage:"));
4850
4895
  console.log(" vibgrate push [options]");
4851
4896
  console.log("");
4852
- console.log(chalk13.bold("Options:"));
4853
- console.log(` ${chalk13.cyan("--dsn <dsn>")} DSN token (or set VIBGRATE_DSN env var)`);
4854
- console.log(` ${chalk13.cyan("--file <file>")} Artifact to upload (default: .vibgrate/scan_result.json)`);
4855
- console.log(` ${chalk13.cyan("--region <region>")} Override data residency region: us | eu`);
4856
- console.log(` ${chalk13.cyan("--strict")} Fail with non-zero exit code on upload error`);
4897
+ console.log(chalk14.bold("Options:"));
4898
+ console.log(` ${chalk14.cyan("--dsn <dsn>")} DSN token (or set VIBGRATE_DSN env var)`);
4899
+ console.log(` ${chalk14.cyan("--file <file>")} Artifact to upload (default: .vibgrate/scan_result.json)`);
4900
+ console.log(` ${chalk14.cyan("--region <region>")} Override data residency region: us | eu`);
4901
+ console.log(` ${chalk14.cyan("--strict")} Fail with non-zero exit code on upload error`);
4857
4902
  console.log("");
4858
- console.log(chalk13.bold("Examples:"));
4903
+ console.log(chalk14.bold("Examples:"));
4859
4904
  console.log(" vibgrate push --dsn $VIBGRATE_DSN");
4860
4905
  console.log(" vibgrate push --file ./ci/scan_result.json --strict");
4861
4906
  },
4862
4907
  dsn: () => {
4863
4908
  console.log("");
4864
- console.log(chalk13.bold.underline("vibgrate dsn") + chalk13.dim(" \u2014 Manage DSN tokens for API authentication"));
4909
+ console.log(chalk14.bold.underline("vibgrate dsn") + chalk14.dim(" \u2014 Manage DSN tokens for API authentication"));
4865
4910
  console.log("");
4866
- console.log(chalk13.bold("Subcommands:"));
4867
- console.log(` ${chalk13.cyan("vibgrate dsn create")} Generate a new DSN token`);
4911
+ console.log(chalk14.bold("Subcommands:"));
4912
+ console.log(` ${chalk14.cyan("vibgrate dsn create")} Generate a new DSN token`);
4868
4913
  console.log("");
4869
- console.log(chalk13.bold("dsn create options:"));
4870
- console.log(` ${chalk13.cyan("--workspace <id>")} Workspace ID or "new" to auto-generate ${chalk13.red("(required)")}`);
4871
- console.log(` ${chalk13.cyan("--region <region>")} Data residency region: us | eu (default: us)`);
4872
- console.log(` ${chalk13.cyan("--ingest <url>")} Override ingest API URL`);
4873
- console.log(` ${chalk13.cyan("--write <path>")} Write the DSN to a file (add to .gitignore!)`);
4914
+ console.log(chalk14.bold("dsn create options:"));
4915
+ console.log(` ${chalk14.cyan("--workspace <id>")} Workspace ID or "new" to auto-generate ${chalk14.red("(required)")}`);
4916
+ console.log(` ${chalk14.cyan("--region <region>")} Data residency region: us | eu (default: us)`);
4917
+ console.log(` ${chalk14.cyan("--ingest <url>")} Override ingest API URL`);
4918
+ console.log(` ${chalk14.cyan("--write <path>")} Write the DSN to a file (add to .gitignore!)`);
4874
4919
  console.log("");
4875
- console.log(chalk13.bold("Examples:"));
4920
+ console.log(chalk14.bold("Examples:"));
4876
4921
  console.log(" vibgrate dsn create --workspace new");
4877
4922
  console.log(" vibgrate dsn create --workspace abc123");
4878
4923
  console.log(" vibgrate dsn create --workspace new --region eu --write .vibgrate/.dsn");
4879
4924
  },
4880
4925
  update: () => {
4881
4926
  console.log("");
4882
- console.log(chalk13.bold.underline("vibgrate update") + chalk13.dim(" \u2014 Update the vibgrate CLI to the latest version"));
4927
+ console.log(chalk14.bold.underline("vibgrate update") + chalk14.dim(" \u2014 Update the vibgrate CLI to the latest version"));
4883
4928
  console.log("");
4884
- console.log(chalk13.bold("Usage:"));
4929
+ console.log(chalk14.bold("Usage:"));
4885
4930
  console.log(" vibgrate update [options]");
4886
4931
  console.log("");
4887
- console.log(chalk13.bold("Options:"));
4888
- console.log(` ${chalk13.cyan("--check")} Check for a newer version without installing`);
4889
- console.log(` ${chalk13.cyan("--pm <manager>")} Force a package manager: npm | pnpm | yarn | bun`);
4932
+ console.log(chalk14.bold("Options:"));
4933
+ console.log(` ${chalk14.cyan("--check")} Check for a newer version without installing`);
4934
+ console.log(` ${chalk14.cyan("--pm <manager>")} Force a package manager: npm | pnpm | yarn | bun`);
4890
4935
  console.log("");
4891
- console.log(chalk13.bold("Examples:"));
4936
+ console.log(chalk14.bold("Examples:"));
4892
4937
  console.log(" vibgrate update");
4893
4938
  console.log(" vibgrate update --check");
4894
4939
  console.log(" vibgrate update --pm pnpm");
@@ -4896,33 +4941,33 @@ var detailedHelp = {
4896
4941
  };
4897
4942
  function printSummaryHelp() {
4898
4943
  console.log("");
4899
- console.log(chalk13.bold("vibgrate") + chalk13.dim(" \u2014 Continuous Drift Intelligence"));
4944
+ console.log(chalk14.bold("vibgrate") + chalk14.dim(" \u2014 Continuous Drift Intelligence"));
4900
4945
  console.log("");
4901
- console.log(chalk13.bold("Usage:"));
4946
+ console.log(chalk14.bold("Usage:"));
4902
4947
  console.log(" vibgrate <command> [options]");
4903
4948
  console.log(" vibgrate help [command] Show detailed help for a command");
4904
4949
  console.log("");
4905
- console.log(chalk13.bold("Getting started:"));
4906
- console.log(` ${chalk13.cyan("init")} Initialise vibgrate in a project (creates config & .vibgrate/ dir)`);
4907
- console.log(` ${chalk13.cyan("login")} Sign the CLI into your workspace via the browser`);
4908
- console.log(` ${chalk13.cyan("logout")} Clear stored login credentials`);
4950
+ console.log(chalk14.bold("Getting started:"));
4951
+ console.log(` ${chalk14.cyan("init")} Initialise vibgrate in a project (creates config & .vibgrate/ dir)`);
4952
+ console.log(` ${chalk14.cyan("login")} Sign the CLI into your workspace via the browser`);
4953
+ console.log(` ${chalk14.cyan("logout")} Clear stored login credentials`);
4909
4954
  console.log("");
4910
- console.log(chalk13.bold("Core scanning:"));
4911
- console.log(` ${chalk13.cyan("scan")} Scan a project for upgrade drift and generate a report`);
4912
- console.log(` ${chalk13.cyan("baseline")} Save a baseline snapshot to compare future scans against`);
4955
+ console.log(chalk14.bold("Core scanning:"));
4956
+ console.log(` ${chalk14.cyan("scan")} Scan a project for upgrade drift and generate a report`);
4957
+ console.log(` ${chalk14.cyan("baseline")} Save a baseline snapshot to compare future scans against`);
4913
4958
  console.log("");
4914
- console.log(chalk13.bold("Reporting & export:"));
4915
- console.log(` ${chalk13.cyan("report")} Re-generate a report from a previously saved scan artifact`);
4916
- console.log(` ${chalk13.cyan("sbom")} Export a Software Bill of Materials (CycloneDX or SPDX)`);
4959
+ console.log(chalk14.bold("Reporting & export:"));
4960
+ console.log(` ${chalk14.cyan("report")} Re-generate a report from a previously saved scan artifact`);
4961
+ console.log(` ${chalk14.cyan("sbom")} Export a Software Bill of Materials (CycloneDX or SPDX)`);
4917
4962
  console.log("");
4918
- console.log(chalk13.bold("CI/CD integration:"));
4919
- console.log(` ${chalk13.cyan("push")} Upload a scan artifact to the Vibgrate API`);
4920
- console.log(` ${chalk13.cyan("dsn")} Create and manage DSN tokens for API authentication`);
4963
+ console.log(chalk14.bold("CI/CD integration:"));
4964
+ console.log(` ${chalk14.cyan("push")} Upload a scan artifact to the Vibgrate API`);
4965
+ console.log(` ${chalk14.cyan("dsn")} Create and manage DSN tokens for API authentication`);
4921
4966
  console.log("");
4922
- console.log(chalk13.bold("Maintenance:"));
4923
- console.log(` ${chalk13.cyan("update")} Update the vibgrate CLI to the latest version`);
4967
+ console.log(chalk14.bold("Maintenance:"));
4968
+ console.log(` ${chalk14.cyan("update")} Update the vibgrate CLI to the latest version`);
4924
4969
  console.log("");
4925
- console.log(chalk13.dim("Run") + ` ${chalk13.cyan("vibgrate help <command>")} ` + chalk13.dim("for detailed options, e.g.") + ` ${chalk13.cyan("vibgrate help scan")}`);
4970
+ console.log(chalk14.dim("Run") + ` ${chalk14.cyan("vibgrate help <command>")} ` + chalk14.dim("for detailed options, e.g.") + ` ${chalk14.cyan("vibgrate help scan")}`);
4926
4971
  }
4927
4972
  var helpCommand = new Command12("help").description("Show help for vibgrate commands").argument("[command]", "Command to show detailed help for").helpOption(false).action((cmd) => {
4928
4973
  const name = cmd?.toLowerCase().trim();
@@ -4930,8 +4975,8 @@ var helpCommand = new Command12("help").description("Show help for vibgrate comm
4930
4975
  detailedHelp[name]();
4931
4976
  } else if (name) {
4932
4977
  console.log("");
4933
- console.log(chalk13.red(`Unknown command: ${name}`));
4934
- console.log(chalk13.dim(`Available commands: ${Object.keys(detailedHelp).join(", ")}`));
4978
+ console.log(chalk14.red(`Unknown command: ${name}`));
4979
+ console.log(chalk14.dim(`Available commands: ${Object.keys(detailedHelp).join(", ")}`));
4935
4980
  printSummaryHelp();
4936
4981
  } else {
4937
4982
  printSummaryHelp();
@@ -4959,8 +5004,8 @@ function notifyIfUpdateAvailable() {
4959
5004
  void checkForUpdate().then((update) => {
4960
5005
  if (!update?.updateAvailable) return;
4961
5006
  console.error("");
4962
- console.error(chalk14.yellow(` Update available: ${update.current} \u2192 ${update.latest}`));
4963
- console.error(chalk14.dim(' Run "vibgrate update" to install the latest version.'));
5007
+ console.error(chalk15.yellow(` Update available: ${update.current} \u2192 ${update.latest}`));
5008
+ console.error(chalk15.dim(' Run "vibgrate update" to install the latest version.'));
4964
5009
  console.error("");
4965
5010
  }).catch(() => {
4966
5011
  });