@aiready/cli 0.9.43 → 0.9.45

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -25,15 +25,15 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_commander = require("commander");
28
- var import_fs5 = require("fs");
29
- var import_path7 = require("path");
28
+ var import_fs6 = require("fs");
29
+ var import_path8 = require("path");
30
30
  var import_url = require("url");
31
31
 
32
32
  // src/commands/scan.ts
33
- var import_chalk2 = __toESM(require("chalk"));
34
- var import_fs2 = require("fs");
35
- var import_path2 = require("path");
36
- var import_core = require("@aiready/core");
33
+ var import_chalk3 = __toESM(require("chalk"));
34
+ var import_fs3 = require("fs");
35
+ var import_path3 = require("path");
36
+ var import_core2 = require("@aiready/core");
37
37
 
38
38
  // src/index.ts
39
39
  var import_pattern_detect = require("@aiready/pattern-detect");
@@ -338,11 +338,79 @@ function truncateArray(arr, cap = 8) {
338
338
  return shown.join(", ") + (more > 0 ? `, ... (+${more} more)` : "");
339
339
  }
340
340
 
341
+ // src/commands/upload.ts
342
+ var import_fs2 = __toESM(require("fs"));
343
+ var import_path2 = require("path");
344
+ var import_chalk2 = __toESM(require("chalk"));
345
+ var import_core = require("@aiready/core");
346
+ async function uploadAction(file, options) {
347
+ const startTime = Date.now();
348
+ const filePath = (0, import_path2.resolve)(process.cwd(), file);
349
+ const serverUrl = options.server || process.env.AIREADY_SERVER || "https://dev.platform.getaiready.dev";
350
+ const apiKey = options.apiKey || process.env.AIREADY_API_KEY;
351
+ if (!apiKey) {
352
+ console.error(import_chalk2.default.red("\u274C API Key is required for upload."));
353
+ console.log(import_chalk2.default.dim(" Set AIREADY_API_KEY environment variable or use --api-key flag."));
354
+ console.log(import_chalk2.default.dim(" Get an API key from https://getaiready.dev/dashboard"));
355
+ process.exit(1);
356
+ }
357
+ if (!import_fs2.default.existsSync(filePath)) {
358
+ console.error(import_chalk2.default.red(`\u274C File not found: ${filePath}`));
359
+ process.exit(1);
360
+ }
361
+ try {
362
+ console.log(import_chalk2.default.blue(`\u{1F680} Uploading report to ${serverUrl}...`));
363
+ const reportData = JSON.parse(import_fs2.default.readFileSync(filePath, "utf-8"));
364
+ const repoId = options.repoId || reportData.repository?.repoId;
365
+ const res = await fetch(`${serverUrl}/api/analysis/upload`, {
366
+ method: "POST",
367
+ headers: {
368
+ "Content-Type": "application/json",
369
+ "Authorization": `Bearer ${apiKey}`
370
+ },
371
+ body: JSON.stringify({
372
+ data: reportData,
373
+ repoId
374
+ // Might be null, server will handle mapping
375
+ })
376
+ });
377
+ const result = await res.json();
378
+ if (!res.ok) {
379
+ console.error(import_chalk2.default.red(`\u274C Upload failed: ${result.error || res.statusText}`));
380
+ if (res.status === 401) {
381
+ console.log(import_chalk2.default.dim(" Hint: Your API key may be invalid or expired."));
382
+ }
383
+ process.exit(1);
384
+ }
385
+ const duration = ((Date.now() - startTime) / 1e3).toFixed(2);
386
+ console.log(import_chalk2.default.green(`
387
+ \u2705 Upload successful! (${duration}s)`));
388
+ console.log(import_chalk2.default.cyan(` View results: ${serverUrl}/dashboard`));
389
+ if (result.analysis) {
390
+ console.log(import_chalk2.default.dim(` Analysis ID: ${result.analysis.id}`));
391
+ console.log(import_chalk2.default.dim(` Score: ${result.analysis.aiScore}/100`));
392
+ }
393
+ } catch (error) {
394
+ (0, import_core.handleCLIError)(error, "Upload");
395
+ }
396
+ }
397
+ var uploadHelpText = `
398
+ EXAMPLES:
399
+ $ aiready upload report.json --api-key ar_...
400
+ $ aiready upload .aiready/latest.json
401
+ $ AIREADY_API_KEY=ar_... aiready upload report.json
402
+
403
+ ENVIRONMENT VARIABLES:
404
+ AIREADY_API_KEY Your platform API key
405
+ AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
406
+ `;
407
+
341
408
  // src/commands/scan.ts
342
409
  async function scanAction(directory, options) {
343
- console.log(import_chalk2.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
410
+ console.log(import_chalk3.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
344
411
  const startTime = Date.now();
345
- const resolvedDir = (0, import_path2.resolve)(process.cwd(), directory || ".");
412
+ const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
413
+ const repoMetadata = (0, import_core2.getRepoMetadata)(resolvedDir);
346
414
  try {
347
415
  const defaults = {
348
416
  tools: [
@@ -385,7 +453,7 @@ async function scanAction(directory, options) {
385
453
  break;
386
454
  default:
387
455
  console.log(
388
- import_chalk2.default.yellow(
456
+ import_chalk3.default.yellow(
389
457
  `
390
458
  \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`
391
459
  )
@@ -399,7 +467,7 @@ async function scanAction(directory, options) {
399
467
  if (profileTools) {
400
468
  cliOverrides.tools = profileTools;
401
469
  }
402
- const baseOptions = await (0, import_core.loadMergedConfig)(
470
+ const baseOptions = await (0, import_core2.loadMergedConfig)(
403
471
  resolvedDir,
404
472
  defaults,
405
473
  cliOverrides
@@ -417,22 +485,22 @@ async function scanAction(directory, options) {
417
485
  ...baseOptions
418
486
  };
419
487
  }
420
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Preview ==="));
488
+ console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
421
489
  console.log(
422
- import_chalk2.default.white("Tools to run:"),
490
+ import_chalk3.default.white("Tools to run:"),
423
491
  (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
424
492
  );
425
- console.log(import_chalk2.default.white("Will use settings from config and defaults."));
426
- console.log(import_chalk2.default.white("\nGeneral settings:"));
493
+ console.log(import_chalk3.default.white("Will use settings from config and defaults."));
494
+ console.log(import_chalk3.default.white("\nGeneral settings:"));
427
495
  if (finalOptions.rootDir)
428
- console.log(` rootDir: ${import_chalk2.default.bold(String(finalOptions.rootDir))}`);
496
+ console.log(` rootDir: ${import_chalk3.default.bold(String(finalOptions.rootDir))}`);
429
497
  if (finalOptions.include)
430
498
  console.log(
431
- ` include: ${import_chalk2.default.bold(truncateArray(finalOptions.include, 6))}`
499
+ ` include: ${import_chalk3.default.bold(truncateArray(finalOptions.include, 6))}`
432
500
  );
433
501
  if (finalOptions.exclude)
434
502
  console.log(
435
- ` exclude: ${import_chalk2.default.bold(truncateArray(finalOptions.exclude, 6))}`
503
+ ` exclude: ${import_chalk3.default.bold(truncateArray(finalOptions.exclude, 6))}`
436
504
  );
437
505
  if (finalOptions["pattern-detect"] || finalOptions.minSimilarity) {
438
506
  const patternDetectConfig = finalOptions["pattern-detect"] || {
@@ -446,40 +514,40 @@ async function scanAction(directory, options) {
446
514
  severity: finalOptions.severity,
447
515
  includeTests: finalOptions.includeTests
448
516
  };
449
- console.log(import_chalk2.default.white("\nPattern-detect settings:"));
517
+ console.log(import_chalk3.default.white("\nPattern-detect settings:"));
450
518
  console.log(
451
- ` minSimilarity: ${import_chalk2.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
519
+ ` minSimilarity: ${import_chalk3.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
452
520
  );
453
521
  console.log(
454
- ` minLines: ${import_chalk2.default.bold(patternDetectConfig.minLines ?? "default")}`
522
+ ` minLines: ${import_chalk3.default.bold(patternDetectConfig.minLines ?? "default")}`
455
523
  );
456
524
  if (patternDetectConfig.approx !== void 0)
457
525
  console.log(
458
- ` approx: ${import_chalk2.default.bold(String(patternDetectConfig.approx))}`
526
+ ` approx: ${import_chalk3.default.bold(String(patternDetectConfig.approx))}`
459
527
  );
460
528
  if (patternDetectConfig.minSharedTokens !== void 0)
461
529
  console.log(
462
- ` minSharedTokens: ${import_chalk2.default.bold(String(patternDetectConfig.minSharedTokens))}`
530
+ ` minSharedTokens: ${import_chalk3.default.bold(String(patternDetectConfig.minSharedTokens))}`
463
531
  );
464
532
  if (patternDetectConfig.maxCandidatesPerBlock !== void 0)
465
533
  console.log(
466
- ` maxCandidatesPerBlock: ${import_chalk2.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
534
+ ` maxCandidatesPerBlock: ${import_chalk3.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
467
535
  );
468
536
  if (patternDetectConfig.batchSize !== void 0)
469
537
  console.log(
470
- ` batchSize: ${import_chalk2.default.bold(String(patternDetectConfig.batchSize))}`
538
+ ` batchSize: ${import_chalk3.default.bold(String(patternDetectConfig.batchSize))}`
471
539
  );
472
540
  if (patternDetectConfig.streamResults !== void 0)
473
541
  console.log(
474
- ` streamResults: ${import_chalk2.default.bold(String(patternDetectConfig.streamResults))}`
542
+ ` streamResults: ${import_chalk3.default.bold(String(patternDetectConfig.streamResults))}`
475
543
  );
476
544
  if (patternDetectConfig.severity !== void 0)
477
545
  console.log(
478
- ` severity: ${import_chalk2.default.bold(String(patternDetectConfig.severity))}`
546
+ ` severity: ${import_chalk3.default.bold(String(patternDetectConfig.severity))}`
479
547
  );
480
548
  if (patternDetectConfig.includeTests !== void 0)
481
549
  console.log(
482
- ` includeTests: ${import_chalk2.default.bold(String(patternDetectConfig.includeTests))}`
550
+ ` includeTests: ${import_chalk3.default.bold(String(patternDetectConfig.includeTests))}`
483
551
  );
484
552
  }
485
553
  if (finalOptions["context-analyzer"] || finalOptions.maxDepth) {
@@ -490,57 +558,57 @@ async function scanAction(directory, options) {
490
558
  maxFragmentation: finalOptions.maxFragmentation,
491
559
  includeNodeModules: finalOptions.includeNodeModules
492
560
  };
493
- console.log(import_chalk2.default.white("\nContext-analyzer settings:"));
494
- console.log(` maxDepth: ${import_chalk2.default.bold(ca.maxDepth ?? "default")}`);
561
+ console.log(import_chalk3.default.white("\nContext-analyzer settings:"));
562
+ console.log(` maxDepth: ${import_chalk3.default.bold(ca.maxDepth ?? "default")}`);
495
563
  console.log(
496
- ` maxContextBudget: ${import_chalk2.default.bold(ca.maxContextBudget ?? "default")}`
564
+ ` maxContextBudget: ${import_chalk3.default.bold(ca.maxContextBudget ?? "default")}`
497
565
  );
498
566
  if (ca.minCohesion !== void 0)
499
- console.log(` minCohesion: ${import_chalk2.default.bold(String(ca.minCohesion))}`);
567
+ console.log(` minCohesion: ${import_chalk3.default.bold(String(ca.minCohesion))}`);
500
568
  if (ca.maxFragmentation !== void 0)
501
569
  console.log(
502
- ` maxFragmentation: ${import_chalk2.default.bold(String(ca.maxFragmentation))}`
570
+ ` maxFragmentation: ${import_chalk3.default.bold(String(ca.maxFragmentation))}`
503
571
  );
504
572
  if (ca.includeNodeModules !== void 0)
505
573
  console.log(
506
- ` includeNodeModules: ${import_chalk2.default.bold(String(ca.includeNodeModules))}`
574
+ ` includeNodeModules: ${import_chalk3.default.bold(String(ca.includeNodeModules))}`
507
575
  );
508
576
  }
509
577
  if (finalOptions.consistency) {
510
578
  const c = finalOptions.consistency;
511
- console.log(import_chalk2.default.white("\nConsistency settings:"));
579
+ console.log(import_chalk3.default.white("\nConsistency settings:"));
512
580
  console.log(
513
- ` checkNaming: ${import_chalk2.default.bold(String(c.checkNaming ?? true))}`
581
+ ` checkNaming: ${import_chalk3.default.bold(String(c.checkNaming ?? true))}`
514
582
  );
515
583
  console.log(
516
- ` checkPatterns: ${import_chalk2.default.bold(String(c.checkPatterns ?? true))}`
584
+ ` checkPatterns: ${import_chalk3.default.bold(String(c.checkPatterns ?? true))}`
517
585
  );
518
586
  console.log(
519
- ` checkArchitecture: ${import_chalk2.default.bold(String(c.checkArchitecture ?? false))}`
587
+ ` checkArchitecture: ${import_chalk3.default.bold(String(c.checkArchitecture ?? false))}`
520
588
  );
521
589
  if (c.minSeverity)
522
- console.log(` minSeverity: ${import_chalk2.default.bold(c.minSeverity)}`);
590
+ console.log(` minSeverity: ${import_chalk3.default.bold(c.minSeverity)}`);
523
591
  if (c.acceptedAbbreviations)
524
592
  console.log(
525
- ` acceptedAbbreviations: ${import_chalk2.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
593
+ ` acceptedAbbreviations: ${import_chalk3.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
526
594
  );
527
595
  if (c.shortWords)
528
596
  console.log(
529
- ` shortWords: ${import_chalk2.default.bold(truncateArray(c.shortWords, 8))}`
597
+ ` shortWords: ${import_chalk3.default.bold(truncateArray(c.shortWords, 8))}`
530
598
  );
531
599
  }
532
- console.log(import_chalk2.default.white("\nStarting analysis..."));
600
+ console.log(import_chalk3.default.white("\nStarting analysis..."));
533
601
  const progressCallback = (event) => {
534
- console.log(import_chalk2.default.cyan(`
602
+ console.log(import_chalk3.default.cyan(`
535
603
  --- ${event.tool.toUpperCase()} RESULTS ---`));
536
604
  try {
537
605
  if (event.tool === "patterns") {
538
606
  const pr = event.data;
539
607
  console.log(
540
- ` Duplicate patterns: ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))}`
608
+ ` Duplicate patterns: ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))}`
541
609
  );
542
610
  console.log(
543
- ` Files with pattern issues: ${import_chalk2.default.bold(String(pr.results?.length || 0))}`
611
+ ` Files with pattern issues: ${import_chalk3.default.bold(String(pr.results?.length || 0))}`
544
612
  );
545
613
  if (pr.duplicates && pr.duplicates.length > 0) {
546
614
  pr.duplicates.slice(0, 5).forEach((d, i) => {
@@ -562,12 +630,12 @@ async function scanAction(directory, options) {
562
630
  }
563
631
  if (pr.groups && pr.groups.length >= 0) {
564
632
  console.log(
565
- ` \u2705 Grouped ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk2.default.bold(String(pr.groups.length))} file pairs`
633
+ ` \u2705 Grouped ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk3.default.bold(String(pr.groups.length))} file pairs`
566
634
  );
567
635
  }
568
636
  if (pr.clusters && pr.clusters.length >= 0) {
569
637
  console.log(
570
- ` \u2705 Created ${import_chalk2.default.bold(String(pr.clusters.length))} refactor clusters`
638
+ ` \u2705 Created ${import_chalk3.default.bold(String(pr.clusters.length))} refactor clusters`
571
639
  );
572
640
  pr.clusters.slice(0, 3).forEach((cl, idx) => {
573
641
  const files = (cl.files || []).map((f) => f.path.split("/").pop()).join(", ");
@@ -579,7 +647,7 @@ async function scanAction(directory, options) {
579
647
  } else if (event.tool === "context") {
580
648
  const cr = event.data;
581
649
  console.log(
582
- ` Context issues found: ${import_chalk2.default.bold(String(cr.length || 0))}`
650
+ ` Context issues found: ${import_chalk3.default.bold(String(cr.length || 0))}`
583
651
  );
584
652
  cr.slice(0, 5).forEach((c, i) => {
585
653
  const msg = c.message ? ` - ${c.message}` : "";
@@ -590,7 +658,7 @@ async function scanAction(directory, options) {
590
658
  } else if (event.tool === "consistency") {
591
659
  const rep = event.data;
592
660
  console.log(
593
- ` Consistency totalIssues: ${import_chalk2.default.bold(String(rep.summary?.totalIssues || 0))}`
661
+ ` Consistency totalIssues: ${import_chalk3.default.bold(String(rep.summary?.totalIssues || 0))}`
594
662
  );
595
663
  if (rep.results && rep.results.length > 0) {
596
664
  const fileMap = /* @__PURE__ */ new Map();
@@ -625,7 +693,7 @@ async function scanAction(directory, options) {
625
693
  const remaining = files.length - topFiles.length;
626
694
  if (remaining > 0) {
627
695
  console.log(
628
- import_chalk2.default.dim(
696
+ import_chalk3.default.dim(
629
697
  ` ... and ${remaining} more files with issues (use --output json for full details)`
630
698
  )
631
699
  );
@@ -634,37 +702,37 @@ async function scanAction(directory, options) {
634
702
  } else if (event.tool === "doc-drift") {
635
703
  const dr = event.data;
636
704
  console.log(
637
- ` Issues found: ${import_chalk2.default.bold(String(dr.issues?.length || 0))}`
705
+ ` Issues found: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
638
706
  );
639
707
  if (dr.rawData) {
640
708
  console.log(
641
- ` Signature Mismatches: ${import_chalk2.default.bold(dr.rawData.outdatedComments || 0)}`
709
+ ` Signature Mismatches: ${import_chalk3.default.bold(dr.rawData.outdatedComments || 0)}`
642
710
  );
643
711
  console.log(
644
- ` Undocumented Complexity: ${import_chalk2.default.bold(dr.rawData.undocumentedComplexity || 0)}`
712
+ ` Undocumented Complexity: ${import_chalk3.default.bold(dr.rawData.undocumentedComplexity || 0)}`
645
713
  );
646
714
  }
647
715
  } else if (event.tool === "deps-health") {
648
716
  const dr = event.data;
649
717
  console.log(
650
- ` Packages Analyzed: ${import_chalk2.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
718
+ ` Packages Analyzed: ${import_chalk3.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
651
719
  );
652
720
  if (dr.rawData) {
653
721
  console.log(
654
- ` Deprecated Packages: ${import_chalk2.default.bold(dr.rawData.deprecatedPackages || 0)}`
722
+ ` Deprecated Packages: ${import_chalk3.default.bold(dr.rawData.deprecatedPackages || 0)}`
655
723
  );
656
724
  console.log(
657
- ` AI Cutoff Skew Score: ${import_chalk2.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
725
+ ` AI Cutoff Skew Score: ${import_chalk3.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
658
726
  );
659
727
  }
660
728
  } else if (event.tool === "change-amplification" || event.tool === "changeAmplification") {
661
729
  const dr = event.data;
662
730
  console.log(
663
- ` Coupling issues: ${import_chalk2.default.bold(String(dr.issues?.length || 0))}`
731
+ ` Coupling issues: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
664
732
  );
665
733
  if (dr.summary) {
666
734
  console.log(
667
- ` Complexity Score: ${import_chalk2.default.bold(dr.summary.score || 0)}/100`
735
+ ` Complexity Score: ${import_chalk3.default.bold(dr.summary.score || 0)}/100`
668
736
  );
669
737
  }
670
738
  }
@@ -685,36 +753,36 @@ async function scanAction(directory, options) {
685
753
  },
686
754
  suppressToolConfig: true
687
755
  });
688
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Summary ==="));
756
+ console.log(import_chalk3.default.cyan("\n=== AIReady Run Summary ==="));
689
757
  console.log(
690
- import_chalk2.default.white("Tools run:"),
758
+ import_chalk3.default.white("Tools run:"),
691
759
  (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
692
760
  );
693
- console.log(import_chalk2.default.cyan("\nResults summary:"));
761
+ console.log(import_chalk3.default.cyan("\nResults summary:"));
694
762
  console.log(
695
- ` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues || 0))}`
763
+ ` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
696
764
  );
697
765
  if (results.duplicates)
698
766
  console.log(
699
- ` Duplicate patterns found: ${import_chalk2.default.bold(String(results.duplicates.length || 0))}`
767
+ ` Duplicate patterns found: ${import_chalk3.default.bold(String(results.duplicates.length || 0))}`
700
768
  );
701
769
  if (results.patterns)
702
770
  console.log(
703
- ` Pattern files with issues: ${import_chalk2.default.bold(String(results.patterns.length || 0))}`
771
+ ` Pattern files with issues: ${import_chalk3.default.bold(String(results.patterns.length || 0))}`
704
772
  );
705
773
  if (results.context)
706
774
  console.log(
707
- ` Context issues: ${import_chalk2.default.bold(String(results.context.length || 0))}`
775
+ ` Context issues: ${import_chalk3.default.bold(String(results.context.length || 0))}`
708
776
  );
709
777
  console.log(
710
- ` Consistency issues: ${import_chalk2.default.bold(String(results.consistency?.summary?.totalIssues || 0))}`
778
+ ` Consistency issues: ${import_chalk3.default.bold(String(results.consistency?.summary?.totalIssues || 0))}`
711
779
  );
712
780
  if (results.changeAmplification)
713
781
  console.log(
714
- ` Change amplification: ${import_chalk2.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
782
+ ` Change amplification: ${import_chalk3.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
715
783
  );
716
- console.log(import_chalk2.default.cyan("===========================\n"));
717
- const elapsedTime = (0, import_core.getElapsedTime)(startTime);
784
+ console.log(import_chalk3.default.cyan("===========================\n"));
785
+ const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
718
786
  void elapsedTime;
719
787
  let scoringResult;
720
788
  if (options.score || finalOptions.scoring?.showBreakdown) {
@@ -726,6 +794,16 @@ async function scanAction(directory, options) {
726
794
  results.duplicates,
727
795
  results.patterns?.length || 0
728
796
  );
797
+ const wastedTokens = results.duplicates.reduce((sum, d) => sum + (d.tokenCost || 0), 0);
798
+ patternScore.tokenBudget = (0, import_core2.calculateTokenBudget)({
799
+ totalContextTokens: wastedTokens * 2,
800
+ // Estimated context
801
+ wastedTokens: {
802
+ duplication: wastedTokens,
803
+ fragmentation: 0,
804
+ chattiness: 0
805
+ }
806
+ });
729
807
  toolScores.set("pattern-detect", patternScore);
730
808
  } catch (err) {
731
809
  void err;
@@ -736,6 +814,14 @@ async function scanAction(directory, options) {
736
814
  try {
737
815
  const ctxSummary = genContextSummary(results.context);
738
816
  const contextScore = calculateContextScore(ctxSummary);
817
+ contextScore.tokenBudget = (0, import_core2.calculateTokenBudget)({
818
+ totalContextTokens: ctxSummary.totalTokens,
819
+ wastedTokens: {
820
+ duplication: 0,
821
+ fragmentation: ctxSummary.totalPotentialSavings || 0,
822
+ chattiness: 0
823
+ }
824
+ });
739
825
  toolScores.set("context-analyzer", contextScore);
740
826
  } catch (err) {
741
827
  void err;
@@ -827,19 +913,19 @@ async function scanAction(directory, options) {
827
913
  }))
828
914
  });
829
915
  }
830
- const cliWeights = (0, import_core.parseWeightString)(options.weights);
916
+ const cliWeights = (0, import_core2.parseWeightString)(options.weights);
831
917
  if (toolScores.size > 0) {
832
- scoringResult = (0, import_core.calculateOverallScore)(
918
+ scoringResult = (0, import_core2.calculateOverallScore)(
833
919
  toolScores,
834
920
  finalOptions,
835
921
  cliWeights.size ? cliWeights : void 0
836
922
  );
837
- console.log(import_chalk2.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
838
- console.log(` ${(0, import_core.formatScore)(scoringResult)}`);
923
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
924
+ console.log(` ${(0, import_core2.formatScore)(scoringResult)}`);
839
925
  if (options.compareTo) {
840
926
  try {
841
- const prevReportStr = (0, import_fs2.readFileSync)(
842
- (0, import_path2.resolve)(process.cwd(), options.compareTo),
927
+ const prevReportStr = (0, import_fs3.readFileSync)(
928
+ (0, import_path3.resolve)(process.cwd(), options.compareTo),
843
929
  "utf8"
844
930
  );
845
931
  const prevReport = JSON.parse(prevReportStr);
@@ -850,19 +936,19 @@ async function scanAction(directory, options) {
850
936
  console.log();
851
937
  if (diff > 0) {
852
938
  console.log(
853
- import_chalk2.default.green(
939
+ import_chalk3.default.green(
854
940
  ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
855
941
  )
856
942
  );
857
943
  } else if (diff < 0) {
858
944
  console.log(
859
- import_chalk2.default.red(
945
+ import_chalk3.default.red(
860
946
  ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
861
947
  )
862
948
  );
863
949
  } else {
864
950
  console.log(
865
- import_chalk2.default.blue(
951
+ import_chalk3.default.blue(
866
952
  ` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
867
953
  )
868
954
  );
@@ -873,7 +959,7 @@ async function scanAction(directory, options) {
873
959
  };
874
960
  } else {
875
961
  console.log(
876
- import_chalk2.default.yellow(
962
+ import_chalk3.default.yellow(
877
963
  `
878
964
  \u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`
879
965
  )
@@ -882,27 +968,61 @@ async function scanAction(directory, options) {
882
968
  } catch (e) {
883
969
  void e;
884
970
  console.log(
885
- import_chalk2.default.yellow(
971
+ import_chalk3.default.yellow(
886
972
  `
887
973
  \u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`
888
974
  )
889
975
  );
890
976
  }
891
977
  }
978
+ const totalWastedDuplication = Array.from(toolScores.values()).reduce((sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.duplication || 0), 0);
979
+ const totalWastedFragmentation = Array.from(toolScores.values()).reduce((sum, s) => sum + (s.tokenBudget?.wastedTokens.bySource.fragmentation || 0), 0);
980
+ const totalContext = Math.max(...Array.from(toolScores.values()).map((s) => s.tokenBudget?.totalContextTokens || 0));
981
+ if (totalContext > 0) {
982
+ const unifiedBudget = (0, import_core2.calculateTokenBudget)({
983
+ totalContextTokens: totalContext,
984
+ wastedTokens: {
985
+ duplication: totalWastedDuplication,
986
+ fragmentation: totalWastedFragmentation,
987
+ chattiness: 0
988
+ }
989
+ });
990
+ const targetModel = options.model || "claude-4.6";
991
+ const modelPreset = (0, import_core2.getModelPreset)(targetModel);
992
+ const costEstimate = (0, import_core2.estimateCostFromBudget)(unifiedBudget, modelPreset);
993
+ const barWidth = 20;
994
+ const filled = Math.round(unifiedBudget.efficiencyRatio * barWidth);
995
+ const bar = import_chalk3.default.green("\u2588".repeat(filled)) + import_chalk3.default.dim("\u2591".repeat(barWidth - filled));
996
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis (v0.13)"));
997
+ console.log(` Efficiency: [${bar}] ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`);
998
+ console.log(` Total Context: ${import_chalk3.default.bold(unifiedBudget.totalContextTokens.toLocaleString())} tokens`);
999
+ console.log(` Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())} (${(unifiedBudget.wastedTokens.total / unifiedBudget.totalContextTokens * 100).toFixed(1)}%)`);
1000
+ console.log(` Waste Breakdown:`);
1001
+ console.log(` \u2022 Duplication: ${unifiedBudget.wastedTokens.bySource.duplication.toLocaleString()} tokens`);
1002
+ console.log(` \u2022 Fragmentation: ${unifiedBudget.wastedTokens.bySource.fragmentation.toLocaleString()} tokens`);
1003
+ console.log(` Potential Savings: ${import_chalk3.default.green(unifiedBudget.potentialRetrievableTokens.toLocaleString())} tokens retrievable`);
1004
+ console.log(`
1005
+ Est. Monthly Cost (${modelPreset.name}): ${import_chalk3.default.bold("$" + costEstimate.total)} [range: $${costEstimate.range[0]}-$${costEstimate.range[1]}]`);
1006
+ scoringResult.tokenBudget = unifiedBudget;
1007
+ scoringResult.costEstimate = {
1008
+ model: modelPreset.name,
1009
+ ...costEstimate
1010
+ };
1011
+ }
892
1012
  if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
893
- console.log(import_chalk2.default.bold("\nTool breakdown:"));
1013
+ console.log(import_chalk3.default.bold("\nTool breakdown:"));
894
1014
  scoringResult.breakdown.forEach((tool) => {
895
- const rating = (0, import_core.getRating)(tool.score);
896
- const rd = (0, import_core.getRatingDisplay)(rating);
1015
+ const rating = (0, import_core2.getRating)(tool.score);
1016
+ const rd = (0, import_core2.getRatingDisplay)(rating);
897
1017
  console.log(
898
1018
  ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${rd.emoji}`
899
1019
  );
900
1020
  });
901
1021
  console.log();
902
1022
  if (finalOptions.scoring?.showBreakdown) {
903
- console.log(import_chalk2.default.bold("Detailed tool breakdown:"));
1023
+ console.log(import_chalk3.default.bold("Detailed tool breakdown:"));
904
1024
  scoringResult.breakdown.forEach((tool) => {
905
- console.log((0, import_core.formatToolScore)(tool));
1025
+ console.log((0, import_core2.formatToolScore)(tool));
906
1026
  });
907
1027
  console.log();
908
1028
  }
@@ -914,30 +1034,52 @@ async function scanAction(directory, options) {
914
1034
  if (outputFormat === "json") {
915
1035
  const timestamp = getReportTimestamp();
916
1036
  const defaultFilename = `aiready-report-${timestamp}.json`;
917
- const outputPath = (0, import_core.resolveOutputPath)(
1037
+ const outputPath = (0, import_core2.resolveOutputPath)(
918
1038
  userOutputFile,
919
1039
  defaultFilename,
920
1040
  resolvedDir
921
1041
  );
922
- const outputData = { ...results, scoring: scoringResult };
923
- (0, import_core.handleJSONOutput)(
1042
+ const outputData = {
1043
+ ...results,
1044
+ scoring: scoringResult,
1045
+ repository: repoMetadata
1046
+ };
1047
+ (0, import_core2.handleJSONOutput)(
924
1048
  outputData,
925
1049
  outputPath,
926
1050
  `\u2705 Report saved to ${outputPath}`
927
1051
  );
1052
+ if (options.upload) {
1053
+ console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1054
+ await uploadAction(outputPath, {
1055
+ apiKey: options.apiKey,
1056
+ server: options.server
1057
+ });
1058
+ }
928
1059
  await warnIfGraphCapExceeded(outputData, resolvedDir);
929
1060
  } else {
930
1061
  const timestamp = getReportTimestamp();
931
1062
  const defaultFilename = `aiready-report-${timestamp}.json`;
932
- const outputPath = (0, import_core.resolveOutputPath)(
1063
+ const outputPath = (0, import_core2.resolveOutputPath)(
933
1064
  userOutputFile,
934
1065
  defaultFilename,
935
1066
  resolvedDir
936
1067
  );
937
- const outputData = { ...results, scoring: scoringResult };
1068
+ const outputData = {
1069
+ ...results,
1070
+ scoring: scoringResult,
1071
+ repository: repoMetadata
1072
+ };
938
1073
  try {
939
- (0, import_fs2.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
940
- console.log(import_chalk2.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
1074
+ (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
1075
+ console.log(import_chalk3.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
1076
+ if (options.upload) {
1077
+ console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1078
+ await uploadAction(outputPath, {
1079
+ apiKey: options.apiKey,
1080
+ server: options.server
1081
+ });
1082
+ }
941
1083
  await warnIfGraphCapExceeded(outputData, resolvedDir);
942
1084
  } catch (err) {
943
1085
  void err;
@@ -1019,37 +1161,37 @@ async function scanAction(directory, options) {
1019
1161
  }
1020
1162
  }
1021
1163
  if (shouldFail) {
1022
- console.log(import_chalk2.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
1023
- console.log(import_chalk2.default.red(` Reason: ${failReason}`));
1024
- console.log(import_chalk2.default.dim("\n Remediation steps:"));
1164
+ console.log(import_chalk3.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
1165
+ console.log(import_chalk3.default.red(` Reason: ${failReason}`));
1166
+ console.log(import_chalk3.default.dim("\n Remediation steps:"));
1025
1167
  console.log(
1026
- import_chalk2.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
1168
+ import_chalk3.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
1027
1169
  );
1028
- console.log(import_chalk2.default.dim(" 2. Fix the critical issues before merging"));
1170
+ console.log(import_chalk3.default.dim(" 2. Fix the critical issues before merging"));
1029
1171
  console.log(
1030
- import_chalk2.default.dim(
1172
+ import_chalk3.default.dim(
1031
1173
  " 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"
1032
1174
  )
1033
1175
  );
1034
1176
  process.exit(1);
1035
1177
  } else {
1036
- console.log(import_chalk2.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
1178
+ console.log(import_chalk3.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
1037
1179
  if (threshold) {
1038
1180
  console.log(
1039
- import_chalk2.default.green(
1181
+ import_chalk3.default.green(
1040
1182
  ` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`
1041
1183
  )
1042
1184
  );
1043
1185
  }
1044
1186
  console.log(
1045
- import_chalk2.default.dim(
1187
+ import_chalk3.default.dim(
1046
1188
  "\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"
1047
1189
  )
1048
1190
  );
1049
1191
  }
1050
1192
  }
1051
1193
  } catch (error) {
1052
- (0, import_core.handleCLIError)(error, "Analysis");
1194
+ (0, import_core2.handleCLIError)(error, "Analysis");
1053
1195
  }
1054
1196
  }
1055
1197
  var scanHelpText = `
@@ -1063,6 +1205,8 @@ EXAMPLES:
1063
1205
  $ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
1064
1206
  $ aiready scan --ci --fail-on major # Fail on major+ issues
1065
1207
  $ aiready scan --output json --output-file report.json
1208
+ $ aiready scan --upload --api-key ar_... # Automatic platform upload
1209
+ $ aiready scan --upload --server custom-url.com # Upload to custom platform
1066
1210
 
1067
1211
  PROFILES:
1068
1212
  agentic: aiSignalClarity, grounding, testability
@@ -1082,13 +1226,13 @@ CI/CD INTEGRATION (Gatekeeper Mode):
1082
1226
  `;
1083
1227
 
1084
1228
  // src/commands/patterns.ts
1085
- var import_chalk3 = __toESM(require("chalk"));
1086
- var import_path3 = require("path");
1087
- var import_core2 = require("@aiready/core");
1229
+ var import_chalk4 = __toESM(require("chalk"));
1230
+ var import_path4 = require("path");
1231
+ var import_core3 = require("@aiready/core");
1088
1232
  async function patternsAction(directory, options) {
1089
- console.log(import_chalk3.default.blue("\u{1F50D} Analyzing patterns...\n"));
1233
+ console.log(import_chalk4.default.blue("\u{1F50D} Analyzing patterns...\n"));
1090
1234
  const startTime = Date.now();
1091
- const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
1235
+ const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
1092
1236
  try {
1093
1237
  const useSmartDefaults = !options.fullScan;
1094
1238
  const defaults = {
@@ -1117,14 +1261,14 @@ async function patternsAction(directory, options) {
1117
1261
  if (options.minSharedTokens) {
1118
1262
  cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
1119
1263
  }
1120
- const finalOptions = await (0, import_core2.loadMergedConfig)(
1264
+ const finalOptions = await (0, import_core3.loadMergedConfig)(
1121
1265
  resolvedDir,
1122
1266
  defaults,
1123
1267
  cliOptions
1124
1268
  );
1125
1269
  const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
1126
1270
  const { results, duplicates } = await analyzePatterns2(finalOptions);
1127
- const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
1271
+ const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
1128
1272
  const summary = generateSummary(results);
1129
1273
  let patternScore;
1130
1274
  if (options.score) {
@@ -1138,12 +1282,12 @@ async function patternsAction(directory, options) {
1138
1282
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1139
1283
  ...patternScore && { scoring: patternScore }
1140
1284
  };
1141
- const outputPath = (0, import_core2.resolveOutputPath)(
1285
+ const outputPath = (0, import_core3.resolveOutputPath)(
1142
1286
  userOutputFile,
1143
1287
  `aiready-report-${getReportTimestamp()}.json`,
1144
1288
  resolvedDir
1145
1289
  );
1146
- (0, import_core2.handleJSONOutput)(
1290
+ (0, import_core3.handleJSONOutput)(
1147
1291
  outputData,
1148
1292
  outputPath,
1149
1293
  `\u2705 Results saved to ${outputPath}`
@@ -1152,38 +1296,38 @@ async function patternsAction(directory, options) {
1152
1296
  const terminalWidth = process.stdout.columns || 80;
1153
1297
  const dividerWidth = Math.min(60, terminalWidth - 2);
1154
1298
  const divider = "\u2501".repeat(dividerWidth);
1155
- console.log(import_chalk3.default.cyan(divider));
1156
- console.log(import_chalk3.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1157
- console.log(import_chalk3.default.cyan(divider) + "\n");
1299
+ console.log(import_chalk4.default.cyan(divider));
1300
+ console.log(import_chalk4.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1301
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1158
1302
  console.log(
1159
- import_chalk3.default.white(`\u{1F4C1} Files analyzed: ${import_chalk3.default.bold(results.length)}`)
1303
+ import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(results.length)}`)
1160
1304
  );
1161
1305
  console.log(
1162
- import_chalk3.default.yellow(
1163
- `\u26A0 Duplicate patterns found: ${import_chalk3.default.bold(summary.totalPatterns)}`
1306
+ import_chalk4.default.yellow(
1307
+ `\u26A0 Duplicate patterns found: ${import_chalk4.default.bold(summary.totalPatterns)}`
1164
1308
  )
1165
1309
  );
1166
1310
  console.log(
1167
- import_chalk3.default.red(
1168
- `\u{1F4B0} Token cost (wasted): ${import_chalk3.default.bold(summary.totalTokenCost.toLocaleString())}`
1311
+ import_chalk4.default.red(
1312
+ `\u{1F4B0} Token cost (wasted): ${import_chalk4.default.bold(summary.totalTokenCost.toLocaleString())}`
1169
1313
  )
1170
1314
  );
1171
1315
  console.log(
1172
- import_chalk3.default.gray(`\u23F1 Analysis time: ${import_chalk3.default.bold(elapsedTime + "s")}`)
1316
+ import_chalk4.default.gray(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}`)
1173
1317
  );
1174
1318
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
1175
1319
  if (sortedTypes.length > 0) {
1176
- console.log(import_chalk3.default.cyan("\n" + divider));
1177
- console.log(import_chalk3.default.bold.white(" PATTERNS BY TYPE"));
1178
- console.log(import_chalk3.default.cyan(divider) + "\n");
1320
+ console.log(import_chalk4.default.cyan("\n" + divider));
1321
+ console.log(import_chalk4.default.bold.white(" PATTERNS BY TYPE"));
1322
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1179
1323
  sortedTypes.forEach(([type, count]) => {
1180
- console.log(` ${import_chalk3.default.white(type.padEnd(15))} ${import_chalk3.default.bold(count)}`);
1324
+ console.log(` ${import_chalk4.default.white(type.padEnd(15))} ${import_chalk4.default.bold(count)}`);
1181
1325
  });
1182
1326
  }
1183
1327
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
1184
- console.log(import_chalk3.default.cyan("\n" + divider));
1185
- console.log(import_chalk3.default.bold.white(" TOP DUPLICATE PATTERNS"));
1186
- console.log(import_chalk3.default.cyan(divider) + "\n");
1328
+ console.log(import_chalk4.default.cyan("\n" + divider));
1329
+ console.log(import_chalk4.default.bold.white(" TOP DUPLICATE PATTERNS"));
1330
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1187
1331
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
1188
1332
  topDuplicates.forEach((dup) => {
1189
1333
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -1191,31 +1335,31 @@ async function patternsAction(directory, options) {
1191
1335
  const file1Name = dup.file1.split("/").pop() || dup.file1;
1192
1336
  const file2Name = dup.file2.split("/").pop() || dup.file2;
1193
1337
  console.log(
1194
- `${severityIcon} ${severity}: ${import_chalk3.default.bold(file1Name)} \u2194 ${import_chalk3.default.bold(file2Name)}`
1338
+ `${severityIcon} ${severity}: ${import_chalk4.default.bold(file1Name)} \u2194 ${import_chalk4.default.bold(file2Name)}`
1195
1339
  );
1196
1340
  console.log(
1197
- ` Similarity: ${import_chalk3.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk3.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1341
+ ` Similarity: ${import_chalk4.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk4.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1198
1342
  );
1199
1343
  console.log(
1200
- ` Lines: ${import_chalk3.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk3.default.cyan(dup.line2 + "-" + dup.endLine2)}
1344
+ ` Lines: ${import_chalk4.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk4.default.cyan(dup.line2 + "-" + dup.endLine2)}
1201
1345
  `
1202
1346
  );
1203
1347
  });
1204
1348
  } else {
1205
1349
  console.log(
1206
- import_chalk3.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1350
+ import_chalk4.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1207
1351
  );
1208
1352
  }
1209
1353
  if (patternScore) {
1210
- console.log(import_chalk3.default.cyan(divider));
1211
- console.log(import_chalk3.default.bold.white(" AI READINESS SCORE (Patterns)"));
1212
- console.log(import_chalk3.default.cyan(divider) + "\n");
1213
- console.log((0, import_core2.formatToolScore)(patternScore));
1354
+ console.log(import_chalk4.default.cyan(divider));
1355
+ console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Patterns)"));
1356
+ console.log(import_chalk4.default.cyan(divider) + "\n");
1357
+ console.log((0, import_core3.formatToolScore)(patternScore));
1214
1358
  console.log();
1215
1359
  }
1216
1360
  }
1217
1361
  } catch (error) {
1218
- (0, import_core2.handleCLIError)(error, "Pattern analysis");
1362
+ (0, import_core3.handleCLIError)(error, "Pattern analysis");
1219
1363
  }
1220
1364
  }
1221
1365
  var patternsHelpText = `
@@ -1226,13 +1370,13 @@ EXAMPLES:
1226
1370
  `;
1227
1371
 
1228
1372
  // src/commands/context.ts
1229
- var import_chalk4 = __toESM(require("chalk"));
1230
- var import_path4 = require("path");
1231
- var import_core3 = require("@aiready/core");
1373
+ var import_chalk5 = __toESM(require("chalk"));
1374
+ var import_path5 = require("path");
1375
+ var import_core4 = require("@aiready/core");
1232
1376
  async function contextAction(directory, options) {
1233
- console.log(import_chalk4.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1377
+ console.log(import_chalk5.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1234
1378
  const startTime = Date.now();
1235
- const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
1379
+ const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
1236
1380
  try {
1237
1381
  const defaults = {
1238
1382
  maxDepth: 5,
@@ -1244,7 +1388,7 @@ async function contextAction(directory, options) {
1244
1388
  file: void 0
1245
1389
  }
1246
1390
  };
1247
- const baseOptions = await (0, import_core3.loadMergedConfig)(resolvedDir, defaults, {
1391
+ const baseOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
1248
1392
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
1249
1393
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
1250
1394
  include: options.include?.split(","),
@@ -1270,7 +1414,7 @@ async function contextAction(directory, options) {
1270
1414
  console.log("");
1271
1415
  const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1272
1416
  const results = await analyzeContext2(finalOptions);
1273
- const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
1417
+ const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1274
1418
  const summary = generateSummary(results);
1275
1419
  let contextScore;
1276
1420
  if (options.score) {
@@ -1284,12 +1428,12 @@ async function contextAction(directory, options) {
1284
1428
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1285
1429
  ...contextScore && { scoring: contextScore }
1286
1430
  };
1287
- const outputPath = (0, import_core3.resolveOutputPath)(
1431
+ const outputPath = (0, import_core4.resolveOutputPath)(
1288
1432
  userOutputFile,
1289
1433
  `aiready-report-${getReportTimestamp()}.json`,
1290
1434
  resolvedDir
1291
1435
  );
1292
- (0, import_core3.handleJSONOutput)(
1436
+ (0, import_core4.handleJSONOutput)(
1293
1437
  outputData,
1294
1438
  outputPath,
1295
1439
  `\u2705 Results saved to ${outputPath}`
@@ -1298,85 +1442,85 @@ async function contextAction(directory, options) {
1298
1442
  const terminalWidth = process.stdout.columns || 80;
1299
1443
  const dividerWidth = Math.min(60, terminalWidth - 2);
1300
1444
  const divider = "\u2501".repeat(dividerWidth);
1301
- console.log(import_chalk4.default.cyan(divider));
1302
- console.log(import_chalk4.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1303
- console.log(import_chalk4.default.cyan(divider) + "\n");
1445
+ console.log(import_chalk5.default.cyan(divider));
1446
+ console.log(import_chalk5.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1447
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1304
1448
  console.log(
1305
- import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(summary.totalFiles)}`)
1449
+ import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(summary.totalFiles)}`)
1306
1450
  );
1307
1451
  console.log(
1308
- import_chalk4.default.white(
1309
- `\u{1F4CA} Total tokens: ${import_chalk4.default.bold(summary.totalTokens.toLocaleString())}`
1452
+ import_chalk5.default.white(
1453
+ `\u{1F4CA} Total tokens: ${import_chalk5.default.bold(summary.totalTokens.toLocaleString())}`
1310
1454
  )
1311
1455
  );
1312
1456
  console.log(
1313
- import_chalk4.default.yellow(
1314
- `\u{1F4B0} Avg context budget: ${import_chalk4.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1457
+ import_chalk5.default.yellow(
1458
+ `\u{1F4B0} Avg context budget: ${import_chalk5.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1315
1459
  )
1316
1460
  );
1317
1461
  console.log(
1318
- import_chalk4.default.white(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}
1462
+ import_chalk5.default.white(`\u23F1 Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}
1319
1463
  `)
1320
1464
  );
1321
1465
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
1322
1466
  if (totalIssues > 0) {
1323
- console.log(import_chalk4.default.bold("\u26A0\uFE0F Issues Found:\n"));
1467
+ console.log(import_chalk5.default.bold("\u26A0\uFE0F Issues Found:\n"));
1324
1468
  if (summary.criticalIssues > 0) {
1325
1469
  console.log(
1326
- import_chalk4.default.red(` \u{1F534} Critical: ${import_chalk4.default.bold(summary.criticalIssues)}`)
1470
+ import_chalk5.default.red(` \u{1F534} Critical: ${import_chalk5.default.bold(summary.criticalIssues)}`)
1327
1471
  );
1328
1472
  }
1329
1473
  if (summary.majorIssues > 0) {
1330
1474
  console.log(
1331
- import_chalk4.default.yellow(` \u{1F7E1} Major: ${import_chalk4.default.bold(summary.majorIssues)}`)
1475
+ import_chalk5.default.yellow(` \u{1F7E1} Major: ${import_chalk5.default.bold(summary.majorIssues)}`)
1332
1476
  );
1333
1477
  }
1334
1478
  if (summary.minorIssues > 0) {
1335
1479
  console.log(
1336
- import_chalk4.default.blue(` \u{1F535} Minor: ${import_chalk4.default.bold(summary.minorIssues)}`)
1480
+ import_chalk5.default.blue(` \u{1F535} Minor: ${import_chalk5.default.bold(summary.minorIssues)}`)
1337
1481
  );
1338
1482
  }
1339
1483
  console.log(
1340
- import_chalk4.default.green(
1484
+ import_chalk5.default.green(
1341
1485
  `
1342
- \u{1F4A1} Potential savings: ${import_chalk4.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1486
+ \u{1F4A1} Potential savings: ${import_chalk5.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1343
1487
  `
1344
1488
  )
1345
1489
  );
1346
1490
  } else {
1347
- console.log(import_chalk4.default.green("\u2705 No significant issues found!\n"));
1491
+ console.log(import_chalk5.default.green("\u2705 No significant issues found!\n"));
1348
1492
  }
1349
1493
  if (summary.deepFiles.length > 0) {
1350
- console.log(import_chalk4.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1494
+ console.log(import_chalk5.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1351
1495
  console.log(
1352
- import_chalk4.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1496
+ import_chalk5.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1353
1497
  );
1354
1498
  console.log(
1355
- import_chalk4.default.gray(` Maximum depth: ${summary.maxImportDepth}
1499
+ import_chalk5.default.gray(` Maximum depth: ${summary.maxImportDepth}
1356
1500
  `)
1357
1501
  );
1358
1502
  summary.deepFiles.slice(0, 10).forEach((item) => {
1359
1503
  const fileName = item.file.split("/").slice(-2).join("/");
1360
1504
  console.log(
1361
- ` ${import_chalk4.default.cyan("\u2192")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(depth: ${item.depth})`)}`
1505
+ ` ${import_chalk5.default.cyan("\u2192")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(depth: ${item.depth})`)}`
1362
1506
  );
1363
1507
  });
1364
1508
  console.log();
1365
1509
  }
1366
1510
  if (summary.fragmentedModules.length > 0) {
1367
- console.log(import_chalk4.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1511
+ console.log(import_chalk5.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1368
1512
  console.log(
1369
- import_chalk4.default.gray(
1513
+ import_chalk5.default.gray(
1370
1514
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1371
1515
  `
1372
1516
  )
1373
1517
  );
1374
1518
  summary.fragmentedModules.slice(0, 10).forEach((module2) => {
1375
1519
  console.log(
1376
- ` ${import_chalk4.default.yellow("\u25CF")} ${import_chalk4.default.white(module2.domain)} - ${import_chalk4.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1520
+ ` ${import_chalk5.default.yellow("\u25CF")} ${import_chalk5.default.white(module2.domain)} - ${import_chalk5.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1377
1521
  );
1378
1522
  console.log(
1379
- import_chalk4.default.dim(
1523
+ import_chalk5.default.dim(
1380
1524
  ` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
1381
1525
  )
1382
1526
  );
@@ -1384,9 +1528,9 @@ async function contextAction(directory, options) {
1384
1528
  console.log();
1385
1529
  }
1386
1530
  if (summary.lowCohesionFiles.length > 0) {
1387
- console.log(import_chalk4.default.bold("\u{1F500} Low Cohesion Files:\n"));
1531
+ console.log(import_chalk5.default.bold("\u{1F500} Low Cohesion Files:\n"));
1388
1532
  console.log(
1389
- import_chalk4.default.gray(
1533
+ import_chalk5.default.gray(
1390
1534
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1391
1535
  `
1392
1536
  )
@@ -1394,46 +1538,46 @@ async function contextAction(directory, options) {
1394
1538
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
1395
1539
  const fileName = item.file.split("/").slice(-2).join("/");
1396
1540
  const scorePercent = (item.score * 100).toFixed(0);
1397
- const color = item.score < 0.4 ? import_chalk4.default.red : import_chalk4.default.yellow;
1541
+ const color = item.score < 0.4 ? import_chalk5.default.red : import_chalk5.default.yellow;
1398
1542
  console.log(
1399
- ` ${color("\u25CB")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${scorePercent}% cohesion)`)}`
1543
+ ` ${color("\u25CB")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${scorePercent}% cohesion)`)}`
1400
1544
  );
1401
1545
  });
1402
1546
  console.log();
1403
1547
  }
1404
1548
  if (summary.topExpensiveFiles.length > 0) {
1405
- console.log(import_chalk4.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1549
+ console.log(import_chalk5.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1406
1550
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
1407
1551
  const fileName = item.file.split("/").slice(-2).join("/");
1408
- const severityColor = item.severity === "critical" ? import_chalk4.default.red : item.severity === "major" ? import_chalk4.default.yellow : import_chalk4.default.blue;
1552
+ const severityColor = item.severity === "critical" ? import_chalk5.default.red : item.severity === "major" ? import_chalk5.default.yellow : import_chalk5.default.blue;
1409
1553
  console.log(
1410
- ` ${severityColor("\u25CF")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1554
+ ` ${severityColor("\u25CF")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1411
1555
  );
1412
1556
  });
1413
1557
  console.log();
1414
1558
  }
1415
1559
  if (contextScore) {
1416
- console.log(import_chalk4.default.cyan(divider));
1417
- console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Context)"));
1418
- console.log(import_chalk4.default.cyan(divider) + "\n");
1419
- console.log((0, import_core3.formatToolScore)(contextScore));
1560
+ console.log(import_chalk5.default.cyan(divider));
1561
+ console.log(import_chalk5.default.bold.white(" AI READINESS SCORE (Context)"));
1562
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1563
+ console.log((0, import_core4.formatToolScore)(contextScore));
1420
1564
  console.log();
1421
1565
  }
1422
1566
  }
1423
1567
  } catch (error) {
1424
- (0, import_core3.handleCLIError)(error, "Context analysis");
1568
+ (0, import_core4.handleCLIError)(error, "Context analysis");
1425
1569
  }
1426
1570
  }
1427
1571
 
1428
1572
  // src/commands/consistency.ts
1429
- var import_chalk5 = __toESM(require("chalk"));
1430
- var import_fs3 = require("fs");
1431
- var import_path5 = require("path");
1432
- var import_core4 = require("@aiready/core");
1573
+ var import_chalk6 = __toESM(require("chalk"));
1574
+ var import_fs4 = require("fs");
1575
+ var import_path6 = require("path");
1576
+ var import_core5 = require("@aiready/core");
1433
1577
  async function consistencyAction(directory, options) {
1434
- console.log(import_chalk5.default.blue("\u{1F50D} Analyzing consistency...\n"));
1578
+ console.log(import_chalk6.default.blue("\u{1F50D} Analyzing consistency...\n"));
1435
1579
  const startTime = Date.now();
1436
- const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
1580
+ const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
1437
1581
  try {
1438
1582
  const defaults = {
1439
1583
  checkNaming: true,
@@ -1446,7 +1590,7 @@ async function consistencyAction(directory, options) {
1446
1590
  file: void 0
1447
1591
  }
1448
1592
  };
1449
- const finalOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
1593
+ const finalOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, {
1450
1594
  checkNaming: options.naming !== false,
1451
1595
  checkPatterns: options.patterns !== false,
1452
1596
  minSeverity: options.minSeverity,
@@ -1455,7 +1599,7 @@ async function consistencyAction(directory, options) {
1455
1599
  });
1456
1600
  const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
1457
1601
  const report = await analyzeConsistency2(finalOptions);
1458
- const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1602
+ const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
1459
1603
  let consistencyScore;
1460
1604
  if (options.score) {
1461
1605
  const issues = report.results?.flatMap((r) => r.issues) || [];
@@ -1475,41 +1619,41 @@ async function consistencyAction(directory, options) {
1475
1619
  },
1476
1620
  ...consistencyScore && { scoring: consistencyScore }
1477
1621
  };
1478
- const outputPath = (0, import_core4.resolveOutputPath)(
1622
+ const outputPath = (0, import_core5.resolveOutputPath)(
1479
1623
  userOutputFile,
1480
1624
  `aiready-report-${getReportTimestamp()}.json`,
1481
1625
  resolvedDir
1482
1626
  );
1483
- (0, import_core4.handleJSONOutput)(
1627
+ (0, import_core5.handleJSONOutput)(
1484
1628
  outputData,
1485
1629
  outputPath,
1486
1630
  `\u2705 Results saved to ${outputPath}`
1487
1631
  );
1488
1632
  } else if (outputFormat === "markdown") {
1489
1633
  const markdown = generateMarkdownReport(report, elapsedTime);
1490
- const outputPath = (0, import_core4.resolveOutputPath)(
1634
+ const outputPath = (0, import_core5.resolveOutputPath)(
1491
1635
  userOutputFile,
1492
1636
  `aiready-report-${getReportTimestamp()}.md`,
1493
1637
  resolvedDir
1494
1638
  );
1495
- (0, import_fs3.writeFileSync)(outputPath, markdown);
1496
- console.log(import_chalk5.default.green(`\u2705 Report saved to ${outputPath}`));
1639
+ (0, import_fs4.writeFileSync)(outputPath, markdown);
1640
+ console.log(import_chalk6.default.green(`\u2705 Report saved to ${outputPath}`));
1497
1641
  } else {
1498
- console.log(import_chalk5.default.bold("\n\u{1F4CA} Summary\n"));
1642
+ console.log(import_chalk6.default.bold("\n\u{1F4CA} Summary\n"));
1499
1643
  console.log(
1500
- `Files Analyzed: ${import_chalk5.default.cyan(report.summary.filesAnalyzed)}`
1644
+ `Files Analyzed: ${import_chalk6.default.cyan(report.summary.filesAnalyzed)}`
1501
1645
  );
1502
- console.log(`Total Issues: ${import_chalk5.default.yellow(report.summary.totalIssues)}`);
1503
- console.log(` Naming: ${import_chalk5.default.yellow(report.summary.namingIssues)}`);
1504
- console.log(` Patterns: ${import_chalk5.default.yellow(report.summary.patternIssues)}`);
1646
+ console.log(`Total Issues: ${import_chalk6.default.yellow(report.summary.totalIssues)}`);
1647
+ console.log(` Naming: ${import_chalk6.default.yellow(report.summary.namingIssues)}`);
1648
+ console.log(` Patterns: ${import_chalk6.default.yellow(report.summary.patternIssues)}`);
1505
1649
  console.log(
1506
- ` Architecture: ${import_chalk5.default.yellow(report.summary.architectureIssues || 0)}`
1650
+ ` Architecture: ${import_chalk6.default.yellow(report.summary.architectureIssues || 0)}`
1507
1651
  );
1508
- console.log(`Analysis Time: ${import_chalk5.default.gray(elapsedTime + "s")}
1652
+ console.log(`Analysis Time: ${import_chalk6.default.gray(elapsedTime + "s")}
1509
1653
  `);
1510
1654
  if (report.summary.totalIssues === 0) {
1511
1655
  console.log(
1512
- import_chalk5.default.green(
1656
+ import_chalk6.default.green(
1513
1657
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1514
1658
  )
1515
1659
  );
@@ -1521,20 +1665,20 @@ async function consistencyAction(directory, options) {
1521
1665
  (r) => r.issues.some((i) => i.category === "patterns")
1522
1666
  );
1523
1667
  if (namingResults.length > 0) {
1524
- console.log(import_chalk5.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1668
+ console.log(import_chalk6.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1525
1669
  let shown = 0;
1526
1670
  for (const result of namingResults) {
1527
1671
  if (shown >= 5) break;
1528
1672
  for (const issue of result.issues) {
1529
1673
  if (shown >= 5) break;
1530
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
1674
+ const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1531
1675
  console.log(
1532
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1676
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1533
1677
  );
1534
1678
  console.log(` ${issue.message}`);
1535
1679
  if (issue.suggestion) {
1536
1680
  console.log(
1537
- ` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`
1681
+ ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1538
1682
  );
1539
1683
  }
1540
1684
  console.log();
@@ -1543,25 +1687,25 @@ async function consistencyAction(directory, options) {
1543
1687
  }
1544
1688
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1545
1689
  if (remaining > 0) {
1546
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1690
+ console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1547
1691
  `));
1548
1692
  }
1549
1693
  }
1550
1694
  if (patternResults.length > 0) {
1551
- console.log(import_chalk5.default.bold("\u{1F504} Pattern Issues\n"));
1695
+ console.log(import_chalk6.default.bold("\u{1F504} Pattern Issues\n"));
1552
1696
  let shown = 0;
1553
1697
  for (const result of patternResults) {
1554
1698
  if (shown >= 5) break;
1555
1699
  for (const issue of result.issues) {
1556
1700
  if (shown >= 5) break;
1557
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
1701
+ const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1558
1702
  console.log(
1559
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1703
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1560
1704
  );
1561
1705
  console.log(` ${issue.message}`);
1562
1706
  if (issue.suggestion) {
1563
1707
  console.log(
1564
- ` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`
1708
+ ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1565
1709
  );
1566
1710
  }
1567
1711
  console.log();
@@ -1570,12 +1714,12 @@ async function consistencyAction(directory, options) {
1570
1714
  }
1571
1715
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1572
1716
  if (remaining > 0) {
1573
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1717
+ console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1574
1718
  `));
1575
1719
  }
1576
1720
  }
1577
1721
  if (report.recommendations.length > 0) {
1578
- console.log(import_chalk5.default.bold("\u{1F4A1} Recommendations\n"));
1722
+ console.log(import_chalk6.default.bold("\u{1F4A1} Recommendations\n"));
1579
1723
  report.recommendations.forEach((rec, i) => {
1580
1724
  console.log(`${i + 1}. ${rec}`);
1581
1725
  });
@@ -1583,38 +1727,38 @@ async function consistencyAction(directory, options) {
1583
1727
  }
1584
1728
  }
1585
1729
  if (consistencyScore) {
1586
- console.log(import_chalk5.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1587
- console.log((0, import_core4.formatToolScore)(consistencyScore));
1730
+ console.log(import_chalk6.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1731
+ console.log((0, import_core5.formatToolScore)(consistencyScore));
1588
1732
  console.log();
1589
1733
  }
1590
1734
  }
1591
1735
  } catch (error) {
1592
- (0, import_core4.handleCLIError)(error, "Consistency analysis");
1736
+ (0, import_core5.handleCLIError)(error, "Consistency analysis");
1593
1737
  }
1594
1738
  }
1595
1739
 
1596
1740
  // src/commands/visualize.ts
1597
- var import_chalk6 = __toESM(require("chalk"));
1598
- var import_fs4 = require("fs");
1599
- var import_path6 = require("path");
1741
+ var import_chalk7 = __toESM(require("chalk"));
1742
+ var import_fs5 = require("fs");
1743
+ var import_path7 = require("path");
1600
1744
  var import_child_process = require("child_process");
1601
- var import_core5 = require("@aiready/core");
1602
1745
  var import_core6 = require("@aiready/core");
1746
+ var import_core7 = require("@aiready/core");
1603
1747
  async function visualizeAction(directory, options) {
1604
1748
  try {
1605
- const dirPath = (0, import_path6.resolve)(process.cwd(), directory || ".");
1606
- let reportPath = options.report ? (0, import_path6.resolve)(dirPath, options.report) : null;
1607
- if (!reportPath || !(0, import_fs4.existsSync)(reportPath)) {
1749
+ const dirPath = (0, import_path7.resolve)(process.cwd(), directory || ".");
1750
+ let reportPath = options.report ? (0, import_path7.resolve)(dirPath, options.report) : null;
1751
+ if (!reportPath || !(0, import_fs5.existsSync)(reportPath)) {
1608
1752
  const latestScan = findLatestScanReport(dirPath);
1609
1753
  if (latestScan) {
1610
1754
  reportPath = latestScan;
1611
1755
  console.log(
1612
- import_chalk6.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1756
+ import_chalk7.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1613
1757
  );
1614
1758
  } else {
1615
- console.error(import_chalk6.default.red("\u274C No AI readiness report found"));
1759
+ console.error(import_chalk7.default.red("\u274C No AI readiness report found"));
1616
1760
  console.log(
1617
- import_chalk6.default.dim(
1761
+ import_chalk7.default.dim(
1618
1762
  `
1619
1763
  Generate a report with:
1620
1764
  aiready scan --output json
@@ -1626,13 +1770,13 @@ Or specify a custom report:
1626
1770
  return;
1627
1771
  }
1628
1772
  }
1629
- const raw = (0, import_fs4.readFileSync)(reportPath, "utf8");
1773
+ const raw = (0, import_fs5.readFileSync)(reportPath, "utf8");
1630
1774
  const report = JSON.parse(raw);
1631
- const configPath = (0, import_path6.resolve)(dirPath, "aiready.json");
1775
+ const configPath = (0, import_path7.resolve)(dirPath, "aiready.json");
1632
1776
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1633
- if ((0, import_fs4.existsSync)(configPath)) {
1777
+ if ((0, import_fs5.existsSync)(configPath)) {
1634
1778
  try {
1635
- const rawConfig = JSON.parse((0, import_fs4.readFileSync)(configPath, "utf8"));
1779
+ const rawConfig = JSON.parse((0, import_fs5.readFileSync)(configPath, "utf8"));
1636
1780
  if (rawConfig.visualizer?.graph) {
1637
1781
  graphConfig = {
1638
1782
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1652,16 +1796,16 @@ Or specify a custom report:
1652
1796
  let devServerStarted = false;
1653
1797
  if (useDevMode) {
1654
1798
  try {
1655
- const monorepoWebDir = (0, import_path6.resolve)(dirPath, "packages/visualizer");
1799
+ const monorepoWebDir = (0, import_path7.resolve)(dirPath, "packages/visualizer");
1656
1800
  let webDir = "";
1657
1801
  let visualizerAvailable = false;
1658
- if ((0, import_fs4.existsSync)(monorepoWebDir)) {
1802
+ if ((0, import_fs5.existsSync)(monorepoWebDir)) {
1659
1803
  webDir = monorepoWebDir;
1660
1804
  visualizerAvailable = true;
1661
1805
  } else {
1662
1806
  const nodemodulesLocations = [
1663
- (0, import_path6.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1664
- (0, import_path6.resolve)(
1807
+ (0, import_path7.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1808
+ (0, import_path7.resolve)(
1665
1809
  process.cwd(),
1666
1810
  "node_modules",
1667
1811
  "@aiready",
@@ -1671,14 +1815,14 @@ Or specify a custom report:
1671
1815
  let currentDir = dirPath;
1672
1816
  while (currentDir !== "/" && currentDir !== ".") {
1673
1817
  nodemodulesLocations.push(
1674
- (0, import_path6.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1818
+ (0, import_path7.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1675
1819
  );
1676
- const parent = (0, import_path6.resolve)(currentDir, "..");
1820
+ const parent = (0, import_path7.resolve)(currentDir, "..");
1677
1821
  if (parent === currentDir) break;
1678
1822
  currentDir = parent;
1679
1823
  }
1680
1824
  for (const location of nodemodulesLocations) {
1681
- if ((0, import_fs4.existsSync)(location) && (0, import_fs4.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1825
+ if ((0, import_fs5.existsSync)(location) && (0, import_fs5.existsSync)((0, import_path7.resolve)(location, "package.json"))) {
1682
1826
  webDir = location;
1683
1827
  visualizerAvailable = true;
1684
1828
  break;
@@ -1687,21 +1831,21 @@ Or specify a custom report:
1687
1831
  if (!visualizerAvailable) {
1688
1832
  try {
1689
1833
  const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
1690
- webDir = (0, import_path6.resolve)(vizPkgPath, "..");
1834
+ webDir = (0, import_path7.resolve)(vizPkgPath, "..");
1691
1835
  visualizerAvailable = true;
1692
1836
  } catch (err) {
1693
1837
  void err;
1694
1838
  }
1695
1839
  }
1696
1840
  }
1697
- const webViteConfigExists = webDir && (0, import_fs4.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1841
+ const webViteConfigExists = webDir && (0, import_fs5.existsSync)((0, import_path7.resolve)(webDir, "web", "vite.config.ts"));
1698
1842
  if (visualizerAvailable && webViteConfigExists) {
1699
1843
  const spawnCwd = webDir;
1700
1844
  const { watch } = await import("fs");
1701
1845
  const copyReportToViz = () => {
1702
1846
  try {
1703
- const destPath = (0, import_path6.resolve)(spawnCwd, "web", "report-data.json");
1704
- (0, import_fs4.copyFileSync)(reportPath, destPath);
1847
+ const destPath = (0, import_path7.resolve)(spawnCwd, "web", "report-data.json");
1848
+ (0, import_fs5.copyFileSync)(reportPath, destPath);
1705
1849
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1706
1850
  } catch (e) {
1707
1851
  console.error("Failed to sync report:", e);
@@ -1744,29 +1888,29 @@ Or specify a custom report:
1744
1888
  return;
1745
1889
  } else {
1746
1890
  console.log(
1747
- import_chalk6.default.yellow(
1891
+ import_chalk7.default.yellow(
1748
1892
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1749
1893
  )
1750
1894
  );
1751
1895
  console.log(
1752
- import_chalk6.default.cyan(" Falling back to static HTML generation...\n")
1896
+ import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1753
1897
  );
1754
1898
  useDevMode = false;
1755
1899
  }
1756
1900
  } catch (err) {
1757
1901
  console.error("Failed to start dev server:", err);
1758
1902
  console.log(
1759
- import_chalk6.default.cyan(" Falling back to static HTML generation...\n")
1903
+ import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1760
1904
  );
1761
1905
  useDevMode = false;
1762
1906
  }
1763
1907
  }
1764
1908
  console.log("Generating HTML...");
1765
- const html = (0, import_core6.generateHTML)(graph);
1909
+ const html = (0, import_core7.generateHTML)(graph);
1766
1910
  const defaultOutput = "visualization.html";
1767
- const outPath = (0, import_path6.resolve)(dirPath, options.output || defaultOutput);
1768
- (0, import_fs4.writeFileSync)(outPath, html, "utf8");
1769
- console.log(import_chalk6.default.green(`\u2705 Visualization written to: ${outPath}`));
1911
+ const outPath = (0, import_path7.resolve)(dirPath, options.output || defaultOutput);
1912
+ (0, import_fs5.writeFileSync)(outPath, html, "utf8");
1913
+ console.log(import_chalk7.default.green(`\u2705 Visualization written to: ${outPath}`));
1770
1914
  if (options.open || options.serve) {
1771
1915
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1772
1916
  if (options.serve) {
@@ -1796,7 +1940,7 @@ Or specify a custom report:
1796
1940
  server.listen(port, () => {
1797
1941
  const addr = `http://localhost:${port}/`;
1798
1942
  console.log(
1799
- import_chalk6.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1943
+ import_chalk7.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1800
1944
  );
1801
1945
  (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
1802
1946
  });
@@ -1812,7 +1956,7 @@ Or specify a custom report:
1812
1956
  }
1813
1957
  }
1814
1958
  } catch (err) {
1815
- (0, import_core5.handleCLIError)(err, "Visualization");
1959
+ (0, import_core6.handleCLIError)(err, "Visualization");
1816
1960
  }
1817
1961
  }
1818
1962
  var visualizeHelpText = `
@@ -1843,17 +1987,17 @@ NOTES:
1843
1987
  `;
1844
1988
 
1845
1989
  // src/commands/ai-signal-clarity.ts
1846
- var import_chalk7 = __toESM(require("chalk"));
1847
- var import_core7 = require("@aiready/core");
1848
-
1849
- // src/commands/agent-grounding.ts
1850
1990
  var import_chalk8 = __toESM(require("chalk"));
1851
1991
  var import_core8 = require("@aiready/core");
1852
1992
 
1853
- // src/commands/testability.ts
1993
+ // src/commands/agent-grounding.ts
1854
1994
  var import_chalk9 = __toESM(require("chalk"));
1855
1995
  var import_core9 = require("@aiready/core");
1856
1996
 
1997
+ // src/commands/testability.ts
1998
+ var import_chalk10 = __toESM(require("chalk"));
1999
+ var import_core10 = require("@aiready/core");
2000
+
1857
2001
  // src/commands/change-amplification.ts
1858
2002
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
1859
2003
 
@@ -1861,10 +2005,10 @@ var import_cli = require("@aiready/change-amplification/dist/cli.js");
1861
2005
  var import_meta = {};
1862
2006
  var getDirname = () => {
1863
2007
  if (typeof __dirname !== "undefined") return __dirname;
1864
- return (0, import_path7.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2008
+ return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1865
2009
  };
1866
2010
  var packageJson = JSON.parse(
1867
- (0, import_fs5.readFileSync)((0, import_path7.join)(getDirname(), "../package.json"), "utf8")
2011
+ (0, import_fs6.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
1868
2012
  );
1869
2013
  var program = new import_commander.Command();
1870
2014
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -1927,7 +2071,7 @@ program.command("scan").description(
1927
2071
  "--fail-on <level>",
1928
2072
  "Fail on issues: critical, major, any",
1929
2073
  "critical"
1930
- ).addHelpText("after", scanHelpText).action(async (directory, options) => {
2074
+ ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", scanHelpText).action(async (directory, options) => {
1931
2075
  await scanAction(directory, options);
1932
2076
  });
1933
2077
  program.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option(
@@ -2008,4 +2152,7 @@ program.command("visualize").description("Generate interactive visualization fro
2008
2152
  program.command("change-amplification").description("Analyze graph metrics for change amplification").argument("[directory]", "Directory to analyze", ".").option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").action(async (directory, options) => {
2009
2153
  await (0, import_cli.changeAmplificationAction)(directory, options);
2010
2154
  });
2155
+ program.command("upload").description("Upload an AIReady report JSON to the platform").argument("<file>", "Report JSON file to upload").option("--api-key <key>", "Platform API key").option("--repo-id <id>", "Platform repository ID (optional)").option("--server <url>", "Custom platform URL").addHelpText("after", uploadHelpText).action(async (file, options) => {
2156
+ await uploadAction(file, options);
2157
+ });
2011
2158
  program.parse();