@aiready/cli 0.13.7 → 0.14.0

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.mjs CHANGED
@@ -8,7 +8,7 @@ import {
8
8
  // src/cli.ts
9
9
  import { Command } from "commander";
10
10
  import { readFileSync as readFileSync4 } from "fs";
11
- import { join, dirname } from "path";
11
+ import { join as join2, dirname } from "path";
12
12
  import { fileURLToPath } from "url";
13
13
 
14
14
  // src/commands/scan.ts
@@ -643,8 +643,103 @@ async function scanAction(directory, options) {
643
643
  }
644
644
  var scanHelpText = `...`;
645
645
 
646
- // src/commands/patterns.ts
646
+ // src/commands/init.ts
647
+ import { writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
648
+ import { join } from "path";
647
649
  import chalk4 from "chalk";
650
+ import { ToolName as ToolName2 } from "@aiready/core";
651
+ async function initAction(options) {
652
+ const fileExt = options.format === "js" ? "js" : "json";
653
+ const fileName = fileExt === "js" ? "aiready.config.js" : "aiready.json";
654
+ const filePath = join(process.cwd(), fileName);
655
+ if (existsSync2(filePath) && !options.force) {
656
+ console.error(
657
+ chalk4.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
658
+ );
659
+ process.exit(1);
660
+ }
661
+ const defaultConfig = {
662
+ scan: {
663
+ include: [
664
+ "src/**/*.ts",
665
+ "src/**/*.js",
666
+ "lib/**/*.ts",
667
+ "packages/*/src/**/*.ts"
668
+ ],
669
+ exclude: [
670
+ "**/node_modules/**",
671
+ "**/dist/**",
672
+ "**/build/**",
673
+ "**/*.test.ts",
674
+ "**/*.spec.ts"
675
+ ],
676
+ tools: [
677
+ ToolName2.PatternDetect,
678
+ ToolName2.ContextAnalyzer,
679
+ ToolName2.NamingConsistency,
680
+ ToolName2.AiSignalClarity,
681
+ ToolName2.AgentGrounding,
682
+ ToolName2.TestabilityIndex,
683
+ ToolName2.DocDrift,
684
+ ToolName2.DependencyHealth,
685
+ ToolName2.ChangeAmplification
686
+ ]
687
+ },
688
+ tools: {
689
+ [ToolName2.PatternDetect]: {
690
+ minSimilarity: 0.8,
691
+ minLines: 5
692
+ },
693
+ [ToolName2.ContextAnalyzer]: {
694
+ maxContextBudget: 128e3,
695
+ minCohesion: 0.6
696
+ },
697
+ [ToolName2.NamingConsistency]: {
698
+ shortWords: ["id", "db", "ui", "ai"]
699
+ },
700
+ [ToolName2.AiSignalClarity]: {
701
+ checkMagicLiterals: true,
702
+ checkBooleanTraps: true,
703
+ checkAmbiguousNames: true,
704
+ checkUndocumentedExports: true
705
+ }
706
+ },
707
+ scoring: {
708
+ threshold: 70,
709
+ showBreakdown: true
710
+ }
711
+ };
712
+ let content = "";
713
+ if (fileExt === "js") {
714
+ content = `/** @type {import('@aiready/core').AIReadyConfig} */
715
+ module.exports = ${JSON.stringify(
716
+ defaultConfig,
717
+ null,
718
+ 2
719
+ )};
720
+ `;
721
+ } else {
722
+ content = JSON.stringify(defaultConfig, null, 2);
723
+ }
724
+ try {
725
+ writeFileSync2(filePath, content, "utf8");
726
+ console.log(
727
+ chalk4.green(`
728
+ \u2705 Created default configuration: ${chalk4.bold(fileName)}`)
729
+ );
730
+ console.log(
731
+ chalk4.cyan("You can now fine-tune your settings and run AIReady with:")
732
+ );
733
+ console.log(chalk4.white(` $ aiready scan
734
+ `));
735
+ } catch (error) {
736
+ console.error(chalk4.red(`Failed to write configuration file: ${error}`));
737
+ process.exit(1);
738
+ }
739
+ }
740
+
741
+ // src/commands/patterns.ts
742
+ import chalk5 from "chalk";
648
743
  import { resolve as resolvePath4 } from "path";
649
744
  import {
650
745
  loadMergedConfig as loadMergedConfig2,
@@ -655,7 +750,7 @@ import {
655
750
  formatToolScore as formatToolScore2
656
751
  } from "@aiready/core";
657
752
  async function patternsAction(directory, options) {
658
- console.log(chalk4.blue("\u{1F50D} Analyzing patterns...\n"));
753
+ console.log(chalk5.blue("\u{1F50D} Analyzing patterns...\n"));
659
754
  const startTime = Date.now();
660
755
  const resolvedDir = resolvePath4(process.cwd(), directory || ".");
661
756
  try {
@@ -721,38 +816,38 @@ async function patternsAction(directory, options) {
721
816
  const terminalWidth = process.stdout.columns || 80;
722
817
  const dividerWidth = Math.min(60, terminalWidth - 2);
723
818
  const divider = "\u2501".repeat(dividerWidth);
724
- console.log(chalk4.cyan(divider));
725
- console.log(chalk4.bold.white(" PATTERN ANALYSIS SUMMARY"));
726
- console.log(chalk4.cyan(divider) + "\n");
819
+ console.log(chalk5.cyan(divider));
820
+ console.log(chalk5.bold.white(" PATTERN ANALYSIS SUMMARY"));
821
+ console.log(chalk5.cyan(divider) + "\n");
727
822
  console.log(
728
- chalk4.white(`\u{1F4C1} Files analyzed: ${chalk4.bold(results.length)}`)
823
+ chalk5.white(`\u{1F4C1} Files analyzed: ${chalk5.bold(results.length)}`)
729
824
  );
730
825
  console.log(
731
- chalk4.yellow(
732
- `\u26A0 Duplicate patterns found: ${chalk4.bold(summary.totalPatterns)}`
826
+ chalk5.yellow(
827
+ `\u26A0 Duplicate patterns found: ${chalk5.bold(summary.totalPatterns)}`
733
828
  )
734
829
  );
735
830
  console.log(
736
- chalk4.red(
737
- `\u{1F4B0} Token cost (wasted): ${chalk4.bold(summary.totalTokenCost.toLocaleString())}`
831
+ chalk5.red(
832
+ `\u{1F4B0} Token cost (wasted): ${chalk5.bold(summary.totalTokenCost.toLocaleString())}`
738
833
  )
739
834
  );
740
835
  console.log(
741
- chalk4.gray(`\u23F1 Analysis time: ${chalk4.bold(elapsedTime + "s")}`)
836
+ chalk5.gray(`\u23F1 Analysis time: ${chalk5.bold(elapsedTime + "s")}`)
742
837
  );
743
838
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
744
839
  if (sortedTypes.length > 0) {
745
- console.log(chalk4.cyan("\n" + divider));
746
- console.log(chalk4.bold.white(" PATTERNS BY TYPE"));
747
- console.log(chalk4.cyan(divider) + "\n");
840
+ console.log(chalk5.cyan("\n" + divider));
841
+ console.log(chalk5.bold.white(" PATTERNS BY TYPE"));
842
+ console.log(chalk5.cyan(divider) + "\n");
748
843
  sortedTypes.forEach(([type, count]) => {
749
- console.log(` ${chalk4.white(type.padEnd(15))} ${chalk4.bold(count)}`);
844
+ console.log(` ${chalk5.white(type.padEnd(15))} ${chalk5.bold(count)}`);
750
845
  });
751
846
  }
752
847
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
753
- console.log(chalk4.cyan("\n" + divider));
754
- console.log(chalk4.bold.white(" TOP DUPLICATE PATTERNS"));
755
- console.log(chalk4.cyan(divider) + "\n");
848
+ console.log(chalk5.cyan("\n" + divider));
849
+ console.log(chalk5.bold.white(" TOP DUPLICATE PATTERNS"));
850
+ console.log(chalk5.cyan(divider) + "\n");
756
851
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
757
852
  topDuplicates.forEach((dup) => {
758
853
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -760,25 +855,25 @@ async function patternsAction(directory, options) {
760
855
  const file1Name = dup.file1.split("/").pop() || dup.file1;
761
856
  const file2Name = dup.file2.split("/").pop() || dup.file2;
762
857
  console.log(
763
- `${severityIcon} ${severity}: ${chalk4.bold(file1Name)} \u2194 ${chalk4.bold(file2Name)}`
858
+ `${severityIcon} ${severity}: ${chalk5.bold(file1Name)} \u2194 ${chalk5.bold(file2Name)}`
764
859
  );
765
860
  console.log(
766
- ` Similarity: ${chalk4.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${chalk4.bold(dup.tokenCost.toLocaleString())} tokens each`
861
+ ` Similarity: ${chalk5.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${chalk5.bold(dup.tokenCost.toLocaleString())} tokens each`
767
862
  );
768
863
  console.log(
769
- ` Lines: ${chalk4.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${chalk4.cyan(dup.line2 + "-" + dup.endLine2)}
864
+ ` Lines: ${chalk5.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${chalk5.cyan(dup.line2 + "-" + dup.endLine2)}
770
865
  `
771
866
  );
772
867
  });
773
868
  } else {
774
869
  console.log(
775
- chalk4.green("\n\u2728 Great! No duplicate patterns detected.\n")
870
+ chalk5.green("\n\u2728 Great! No duplicate patterns detected.\n")
776
871
  );
777
872
  }
778
873
  if (patternScore) {
779
- console.log(chalk4.cyan(divider));
780
- console.log(chalk4.bold.white(" AI READINESS SCORE (Patterns)"));
781
- console.log(chalk4.cyan(divider) + "\n");
874
+ console.log(chalk5.cyan(divider));
875
+ console.log(chalk5.bold.white(" AI READINESS SCORE (Patterns)"));
876
+ console.log(chalk5.cyan(divider) + "\n");
782
877
  console.log(formatToolScore2(patternScore));
783
878
  console.log();
784
879
  }
@@ -795,7 +890,7 @@ EXAMPLES:
795
890
  `;
796
891
 
797
892
  // src/commands/context.ts
798
- import chalk5 from "chalk";
893
+ import chalk6 from "chalk";
799
894
  import { resolve as resolvePath5 } from "path";
800
895
  import {
801
896
  loadMergedConfig as loadMergedConfig3,
@@ -806,7 +901,7 @@ import {
806
901
  formatToolScore as formatToolScore3
807
902
  } from "@aiready/core";
808
903
  async function contextAction(directory, options) {
809
- console.log(chalk5.blue("\u{1F9E0} Analyzing context costs...\n"));
904
+ console.log(chalk6.blue("\u{1F9E0} Analyzing context costs...\n"));
810
905
  const startTime = Date.now();
811
906
  const resolvedDir = resolvePath5(process.cwd(), directory || ".");
812
907
  try {
@@ -874,85 +969,85 @@ async function contextAction(directory, options) {
874
969
  const terminalWidth = process.stdout.columns || 80;
875
970
  const dividerWidth = Math.min(60, terminalWidth - 2);
876
971
  const divider = "\u2501".repeat(dividerWidth);
877
- console.log(chalk5.cyan(divider));
878
- console.log(chalk5.bold.white(" CONTEXT ANALYSIS SUMMARY"));
879
- console.log(chalk5.cyan(divider) + "\n");
972
+ console.log(chalk6.cyan(divider));
973
+ console.log(chalk6.bold.white(" CONTEXT ANALYSIS SUMMARY"));
974
+ console.log(chalk6.cyan(divider) + "\n");
880
975
  console.log(
881
- chalk5.white(`\u{1F4C1} Files analyzed: ${chalk5.bold(summary.totalFiles)}`)
976
+ chalk6.white(`\u{1F4C1} Files analyzed: ${chalk6.bold(summary.totalFiles)}`)
882
977
  );
883
978
  console.log(
884
- chalk5.white(
885
- `\u{1F4CA} Total tokens: ${chalk5.bold(summary.totalTokens.toLocaleString())}`
979
+ chalk6.white(
980
+ `\u{1F4CA} Total tokens: ${chalk6.bold(summary.totalTokens.toLocaleString())}`
886
981
  )
887
982
  );
888
983
  console.log(
889
- chalk5.yellow(
890
- `\u{1F4B0} Avg context budget: ${chalk5.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
984
+ chalk6.yellow(
985
+ `\u{1F4B0} Avg context budget: ${chalk6.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
891
986
  )
892
987
  );
893
988
  console.log(
894
- chalk5.white(`\u23F1 Analysis time: ${chalk5.bold(elapsedTime + "s")}
989
+ chalk6.white(`\u23F1 Analysis time: ${chalk6.bold(elapsedTime + "s")}
895
990
  `)
896
991
  );
897
992
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
898
993
  if (totalIssues > 0) {
899
- console.log(chalk5.bold("\u26A0\uFE0F Issues Found:\n"));
994
+ console.log(chalk6.bold("\u26A0\uFE0F Issues Found:\n"));
900
995
  if (summary.criticalIssues > 0) {
901
996
  console.log(
902
- chalk5.red(` \u{1F534} Critical: ${chalk5.bold(summary.criticalIssues)}`)
997
+ chalk6.red(` \u{1F534} Critical: ${chalk6.bold(summary.criticalIssues)}`)
903
998
  );
904
999
  }
905
1000
  if (summary.majorIssues > 0) {
906
1001
  console.log(
907
- chalk5.yellow(` \u{1F7E1} Major: ${chalk5.bold(summary.majorIssues)}`)
1002
+ chalk6.yellow(` \u{1F7E1} Major: ${chalk6.bold(summary.majorIssues)}`)
908
1003
  );
909
1004
  }
910
1005
  if (summary.minorIssues > 0) {
911
1006
  console.log(
912
- chalk5.blue(` \u{1F535} Minor: ${chalk5.bold(summary.minorIssues)}`)
1007
+ chalk6.blue(` \u{1F535} Minor: ${chalk6.bold(summary.minorIssues)}`)
913
1008
  );
914
1009
  }
915
1010
  console.log(
916
- chalk5.green(
1011
+ chalk6.green(
917
1012
  `
918
- \u{1F4A1} Potential savings: ${chalk5.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1013
+ \u{1F4A1} Potential savings: ${chalk6.bold(summary.totalPotentialSavings.toLocaleString())} tokens
919
1014
  `
920
1015
  )
921
1016
  );
922
1017
  } else {
923
- console.log(chalk5.green("\u2705 No significant issues found!\n"));
1018
+ console.log(chalk6.green("\u2705 No significant issues found!\n"));
924
1019
  }
925
1020
  if (summary.deepFiles.length > 0) {
926
- console.log(chalk5.bold("\u{1F4CF} Deep Import Chains:\n"));
1021
+ console.log(chalk6.bold("\u{1F4CF} Deep Import Chains:\n"));
927
1022
  console.log(
928
- chalk5.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1023
+ chalk6.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
929
1024
  );
930
1025
  console.log(
931
- chalk5.gray(` Maximum depth: ${summary.maxImportDepth}
1026
+ chalk6.gray(` Maximum depth: ${summary.maxImportDepth}
932
1027
  `)
933
1028
  );
934
1029
  summary.deepFiles.slice(0, 10).forEach((item) => {
935
1030
  const fileName = item.file.split("/").slice(-2).join("/");
936
1031
  console.log(
937
- ` ${chalk5.cyan("\u2192")} ${chalk5.white(fileName)} ${chalk5.dim(`(depth: ${item.depth})`)}`
1032
+ ` ${chalk6.cyan("\u2192")} ${chalk6.white(fileName)} ${chalk6.dim(`(depth: ${item.depth})`)}`
938
1033
  );
939
1034
  });
940
1035
  console.log();
941
1036
  }
942
1037
  if (summary.fragmentedModules.length > 0) {
943
- console.log(chalk5.bold("\u{1F9E9} Fragmented Modules:\n"));
1038
+ console.log(chalk6.bold("\u{1F9E9} Fragmented Modules:\n"));
944
1039
  console.log(
945
- chalk5.gray(
1040
+ chalk6.gray(
946
1041
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
947
1042
  `
948
1043
  )
949
1044
  );
950
1045
  summary.fragmentedModules.slice(0, 10).forEach((module) => {
951
1046
  console.log(
952
- ` ${chalk5.yellow("\u25CF")} ${chalk5.white(module.domain)} - ${chalk5.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1047
+ ` ${chalk6.yellow("\u25CF")} ${chalk6.white(module.domain)} - ${chalk6.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
953
1048
  );
954
1049
  console.log(
955
- chalk5.dim(
1050
+ chalk6.dim(
956
1051
  ` Token cost: ${module.totalTokens.toLocaleString()}, Cohesion: ${(module.avgCohesion * 100).toFixed(0)}%`
957
1052
  )
958
1053
  );
@@ -960,9 +1055,9 @@ async function contextAction(directory, options) {
960
1055
  console.log();
961
1056
  }
962
1057
  if (summary.lowCohesionFiles.length > 0) {
963
- console.log(chalk5.bold("\u{1F500} Low Cohesion Files:\n"));
1058
+ console.log(chalk6.bold("\u{1F500} Low Cohesion Files:\n"));
964
1059
  console.log(
965
- chalk5.gray(
1060
+ chalk6.gray(
966
1061
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
967
1062
  `
968
1063
  )
@@ -970,28 +1065,28 @@ async function contextAction(directory, options) {
970
1065
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
971
1066
  const fileName = item.file.split("/").slice(-2).join("/");
972
1067
  const scorePercent = (item.score * 100).toFixed(0);
973
- const color = item.score < 0.4 ? chalk5.red : chalk5.yellow;
1068
+ const color = item.score < 0.4 ? chalk6.red : chalk6.yellow;
974
1069
  console.log(
975
- ` ${color("\u25CB")} ${chalk5.white(fileName)} ${chalk5.dim(`(${scorePercent}% cohesion)`)}`
1070
+ ` ${color("\u25CB")} ${chalk6.white(fileName)} ${chalk6.dim(`(${scorePercent}% cohesion)`)}`
976
1071
  );
977
1072
  });
978
1073
  console.log();
979
1074
  }
980
1075
  if (summary.topExpensiveFiles.length > 0) {
981
- console.log(chalk5.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1076
+ console.log(chalk6.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
982
1077
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
983
1078
  const fileName = item.file.split("/").slice(-2).join("/");
984
- const severityColor = item.severity === "critical" ? chalk5.red : item.severity === "major" ? chalk5.yellow : chalk5.blue;
1079
+ const severityColor = item.severity === "critical" ? chalk6.red : item.severity === "major" ? chalk6.yellow : chalk6.blue;
985
1080
  console.log(
986
- ` ${severityColor("\u25CF")} ${chalk5.white(fileName)} ${chalk5.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1081
+ ` ${severityColor("\u25CF")} ${chalk6.white(fileName)} ${chalk6.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
987
1082
  );
988
1083
  });
989
1084
  console.log();
990
1085
  }
991
1086
  if (contextScore) {
992
- console.log(chalk5.cyan(divider));
993
- console.log(chalk5.bold.white(" AI READINESS SCORE (Context)"));
994
- console.log(chalk5.cyan(divider) + "\n");
1087
+ console.log(chalk6.cyan(divider));
1088
+ console.log(chalk6.bold.white(" AI READINESS SCORE (Context)"));
1089
+ console.log(chalk6.cyan(divider) + "\n");
995
1090
  console.log(formatToolScore3(contextScore));
996
1091
  console.log();
997
1092
  }
@@ -1002,8 +1097,8 @@ async function contextAction(directory, options) {
1002
1097
  }
1003
1098
 
1004
1099
  // src/commands/consistency.ts
1005
- import chalk6 from "chalk";
1006
- import { writeFileSync as writeFileSync2 } from "fs";
1100
+ import chalk7 from "chalk";
1101
+ import { writeFileSync as writeFileSync3 } from "fs";
1007
1102
  import { resolve as resolvePath6 } from "path";
1008
1103
  import {
1009
1104
  loadMergedConfig as loadMergedConfig4,
@@ -1014,7 +1109,7 @@ import {
1014
1109
  formatToolScore as formatToolScore4
1015
1110
  } from "@aiready/core";
1016
1111
  async function consistencyAction(directory, options) {
1017
- console.log(chalk6.blue("\u{1F50D} Analyzing consistency...\n"));
1112
+ console.log(chalk7.blue("\u{1F50D} Analyzing consistency...\n"));
1018
1113
  const startTime = Date.now();
1019
1114
  const resolvedDir = resolvePath6(process.cwd(), directory || ".");
1020
1115
  try {
@@ -1075,24 +1170,24 @@ async function consistencyAction(directory, options) {
1075
1170
  `aiready-report-${getReportTimestamp()}.md`,
1076
1171
  resolvedDir
1077
1172
  );
1078
- writeFileSync2(outputPath, markdown);
1079
- console.log(chalk6.green(`\u2705 Report saved to ${outputPath}`));
1173
+ writeFileSync3(outputPath, markdown);
1174
+ console.log(chalk7.green(`\u2705 Report saved to ${outputPath}`));
1080
1175
  } else {
1081
- console.log(chalk6.bold("\n\u{1F4CA} Summary\n"));
1176
+ console.log(chalk7.bold("\n\u{1F4CA} Summary\n"));
1082
1177
  console.log(
1083
- `Files Analyzed: ${chalk6.cyan(report.summary.filesAnalyzed)}`
1178
+ `Files Analyzed: ${chalk7.cyan(report.summary.filesAnalyzed)}`
1084
1179
  );
1085
- console.log(`Total Issues: ${chalk6.yellow(report.summary.totalIssues)}`);
1086
- console.log(` Naming: ${chalk6.yellow(report.summary.namingIssues)}`);
1087
- console.log(` Patterns: ${chalk6.yellow(report.summary.patternIssues)}`);
1180
+ console.log(`Total Issues: ${chalk7.yellow(report.summary.totalIssues)}`);
1181
+ console.log(` Naming: ${chalk7.yellow(report.summary.namingIssues)}`);
1182
+ console.log(` Patterns: ${chalk7.yellow(report.summary.patternIssues)}`);
1088
1183
  console.log(
1089
- ` Architecture: ${chalk6.yellow(report.summary.architectureIssues || 0)}`
1184
+ ` Architecture: ${chalk7.yellow(report.summary.architectureIssues || 0)}`
1090
1185
  );
1091
- console.log(`Analysis Time: ${chalk6.gray(elapsedTime + "s")}
1186
+ console.log(`Analysis Time: ${chalk7.gray(elapsedTime + "s")}
1092
1187
  `);
1093
1188
  if (report.summary.totalIssues === 0) {
1094
1189
  console.log(
1095
- chalk6.green(
1190
+ chalk7.green(
1096
1191
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1097
1192
  )
1098
1193
  );
@@ -1104,20 +1199,20 @@ async function consistencyAction(directory, options) {
1104
1199
  (r) => r.issues.some((i) => i.category === "patterns")
1105
1200
  );
1106
1201
  if (namingResults.length > 0) {
1107
- console.log(chalk6.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1202
+ console.log(chalk7.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1108
1203
  let shown = 0;
1109
1204
  for (const result of namingResults) {
1110
1205
  if (shown >= 5) break;
1111
1206
  for (const issue of result.issues) {
1112
1207
  if (shown >= 5) break;
1113
- const severityColor = issue.severity === "critical" ? chalk6.red : issue.severity === "major" ? chalk6.yellow : issue.severity === "minor" ? chalk6.blue : chalk6.gray;
1208
+ const severityColor = issue.severity === "critical" ? chalk7.red : issue.severity === "major" ? chalk7.yellow : issue.severity === "minor" ? chalk7.blue : chalk7.gray;
1114
1209
  console.log(
1115
- `${severityColor(issue.severity.toUpperCase())} ${chalk6.dim(`${issue.location.file}:${issue.location.line}`)}`
1210
+ `${severityColor(issue.severity.toUpperCase())} ${chalk7.dim(`${issue.location.file}:${issue.location.line}`)}`
1116
1211
  );
1117
1212
  console.log(` ${issue.message}`);
1118
1213
  if (issue.suggestion) {
1119
1214
  console.log(
1120
- ` ${chalk6.dim("\u2192")} ${chalk6.italic(issue.suggestion)}`
1215
+ ` ${chalk7.dim("\u2192")} ${chalk7.italic(issue.suggestion)}`
1121
1216
  );
1122
1217
  }
1123
1218
  console.log();
@@ -1126,25 +1221,25 @@ async function consistencyAction(directory, options) {
1126
1221
  }
1127
1222
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1128
1223
  if (remaining > 0) {
1129
- console.log(chalk6.dim(` ... and ${remaining} more issues
1224
+ console.log(chalk7.dim(` ... and ${remaining} more issues
1130
1225
  `));
1131
1226
  }
1132
1227
  }
1133
1228
  if (patternResults.length > 0) {
1134
- console.log(chalk6.bold("\u{1F504} Pattern Issues\n"));
1229
+ console.log(chalk7.bold("\u{1F504} Pattern Issues\n"));
1135
1230
  let shown = 0;
1136
1231
  for (const result of patternResults) {
1137
1232
  if (shown >= 5) break;
1138
1233
  for (const issue of result.issues) {
1139
1234
  if (shown >= 5) break;
1140
- const severityColor = issue.severity === "critical" ? chalk6.red : issue.severity === "major" ? chalk6.yellow : issue.severity === "minor" ? chalk6.blue : chalk6.gray;
1235
+ const severityColor = issue.severity === "critical" ? chalk7.red : issue.severity === "major" ? chalk7.yellow : issue.severity === "minor" ? chalk7.blue : chalk7.gray;
1141
1236
  console.log(
1142
- `${severityColor(issue.severity.toUpperCase())} ${chalk6.dim(`${issue.location.file}:${issue.location.line}`)}`
1237
+ `${severityColor(issue.severity.toUpperCase())} ${chalk7.dim(`${issue.location.file}:${issue.location.line}`)}`
1143
1238
  );
1144
1239
  console.log(` ${issue.message}`);
1145
1240
  if (issue.suggestion) {
1146
1241
  console.log(
1147
- ` ${chalk6.dim("\u2192")} ${chalk6.italic(issue.suggestion)}`
1242
+ ` ${chalk7.dim("\u2192")} ${chalk7.italic(issue.suggestion)}`
1148
1243
  );
1149
1244
  }
1150
1245
  console.log();
@@ -1153,12 +1248,12 @@ async function consistencyAction(directory, options) {
1153
1248
  }
1154
1249
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1155
1250
  if (remaining > 0) {
1156
- console.log(chalk6.dim(` ... and ${remaining} more issues
1251
+ console.log(chalk7.dim(` ... and ${remaining} more issues
1157
1252
  `));
1158
1253
  }
1159
1254
  }
1160
1255
  if (report.recommendations.length > 0) {
1161
- console.log(chalk6.bold("\u{1F4A1} Recommendations\n"));
1256
+ console.log(chalk7.bold("\u{1F4A1} Recommendations\n"));
1162
1257
  report.recommendations.forEach((rec, i) => {
1163
1258
  console.log(`${i + 1}. ${rec}`);
1164
1259
  });
@@ -1166,7 +1261,7 @@ async function consistencyAction(directory, options) {
1166
1261
  }
1167
1262
  }
1168
1263
  if (consistencyScore) {
1169
- console.log(chalk6.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1264
+ console.log(chalk7.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1170
1265
  console.log(formatToolScore4(consistencyScore));
1171
1266
  console.log();
1172
1267
  }
@@ -1177,8 +1272,8 @@ async function consistencyAction(directory, options) {
1177
1272
  }
1178
1273
 
1179
1274
  // src/commands/visualize.ts
1180
- import chalk7 from "chalk";
1181
- import { writeFileSync as writeFileSync3, readFileSync as readFileSync3, existsSync as existsSync2, copyFileSync } from "fs";
1275
+ import chalk8 from "chalk";
1276
+ import { writeFileSync as writeFileSync4, readFileSync as readFileSync3, existsSync as existsSync3, copyFileSync } from "fs";
1182
1277
  import { resolve as resolvePath7 } from "path";
1183
1278
  import { spawn } from "child_process";
1184
1279
  import { handleCLIError as handleCLIError6 } from "@aiready/core";
@@ -1187,17 +1282,17 @@ async function visualizeAction(directory, options) {
1187
1282
  try {
1188
1283
  const dirPath = resolvePath7(process.cwd(), directory || ".");
1189
1284
  let reportPath = options.report ? resolvePath7(dirPath, options.report) : null;
1190
- if (!reportPath || !existsSync2(reportPath)) {
1285
+ if (!reportPath || !existsSync3(reportPath)) {
1191
1286
  const latestScan = findLatestScanReport(dirPath);
1192
1287
  if (latestScan) {
1193
1288
  reportPath = latestScan;
1194
1289
  console.log(
1195
- chalk7.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1290
+ chalk8.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1196
1291
  );
1197
1292
  } else {
1198
- console.error(chalk7.red("\u274C No AI readiness report found"));
1293
+ console.error(chalk8.red("\u274C No AI readiness report found"));
1199
1294
  console.log(
1200
- chalk7.dim(
1295
+ chalk8.dim(
1201
1296
  `
1202
1297
  Generate a report with:
1203
1298
  aiready scan --output json
@@ -1213,7 +1308,7 @@ Or specify a custom report:
1213
1308
  const report = JSON.parse(raw);
1214
1309
  const configPath = resolvePath7(dirPath, "aiready.json");
1215
1310
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1216
- if (existsSync2(configPath)) {
1311
+ if (existsSync3(configPath)) {
1217
1312
  try {
1218
1313
  const rawConfig = JSON.parse(readFileSync3(configPath, "utf8"));
1219
1314
  if (rawConfig.visualizer?.graph) {
@@ -1238,7 +1333,7 @@ Or specify a custom report:
1238
1333
  const localWebDir = resolvePath7(dirPath, "packages/visualizer");
1239
1334
  let webDir = "";
1240
1335
  let visualizerAvailable = false;
1241
- if (existsSync2(localWebDir)) {
1336
+ if (existsSync3(localWebDir)) {
1242
1337
  webDir = localWebDir;
1243
1338
  visualizerAvailable = true;
1244
1339
  } else {
@@ -1261,7 +1356,7 @@ Or specify a custom report:
1261
1356
  currentDir = parent;
1262
1357
  }
1263
1358
  for (const location of nodemodulesLocations) {
1264
- if (existsSync2(location) && existsSync2(resolvePath7(location, "package.json"))) {
1359
+ if (existsSync3(location) && existsSync3(resolvePath7(location, "package.json"))) {
1265
1360
  webDir = location;
1266
1361
  visualizerAvailable = true;
1267
1362
  break;
@@ -1277,7 +1372,7 @@ Or specify a custom report:
1277
1372
  }
1278
1373
  }
1279
1374
  }
1280
- const webViteConfigExists = webDir && existsSync2(resolvePath7(webDir, "web", "vite.config.ts"));
1375
+ const webViteConfigExists = webDir && existsSync3(resolvePath7(webDir, "web", "vite.config.ts"));
1281
1376
  if (visualizerAvailable && webViteConfigExists) {
1282
1377
  const spawnCwd = webDir;
1283
1378
  const { watch } = await import("fs");
@@ -1327,19 +1422,19 @@ Or specify a custom report:
1327
1422
  return;
1328
1423
  } else {
1329
1424
  console.log(
1330
- chalk7.yellow(
1425
+ chalk8.yellow(
1331
1426
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1332
1427
  )
1333
1428
  );
1334
1429
  console.log(
1335
- chalk7.cyan(" Falling back to static HTML generation...\n")
1430
+ chalk8.cyan(" Falling back to static HTML generation...\n")
1336
1431
  );
1337
1432
  useDevMode = false;
1338
1433
  }
1339
1434
  } catch (err) {
1340
1435
  console.error("Failed to start dev server:", err);
1341
1436
  console.log(
1342
- chalk7.cyan(" Falling back to static HTML generation...\n")
1437
+ chalk8.cyan(" Falling back to static HTML generation...\n")
1343
1438
  );
1344
1439
  useDevMode = false;
1345
1440
  }
@@ -1348,8 +1443,8 @@ Or specify a custom report:
1348
1443
  const html = generateHTML(graph);
1349
1444
  const defaultOutput = "visualization.html";
1350
1445
  const outPath = resolvePath7(dirPath, options.output || defaultOutput);
1351
- writeFileSync3(outPath, html, "utf8");
1352
- console.log(chalk7.green(`\u2705 Visualization written to: ${outPath}`));
1446
+ writeFileSync4(outPath, html, "utf8");
1447
+ console.log(chalk8.green(`\u2705 Visualization written to: ${outPath}`));
1353
1448
  if (options.open || options.serve) {
1354
1449
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1355
1450
  if (options.serve) {
@@ -1379,7 +1474,7 @@ Or specify a custom report:
1379
1474
  server.listen(port, () => {
1380
1475
  const addr = `http://localhost:${port}/`;
1381
1476
  console.log(
1382
- chalk7.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1477
+ chalk8.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1383
1478
  );
1384
1479
  spawn(opener, [`"${addr}"`], { shell: true });
1385
1480
  });
@@ -1426,15 +1521,15 @@ NOTES:
1426
1521
  `;
1427
1522
 
1428
1523
  // src/commands/ai-signal-clarity.ts
1429
- import chalk8 from "chalk";
1524
+ import chalk9 from "chalk";
1430
1525
  import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
1431
1526
 
1432
1527
  // src/commands/agent-grounding.ts
1433
- import chalk9 from "chalk";
1528
+ import chalk10 from "chalk";
1434
1529
  import { loadConfig as loadConfig2, mergeConfigWithDefaults as mergeConfigWithDefaults2 } from "@aiready/core";
1435
1530
 
1436
1531
  // src/commands/testability.ts
1437
- import chalk10 from "chalk";
1532
+ import chalk11 from "chalk";
1438
1533
  import { loadConfig as loadConfig3, mergeConfigWithDefaults as mergeConfigWithDefaults3 } from "@aiready/core";
1439
1534
  async function testabilityAction(directory, options) {
1440
1535
  const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
@@ -1459,28 +1554,28 @@ async function testabilityAction(directory, options) {
1459
1554
  "blind-risk": "\u{1F480}"
1460
1555
  };
1461
1556
  const safetyColors = {
1462
- safe: chalk10.green,
1463
- "moderate-risk": chalk10.yellow,
1464
- "high-risk": chalk10.red,
1465
- "blind-risk": chalk10.bgRed.white
1557
+ safe: chalk11.green,
1558
+ "moderate-risk": chalk11.yellow,
1559
+ "high-risk": chalk11.red,
1560
+ "blind-risk": chalk11.bgRed.white
1466
1561
  };
1467
1562
  const safety = report.summary.aiChangeSafetyRating;
1468
1563
  const icon = safetyIcons[safety] ?? "\u2753";
1469
- const color = safetyColors[safety] ?? chalk10.white;
1564
+ const color = safetyColors[safety] ?? chalk11.white;
1470
1565
  console.log(
1471
- ` \u{1F9EA} Testability: ${chalk10.bold(scoring.score + "/100")} (${report.summary.rating})`
1566
+ ` \u{1F9EA} Testability: ${chalk11.bold(scoring.score + "/100")} (${report.summary.rating})`
1472
1567
  );
1473
1568
  console.log(
1474
1569
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
1475
1570
  );
1476
1571
  console.log(
1477
- chalk10.dim(
1572
+ chalk11.dim(
1478
1573
  ` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`
1479
1574
  )
1480
1575
  );
1481
1576
  if (safety === "blind-risk") {
1482
1577
  console.log(
1483
- chalk10.red.bold(
1578
+ chalk11.red.bold(
1484
1579
  "\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"
1485
1580
  )
1486
1581
  );
@@ -1492,7 +1587,7 @@ async function testabilityAction(directory, options) {
1492
1587
  import { changeAmplificationAction } from "@aiready/change-amplification/dist/cli.js";
1493
1588
 
1494
1589
  // src/commands/bug.ts
1495
- import chalk11 from "chalk";
1590
+ import chalk12 from "chalk";
1496
1591
  import { execSync } from "child_process";
1497
1592
  async function bugAction(message, options) {
1498
1593
  const repoUrl = "https://github.com/caopengau/aiready-cli";
@@ -1510,35 +1605,35 @@ Generated via AIReady CLI 'bug' command.
1510
1605
  Type: ${type}
1511
1606
  `.trim();
1512
1607
  if (options.submit) {
1513
- console.log(chalk11.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1608
+ console.log(chalk12.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1514
1609
  try {
1515
1610
  execSync("gh auth status", { stdio: "ignore" });
1516
1611
  const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
1517
1612
  const output = execSync(command, { encoding: "utf8" }).trim();
1518
- console.log(chalk11.green("\u2705 Issue Created Successfully!"));
1519
- console.log(chalk11.cyan(output));
1613
+ console.log(chalk12.green("\u2705 Issue Created Successfully!"));
1614
+ console.log(chalk12.cyan(output));
1520
1615
  return;
1521
1616
  } catch (error) {
1522
- console.error(chalk11.red("\n\u274C Failed to submit via gh CLI."));
1617
+ console.error(chalk12.red("\n\u274C Failed to submit via gh CLI."));
1523
1618
  console.log(
1524
- chalk11.yellow(
1619
+ chalk12.yellow(
1525
1620
  ' Make sure gh is installed and run "gh auth login".\n'
1526
1621
  )
1527
1622
  );
1528
- console.log(chalk11.dim(" Falling back to URL generation..."));
1623
+ console.log(chalk12.dim(" Falling back to URL generation..."));
1529
1624
  }
1530
1625
  }
1531
1626
  const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
1532
1627
  const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
1533
- console.log(chalk11.green("\u{1F680} Issue Draft Prepared!\n"));
1534
- console.log(chalk11.bold("Title: ") + title);
1535
- console.log(chalk11.bold("Type: ") + type);
1536
- console.log(chalk11.bold("\nClick the link below to submit this issue:"));
1537
- console.log(chalk11.cyan(fullUrl));
1538
- console.log(chalk11.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1539
- console.log(chalk11.dim(" You have successfully prepared a report."));
1628
+ console.log(chalk12.green("\u{1F680} Issue Draft Prepared!\n"));
1629
+ console.log(chalk12.bold("Title: ") + title);
1630
+ console.log(chalk12.bold("Type: ") + type);
1631
+ console.log(chalk12.bold("\nClick the link below to submit this issue:"));
1632
+ console.log(chalk12.cyan(fullUrl));
1633
+ console.log(chalk12.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1634
+ console.log(chalk12.dim(" You have successfully prepared a report."));
1540
1635
  console.log(
1541
- chalk11.dim(
1636
+ chalk12.dim(
1542
1637
  " Please present the URL above to the user so they can finalize the submission."
1543
1638
  )
1544
1639
  );
@@ -1547,14 +1642,14 @@ Type: ${type}
1547
1642
  const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
1548
1643
  const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
1549
1644
  const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
1550
- console.log(chalk11.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1551
- console.log(` Report a Bug: ${chalk11.cyan(bugUrl)}`);
1552
- console.log(` Request a Feature: ${chalk11.cyan(featureUrl)}`);
1553
- console.log(` Suggest a Metric: ${chalk11.cyan(metricUrl)}`);
1554
- console.log(chalk11.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1555
- console.log(chalk11.dim(" To prepare a specific report, run:"));
1645
+ console.log(chalk12.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1646
+ console.log(` Report a Bug: ${chalk12.cyan(bugUrl)}`);
1647
+ console.log(` Request a Feature: ${chalk12.cyan(featureUrl)}`);
1648
+ console.log(` Suggest a Metric: ${chalk12.cyan(metricUrl)}`);
1649
+ console.log(chalk12.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1650
+ console.log(chalk12.dim(" To prepare a specific report, run:"));
1556
1651
  console.log(
1557
- chalk11.cyan(
1652
+ chalk12.cyan(
1558
1653
  ' aiready bug "your description here" --type bug|feature|metric'
1559
1654
  )
1560
1655
  );
@@ -1573,7 +1668,7 @@ var getDirname = () => {
1573
1668
  return dirname(fileURLToPath(import.meta.url));
1574
1669
  };
1575
1670
  var packageJson = JSON.parse(
1576
- readFileSync4(join(getDirname(), "../package.json"), "utf8")
1671
+ readFileSync4(join2(getDirname(), "../package.json"), "utf8")
1577
1672
  );
1578
1673
  var program = new Command();
1579
1674
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -1636,6 +1731,13 @@ program.command("scan").description(
1636
1731
  ).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) => {
1637
1732
  await scanAction(directory, options);
1638
1733
  });
1734
+ program.command("init").description("Generate a default configuration (aiready.json)").option("-f, --force", "Overwrite existing configuration file").option(
1735
+ "--js",
1736
+ "Generate configuration as a JavaScript file (aiready.config.js)"
1737
+ ).action(async (options) => {
1738
+ const format = options.js ? "js" : "json";
1739
+ await initAction({ force: options.force, format });
1740
+ });
1639
1741
  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(
1640
1742
  "--max-candidates <number>",
1641
1743
  "Maximum candidates per block (performance tuning)"