@aiready/cli 0.14.21 → 0.14.22

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 (3) hide show
  1. package/dist/cli.js +299 -295
  2. package/dist/cli.mjs +262 -258
  3. package/package.json +12 -12
package/dist/cli.mjs CHANGED
@@ -12,7 +12,7 @@ import { join as join2, dirname } from "path";
12
12
  import { fileURLToPath } from "url";
13
13
 
14
14
  // src/commands/scan.ts
15
- import chalk4 from "chalk";
15
+ import chalk5 from "chalk";
16
16
  import { writeFileSync, readFileSync as readFileSync2 } from "fs";
17
17
  import { resolve as resolvePath3 } from "path";
18
18
  import {
@@ -22,7 +22,7 @@ import {
22
22
  resolveOutputPath,
23
23
  getRepoMetadata,
24
24
  calculateTokenBudget,
25
- ToolName,
25
+ ToolName as ToolName2,
26
26
  emitIssuesAsAnnotations
27
27
  } from "@aiready/core";
28
28
 
@@ -388,7 +388,7 @@ async function uploadAction(file, options) {
388
388
  handleCLIError(error, "Upload");
389
389
  }
390
390
  }
391
- var uploadHelpText = `
391
+ var UPLOAD_HELP_TEXT = `
392
392
  EXAMPLES:
393
393
  $ aiready upload report.json --api-key ar_...
394
394
  $ aiready upload .aiready/latest.json
@@ -399,9 +399,80 @@ ENVIRONMENT VARIABLES:
399
399
  AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
400
400
  `;
401
401
 
402
+ // src/commands/scan-helpers.ts
403
+ import chalk4 from "chalk";
404
+ import { ToolName } from "@aiready/core";
405
+ function getProfileTools(profile) {
406
+ switch (profile.toLowerCase()) {
407
+ case "agentic":
408
+ return [
409
+ ToolName.AiSignalClarity,
410
+ ToolName.AgentGrounding,
411
+ ToolName.TestabilityIndex
412
+ ];
413
+ case "cost":
414
+ return [ToolName.PatternDetect, ToolName.ContextAnalyzer];
415
+ case "logic":
416
+ return [
417
+ ToolName.TestabilityIndex,
418
+ ToolName.NamingConsistency,
419
+ ToolName.ContextAnalyzer,
420
+ ToolName.PatternDetect,
421
+ ToolName.ChangeAmplification
422
+ ];
423
+ case "ui":
424
+ return [
425
+ ToolName.NamingConsistency,
426
+ ToolName.ContextAnalyzer,
427
+ ToolName.PatternDetect,
428
+ ToolName.DocDrift,
429
+ ToolName.AiSignalClarity
430
+ ];
431
+ case "security":
432
+ return [ToolName.NamingConsistency, ToolName.TestabilityIndex];
433
+ case "onboarding":
434
+ return [
435
+ ToolName.ContextAnalyzer,
436
+ ToolName.NamingConsistency,
437
+ ToolName.AgentGrounding
438
+ ];
439
+ default:
440
+ console.log(
441
+ chalk4.yellow(`
442
+ \u26A0\uFE0F Unknown profile '${profile}'. Using defaults.`)
443
+ );
444
+ return void 0;
445
+ }
446
+ }
447
+ function createProgressCallback() {
448
+ return (event) => {
449
+ if (event.message) {
450
+ process.stdout.write(`\r\x1B[K [${event.tool}] ${event.message}`);
451
+ return;
452
+ }
453
+ process.stdout.write("\r\x1B[K");
454
+ console.log(chalk4.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
455
+ const toolResult = event.data;
456
+ if (toolResult && toolResult.summary) {
457
+ if (toolResult.summary.totalIssues !== void 0)
458
+ console.log(
459
+ ` Issues found: ${chalk4.bold(toolResult.summary.totalIssues)}`
460
+ );
461
+ if (toolResult.summary.score !== void 0)
462
+ console.log(
463
+ ` Tool Score: ${chalk4.bold(toolResult.summary.score)}/100`
464
+ );
465
+ if (toolResult.summary.totalFiles !== void 0)
466
+ console.log(
467
+ ` Files analyzed: ${chalk4.bold(toolResult.summary.totalFiles)}`
468
+ );
469
+ }
470
+ };
471
+ }
472
+
402
473
  // src/commands/scan.ts
403
474
  async function scanAction(directory, options) {
404
- console.log(chalk4.blue("\u{1F680} Starting AIReady unified analysis...\n"));
475
+ console.log(chalk5.blue("\u{1F680} Starting AIReady unified analysis...\n"));
405
476
  const startTime = Date.now();
406
477
  const resolvedDir = resolvePath3(process.cwd(), directory ?? ".");
407
478
  const repoMetadata = getRepoMetadata(resolvedDir);
@@ -427,56 +498,7 @@ async function scanAction(directory, options) {
427
498
  };
428
499
  let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
429
500
  if (options.profile) {
430
- switch (options.profile.toLowerCase()) {
431
- case "agentic":
432
- profileTools = [
433
- ToolName.AiSignalClarity,
434
- ToolName.AgentGrounding,
435
- ToolName.TestabilityIndex
436
- ];
437
- break;
438
- case "cost":
439
- profileTools = [ToolName.PatternDetect, ToolName.ContextAnalyzer];
440
- break;
441
- case "logic":
442
- profileTools = [
443
- ToolName.TestabilityIndex,
444
- ToolName.NamingConsistency,
445
- ToolName.ContextAnalyzer,
446
- ToolName.PatternDetect,
447
- ToolName.ChangeAmplification
448
- ];
449
- break;
450
- case "ui":
451
- profileTools = [
452
- ToolName.NamingConsistency,
453
- ToolName.ContextAnalyzer,
454
- ToolName.PatternDetect,
455
- ToolName.DocDrift,
456
- ToolName.AiSignalClarity
457
- ];
458
- break;
459
- case "security":
460
- profileTools = [
461
- ToolName.NamingConsistency,
462
- ToolName.TestabilityIndex
463
- ];
464
- break;
465
- case "onboarding":
466
- profileTools = [
467
- ToolName.ContextAnalyzer,
468
- ToolName.NamingConsistency,
469
- ToolName.AgentGrounding
470
- ];
471
- break;
472
- default:
473
- console.log(
474
- chalk4.yellow(
475
- `
476
- \u26A0\uFE0F Unknown profile '${options.profile}'. Using defaults.`
477
- )
478
- );
479
- }
501
+ profileTools = getProfileTools(options.profile);
480
502
  }
481
503
  const cliOverrides = {
482
504
  include: options.include?.split(","),
@@ -489,42 +511,24 @@ async function scanAction(directory, options) {
489
511
  cliOverrides
490
512
  );
491
513
  const finalOptions = { ...baseOptions };
492
- if (baseOptions.tools.includes(ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
514
+ if (baseOptions.tools.includes(ToolName2.PatternDetect) || baseOptions.tools.includes("patterns")) {
493
515
  const { getSmartDefaults } = await import("@aiready/pattern-detect");
494
516
  const patternSmartDefaults = await getSmartDefaults(
495
517
  resolvedDir,
496
- finalOptions.toolConfigs?.[ToolName.PatternDetect] ?? {}
518
+ finalOptions.toolConfigs?.[ToolName2.PatternDetect] ?? {}
497
519
  );
498
520
  if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
499
- finalOptions.toolConfigs[ToolName.PatternDetect] = {
521
+ finalOptions.toolConfigs[ToolName2.PatternDetect] = {
500
522
  ...patternSmartDefaults,
501
- ...finalOptions.toolConfigs[ToolName.PatternDetect]
523
+ ...finalOptions.toolConfigs[ToolName2.PatternDetect]
502
524
  };
503
525
  }
504
- console.log(chalk4.cyan("\n=== AIReady Run Preview ==="));
526
+ console.log(chalk5.cyan("\n=== AIReady Run Preview ==="));
505
527
  console.log(
506
- chalk4.white("Tools to run:"),
528
+ chalk5.white("Tools to run:"),
507
529
  (finalOptions.tools ?? []).join(", ")
508
530
  );
509
- const progressCallback = (event) => {
510
- if (event.message) {
511
- process.stdout.write(`\r\x1B[K [${event.tool}] ${event.message}`);
512
- return;
513
- }
514
- process.stdout.write("\r\x1B[K");
515
- console.log(chalk4.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
516
- const res = event.data;
517
- if (res && res.summary) {
518
- if (res.summary.totalIssues !== void 0)
519
- console.log(` Issues found: ${chalk4.bold(res.summary.totalIssues)}`);
520
- if (res.summary.score !== void 0)
521
- console.log(` Tool Score: ${chalk4.bold(res.summary.score)}/100`);
522
- if (res.summary.totalFiles !== void 0)
523
- console.log(
524
- ` Files analyzed: ${chalk4.bold(res.summary.totalFiles)}`
525
- );
526
- }
527
- };
531
+ const progressCallback = createProgressCallback();
528
532
  const scoringProfile = options.profile ?? baseOptions.scoring?.profile ?? "default";
529
533
  const results = await analyzeUnified({
530
534
  ...finalOptions,
@@ -555,19 +559,19 @@ async function scanAction(directory, options) {
555
559
  const diffStr = diff > 0 ? `+${diff}` : String(diff);
556
560
  if (diff > 0)
557
561
  console.log(
558
- chalk4.green(
562
+ chalk5.green(
559
563
  ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
560
564
  )
561
565
  );
562
566
  else if (diff < 0)
563
567
  console.log(
564
- chalk4.red(
568
+ chalk5.red(
565
569
  ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
566
570
  )
567
571
  );
568
572
  else
569
573
  console.log(
570
- chalk4.blue(
574
+ chalk5.blue(
571
575
  ` \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
572
576
  )
573
577
  );
@@ -627,19 +631,19 @@ async function scanAction(directory, options) {
627
631
  }
628
632
  }
629
633
  console.log(
630
- chalk4.dim(
634
+ chalk5.dim(
631
635
  "\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
632
636
  )
633
637
  );
634
- console.log(chalk4.dim("\u{1F4AC} Found a bug or have a metric idea?"));
635
- console.log(chalk4.dim("\u{1F449} Copy/paste this to your AI agent:"));
638
+ console.log(chalk5.dim("\u{1F4AC} Found a bug or have a metric idea?"));
639
+ console.log(chalk5.dim("\u{1F449} Copy/paste this to your AI agent:"));
636
640
  console.log(
637
- chalk4.cyan(
641
+ chalk5.cyan(
638
642
  ` "Any feedback for the tools? Please use 'aiready bug' to report \u2764\uFE0F"`
639
643
  )
640
644
  );
641
645
  console.log(
642
- chalk4.dim(
646
+ chalk5.dim(
643
647
  "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
644
648
  )
645
649
  );
@@ -662,7 +666,7 @@ async function scanAction(directory, options) {
662
666
  } else {
663
667
  try {
664
668
  writeFileSync(outputPath, JSON.stringify(outputData, null, 2));
665
- console.log(chalk4.dim(`\u2705 Report auto-persisted to ${outputPath}`));
669
+ console.log(chalk5.dim(`\u2705 Report auto-persisted to ${outputPath}`));
666
670
  } catch (err) {
667
671
  void err;
668
672
  }
@@ -683,7 +687,7 @@ async function scanAction(directory, options) {
683
687
  const report = mapToUnifiedReport(results, scoringResult);
684
688
  if (isCI && report.results && report.results.length > 0) {
685
689
  console.log(
686
- chalk4.cyan(
690
+ chalk5.cyan(
687
691
  `
688
692
  \u{1F4DD} Emitting GitHub Action annotations for ${report.results.length} issues...`
689
693
  )
@@ -704,31 +708,31 @@ async function scanAction(directory, options) {
704
708
  }
705
709
  }
706
710
  if (shouldFail) {
707
- console.log(chalk4.red(`
711
+ console.log(chalk5.red(`
708
712
  \u{1F6AB} SCAN FAILED: ${failReason}`));
709
713
  process.exit(1);
710
714
  } else {
711
- console.log(chalk4.green("\n\u2705 SCAN PASSED"));
715
+ console.log(chalk5.green("\n\u2705 SCAN PASSED"));
712
716
  }
713
717
  }
714
718
  } catch (error) {
715
719
  handleCLIError2(error, "Analysis");
716
720
  }
717
721
  }
718
- var scanHelpText = `...`;
722
+ var SCAN_HELP_TEXT = `...`;
719
723
 
720
724
  // src/commands/init.ts
721
725
  import { writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
722
726
  import { join } from "path";
723
- import chalk5 from "chalk";
724
- import { ToolName as ToolName2 } from "@aiready/core";
727
+ import chalk6 from "chalk";
728
+ import { ToolName as ToolName3 } from "@aiready/core";
725
729
  async function initAction(options) {
726
730
  const fileExt = options.format === "js" ? "js" : "json";
727
731
  const fileName = fileExt === "js" ? "aiready.config.js" : "aiready.json";
728
732
  const filePath = join(process.cwd(), fileName);
729
733
  if (existsSync2(filePath) && !options.force) {
730
734
  console.error(
731
- chalk5.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
735
+ chalk6.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
732
736
  );
733
737
  process.exit(1);
734
738
  }
@@ -752,15 +756,15 @@ async function initAction(options) {
752
756
  "**/*.spec.ts"
753
757
  ],
754
758
  tools: [
755
- ToolName2.PatternDetect,
756
- ToolName2.ContextAnalyzer,
757
- ToolName2.NamingConsistency,
758
- ToolName2.AiSignalClarity,
759
- ToolName2.AgentGrounding,
760
- ToolName2.TestabilityIndex,
761
- ToolName2.DocDrift,
762
- ToolName2.DependencyHealth,
763
- ToolName2.ChangeAmplification
759
+ ToolName3.PatternDetect,
760
+ ToolName3.ContextAnalyzer,
761
+ ToolName3.NamingConsistency,
762
+ ToolName3.AiSignalClarity,
763
+ ToolName3.AgentGrounding,
764
+ ToolName3.TestabilityIndex,
765
+ ToolName3.DocDrift,
766
+ ToolName3.DependencyHealth,
767
+ ToolName3.ChangeAmplification
764
768
  ]
765
769
  },
766
770
  // Output preferences
@@ -775,7 +779,7 @@ async function initAction(options) {
775
779
  },
776
780
  // Tool-specific configurations
777
781
  tools: {
778
- [ToolName2.PatternDetect]: {
782
+ [ToolName3.PatternDetect]: {
779
783
  // Core detection thresholds
780
784
  minSimilarity: 0.4,
781
785
  // Jaccard similarity threshold (0-1)
@@ -805,7 +809,7 @@ async function initAction(options) {
805
809
  // Add any additional advanced options here
806
810
  } : {}
807
811
  },
808
- [ToolName2.ContextAnalyzer]: {
812
+ [ToolName3.ContextAnalyzer]: {
809
813
  // Smart defaults are generated dynamically based on repository size
810
814
  // These are fallback values for when smart defaults can't be calculated
811
815
  maxContextBudget: 25e3,
@@ -822,7 +826,7 @@ async function initAction(options) {
822
826
  includeNodeModules: false
823
827
  // Whether to include node_modules in analysis
824
828
  },
825
- [ToolName2.NamingConsistency]: {
829
+ [ToolName3.NamingConsistency]: {
826
830
  // Core checks
827
831
  checkNaming: true,
828
832
  // Check naming conventions and quality
@@ -869,7 +873,7 @@ async function initAction(options) {
869
873
  ],
870
874
  ...options.full ? { disableChecks: [] } : {}
871
875
  },
872
- [ToolName2.AiSignalClarity]: {
876
+ [ToolName3.AiSignalClarity]: {
873
877
  // All signal clarity checks enabled by default
874
878
  checkMagicLiterals: true,
875
879
  // Detect magic numbers and strings
@@ -888,7 +892,7 @@ async function initAction(options) {
888
892
  checkLargeFiles: true
889
893
  // Detect files that are too large
890
894
  },
891
- [ToolName2.AgentGrounding]: {
895
+ [ToolName3.AgentGrounding]: {
892
896
  // Structure clarity
893
897
  maxRecommendedDepth: 4,
894
898
  // Max directory depth before flagging as "too deep"
@@ -899,7 +903,7 @@ async function initAction(options) {
899
903
  additionalVagueNames: ["stuff", "misc", "temp", "test"]
900
904
  // Custom vague file names
901
905
  },
902
- [ToolName2.TestabilityIndex]: {
906
+ [ToolName3.TestabilityIndex]: {
903
907
  // Coverage thresholds
904
908
  minCoverageRatio: 0.3,
905
909
  // Minimum acceptable test/source ratio
@@ -909,19 +913,19 @@ async function initAction(options) {
909
913
  maxDepth: 10
910
914
  // Maximum scan depth
911
915
  },
912
- [ToolName2.DocDrift]: {
916
+ [ToolName3.DocDrift]: {
913
917
  // Drift detection
914
918
  maxCommits: 50,
915
919
  // Maximum commit distance to check for drift
916
920
  staleMonths: 3
917
921
  // Consider comments older than this as outdated
918
922
  },
919
- [ToolName2.DependencyHealth]: {
923
+ [ToolName3.DependencyHealth]: {
920
924
  // Training cutoff for AI knowledge assessment
921
925
  trainingCutoffYear: 2023
922
926
  // Year cutoff for AI training data
923
927
  },
924
- [ToolName2.ChangeAmplification]: {
928
+ [ToolName3.ChangeAmplification]: {
925
929
  // Change amplification primarily relies on global scan settings
926
930
  // No additional tool-specific configuration required
927
931
  }
@@ -950,22 +954,22 @@ module.exports = ${JSON.stringify(defaultConfig, null, 2)};
950
954
  try {
951
955
  writeFileSync2(filePath, content, "utf8");
952
956
  console.log(
953
- chalk5.green(`
954
- \u2705 Created default configuration: ${chalk5.bold(fileName)}`)
957
+ chalk6.green(`
958
+ \u2705 Created default configuration: ${chalk6.bold(fileName)}`)
955
959
  );
956
960
  console.log(
957
- chalk5.cyan("You can now fine-tune your settings and run AIReady with:")
961
+ chalk6.cyan("You can now fine-tune your settings and run AIReady with:")
958
962
  );
959
- console.log(chalk5.white(` $ aiready scan
963
+ console.log(chalk6.white(` $ aiready scan
960
964
  `));
961
965
  } catch (error) {
962
- console.error(chalk5.red(`Failed to write configuration file: ${error}`));
966
+ console.error(chalk6.red(`Failed to write configuration file: ${error}`));
963
967
  process.exit(1);
964
968
  }
965
969
  }
966
970
 
967
971
  // src/commands/patterns.ts
968
- import chalk6 from "chalk";
972
+ import chalk7 from "chalk";
969
973
  import { resolve as resolvePath4 } from "path";
970
974
  import {
971
975
  loadMergedConfig as loadMergedConfig2,
@@ -976,7 +980,7 @@ import {
976
980
  formatToolScore
977
981
  } from "@aiready/core";
978
982
  async function patternsAction(directory, options) {
979
- console.log(chalk6.blue("\u{1F50D} Analyzing patterns...\n"));
983
+ console.log(chalk7.blue("\u{1F50D} Analyzing patterns...\n"));
980
984
  const startTime = Date.now();
981
985
  const resolvedDir = resolvePath4(process.cwd(), directory ?? ".");
982
986
  try {
@@ -1044,38 +1048,38 @@ async function patternsAction(directory, options) {
1044
1048
  const terminalWidth = process.stdout.columns || 80;
1045
1049
  const dividerWidth = Math.min(60, terminalWidth - 2);
1046
1050
  const divider = "\u2501".repeat(dividerWidth);
1047
- console.log(chalk6.cyan(divider));
1048
- console.log(chalk6.bold.white(" PATTERN ANALYSIS SUMMARY"));
1049
- console.log(chalk6.cyan(divider) + "\n");
1051
+ console.log(chalk7.cyan(divider));
1052
+ console.log(chalk7.bold.white(" PATTERN ANALYSIS SUMMARY"));
1053
+ console.log(chalk7.cyan(divider) + "\n");
1050
1054
  console.log(
1051
- chalk6.white(`\u{1F4C1} Files analyzed: ${chalk6.bold(results.length)}`)
1055
+ chalk7.white(`\u{1F4C1} Files analyzed: ${chalk7.bold(results.length)}`)
1052
1056
  );
1053
1057
  console.log(
1054
- chalk6.yellow(
1055
- `\u26A0 Duplicate patterns found: ${chalk6.bold(summary.totalPatterns)}`
1058
+ chalk7.yellow(
1059
+ `\u26A0 Duplicate patterns found: ${chalk7.bold(summary.totalPatterns)}`
1056
1060
  )
1057
1061
  );
1058
1062
  console.log(
1059
- chalk6.red(
1060
- `\u{1F4B0} Token cost (wasted): ${chalk6.bold(summary.totalTokenCost.toLocaleString())}`
1063
+ chalk7.red(
1064
+ `\u{1F4B0} Token cost (wasted): ${chalk7.bold(summary.totalTokenCost.toLocaleString())}`
1061
1065
  )
1062
1066
  );
1063
1067
  console.log(
1064
- chalk6.gray(`\u23F1 Analysis time: ${chalk6.bold(elapsedTime + "s")}`)
1068
+ chalk7.gray(`\u23F1 Analysis time: ${chalk7.bold(elapsedTime + "s")}`)
1065
1069
  );
1066
1070
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
1067
1071
  if (sortedTypes.length > 0) {
1068
- console.log(chalk6.cyan("\n" + divider));
1069
- console.log(chalk6.bold.white(" PATTERNS BY TYPE"));
1070
- console.log(chalk6.cyan(divider) + "\n");
1072
+ console.log(chalk7.cyan("\n" + divider));
1073
+ console.log(chalk7.bold.white(" PATTERNS BY TYPE"));
1074
+ console.log(chalk7.cyan(divider) + "\n");
1071
1075
  sortedTypes.forEach(([type, count]) => {
1072
- console.log(` ${chalk6.white(type.padEnd(15))} ${chalk6.bold(count)}`);
1076
+ console.log(` ${chalk7.white(type.padEnd(15))} ${chalk7.bold(count)}`);
1073
1077
  });
1074
1078
  }
1075
1079
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
1076
- console.log(chalk6.cyan("\n" + divider));
1077
- console.log(chalk6.bold.white(" TOP DUPLICATE PATTERNS"));
1078
- console.log(chalk6.cyan(divider) + "\n");
1080
+ console.log(chalk7.cyan("\n" + divider));
1081
+ console.log(chalk7.bold.white(" TOP DUPLICATE PATTERNS"));
1082
+ console.log(chalk7.cyan(divider) + "\n");
1079
1083
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
1080
1084
  topDuplicates.forEach((dup) => {
1081
1085
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -1083,25 +1087,25 @@ async function patternsAction(directory, options) {
1083
1087
  const file1Name = dup.file1.split("/").pop() || dup.file1;
1084
1088
  const file2Name = dup.file2.split("/").pop() || dup.file2;
1085
1089
  console.log(
1086
- `${severityIcon} ${severity}: ${chalk6.bold(file1Name)} \u2194 ${chalk6.bold(file2Name)}`
1090
+ `${severityIcon} ${severity}: ${chalk7.bold(file1Name)} \u2194 ${chalk7.bold(file2Name)}`
1087
1091
  );
1088
1092
  console.log(
1089
- ` Similarity: ${chalk6.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${chalk6.bold(dup.tokenCost.toLocaleString())} tokens each`
1093
+ ` Similarity: ${chalk7.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${chalk7.bold(dup.tokenCost.toLocaleString())} tokens each`
1090
1094
  );
1091
1095
  console.log(
1092
- ` Lines: ${chalk6.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${chalk6.cyan(dup.line2 + "-" + dup.endLine2)}
1096
+ ` Lines: ${chalk7.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${chalk7.cyan(dup.line2 + "-" + dup.endLine2)}
1093
1097
  `
1094
1098
  );
1095
1099
  });
1096
1100
  } else {
1097
1101
  console.log(
1098
- chalk6.green("\n\u2728 Great! No duplicate patterns detected.\n")
1102
+ chalk7.green("\n\u2728 Great! No duplicate patterns detected.\n")
1099
1103
  );
1100
1104
  }
1101
1105
  if (patternScore) {
1102
- console.log(chalk6.cyan(divider));
1103
- console.log(chalk6.bold.white(" AI READINESS SCORE (Patterns)"));
1104
- console.log(chalk6.cyan(divider) + "\n");
1106
+ console.log(chalk7.cyan(divider));
1107
+ console.log(chalk7.bold.white(" AI READINESS SCORE (Patterns)"));
1108
+ console.log(chalk7.cyan(divider) + "\n");
1105
1109
  console.log(formatToolScore(patternScore));
1106
1110
  console.log();
1107
1111
  }
@@ -1110,7 +1114,7 @@ async function patternsAction(directory, options) {
1110
1114
  handleCLIError3(error, "Pattern analysis");
1111
1115
  }
1112
1116
  }
1113
- var patternsHelpText = `
1117
+ var PATTERNS_HELP_TEXT = `
1114
1118
  EXAMPLES:
1115
1119
  $ aiready patterns # Default analysis
1116
1120
  $ aiready patterns --similarity 0.6 # Stricter matching
@@ -1118,7 +1122,7 @@ EXAMPLES:
1118
1122
  `;
1119
1123
 
1120
1124
  // src/commands/context.ts
1121
- import chalk7 from "chalk";
1125
+ import chalk8 from "chalk";
1122
1126
  import { resolve as resolvePath5 } from "path";
1123
1127
  import {
1124
1128
  loadMergedConfig as loadMergedConfig3,
@@ -1129,7 +1133,7 @@ import {
1129
1133
  formatToolScore as formatToolScore2
1130
1134
  } from "@aiready/core";
1131
1135
  async function contextAction(directory, options) {
1132
- console.log(chalk7.blue("\u{1F9E0} Analyzing context costs...\n"));
1136
+ console.log(chalk8.blue("\u{1F9E0} Analyzing context costs...\n"));
1133
1137
  const startTime = Date.now();
1134
1138
  const resolvedDir = resolvePath5(process.cwd(), directory ?? ".");
1135
1139
  try {
@@ -1197,85 +1201,85 @@ async function contextAction(directory, options) {
1197
1201
  const terminalWidth = process.stdout.columns ?? 80;
1198
1202
  const dividerWidth = Math.min(60, terminalWidth - 2);
1199
1203
  const divider = "\u2501".repeat(dividerWidth);
1200
- console.log(chalk7.cyan(divider));
1201
- console.log(chalk7.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1202
- console.log(chalk7.cyan(divider) + "\n");
1204
+ console.log(chalk8.cyan(divider));
1205
+ console.log(chalk8.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1206
+ console.log(chalk8.cyan(divider) + "\n");
1203
1207
  console.log(
1204
- chalk7.white(`\u{1F4C1} Files analyzed: ${chalk7.bold(summary.totalFiles)}`)
1208
+ chalk8.white(`\u{1F4C1} Files analyzed: ${chalk8.bold(summary.totalFiles)}`)
1205
1209
  );
1206
1210
  console.log(
1207
- chalk7.white(
1208
- `\u{1F4CA} Total tokens: ${chalk7.bold(summary.totalTokens.toLocaleString())}`
1211
+ chalk8.white(
1212
+ `\u{1F4CA} Total tokens: ${chalk8.bold(summary.totalTokens.toLocaleString())}`
1209
1213
  )
1210
1214
  );
1211
1215
  console.log(
1212
- chalk7.yellow(
1213
- `\u{1F4B0} Avg context budget: ${chalk7.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1216
+ chalk8.yellow(
1217
+ `\u{1F4B0} Avg context budget: ${chalk8.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1214
1218
  )
1215
1219
  );
1216
1220
  console.log(
1217
- chalk7.white(`\u23F1 Analysis time: ${chalk7.bold(elapsedTime + "s")}
1221
+ chalk8.white(`\u23F1 Analysis time: ${chalk8.bold(elapsedTime + "s")}
1218
1222
  `)
1219
1223
  );
1220
1224
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
1221
1225
  if (totalIssues > 0) {
1222
- console.log(chalk7.bold("\u26A0\uFE0F Issues Found:\n"));
1226
+ console.log(chalk8.bold("\u26A0\uFE0F Issues Found:\n"));
1223
1227
  if (summary.criticalIssues > 0) {
1224
1228
  console.log(
1225
- chalk7.red(` \u{1F534} Critical: ${chalk7.bold(summary.criticalIssues)}`)
1229
+ chalk8.red(` \u{1F534} Critical: ${chalk8.bold(summary.criticalIssues)}`)
1226
1230
  );
1227
1231
  }
1228
1232
  if (summary.majorIssues > 0) {
1229
1233
  console.log(
1230
- chalk7.yellow(` \u{1F7E1} Major: ${chalk7.bold(summary.majorIssues)}`)
1234
+ chalk8.yellow(` \u{1F7E1} Major: ${chalk8.bold(summary.majorIssues)}`)
1231
1235
  );
1232
1236
  }
1233
1237
  if (summary.minorIssues > 0) {
1234
1238
  console.log(
1235
- chalk7.blue(` \u{1F535} Minor: ${chalk7.bold(summary.minorIssues)}`)
1239
+ chalk8.blue(` \u{1F535} Minor: ${chalk8.bold(summary.minorIssues)}`)
1236
1240
  );
1237
1241
  }
1238
1242
  console.log(
1239
- chalk7.green(
1243
+ chalk8.green(
1240
1244
  `
1241
- \u{1F4A1} Potential savings: ${chalk7.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1245
+ \u{1F4A1} Potential savings: ${chalk8.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1242
1246
  `
1243
1247
  )
1244
1248
  );
1245
1249
  } else {
1246
- console.log(chalk7.green("\u2705 No significant issues found!\n"));
1250
+ console.log(chalk8.green("\u2705 No significant issues found!\n"));
1247
1251
  }
1248
1252
  if (summary.deepFiles.length > 0) {
1249
- console.log(chalk7.bold("\u{1F4CF} Deep Import Chains:\n"));
1253
+ console.log(chalk8.bold("\u{1F4CF} Deep Import Chains:\n"));
1250
1254
  console.log(
1251
- chalk7.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1255
+ chalk8.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1252
1256
  );
1253
1257
  console.log(
1254
- chalk7.gray(` Maximum depth: ${summary.maxImportDepth}
1258
+ chalk8.gray(` Maximum depth: ${summary.maxImportDepth}
1255
1259
  `)
1256
1260
  );
1257
1261
  summary.deepFiles.slice(0, 10).forEach((item) => {
1258
1262
  const fileName = item.file.split("/").slice(-2).join("/");
1259
1263
  console.log(
1260
- ` ${chalk7.cyan("\u2192")} ${chalk7.white(fileName)} ${chalk7.dim(`(depth: ${item.depth})`)}`
1264
+ ` ${chalk8.cyan("\u2192")} ${chalk8.white(fileName)} ${chalk8.dim(`(depth: ${item.depth})`)}`
1261
1265
  );
1262
1266
  });
1263
1267
  console.log();
1264
1268
  }
1265
1269
  if (summary.fragmentedModules.length > 0) {
1266
- console.log(chalk7.bold("\u{1F9E9} Fragmented Modules:\n"));
1270
+ console.log(chalk8.bold("\u{1F9E9} Fragmented Modules:\n"));
1267
1271
  console.log(
1268
- chalk7.gray(
1272
+ chalk8.gray(
1269
1273
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1270
1274
  `
1271
1275
  )
1272
1276
  );
1273
1277
  summary.fragmentedModules.slice(0, 10).forEach((module) => {
1274
1278
  console.log(
1275
- ` ${chalk7.yellow("\u25CF")} ${chalk7.white(module.domain)} - ${chalk7.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1279
+ ` ${chalk8.yellow("\u25CF")} ${chalk8.white(module.domain)} - ${chalk8.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1276
1280
  );
1277
1281
  console.log(
1278
- chalk7.dim(
1282
+ chalk8.dim(
1279
1283
  ` Token cost: ${module.totalTokens.toLocaleString()}, Cohesion: ${(module.avgCohesion * 100).toFixed(0)}%`
1280
1284
  )
1281
1285
  );
@@ -1283,9 +1287,9 @@ async function contextAction(directory, options) {
1283
1287
  console.log();
1284
1288
  }
1285
1289
  if (summary.lowCohesionFiles.length > 0) {
1286
- console.log(chalk7.bold("\u{1F500} Low Cohesion Files:\n"));
1290
+ console.log(chalk8.bold("\u{1F500} Low Cohesion Files:\n"));
1287
1291
  console.log(
1288
- chalk7.gray(
1292
+ chalk8.gray(
1289
1293
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1290
1294
  `
1291
1295
  )
@@ -1293,28 +1297,28 @@ async function contextAction(directory, options) {
1293
1297
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
1294
1298
  const fileName = item.file.split("/").slice(-2).join("/");
1295
1299
  const scorePercent = (item.score * 100).toFixed(0);
1296
- const color = item.score < 0.4 ? chalk7.red : chalk7.yellow;
1300
+ const color = item.score < 0.4 ? chalk8.red : chalk8.yellow;
1297
1301
  console.log(
1298
- ` ${color("\u25CB")} ${chalk7.white(fileName)} ${chalk7.dim(`(${scorePercent}% cohesion)`)}`
1302
+ ` ${color("\u25CB")} ${chalk8.white(fileName)} ${chalk8.dim(`(${scorePercent}% cohesion)`)}`
1299
1303
  );
1300
1304
  });
1301
1305
  console.log();
1302
1306
  }
1303
1307
  if (summary.topExpensiveFiles.length > 0) {
1304
- console.log(chalk7.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1308
+ console.log(chalk8.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1305
1309
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
1306
1310
  const fileName = item.file.split("/").slice(-2).join("/");
1307
- const severityColor = item.severity === "critical" ? chalk7.red : item.severity === "major" ? chalk7.yellow : chalk7.blue;
1311
+ const severityColor = item.severity === "critical" ? chalk8.red : item.severity === "major" ? chalk8.yellow : chalk8.blue;
1308
1312
  console.log(
1309
- ` ${severityColor("\u25CF")} ${chalk7.white(fileName)} ${chalk7.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1313
+ ` ${severityColor("\u25CF")} ${chalk8.white(fileName)} ${chalk8.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1310
1314
  );
1311
1315
  });
1312
1316
  console.log();
1313
1317
  }
1314
1318
  if (contextScore) {
1315
- console.log(chalk7.cyan(divider));
1316
- console.log(chalk7.bold.white(" AI READINESS SCORE (Context)"));
1317
- console.log(chalk7.cyan(divider) + "\n");
1319
+ console.log(chalk8.cyan(divider));
1320
+ console.log(chalk8.bold.white(" AI READINESS SCORE (Context)"));
1321
+ console.log(chalk8.cyan(divider) + "\n");
1318
1322
  console.log(formatToolScore2(contextScore));
1319
1323
  console.log();
1320
1324
  }
@@ -1325,7 +1329,7 @@ async function contextAction(directory, options) {
1325
1329
  }
1326
1330
 
1327
1331
  // src/commands/consistency.ts
1328
- import chalk8 from "chalk";
1332
+ import chalk9 from "chalk";
1329
1333
  import { writeFileSync as writeFileSync3 } from "fs";
1330
1334
  import { resolve as resolvePath6 } from "path";
1331
1335
  import {
@@ -1337,7 +1341,7 @@ import {
1337
1341
  formatToolScore as formatToolScore3
1338
1342
  } from "@aiready/core";
1339
1343
  async function consistencyAction(directory, options) {
1340
- console.log(chalk8.blue("\u{1F50D} Analyzing consistency...\n"));
1344
+ console.log(chalk9.blue("\u{1F50D} Analyzing consistency...\n"));
1341
1345
  const startTime = Date.now();
1342
1346
  const resolvedDir = resolvePath6(process.cwd(), directory ?? ".");
1343
1347
  try {
@@ -1399,23 +1403,23 @@ async function consistencyAction(directory, options) {
1399
1403
  resolvedDir
1400
1404
  );
1401
1405
  writeFileSync3(outputPath, markdown);
1402
- console.log(chalk8.green(`\u2705 Report saved to ${outputPath}`));
1406
+ console.log(chalk9.green(`\u2705 Report saved to ${outputPath}`));
1403
1407
  } else {
1404
- console.log(chalk8.bold("\n\u{1F4CA} Summary\n"));
1408
+ console.log(chalk9.bold("\n\u{1F4CA} Summary\n"));
1405
1409
  console.log(
1406
- `Files Analyzed: ${chalk8.cyan(report.summary.filesAnalyzed)}`
1410
+ `Files Analyzed: ${chalk9.cyan(report.summary.filesAnalyzed)}`
1407
1411
  );
1408
- console.log(`Total Issues: ${chalk8.yellow(report.summary.totalIssues)}`);
1409
- console.log(` Naming: ${chalk8.yellow(report.summary.namingIssues)}`);
1410
- console.log(` Patterns: ${chalk8.yellow(report.summary.patternIssues)}`);
1412
+ console.log(`Total Issues: ${chalk9.yellow(report.summary.totalIssues)}`);
1413
+ console.log(` Naming: ${chalk9.yellow(report.summary.namingIssues)}`);
1414
+ console.log(` Patterns: ${chalk9.yellow(report.summary.patternIssues)}`);
1411
1415
  console.log(
1412
- ` Architecture: ${chalk8.yellow(report.summary.architectureIssues ?? 0)}`
1416
+ ` Architecture: ${chalk9.yellow(report.summary.architectureIssues ?? 0)}`
1413
1417
  );
1414
- console.log(`Analysis Time: ${chalk8.gray(elapsedTime + "s")}
1418
+ console.log(`Analysis Time: ${chalk9.gray(elapsedTime + "s")}
1415
1419
  `);
1416
1420
  if (report.summary.totalIssues === 0) {
1417
1421
  console.log(
1418
- chalk8.green(
1422
+ chalk9.green(
1419
1423
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1420
1424
  )
1421
1425
  );
@@ -1427,20 +1431,20 @@ async function consistencyAction(directory, options) {
1427
1431
  (r) => r.issues.some((i) => i.category === "patterns")
1428
1432
  );
1429
1433
  if (namingResults.length > 0) {
1430
- console.log(chalk8.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1434
+ console.log(chalk9.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1431
1435
  let shown = 0;
1432
- for (const result of namingResults) {
1436
+ for (const namingFileResult of namingResults) {
1433
1437
  if (shown >= 5) break;
1434
- for (const issue of result.issues) {
1438
+ for (const issue of namingFileResult.issues) {
1435
1439
  if (shown >= 5) break;
1436
- const severityColor = issue.severity === "critical" ? chalk8.red : issue.severity === "major" ? chalk8.yellow : issue.severity === "minor" ? chalk8.blue : chalk8.gray;
1440
+ const severityColor = issue.severity === "critical" ? chalk9.red : issue.severity === "major" ? chalk9.yellow : issue.severity === "minor" ? chalk9.blue : chalk9.gray;
1437
1441
  console.log(
1438
- `${severityColor(issue.severity.toUpperCase())} ${chalk8.dim(`${issue.location.file}:${issue.location.line}`)}`
1442
+ `${severityColor(issue.severity.toUpperCase())} ${chalk9.dim(`${issue.location.file}:${issue.location.line}`)}`
1439
1443
  );
1440
1444
  console.log(` ${issue.message}`);
1441
1445
  if (issue.suggestion) {
1442
1446
  console.log(
1443
- ` ${chalk8.dim("\u2192")} ${chalk8.italic(issue.suggestion)}`
1447
+ ` ${chalk9.dim("\u2192")} ${chalk9.italic(issue.suggestion)}`
1444
1448
  );
1445
1449
  }
1446
1450
  console.log();
@@ -1449,25 +1453,25 @@ async function consistencyAction(directory, options) {
1449
1453
  }
1450
1454
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1451
1455
  if (remaining > 0) {
1452
- console.log(chalk8.dim(` ... and ${remaining} more issues
1456
+ console.log(chalk9.dim(` ... and ${remaining} more issues
1453
1457
  `));
1454
1458
  }
1455
1459
  }
1456
1460
  if (patternResults.length > 0) {
1457
- console.log(chalk8.bold("\u{1F504} Pattern Issues\n"));
1461
+ console.log(chalk9.bold("\u{1F504} Pattern Issues\n"));
1458
1462
  let shown = 0;
1459
- for (const result of patternResults) {
1463
+ for (const patternFileResult of patternResults) {
1460
1464
  if (shown >= 5) break;
1461
- for (const issue of result.issues) {
1465
+ for (const issue of patternFileResult.issues) {
1462
1466
  if (shown >= 5) break;
1463
- const severityColor = issue.severity === "critical" ? chalk8.red : issue.severity === "major" ? chalk8.yellow : issue.severity === "minor" ? chalk8.blue : chalk8.gray;
1467
+ const severityColor = issue.severity === "critical" ? chalk9.red : issue.severity === "major" ? chalk9.yellow : issue.severity === "minor" ? chalk9.blue : chalk9.gray;
1464
1468
  console.log(
1465
- `${severityColor(issue.severity.toUpperCase())} ${chalk8.dim(`${issue.location.file}:${issue.location.line}`)}`
1469
+ `${severityColor(issue.severity.toUpperCase())} ${chalk9.dim(`${issue.location.file}:${issue.location.line}`)}`
1466
1470
  );
1467
1471
  console.log(` ${issue.message}`);
1468
1472
  if (issue.suggestion) {
1469
1473
  console.log(
1470
- ` ${chalk8.dim("\u2192")} ${chalk8.italic(issue.suggestion)}`
1474
+ ` ${chalk9.dim("\u2192")} ${chalk9.italic(issue.suggestion)}`
1471
1475
  );
1472
1476
  }
1473
1477
  console.log();
@@ -1476,12 +1480,12 @@ async function consistencyAction(directory, options) {
1476
1480
  }
1477
1481
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1478
1482
  if (remaining > 0) {
1479
- console.log(chalk8.dim(` ... and ${remaining} more issues
1483
+ console.log(chalk9.dim(` ... and ${remaining} more issues
1480
1484
  `));
1481
1485
  }
1482
1486
  }
1483
1487
  if (report.recommendations.length > 0) {
1484
- console.log(chalk8.bold("\u{1F4A1} Recommendations\n"));
1488
+ console.log(chalk9.bold("\u{1F4A1} Recommendations\n"));
1485
1489
  report.recommendations.forEach((rec, i) => {
1486
1490
  console.log(`${i + 1}. ${rec}`);
1487
1491
  });
@@ -1489,7 +1493,7 @@ async function consistencyAction(directory, options) {
1489
1493
  }
1490
1494
  }
1491
1495
  if (consistencyScore) {
1492
- console.log(chalk8.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1496
+ console.log(chalk9.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1493
1497
  console.log(formatToolScore3(consistencyScore));
1494
1498
  console.log();
1495
1499
  }
@@ -1500,7 +1504,7 @@ async function consistencyAction(directory, options) {
1500
1504
  }
1501
1505
 
1502
1506
  // src/commands/visualize.ts
1503
- import chalk9 from "chalk";
1507
+ import chalk10 from "chalk";
1504
1508
  import { writeFileSync as writeFileSync4, readFileSync as readFileSync3, existsSync as existsSync3, copyFileSync } from "fs";
1505
1509
  import { resolve as resolvePath7 } from "path";
1506
1510
  import { spawn } from "child_process";
@@ -1515,12 +1519,12 @@ async function visualizeAction(directory, options) {
1515
1519
  if (latestScan) {
1516
1520
  reportPath = latestScan;
1517
1521
  console.log(
1518
- chalk9.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1522
+ chalk10.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1519
1523
  );
1520
1524
  } else {
1521
- console.error(chalk9.red("\u274C No AI readiness report found"));
1525
+ console.error(chalk10.red("\u274C No AI readiness report found"));
1522
1526
  console.log(
1523
- chalk9.dim(
1527
+ chalk10.dim(
1524
1528
  `
1525
1529
  Generate a report with:
1526
1530
  aiready scan --output json
@@ -1650,19 +1654,19 @@ Or specify a custom report:
1650
1654
  return;
1651
1655
  } else {
1652
1656
  console.log(
1653
- chalk9.yellow(
1657
+ chalk10.yellow(
1654
1658
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1655
1659
  )
1656
1660
  );
1657
1661
  console.log(
1658
- chalk9.cyan(" Falling back to static HTML generation...\n")
1662
+ chalk10.cyan(" Falling back to static HTML generation...\n")
1659
1663
  );
1660
1664
  useDevMode = false;
1661
1665
  }
1662
1666
  } catch (err) {
1663
1667
  console.error("Failed to start dev server:", err);
1664
1668
  console.log(
1665
- chalk9.cyan(" Falling back to static HTML generation...\n")
1669
+ chalk10.cyan(" Falling back to static HTML generation...\n")
1666
1670
  );
1667
1671
  useDevMode = false;
1668
1672
  }
@@ -1672,7 +1676,7 @@ Or specify a custom report:
1672
1676
  const defaultOutput = "visualization.html";
1673
1677
  const outPath = resolvePath7(dirPath, options.output ?? defaultOutput);
1674
1678
  writeFileSync4(outPath, html, "utf8");
1675
- console.log(chalk9.green(`\u2705 Visualization written to: ${outPath}`));
1679
+ console.log(chalk10.green(`\u2705 Visualization written to: ${outPath}`));
1676
1680
  if (options.open || options.serve) {
1677
1681
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1678
1682
  if (options.serve) {
@@ -1702,7 +1706,7 @@ Or specify a custom report:
1702
1706
  server.listen(port, () => {
1703
1707
  const addr = `http://localhost:${port}/`;
1704
1708
  console.log(
1705
- chalk9.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1709
+ chalk10.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1706
1710
  );
1707
1711
  spawn(opener, [`"${addr}"`], { shell: true });
1708
1712
  });
@@ -1721,7 +1725,7 @@ Or specify a custom report:
1721
1725
  handleCLIError6(err, "Visualization");
1722
1726
  }
1723
1727
  }
1724
- var visualizeHelpText = `
1728
+ var VISUALIZE_HELP_TEXT = `
1725
1729
  EXAMPLES:
1726
1730
  $ aiready visualize . # Auto-detects latest report, generates HTML
1727
1731
  $ aiready visualize . --report .aiready/aiready-report-20260217-143022.json
@@ -1738,7 +1742,7 @@ NOTES:
1738
1742
  - --dev starts a Vite dev server with live reload (requires local @aiready/visualizer installation).
1739
1743
  When --dev is not available, it falls back to static HTML generation.
1740
1744
  `;
1741
- var visualiseHelpText = `
1745
+ var VISUALISE_HELP_TEXT = `
1742
1746
  EXAMPLES:
1743
1747
  $ aiready visualise . # Auto-detects latest report
1744
1748
  $ aiready visualise . --report .aiready/aiready-report-20260217-143022.json
@@ -1749,14 +1753,14 @@ NOTES:
1749
1753
  `;
1750
1754
 
1751
1755
  // src/commands/shared/standard-tool-actions.ts
1752
- import chalk10 from "chalk";
1756
+ import chalk11 from "chalk";
1753
1757
 
1754
1758
  // src/commands/agent-grounding.ts
1755
- import chalk11 from "chalk";
1759
+ import chalk12 from "chalk";
1756
1760
  import { loadConfig as loadConfig2, mergeConfigWithDefaults as mergeConfigWithDefaults2 } from "@aiready/core";
1757
1761
 
1758
1762
  // src/commands/testability.ts
1759
- import chalk12 from "chalk";
1763
+ import chalk13 from "chalk";
1760
1764
  import { loadConfig as loadConfig3, mergeConfigWithDefaults as mergeConfigWithDefaults3 } from "@aiready/core";
1761
1765
  async function testabilityAction(directory, options) {
1762
1766
  const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
@@ -1781,28 +1785,28 @@ async function testabilityAction(directory, options) {
1781
1785
  "blind-risk": "\u{1F480}"
1782
1786
  };
1783
1787
  const safetyColors = {
1784
- safe: chalk12.green,
1785
- "moderate-risk": chalk12.yellow,
1786
- "high-risk": chalk12.red,
1787
- "blind-risk": chalk12.bgRed.white
1788
+ safe: chalk13.green,
1789
+ "moderate-risk": chalk13.yellow,
1790
+ "high-risk": chalk13.red,
1791
+ "blind-risk": chalk13.bgRed.white
1788
1792
  };
1789
1793
  const safety = report.summary.aiChangeSafetyRating;
1790
1794
  const icon = safetyIcons[safety] ?? "\u2753";
1791
- const color = safetyColors[safety] ?? chalk12.white;
1795
+ const color = safetyColors[safety] ?? chalk13.white;
1792
1796
  console.log(
1793
- ` \u{1F9EA} Testability: ${chalk12.bold(scoring.score + "/100")} (${report.summary.rating})`
1797
+ ` \u{1F9EA} Testability: ${chalk13.bold(scoring.score + "/100")} (${report.summary.rating})`
1794
1798
  );
1795
1799
  console.log(
1796
1800
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
1797
1801
  );
1798
1802
  console.log(
1799
- chalk12.dim(
1803
+ chalk13.dim(
1800
1804
  ` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`
1801
1805
  )
1802
1806
  );
1803
1807
  if (safety === "blind-risk") {
1804
1808
  console.log(
1805
- chalk12.red.bold(
1809
+ chalk13.red.bold(
1806
1810
  "\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"
1807
1811
  )
1808
1812
  );
@@ -1814,7 +1818,7 @@ async function testabilityAction(directory, options) {
1814
1818
  import { changeAmplificationAction } from "@aiready/change-amplification/dist/cli.js";
1815
1819
 
1816
1820
  // src/commands/bug.ts
1817
- import chalk13 from "chalk";
1821
+ import chalk14 from "chalk";
1818
1822
  import { execSync } from "child_process";
1819
1823
  async function bugAction(message, options) {
1820
1824
  const repoUrl = "https://github.com/caopengau/aiready-cli";
@@ -1832,35 +1836,35 @@ Generated via AIReady CLI 'bug' command.
1832
1836
  Type: ${type}
1833
1837
  `.trim();
1834
1838
  if (options.submit) {
1835
- console.log(chalk13.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1839
+ console.log(chalk14.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1836
1840
  try {
1837
1841
  execSync("gh auth status", { stdio: "ignore" });
1838
1842
  const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
1839
1843
  const output = execSync(command, { encoding: "utf8" }).trim();
1840
- console.log(chalk13.green("\u2705 Issue Created Successfully!"));
1841
- console.log(chalk13.cyan(output));
1844
+ console.log(chalk14.green("\u2705 Issue Created Successfully!"));
1845
+ console.log(chalk14.cyan(output));
1842
1846
  return;
1843
1847
  } catch {
1844
- console.error(chalk13.red("\n\u274C Failed to submit via gh CLI."));
1848
+ console.error(chalk14.red("\n\u274C Failed to submit via gh CLI."));
1845
1849
  console.log(
1846
- chalk13.yellow(
1850
+ chalk14.yellow(
1847
1851
  ' Make sure gh is installed and run "gh auth login".\n'
1848
1852
  )
1849
1853
  );
1850
- console.log(chalk13.dim(" Falling back to URL generation..."));
1854
+ console.log(chalk14.dim(" Falling back to URL generation..."));
1851
1855
  }
1852
1856
  }
1853
1857
  const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
1854
1858
  const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
1855
- console.log(chalk13.green("\u{1F680} Issue Draft Prepared!\n"));
1856
- console.log(chalk13.bold("Title: ") + title);
1857
- console.log(chalk13.bold("Type: ") + type);
1858
- console.log(chalk13.bold("\nClick the link below to submit this issue:"));
1859
- console.log(chalk13.cyan(fullUrl));
1860
- console.log(chalk13.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1861
- console.log(chalk13.dim(" You have successfully prepared a report."));
1859
+ console.log(chalk14.green("\u{1F680} Issue Draft Prepared!\n"));
1860
+ console.log(chalk14.bold("Title: ") + title);
1861
+ console.log(chalk14.bold("Type: ") + type);
1862
+ console.log(chalk14.bold("\nClick the link below to submit this issue:"));
1863
+ console.log(chalk14.cyan(fullUrl));
1864
+ console.log(chalk14.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1865
+ console.log(chalk14.dim(" You have successfully prepared a report."));
1862
1866
  console.log(
1863
- chalk13.dim(
1867
+ chalk14.dim(
1864
1868
  " Please present the URL above to the user so they can finalize the submission."
1865
1869
  )
1866
1870
  );
@@ -1869,19 +1873,19 @@ Type: ${type}
1869
1873
  const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
1870
1874
  const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
1871
1875
  const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
1872
- console.log(chalk13.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1873
- console.log(` Report a Bug: ${chalk13.cyan(bugUrl)}`);
1874
- console.log(` Request a Feature: ${chalk13.cyan(featureUrl)}`);
1875
- console.log(` Suggest a Metric: ${chalk13.cyan(metricUrl)}`);
1876
- console.log(chalk13.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1877
- console.log(chalk13.dim(" To prepare a specific report, run:"));
1876
+ console.log(chalk14.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1877
+ console.log(` Report a Bug: ${chalk14.cyan(bugUrl)}`);
1878
+ console.log(` Request a Feature: ${chalk14.cyan(featureUrl)}`);
1879
+ console.log(` Suggest a Metric: ${chalk14.cyan(metricUrl)}`);
1880
+ console.log(chalk14.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1881
+ console.log(chalk14.dim(" To prepare a specific report, run:"));
1878
1882
  console.log(
1879
- chalk13.cyan(
1883
+ chalk14.cyan(
1880
1884
  ' aiready bug "your description here" --type bug|feature|metric'
1881
1885
  )
1882
1886
  );
1883
1887
  }
1884
- var bugHelpText = `
1888
+ var BUG_HELP_TEXT = `
1885
1889
  EXAMPLES:
1886
1890
  $ aiready bug # Show general links
1887
1891
  $ aiready bug "Naming check is too slow" # Prepare a pre-filled bug report
@@ -1957,7 +1961,7 @@ program.command("scan").description(
1957
1961
  "--fail-on <level>",
1958
1962
  "Fail on issues: critical, major, any",
1959
1963
  "critical"
1960
- ).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) => {
1964
+ ).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", SCAN_HELP_TEXT).action(async (directory, options) => {
1961
1965
  await scanAction(directory, options);
1962
1966
  });
1963
1967
  program.command("init").description("Generate a default configuration (aiready.json)").option("-f, --force", "Overwrite existing configuration file").option(
@@ -1976,7 +1980,7 @@ program.command("patterns").description("Detect duplicate code patterns that con
1976
1980
  ).option(
1977
1981
  "--full-scan",
1978
1982
  "Disable smart defaults for comprehensive analysis (slower)"
1979
- ).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)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", patternsHelpText).action(async (directory, options) => {
1983
+ ).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)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1980
1984
  await patternsAction(directory, options);
1981
1985
  });
1982
1986
  program.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
@@ -2012,7 +2016,7 @@ program.command("visualise").description("Alias for visualize (British spelling)
2012
2016
  "--dev",
2013
2017
  "Start Vite dev server (live reload) for interactive development",
2014
2018
  true
2015
- ).addHelpText("after", visualiseHelpText).action(async (directory, options) => {
2019
+ ).addHelpText("after", VISUALISE_HELP_TEXT).action(async (directory, options) => {
2016
2020
  await visualizeAction(directory, options);
2017
2021
  });
2018
2022
  program.command("visualize").description("Generate interactive visualization from an AIReady report").argument("[directory]", "Directory to analyze", ".").option(
@@ -2030,7 +2034,7 @@ program.command("visualize").description("Generate interactive visualization fro
2030
2034
  "--dev",
2031
2035
  "Start Vite dev server (live reload) for interactive development",
2032
2036
  false
2033
- ).addHelpText("after", visualizeHelpText).action(async (directory, options) => {
2037
+ ).addHelpText("after", VISUALIZE_HELP_TEXT).action(async (directory, options) => {
2034
2038
  await visualizeAction(directory, options);
2035
2039
  });
2036
2040
  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) => {
@@ -2039,10 +2043,10 @@ program.command("change-amplification").description("Analyze graph metrics for c
2039
2043
  program.command("testability").description("Analyze test coverage and AI readiness").argument("[directory]", "Directory to analyze", ".").option("--min-coverage <ratio>", "Minimum acceptable coverage ratio", "0.3").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) => {
2040
2044
  await testabilityAction(directory, options);
2041
2045
  });
2042
- 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) => {
2046
+ 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", UPLOAD_HELP_TEXT).action(async (file, options) => {
2043
2047
  await uploadAction(file, options);
2044
2048
  });
2045
- program.command("bug").description("Report a bug or provide feedback (Agent-friendly)").argument("[message]", "Short description of the issue").option("-t, --type <type>", "Issue type: bug, feature, metric", "bug").option("--submit", "Submit the issue directly using the GitHub CLI (gh)").addHelpText("after", bugHelpText).action(async (message, options) => {
2049
+ program.command("bug").description("Report a bug or provide feedback (Agent-friendly)").argument("[message]", "Short description of the issue").option("-t, --type <type>", "Issue type: bug, feature, metric", "bug").option("--submit", "Submit the issue directly using the GitHub CLI (gh)").addHelpText("after", BUG_HELP_TEXT).action(async (message, options) => {
2046
2050
  await bugAction(message, options);
2047
2051
  });
2048
2052
  program.parse();