@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.js CHANGED
@@ -25,8 +25,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_commander = require("commander");
28
- var import_fs6 = require("fs");
29
- var import_path8 = require("path");
28
+ var import_fs7 = require("fs");
29
+ var import_path9 = require("path");
30
30
  var import_url = require("url");
31
31
 
32
32
  // src/commands/scan.ts
@@ -903,14 +903,109 @@ async function scanAction(directory, options) {
903
903
  }
904
904
  var scanHelpText = `...`;
905
905
 
906
- // src/commands/patterns.ts
907
- var import_chalk4 = __toESM(require("chalk"));
906
+ // src/commands/init.ts
907
+ var import_fs4 = require("fs");
908
908
  var import_path4 = require("path");
909
+ var import_chalk4 = __toESM(require("chalk"));
909
910
  var import_core4 = require("@aiready/core");
911
+ async function initAction(options) {
912
+ const fileExt = options.format === "js" ? "js" : "json";
913
+ const fileName = fileExt === "js" ? "aiready.config.js" : "aiready.json";
914
+ const filePath = (0, import_path4.join)(process.cwd(), fileName);
915
+ if ((0, import_fs4.existsSync)(filePath) && !options.force) {
916
+ console.error(
917
+ import_chalk4.default.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
918
+ );
919
+ process.exit(1);
920
+ }
921
+ const defaultConfig = {
922
+ scan: {
923
+ include: [
924
+ "src/**/*.ts",
925
+ "src/**/*.js",
926
+ "lib/**/*.ts",
927
+ "packages/*/src/**/*.ts"
928
+ ],
929
+ exclude: [
930
+ "**/node_modules/**",
931
+ "**/dist/**",
932
+ "**/build/**",
933
+ "**/*.test.ts",
934
+ "**/*.spec.ts"
935
+ ],
936
+ tools: [
937
+ import_core4.ToolName.PatternDetect,
938
+ import_core4.ToolName.ContextAnalyzer,
939
+ import_core4.ToolName.NamingConsistency,
940
+ import_core4.ToolName.AiSignalClarity,
941
+ import_core4.ToolName.AgentGrounding,
942
+ import_core4.ToolName.TestabilityIndex,
943
+ import_core4.ToolName.DocDrift,
944
+ import_core4.ToolName.DependencyHealth,
945
+ import_core4.ToolName.ChangeAmplification
946
+ ]
947
+ },
948
+ tools: {
949
+ [import_core4.ToolName.PatternDetect]: {
950
+ minSimilarity: 0.8,
951
+ minLines: 5
952
+ },
953
+ [import_core4.ToolName.ContextAnalyzer]: {
954
+ maxContextBudget: 128e3,
955
+ minCohesion: 0.6
956
+ },
957
+ [import_core4.ToolName.NamingConsistency]: {
958
+ shortWords: ["id", "db", "ui", "ai"]
959
+ },
960
+ [import_core4.ToolName.AiSignalClarity]: {
961
+ checkMagicLiterals: true,
962
+ checkBooleanTraps: true,
963
+ checkAmbiguousNames: true,
964
+ checkUndocumentedExports: true
965
+ }
966
+ },
967
+ scoring: {
968
+ threshold: 70,
969
+ showBreakdown: true
970
+ }
971
+ };
972
+ let content = "";
973
+ if (fileExt === "js") {
974
+ content = `/** @type {import('@aiready/core').AIReadyConfig} */
975
+ module.exports = ${JSON.stringify(
976
+ defaultConfig,
977
+ null,
978
+ 2
979
+ )};
980
+ `;
981
+ } else {
982
+ content = JSON.stringify(defaultConfig, null, 2);
983
+ }
984
+ try {
985
+ (0, import_fs4.writeFileSync)(filePath, content, "utf8");
986
+ console.log(
987
+ import_chalk4.default.green(`
988
+ \u2705 Created default configuration: ${import_chalk4.default.bold(fileName)}`)
989
+ );
990
+ console.log(
991
+ import_chalk4.default.cyan("You can now fine-tune your settings and run AIReady with:")
992
+ );
993
+ console.log(import_chalk4.default.white(` $ aiready scan
994
+ `));
995
+ } catch (error) {
996
+ console.error(import_chalk4.default.red(`Failed to write configuration file: ${error}`));
997
+ process.exit(1);
998
+ }
999
+ }
1000
+
1001
+ // src/commands/patterns.ts
1002
+ var import_chalk5 = __toESM(require("chalk"));
1003
+ var import_path5 = require("path");
1004
+ var import_core5 = require("@aiready/core");
910
1005
  async function patternsAction(directory, options) {
911
- console.log(import_chalk4.default.blue("\u{1F50D} Analyzing patterns...\n"));
1006
+ console.log(import_chalk5.default.blue("\u{1F50D} Analyzing patterns...\n"));
912
1007
  const startTime = Date.now();
913
- const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
1008
+ const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
914
1009
  try {
915
1010
  const useSmartDefaults = !options.fullScan;
916
1011
  const defaults = {
@@ -939,14 +1034,14 @@ async function patternsAction(directory, options) {
939
1034
  if (options.minSharedTokens) {
940
1035
  cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
941
1036
  }
942
- const finalOptions = await (0, import_core4.loadMergedConfig)(
1037
+ const finalOptions = await (0, import_core5.loadMergedConfig)(
943
1038
  resolvedDir,
944
1039
  defaults,
945
1040
  cliOptions
946
1041
  );
947
1042
  const { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
948
1043
  const { results, duplicates } = await analyzePatterns(finalOptions);
949
- const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1044
+ const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
950
1045
  const summary = generateSummary(results);
951
1046
  let patternScore;
952
1047
  if (options.score) {
@@ -960,12 +1055,12 @@ async function patternsAction(directory, options) {
960
1055
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
961
1056
  ...patternScore && { scoring: patternScore }
962
1057
  };
963
- const outputPath = (0, import_core4.resolveOutputPath)(
1058
+ const outputPath = (0, import_core5.resolveOutputPath)(
964
1059
  userOutputFile,
965
1060
  `aiready-report-${getReportTimestamp()}.json`,
966
1061
  resolvedDir
967
1062
  );
968
- (0, import_core4.handleJSONOutput)(
1063
+ (0, import_core5.handleJSONOutput)(
969
1064
  outputData,
970
1065
  outputPath,
971
1066
  `\u2705 Results saved to ${outputPath}`
@@ -974,38 +1069,38 @@ async function patternsAction(directory, options) {
974
1069
  const terminalWidth = process.stdout.columns || 80;
975
1070
  const dividerWidth = Math.min(60, terminalWidth - 2);
976
1071
  const divider = "\u2501".repeat(dividerWidth);
977
- console.log(import_chalk4.default.cyan(divider));
978
- console.log(import_chalk4.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
979
- console.log(import_chalk4.default.cyan(divider) + "\n");
1072
+ console.log(import_chalk5.default.cyan(divider));
1073
+ console.log(import_chalk5.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1074
+ console.log(import_chalk5.default.cyan(divider) + "\n");
980
1075
  console.log(
981
- import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(results.length)}`)
1076
+ import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(results.length)}`)
982
1077
  );
983
1078
  console.log(
984
- import_chalk4.default.yellow(
985
- `\u26A0 Duplicate patterns found: ${import_chalk4.default.bold(summary.totalPatterns)}`
1079
+ import_chalk5.default.yellow(
1080
+ `\u26A0 Duplicate patterns found: ${import_chalk5.default.bold(summary.totalPatterns)}`
986
1081
  )
987
1082
  );
988
1083
  console.log(
989
- import_chalk4.default.red(
990
- `\u{1F4B0} Token cost (wasted): ${import_chalk4.default.bold(summary.totalTokenCost.toLocaleString())}`
1084
+ import_chalk5.default.red(
1085
+ `\u{1F4B0} Token cost (wasted): ${import_chalk5.default.bold(summary.totalTokenCost.toLocaleString())}`
991
1086
  )
992
1087
  );
993
1088
  console.log(
994
- import_chalk4.default.gray(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}`)
1089
+ import_chalk5.default.gray(`\u23F1 Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}`)
995
1090
  );
996
1091
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
997
1092
  if (sortedTypes.length > 0) {
998
- console.log(import_chalk4.default.cyan("\n" + divider));
999
- console.log(import_chalk4.default.bold.white(" PATTERNS BY TYPE"));
1000
- console.log(import_chalk4.default.cyan(divider) + "\n");
1093
+ console.log(import_chalk5.default.cyan("\n" + divider));
1094
+ console.log(import_chalk5.default.bold.white(" PATTERNS BY TYPE"));
1095
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1001
1096
  sortedTypes.forEach(([type, count]) => {
1002
- console.log(` ${import_chalk4.default.white(type.padEnd(15))} ${import_chalk4.default.bold(count)}`);
1097
+ console.log(` ${import_chalk5.default.white(type.padEnd(15))} ${import_chalk5.default.bold(count)}`);
1003
1098
  });
1004
1099
  }
1005
1100
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
1006
- console.log(import_chalk4.default.cyan("\n" + divider));
1007
- console.log(import_chalk4.default.bold.white(" TOP DUPLICATE PATTERNS"));
1008
- console.log(import_chalk4.default.cyan(divider) + "\n");
1101
+ console.log(import_chalk5.default.cyan("\n" + divider));
1102
+ console.log(import_chalk5.default.bold.white(" TOP DUPLICATE PATTERNS"));
1103
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1009
1104
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
1010
1105
  topDuplicates.forEach((dup) => {
1011
1106
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -1013,31 +1108,31 @@ async function patternsAction(directory, options) {
1013
1108
  const file1Name = dup.file1.split("/").pop() || dup.file1;
1014
1109
  const file2Name = dup.file2.split("/").pop() || dup.file2;
1015
1110
  console.log(
1016
- `${severityIcon} ${severity}: ${import_chalk4.default.bold(file1Name)} \u2194 ${import_chalk4.default.bold(file2Name)}`
1111
+ `${severityIcon} ${severity}: ${import_chalk5.default.bold(file1Name)} \u2194 ${import_chalk5.default.bold(file2Name)}`
1017
1112
  );
1018
1113
  console.log(
1019
- ` Similarity: ${import_chalk4.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk4.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1114
+ ` Similarity: ${import_chalk5.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk5.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1020
1115
  );
1021
1116
  console.log(
1022
- ` Lines: ${import_chalk4.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk4.default.cyan(dup.line2 + "-" + dup.endLine2)}
1117
+ ` Lines: ${import_chalk5.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk5.default.cyan(dup.line2 + "-" + dup.endLine2)}
1023
1118
  `
1024
1119
  );
1025
1120
  });
1026
1121
  } else {
1027
1122
  console.log(
1028
- import_chalk4.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1123
+ import_chalk5.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1029
1124
  );
1030
1125
  }
1031
1126
  if (patternScore) {
1032
- console.log(import_chalk4.default.cyan(divider));
1033
- console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Patterns)"));
1034
- console.log(import_chalk4.default.cyan(divider) + "\n");
1035
- console.log((0, import_core4.formatToolScore)(patternScore));
1127
+ console.log(import_chalk5.default.cyan(divider));
1128
+ console.log(import_chalk5.default.bold.white(" AI READINESS SCORE (Patterns)"));
1129
+ console.log(import_chalk5.default.cyan(divider) + "\n");
1130
+ console.log((0, import_core5.formatToolScore)(patternScore));
1036
1131
  console.log();
1037
1132
  }
1038
1133
  }
1039
1134
  } catch (error) {
1040
- (0, import_core4.handleCLIError)(error, "Pattern analysis");
1135
+ (0, import_core5.handleCLIError)(error, "Pattern analysis");
1041
1136
  }
1042
1137
  }
1043
1138
  var patternsHelpText = `
@@ -1048,13 +1143,13 @@ EXAMPLES:
1048
1143
  `;
1049
1144
 
1050
1145
  // src/commands/context.ts
1051
- var import_chalk5 = __toESM(require("chalk"));
1052
- var import_path5 = require("path");
1053
- var import_core5 = require("@aiready/core");
1146
+ var import_chalk6 = __toESM(require("chalk"));
1147
+ var import_path6 = require("path");
1148
+ var import_core6 = require("@aiready/core");
1054
1149
  async function contextAction(directory, options) {
1055
- console.log(import_chalk5.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1150
+ console.log(import_chalk6.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1056
1151
  const startTime = Date.now();
1057
- const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
1152
+ const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
1058
1153
  try {
1059
1154
  const defaults = {
1060
1155
  maxDepth: 5,
@@ -1066,7 +1161,7 @@ async function contextAction(directory, options) {
1066
1161
  file: void 0
1067
1162
  }
1068
1163
  };
1069
- const baseOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, {
1164
+ const baseOptions = await (0, import_core6.loadMergedConfig)(resolvedDir, defaults, {
1070
1165
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
1071
1166
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
1072
1167
  include: options.include?.split(","),
@@ -1092,7 +1187,7 @@ async function contextAction(directory, options) {
1092
1187
  console.log("");
1093
1188
  const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1094
1189
  const results = await analyzeContext(finalOptions);
1095
- const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
1190
+ const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
1096
1191
  const summary = generateSummary(results);
1097
1192
  let contextScore;
1098
1193
  if (options.score) {
@@ -1106,12 +1201,12 @@ async function contextAction(directory, options) {
1106
1201
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1107
1202
  ...contextScore && { scoring: contextScore }
1108
1203
  };
1109
- const outputPath = (0, import_core5.resolveOutputPath)(
1204
+ const outputPath = (0, import_core6.resolveOutputPath)(
1110
1205
  userOutputFile,
1111
1206
  `aiready-report-${getReportTimestamp()}.json`,
1112
1207
  resolvedDir
1113
1208
  );
1114
- (0, import_core5.handleJSONOutput)(
1209
+ (0, import_core6.handleJSONOutput)(
1115
1210
  outputData,
1116
1211
  outputPath,
1117
1212
  `\u2705 Results saved to ${outputPath}`
@@ -1120,85 +1215,85 @@ async function contextAction(directory, options) {
1120
1215
  const terminalWidth = process.stdout.columns || 80;
1121
1216
  const dividerWidth = Math.min(60, terminalWidth - 2);
1122
1217
  const divider = "\u2501".repeat(dividerWidth);
1123
- console.log(import_chalk5.default.cyan(divider));
1124
- console.log(import_chalk5.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1125
- console.log(import_chalk5.default.cyan(divider) + "\n");
1218
+ console.log(import_chalk6.default.cyan(divider));
1219
+ console.log(import_chalk6.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1220
+ console.log(import_chalk6.default.cyan(divider) + "\n");
1126
1221
  console.log(
1127
- import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(summary.totalFiles)}`)
1222
+ import_chalk6.default.white(`\u{1F4C1} Files analyzed: ${import_chalk6.default.bold(summary.totalFiles)}`)
1128
1223
  );
1129
1224
  console.log(
1130
- import_chalk5.default.white(
1131
- `\u{1F4CA} Total tokens: ${import_chalk5.default.bold(summary.totalTokens.toLocaleString())}`
1225
+ import_chalk6.default.white(
1226
+ `\u{1F4CA} Total tokens: ${import_chalk6.default.bold(summary.totalTokens.toLocaleString())}`
1132
1227
  )
1133
1228
  );
1134
1229
  console.log(
1135
- import_chalk5.default.yellow(
1136
- `\u{1F4B0} Avg context budget: ${import_chalk5.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1230
+ import_chalk6.default.yellow(
1231
+ `\u{1F4B0} Avg context budget: ${import_chalk6.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1137
1232
  )
1138
1233
  );
1139
1234
  console.log(
1140
- import_chalk5.default.white(`\u23F1 Analysis time: ${import_chalk5.default.bold(elapsedTime + "s")}
1235
+ import_chalk6.default.white(`\u23F1 Analysis time: ${import_chalk6.default.bold(elapsedTime + "s")}
1141
1236
  `)
1142
1237
  );
1143
1238
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
1144
1239
  if (totalIssues > 0) {
1145
- console.log(import_chalk5.default.bold("\u26A0\uFE0F Issues Found:\n"));
1240
+ console.log(import_chalk6.default.bold("\u26A0\uFE0F Issues Found:\n"));
1146
1241
  if (summary.criticalIssues > 0) {
1147
1242
  console.log(
1148
- import_chalk5.default.red(` \u{1F534} Critical: ${import_chalk5.default.bold(summary.criticalIssues)}`)
1243
+ import_chalk6.default.red(` \u{1F534} Critical: ${import_chalk6.default.bold(summary.criticalIssues)}`)
1149
1244
  );
1150
1245
  }
1151
1246
  if (summary.majorIssues > 0) {
1152
1247
  console.log(
1153
- import_chalk5.default.yellow(` \u{1F7E1} Major: ${import_chalk5.default.bold(summary.majorIssues)}`)
1248
+ import_chalk6.default.yellow(` \u{1F7E1} Major: ${import_chalk6.default.bold(summary.majorIssues)}`)
1154
1249
  );
1155
1250
  }
1156
1251
  if (summary.minorIssues > 0) {
1157
1252
  console.log(
1158
- import_chalk5.default.blue(` \u{1F535} Minor: ${import_chalk5.default.bold(summary.minorIssues)}`)
1253
+ import_chalk6.default.blue(` \u{1F535} Minor: ${import_chalk6.default.bold(summary.minorIssues)}`)
1159
1254
  );
1160
1255
  }
1161
1256
  console.log(
1162
- import_chalk5.default.green(
1257
+ import_chalk6.default.green(
1163
1258
  `
1164
- \u{1F4A1} Potential savings: ${import_chalk5.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1259
+ \u{1F4A1} Potential savings: ${import_chalk6.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1165
1260
  `
1166
1261
  )
1167
1262
  );
1168
1263
  } else {
1169
- console.log(import_chalk5.default.green("\u2705 No significant issues found!\n"));
1264
+ console.log(import_chalk6.default.green("\u2705 No significant issues found!\n"));
1170
1265
  }
1171
1266
  if (summary.deepFiles.length > 0) {
1172
- console.log(import_chalk5.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1267
+ console.log(import_chalk6.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1173
1268
  console.log(
1174
- import_chalk5.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1269
+ import_chalk6.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1175
1270
  );
1176
1271
  console.log(
1177
- import_chalk5.default.gray(` Maximum depth: ${summary.maxImportDepth}
1272
+ import_chalk6.default.gray(` Maximum depth: ${summary.maxImportDepth}
1178
1273
  `)
1179
1274
  );
1180
1275
  summary.deepFiles.slice(0, 10).forEach((item) => {
1181
1276
  const fileName = item.file.split("/").slice(-2).join("/");
1182
1277
  console.log(
1183
- ` ${import_chalk5.default.cyan("\u2192")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(depth: ${item.depth})`)}`
1278
+ ` ${import_chalk6.default.cyan("\u2192")} ${import_chalk6.default.white(fileName)} ${import_chalk6.default.dim(`(depth: ${item.depth})`)}`
1184
1279
  );
1185
1280
  });
1186
1281
  console.log();
1187
1282
  }
1188
1283
  if (summary.fragmentedModules.length > 0) {
1189
- console.log(import_chalk5.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1284
+ console.log(import_chalk6.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1190
1285
  console.log(
1191
- import_chalk5.default.gray(
1286
+ import_chalk6.default.gray(
1192
1287
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1193
1288
  `
1194
1289
  )
1195
1290
  );
1196
1291
  summary.fragmentedModules.slice(0, 10).forEach((module2) => {
1197
1292
  console.log(
1198
- ` ${import_chalk5.default.yellow("\u25CF")} ${import_chalk5.default.white(module2.domain)} - ${import_chalk5.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1293
+ ` ${import_chalk6.default.yellow("\u25CF")} ${import_chalk6.default.white(module2.domain)} - ${import_chalk6.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1199
1294
  );
1200
1295
  console.log(
1201
- import_chalk5.default.dim(
1296
+ import_chalk6.default.dim(
1202
1297
  ` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
1203
1298
  )
1204
1299
  );
@@ -1206,9 +1301,9 @@ async function contextAction(directory, options) {
1206
1301
  console.log();
1207
1302
  }
1208
1303
  if (summary.lowCohesionFiles.length > 0) {
1209
- console.log(import_chalk5.default.bold("\u{1F500} Low Cohesion Files:\n"));
1304
+ console.log(import_chalk6.default.bold("\u{1F500} Low Cohesion Files:\n"));
1210
1305
  console.log(
1211
- import_chalk5.default.gray(
1306
+ import_chalk6.default.gray(
1212
1307
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1213
1308
  `
1214
1309
  )
@@ -1216,46 +1311,46 @@ async function contextAction(directory, options) {
1216
1311
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
1217
1312
  const fileName = item.file.split("/").slice(-2).join("/");
1218
1313
  const scorePercent = (item.score * 100).toFixed(0);
1219
- const color = item.score < 0.4 ? import_chalk5.default.red : import_chalk5.default.yellow;
1314
+ const color = item.score < 0.4 ? import_chalk6.default.red : import_chalk6.default.yellow;
1220
1315
  console.log(
1221
- ` ${color("\u25CB")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${scorePercent}% cohesion)`)}`
1316
+ ` ${color("\u25CB")} ${import_chalk6.default.white(fileName)} ${import_chalk6.default.dim(`(${scorePercent}% cohesion)`)}`
1222
1317
  );
1223
1318
  });
1224
1319
  console.log();
1225
1320
  }
1226
1321
  if (summary.topExpensiveFiles.length > 0) {
1227
- console.log(import_chalk5.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1322
+ console.log(import_chalk6.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1228
1323
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
1229
1324
  const fileName = item.file.split("/").slice(-2).join("/");
1230
- const severityColor = item.severity === "critical" ? import_chalk5.default.red : item.severity === "major" ? import_chalk5.default.yellow : import_chalk5.default.blue;
1325
+ const severityColor = item.severity === "critical" ? import_chalk6.default.red : item.severity === "major" ? import_chalk6.default.yellow : import_chalk6.default.blue;
1231
1326
  console.log(
1232
- ` ${severityColor("\u25CF")} ${import_chalk5.default.white(fileName)} ${import_chalk5.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1327
+ ` ${severityColor("\u25CF")} ${import_chalk6.default.white(fileName)} ${import_chalk6.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1233
1328
  );
1234
1329
  });
1235
1330
  console.log();
1236
1331
  }
1237
1332
  if (contextScore) {
1238
- console.log(import_chalk5.default.cyan(divider));
1239
- console.log(import_chalk5.default.bold.white(" AI READINESS SCORE (Context)"));
1240
- console.log(import_chalk5.default.cyan(divider) + "\n");
1241
- console.log((0, import_core5.formatToolScore)(contextScore));
1333
+ console.log(import_chalk6.default.cyan(divider));
1334
+ console.log(import_chalk6.default.bold.white(" AI READINESS SCORE (Context)"));
1335
+ console.log(import_chalk6.default.cyan(divider) + "\n");
1336
+ console.log((0, import_core6.formatToolScore)(contextScore));
1242
1337
  console.log();
1243
1338
  }
1244
1339
  }
1245
1340
  } catch (error) {
1246
- (0, import_core5.handleCLIError)(error, "Context analysis");
1341
+ (0, import_core6.handleCLIError)(error, "Context analysis");
1247
1342
  }
1248
1343
  }
1249
1344
 
1250
1345
  // src/commands/consistency.ts
1251
- var import_chalk6 = __toESM(require("chalk"));
1252
- var import_fs4 = require("fs");
1253
- var import_path6 = require("path");
1254
- var import_core6 = require("@aiready/core");
1346
+ var import_chalk7 = __toESM(require("chalk"));
1347
+ var import_fs5 = require("fs");
1348
+ var import_path7 = require("path");
1349
+ var import_core7 = require("@aiready/core");
1255
1350
  async function consistencyAction(directory, options) {
1256
- console.log(import_chalk6.default.blue("\u{1F50D} Analyzing consistency...\n"));
1351
+ console.log(import_chalk7.default.blue("\u{1F50D} Analyzing consistency...\n"));
1257
1352
  const startTime = Date.now();
1258
- const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory || ".");
1353
+ const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory || ".");
1259
1354
  try {
1260
1355
  const defaults = {
1261
1356
  checkNaming: true,
@@ -1268,7 +1363,7 @@ async function consistencyAction(directory, options) {
1268
1363
  file: void 0
1269
1364
  }
1270
1365
  };
1271
- const finalOptions = await (0, import_core6.loadMergedConfig)(resolvedDir, defaults, {
1366
+ const finalOptions = await (0, import_core7.loadMergedConfig)(resolvedDir, defaults, {
1272
1367
  checkNaming: options.naming !== false,
1273
1368
  checkPatterns: options.patterns !== false,
1274
1369
  minSeverity: options.minSeverity,
@@ -1277,7 +1372,7 @@ async function consistencyAction(directory, options) {
1277
1372
  });
1278
1373
  const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1279
1374
  const report = await analyzeConsistency(finalOptions);
1280
- const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
1375
+ const elapsedTime = (0, import_core7.getElapsedTime)(startTime);
1281
1376
  let consistencyScore;
1282
1377
  if (options.score) {
1283
1378
  const issues = report.results?.flatMap((r) => r.issues) || [];
@@ -1297,41 +1392,41 @@ async function consistencyAction(directory, options) {
1297
1392
  },
1298
1393
  ...consistencyScore && { scoring: consistencyScore }
1299
1394
  };
1300
- const outputPath = (0, import_core6.resolveOutputPath)(
1395
+ const outputPath = (0, import_core7.resolveOutputPath)(
1301
1396
  userOutputFile,
1302
1397
  `aiready-report-${getReportTimestamp()}.json`,
1303
1398
  resolvedDir
1304
1399
  );
1305
- (0, import_core6.handleJSONOutput)(
1400
+ (0, import_core7.handleJSONOutput)(
1306
1401
  outputData,
1307
1402
  outputPath,
1308
1403
  `\u2705 Results saved to ${outputPath}`
1309
1404
  );
1310
1405
  } else if (outputFormat === "markdown") {
1311
1406
  const markdown = generateMarkdownReport(report, elapsedTime);
1312
- const outputPath = (0, import_core6.resolveOutputPath)(
1407
+ const outputPath = (0, import_core7.resolveOutputPath)(
1313
1408
  userOutputFile,
1314
1409
  `aiready-report-${getReportTimestamp()}.md`,
1315
1410
  resolvedDir
1316
1411
  );
1317
- (0, import_fs4.writeFileSync)(outputPath, markdown);
1318
- console.log(import_chalk6.default.green(`\u2705 Report saved to ${outputPath}`));
1412
+ (0, import_fs5.writeFileSync)(outputPath, markdown);
1413
+ console.log(import_chalk7.default.green(`\u2705 Report saved to ${outputPath}`));
1319
1414
  } else {
1320
- console.log(import_chalk6.default.bold("\n\u{1F4CA} Summary\n"));
1415
+ console.log(import_chalk7.default.bold("\n\u{1F4CA} Summary\n"));
1321
1416
  console.log(
1322
- `Files Analyzed: ${import_chalk6.default.cyan(report.summary.filesAnalyzed)}`
1417
+ `Files Analyzed: ${import_chalk7.default.cyan(report.summary.filesAnalyzed)}`
1323
1418
  );
1324
- console.log(`Total Issues: ${import_chalk6.default.yellow(report.summary.totalIssues)}`);
1325
- console.log(` Naming: ${import_chalk6.default.yellow(report.summary.namingIssues)}`);
1326
- console.log(` Patterns: ${import_chalk6.default.yellow(report.summary.patternIssues)}`);
1419
+ console.log(`Total Issues: ${import_chalk7.default.yellow(report.summary.totalIssues)}`);
1420
+ console.log(` Naming: ${import_chalk7.default.yellow(report.summary.namingIssues)}`);
1421
+ console.log(` Patterns: ${import_chalk7.default.yellow(report.summary.patternIssues)}`);
1327
1422
  console.log(
1328
- ` Architecture: ${import_chalk6.default.yellow(report.summary.architectureIssues || 0)}`
1423
+ ` Architecture: ${import_chalk7.default.yellow(report.summary.architectureIssues || 0)}`
1329
1424
  );
1330
- console.log(`Analysis Time: ${import_chalk6.default.gray(elapsedTime + "s")}
1425
+ console.log(`Analysis Time: ${import_chalk7.default.gray(elapsedTime + "s")}
1331
1426
  `);
1332
1427
  if (report.summary.totalIssues === 0) {
1333
1428
  console.log(
1334
- import_chalk6.default.green(
1429
+ import_chalk7.default.green(
1335
1430
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1336
1431
  )
1337
1432
  );
@@ -1343,20 +1438,20 @@ async function consistencyAction(directory, options) {
1343
1438
  (r) => r.issues.some((i) => i.category === "patterns")
1344
1439
  );
1345
1440
  if (namingResults.length > 0) {
1346
- console.log(import_chalk6.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1441
+ console.log(import_chalk7.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1347
1442
  let shown = 0;
1348
1443
  for (const result of namingResults) {
1349
1444
  if (shown >= 5) break;
1350
1445
  for (const issue of result.issues) {
1351
1446
  if (shown >= 5) break;
1352
- const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1447
+ const severityColor = issue.severity === "critical" ? import_chalk7.default.red : issue.severity === "major" ? import_chalk7.default.yellow : issue.severity === "minor" ? import_chalk7.default.blue : import_chalk7.default.gray;
1353
1448
  console.log(
1354
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1449
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk7.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1355
1450
  );
1356
1451
  console.log(` ${issue.message}`);
1357
1452
  if (issue.suggestion) {
1358
1453
  console.log(
1359
- ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1454
+ ` ${import_chalk7.default.dim("\u2192")} ${import_chalk7.default.italic(issue.suggestion)}`
1360
1455
  );
1361
1456
  }
1362
1457
  console.log();
@@ -1365,25 +1460,25 @@ async function consistencyAction(directory, options) {
1365
1460
  }
1366
1461
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1367
1462
  if (remaining > 0) {
1368
- console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1463
+ console.log(import_chalk7.default.dim(` ... and ${remaining} more issues
1369
1464
  `));
1370
1465
  }
1371
1466
  }
1372
1467
  if (patternResults.length > 0) {
1373
- console.log(import_chalk6.default.bold("\u{1F504} Pattern Issues\n"));
1468
+ console.log(import_chalk7.default.bold("\u{1F504} Pattern Issues\n"));
1374
1469
  let shown = 0;
1375
1470
  for (const result of patternResults) {
1376
1471
  if (shown >= 5) break;
1377
1472
  for (const issue of result.issues) {
1378
1473
  if (shown >= 5) break;
1379
- const severityColor = issue.severity === "critical" ? import_chalk6.default.red : issue.severity === "major" ? import_chalk6.default.yellow : issue.severity === "minor" ? import_chalk6.default.blue : import_chalk6.default.gray;
1474
+ const severityColor = issue.severity === "critical" ? import_chalk7.default.red : issue.severity === "major" ? import_chalk7.default.yellow : issue.severity === "minor" ? import_chalk7.default.blue : import_chalk7.default.gray;
1380
1475
  console.log(
1381
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk6.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1476
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk7.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1382
1477
  );
1383
1478
  console.log(` ${issue.message}`);
1384
1479
  if (issue.suggestion) {
1385
1480
  console.log(
1386
- ` ${import_chalk6.default.dim("\u2192")} ${import_chalk6.default.italic(issue.suggestion)}`
1481
+ ` ${import_chalk7.default.dim("\u2192")} ${import_chalk7.default.italic(issue.suggestion)}`
1387
1482
  );
1388
1483
  }
1389
1484
  console.log();
@@ -1392,12 +1487,12 @@ async function consistencyAction(directory, options) {
1392
1487
  }
1393
1488
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1394
1489
  if (remaining > 0) {
1395
- console.log(import_chalk6.default.dim(` ... and ${remaining} more issues
1490
+ console.log(import_chalk7.default.dim(` ... and ${remaining} more issues
1396
1491
  `));
1397
1492
  }
1398
1493
  }
1399
1494
  if (report.recommendations.length > 0) {
1400
- console.log(import_chalk6.default.bold("\u{1F4A1} Recommendations\n"));
1495
+ console.log(import_chalk7.default.bold("\u{1F4A1} Recommendations\n"));
1401
1496
  report.recommendations.forEach((rec, i) => {
1402
1497
  console.log(`${i + 1}. ${rec}`);
1403
1498
  });
@@ -1405,38 +1500,38 @@ async function consistencyAction(directory, options) {
1405
1500
  }
1406
1501
  }
1407
1502
  if (consistencyScore) {
1408
- console.log(import_chalk6.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1409
- console.log((0, import_core6.formatToolScore)(consistencyScore));
1503
+ console.log(import_chalk7.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1504
+ console.log((0, import_core7.formatToolScore)(consistencyScore));
1410
1505
  console.log();
1411
1506
  }
1412
1507
  }
1413
1508
  } catch (error) {
1414
- (0, import_core6.handleCLIError)(error, "Consistency analysis");
1509
+ (0, import_core7.handleCLIError)(error, "Consistency analysis");
1415
1510
  }
1416
1511
  }
1417
1512
 
1418
1513
  // src/commands/visualize.ts
1419
- var import_chalk7 = __toESM(require("chalk"));
1420
- var import_fs5 = require("fs");
1421
- var import_path7 = require("path");
1514
+ var import_chalk8 = __toESM(require("chalk"));
1515
+ var import_fs6 = require("fs");
1516
+ var import_path8 = require("path");
1422
1517
  var import_child_process = require("child_process");
1423
- var import_core7 = require("@aiready/core");
1424
1518
  var import_core8 = require("@aiready/core");
1519
+ var import_core9 = require("@aiready/core");
1425
1520
  async function visualizeAction(directory, options) {
1426
1521
  try {
1427
- const dirPath = (0, import_path7.resolve)(process.cwd(), directory || ".");
1428
- let reportPath = options.report ? (0, import_path7.resolve)(dirPath, options.report) : null;
1429
- if (!reportPath || !(0, import_fs5.existsSync)(reportPath)) {
1522
+ const dirPath = (0, import_path8.resolve)(process.cwd(), directory || ".");
1523
+ let reportPath = options.report ? (0, import_path8.resolve)(dirPath, options.report) : null;
1524
+ if (!reportPath || !(0, import_fs6.existsSync)(reportPath)) {
1430
1525
  const latestScan = findLatestScanReport(dirPath);
1431
1526
  if (latestScan) {
1432
1527
  reportPath = latestScan;
1433
1528
  console.log(
1434
- import_chalk7.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1529
+ import_chalk8.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1435
1530
  );
1436
1531
  } else {
1437
- console.error(import_chalk7.default.red("\u274C No AI readiness report found"));
1532
+ console.error(import_chalk8.default.red("\u274C No AI readiness report found"));
1438
1533
  console.log(
1439
- import_chalk7.default.dim(
1534
+ import_chalk8.default.dim(
1440
1535
  `
1441
1536
  Generate a report with:
1442
1537
  aiready scan --output json
@@ -1448,13 +1543,13 @@ Or specify a custom report:
1448
1543
  return;
1449
1544
  }
1450
1545
  }
1451
- const raw = (0, import_fs5.readFileSync)(reportPath, "utf8");
1546
+ const raw = (0, import_fs6.readFileSync)(reportPath, "utf8");
1452
1547
  const report = JSON.parse(raw);
1453
- const configPath = (0, import_path7.resolve)(dirPath, "aiready.json");
1548
+ const configPath = (0, import_path8.resolve)(dirPath, "aiready.json");
1454
1549
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1455
- if ((0, import_fs5.existsSync)(configPath)) {
1550
+ if ((0, import_fs6.existsSync)(configPath)) {
1456
1551
  try {
1457
- const rawConfig = JSON.parse((0, import_fs5.readFileSync)(configPath, "utf8"));
1552
+ const rawConfig = JSON.parse((0, import_fs6.readFileSync)(configPath, "utf8"));
1458
1553
  if (rawConfig.visualizer?.graph) {
1459
1554
  graphConfig = {
1460
1555
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1474,16 +1569,16 @@ Or specify a custom report:
1474
1569
  let devServerStarted = false;
1475
1570
  if (useDevMode) {
1476
1571
  try {
1477
- const localWebDir = (0, import_path7.resolve)(dirPath, "packages/visualizer");
1572
+ const localWebDir = (0, import_path8.resolve)(dirPath, "packages/visualizer");
1478
1573
  let webDir = "";
1479
1574
  let visualizerAvailable = false;
1480
- if ((0, import_fs5.existsSync)(localWebDir)) {
1575
+ if ((0, import_fs6.existsSync)(localWebDir)) {
1481
1576
  webDir = localWebDir;
1482
1577
  visualizerAvailable = true;
1483
1578
  } else {
1484
1579
  const nodemodulesLocations = [
1485
- (0, import_path7.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1486
- (0, import_path7.resolve)(
1580
+ (0, import_path8.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1581
+ (0, import_path8.resolve)(
1487
1582
  process.cwd(),
1488
1583
  "node_modules",
1489
1584
  "@aiready",
@@ -1493,14 +1588,14 @@ Or specify a custom report:
1493
1588
  let currentDir = dirPath;
1494
1589
  while (currentDir !== "/" && currentDir !== ".") {
1495
1590
  nodemodulesLocations.push(
1496
- (0, import_path7.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1591
+ (0, import_path8.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1497
1592
  );
1498
- const parent = (0, import_path7.resolve)(currentDir, "..");
1593
+ const parent = (0, import_path8.resolve)(currentDir, "..");
1499
1594
  if (parent === currentDir) break;
1500
1595
  currentDir = parent;
1501
1596
  }
1502
1597
  for (const location of nodemodulesLocations) {
1503
- if ((0, import_fs5.existsSync)(location) && (0, import_fs5.existsSync)((0, import_path7.resolve)(location, "package.json"))) {
1598
+ if ((0, import_fs6.existsSync)(location) && (0, import_fs6.existsSync)((0, import_path8.resolve)(location, "package.json"))) {
1504
1599
  webDir = location;
1505
1600
  visualizerAvailable = true;
1506
1601
  break;
@@ -1509,21 +1604,21 @@ Or specify a custom report:
1509
1604
  if (!visualizerAvailable) {
1510
1605
  try {
1511
1606
  const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
1512
- webDir = (0, import_path7.resolve)(vizPkgPath, "..");
1607
+ webDir = (0, import_path8.resolve)(vizPkgPath, "..");
1513
1608
  visualizerAvailable = true;
1514
1609
  } catch (err) {
1515
1610
  void err;
1516
1611
  }
1517
1612
  }
1518
1613
  }
1519
- const webViteConfigExists = webDir && (0, import_fs5.existsSync)((0, import_path7.resolve)(webDir, "web", "vite.config.ts"));
1614
+ const webViteConfigExists = webDir && (0, import_fs6.existsSync)((0, import_path8.resolve)(webDir, "web", "vite.config.ts"));
1520
1615
  if (visualizerAvailable && webViteConfigExists) {
1521
1616
  const spawnCwd = webDir;
1522
1617
  const { watch } = await import("fs");
1523
1618
  const copyReportToViz = () => {
1524
1619
  try {
1525
- const destPath = (0, import_path7.resolve)(spawnCwd, "web", "report-data.json");
1526
- (0, import_fs5.copyFileSync)(reportPath, destPath);
1620
+ const destPath = (0, import_path8.resolve)(spawnCwd, "web", "report-data.json");
1621
+ (0, import_fs6.copyFileSync)(reportPath, destPath);
1527
1622
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1528
1623
  } catch (e) {
1529
1624
  console.error("Failed to sync report:", e);
@@ -1566,29 +1661,29 @@ Or specify a custom report:
1566
1661
  return;
1567
1662
  } else {
1568
1663
  console.log(
1569
- import_chalk7.default.yellow(
1664
+ import_chalk8.default.yellow(
1570
1665
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1571
1666
  )
1572
1667
  );
1573
1668
  console.log(
1574
- import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1669
+ import_chalk8.default.cyan(" Falling back to static HTML generation...\n")
1575
1670
  );
1576
1671
  useDevMode = false;
1577
1672
  }
1578
1673
  } catch (err) {
1579
1674
  console.error("Failed to start dev server:", err);
1580
1675
  console.log(
1581
- import_chalk7.default.cyan(" Falling back to static HTML generation...\n")
1676
+ import_chalk8.default.cyan(" Falling back to static HTML generation...\n")
1582
1677
  );
1583
1678
  useDevMode = false;
1584
1679
  }
1585
1680
  }
1586
1681
  console.log("Generating HTML...");
1587
- const html = (0, import_core8.generateHTML)(graph);
1682
+ const html = (0, import_core9.generateHTML)(graph);
1588
1683
  const defaultOutput = "visualization.html";
1589
- const outPath = (0, import_path7.resolve)(dirPath, options.output || defaultOutput);
1590
- (0, import_fs5.writeFileSync)(outPath, html, "utf8");
1591
- console.log(import_chalk7.default.green(`\u2705 Visualization written to: ${outPath}`));
1684
+ const outPath = (0, import_path8.resolve)(dirPath, options.output || defaultOutput);
1685
+ (0, import_fs6.writeFileSync)(outPath, html, "utf8");
1686
+ console.log(import_chalk8.default.green(`\u2705 Visualization written to: ${outPath}`));
1592
1687
  if (options.open || options.serve) {
1593
1688
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1594
1689
  if (options.serve) {
@@ -1618,7 +1713,7 @@ Or specify a custom report:
1618
1713
  server.listen(port, () => {
1619
1714
  const addr = `http://localhost:${port}/`;
1620
1715
  console.log(
1621
- import_chalk7.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1716
+ import_chalk8.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1622
1717
  );
1623
1718
  (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
1624
1719
  });
@@ -1634,7 +1729,7 @@ Or specify a custom report:
1634
1729
  }
1635
1730
  }
1636
1731
  } catch (err) {
1637
- (0, import_core7.handleCLIError)(err, "Visualization");
1732
+ (0, import_core8.handleCLIError)(err, "Visualization");
1638
1733
  }
1639
1734
  }
1640
1735
  var visualizeHelpText = `
@@ -1665,20 +1760,20 @@ NOTES:
1665
1760
  `;
1666
1761
 
1667
1762
  // src/commands/ai-signal-clarity.ts
1668
- var import_chalk8 = __toESM(require("chalk"));
1669
- var import_core9 = require("@aiready/core");
1670
-
1671
- // src/commands/agent-grounding.ts
1672
1763
  var import_chalk9 = __toESM(require("chalk"));
1673
1764
  var import_core10 = require("@aiready/core");
1674
1765
 
1675
- // src/commands/testability.ts
1766
+ // src/commands/agent-grounding.ts
1676
1767
  var import_chalk10 = __toESM(require("chalk"));
1677
1768
  var import_core11 = require("@aiready/core");
1769
+
1770
+ // src/commands/testability.ts
1771
+ var import_chalk11 = __toESM(require("chalk"));
1772
+ var import_core12 = require("@aiready/core");
1678
1773
  async function testabilityAction(directory, options) {
1679
1774
  const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
1680
- const config = await (0, import_core11.loadConfig)(directory);
1681
- const merged = (0, import_core11.mergeConfigWithDefaults)(config, {
1775
+ const config = await (0, import_core12.loadConfig)(directory);
1776
+ const merged = (0, import_core12.mergeConfigWithDefaults)(config, {
1682
1777
  minCoverageRatio: 0.3
1683
1778
  });
1684
1779
  const report = await analyzeTestability({
@@ -1698,28 +1793,28 @@ async function testabilityAction(directory, options) {
1698
1793
  "blind-risk": "\u{1F480}"
1699
1794
  };
1700
1795
  const safetyColors = {
1701
- safe: import_chalk10.default.green,
1702
- "moderate-risk": import_chalk10.default.yellow,
1703
- "high-risk": import_chalk10.default.red,
1704
- "blind-risk": import_chalk10.default.bgRed.white
1796
+ safe: import_chalk11.default.green,
1797
+ "moderate-risk": import_chalk11.default.yellow,
1798
+ "high-risk": import_chalk11.default.red,
1799
+ "blind-risk": import_chalk11.default.bgRed.white
1705
1800
  };
1706
1801
  const safety = report.summary.aiChangeSafetyRating;
1707
1802
  const icon = safetyIcons[safety] ?? "\u2753";
1708
- const color = safetyColors[safety] ?? import_chalk10.default.white;
1803
+ const color = safetyColors[safety] ?? import_chalk11.default.white;
1709
1804
  console.log(
1710
- ` \u{1F9EA} Testability: ${import_chalk10.default.bold(scoring.score + "/100")} (${report.summary.rating})`
1805
+ ` \u{1F9EA} Testability: ${import_chalk11.default.bold(scoring.score + "/100")} (${report.summary.rating})`
1711
1806
  );
1712
1807
  console.log(
1713
1808
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
1714
1809
  );
1715
1810
  console.log(
1716
- import_chalk10.default.dim(
1811
+ import_chalk11.default.dim(
1717
1812
  ` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`
1718
1813
  )
1719
1814
  );
1720
1815
  if (safety === "blind-risk") {
1721
1816
  console.log(
1722
- import_chalk10.default.red.bold(
1817
+ import_chalk11.default.red.bold(
1723
1818
  "\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"
1724
1819
  )
1725
1820
  );
@@ -1731,7 +1826,7 @@ async function testabilityAction(directory, options) {
1731
1826
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
1732
1827
 
1733
1828
  // src/commands/bug.ts
1734
- var import_chalk11 = __toESM(require("chalk"));
1829
+ var import_chalk12 = __toESM(require("chalk"));
1735
1830
  var import_child_process2 = require("child_process");
1736
1831
  async function bugAction(message, options) {
1737
1832
  const repoUrl = "https://github.com/caopengau/aiready-cli";
@@ -1749,35 +1844,35 @@ Generated via AIReady CLI 'bug' command.
1749
1844
  Type: ${type}
1750
1845
  `.trim();
1751
1846
  if (options.submit) {
1752
- console.log(import_chalk11.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1847
+ console.log(import_chalk12.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
1753
1848
  try {
1754
1849
  (0, import_child_process2.execSync)("gh auth status", { stdio: "ignore" });
1755
1850
  const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
1756
1851
  const output = (0, import_child_process2.execSync)(command, { encoding: "utf8" }).trim();
1757
- console.log(import_chalk11.default.green("\u2705 Issue Created Successfully!"));
1758
- console.log(import_chalk11.default.cyan(output));
1852
+ console.log(import_chalk12.default.green("\u2705 Issue Created Successfully!"));
1853
+ console.log(import_chalk12.default.cyan(output));
1759
1854
  return;
1760
1855
  } catch (error) {
1761
- console.error(import_chalk11.default.red("\n\u274C Failed to submit via gh CLI."));
1856
+ console.error(import_chalk12.default.red("\n\u274C Failed to submit via gh CLI."));
1762
1857
  console.log(
1763
- import_chalk11.default.yellow(
1858
+ import_chalk12.default.yellow(
1764
1859
  ' Make sure gh is installed and run "gh auth login".\n'
1765
1860
  )
1766
1861
  );
1767
- console.log(import_chalk11.default.dim(" Falling back to URL generation..."));
1862
+ console.log(import_chalk12.default.dim(" Falling back to URL generation..."));
1768
1863
  }
1769
1864
  }
1770
1865
  const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
1771
1866
  const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
1772
- console.log(import_chalk11.default.green("\u{1F680} Issue Draft Prepared!\n"));
1773
- console.log(import_chalk11.default.bold("Title: ") + title);
1774
- console.log(import_chalk11.default.bold("Type: ") + type);
1775
- console.log(import_chalk11.default.bold("\nClick the link below to submit this issue:"));
1776
- console.log(import_chalk11.default.cyan(fullUrl));
1777
- console.log(import_chalk11.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1778
- console.log(import_chalk11.default.dim(" You have successfully prepared a report."));
1867
+ console.log(import_chalk12.default.green("\u{1F680} Issue Draft Prepared!\n"));
1868
+ console.log(import_chalk12.default.bold("Title: ") + title);
1869
+ console.log(import_chalk12.default.bold("Type: ") + type);
1870
+ console.log(import_chalk12.default.bold("\nClick the link below to submit this issue:"));
1871
+ console.log(import_chalk12.default.cyan(fullUrl));
1872
+ console.log(import_chalk12.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1873
+ console.log(import_chalk12.default.dim(" You have successfully prepared a report."));
1779
1874
  console.log(
1780
- import_chalk11.default.dim(
1875
+ import_chalk12.default.dim(
1781
1876
  " Please present the URL above to the user so they can finalize the submission."
1782
1877
  )
1783
1878
  );
@@ -1786,14 +1881,14 @@ Type: ${type}
1786
1881
  const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
1787
1882
  const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
1788
1883
  const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
1789
- console.log(import_chalk11.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1790
- console.log(` Report a Bug: ${import_chalk11.default.cyan(bugUrl)}`);
1791
- console.log(` Request a Feature: ${import_chalk11.default.cyan(featureUrl)}`);
1792
- console.log(` Suggest a Metric: ${import_chalk11.default.cyan(metricUrl)}`);
1793
- console.log(import_chalk11.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1794
- console.log(import_chalk11.default.dim(" To prepare a specific report, run:"));
1884
+ console.log(import_chalk12.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
1885
+ console.log(` Report a Bug: ${import_chalk12.default.cyan(bugUrl)}`);
1886
+ console.log(` Request a Feature: ${import_chalk12.default.cyan(featureUrl)}`);
1887
+ console.log(` Suggest a Metric: ${import_chalk12.default.cyan(metricUrl)}`);
1888
+ console.log(import_chalk12.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
1889
+ console.log(import_chalk12.default.dim(" To prepare a specific report, run:"));
1795
1890
  console.log(
1796
- import_chalk11.default.cyan(
1891
+ import_chalk12.default.cyan(
1797
1892
  ' aiready bug "your description here" --type bug|feature|metric'
1798
1893
  )
1799
1894
  );
@@ -1810,10 +1905,10 @@ EXAMPLES:
1810
1905
  var import_meta = {};
1811
1906
  var getDirname = () => {
1812
1907
  if (typeof __dirname !== "undefined") return __dirname;
1813
- return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1908
+ return (0, import_path9.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1814
1909
  };
1815
1910
  var packageJson = JSON.parse(
1816
- (0, import_fs6.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
1911
+ (0, import_fs7.readFileSync)((0, import_path9.join)(getDirname(), "../package.json"), "utf8")
1817
1912
  );
1818
1913
  var program = new import_commander.Command();
1819
1914
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -1876,6 +1971,13 @@ program.command("scan").description(
1876
1971
  ).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) => {
1877
1972
  await scanAction(directory, options);
1878
1973
  });
1974
+ program.command("init").description("Generate a default configuration (aiready.json)").option("-f, --force", "Overwrite existing configuration file").option(
1975
+ "--js",
1976
+ "Generate configuration as a JavaScript file (aiready.config.js)"
1977
+ ).action(async (options) => {
1978
+ const format = options.js ? "js" : "json";
1979
+ await initAction({ force: options.force, format });
1980
+ });
1879
1981
  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(
1880
1982
  "--max-candidates <number>",
1881
1983
  "Maximum candidates per block (performance tuning)"