@aiready/cli 0.13.8 → 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/.turbo/turbo-build.log +9 -9
- package/.turbo/turbo-test.log +32 -32
- package/dist/cli.js +290 -188
- package/dist/cli.mjs +239 -137
- package/package.json +12 -12
- package/packages/core/src/.aiready/aiready-report-20260314-161145.json +230 -0
- package/packages/core/src/.aiready/aiready-report-20260314-161152.json +253 -0
- package/packages/pattern-detect/src/.aiready/aiready-report-20260314-161139.json +230 -0
- package/src/cli.ts +15 -0
- package/src/commands/index.ts +1 -0
- package/src/commands/init.ts +97 -0
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
|
|
29
|
-
var
|
|
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/
|
|
907
|
-
var
|
|
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(
|
|
1006
|
+
console.log(import_chalk5.default.blue("\u{1F50D} Analyzing patterns...\n"));
|
|
912
1007
|
const startTime = Date.now();
|
|
913
|
-
const resolvedDir = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1058
|
+
const outputPath = (0, import_core5.resolveOutputPath)(
|
|
964
1059
|
userOutputFile,
|
|
965
1060
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
966
1061
|
resolvedDir
|
|
967
1062
|
);
|
|
968
|
-
(0,
|
|
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(
|
|
978
|
-
console.log(
|
|
979
|
-
console.log(
|
|
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
|
-
|
|
1076
|
+
import_chalk5.default.white(`\u{1F4C1} Files analyzed: ${import_chalk5.default.bold(results.length)}`)
|
|
982
1077
|
);
|
|
983
1078
|
console.log(
|
|
984
|
-
|
|
985
|
-
`\u26A0 Duplicate patterns found: ${
|
|
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
|
-
|
|
990
|
-
`\u{1F4B0} Token cost (wasted): ${
|
|
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
|
-
|
|
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(
|
|
999
|
-
console.log(
|
|
1000
|
-
console.log(
|
|
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(` ${
|
|
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(
|
|
1007
|
-
console.log(
|
|
1008
|
-
console.log(
|
|
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}: ${
|
|
1111
|
+
`${severityIcon} ${severity}: ${import_chalk5.default.bold(file1Name)} \u2194 ${import_chalk5.default.bold(file2Name)}`
|
|
1017
1112
|
);
|
|
1018
1113
|
console.log(
|
|
1019
|
-
` Similarity: ${
|
|
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: ${
|
|
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
|
-
|
|
1123
|
+
import_chalk5.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
|
|
1029
1124
|
);
|
|
1030
1125
|
}
|
|
1031
1126
|
if (patternScore) {
|
|
1032
|
-
console.log(
|
|
1033
|
-
console.log(
|
|
1034
|
-
console.log(
|
|
1035
|
-
console.log((0,
|
|
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,
|
|
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
|
|
1052
|
-
var
|
|
1053
|
-
var
|
|
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(
|
|
1150
|
+
console.log(import_chalk6.default.blue("\u{1F9E0} Analyzing context costs...\n"));
|
|
1056
1151
|
const startTime = Date.now();
|
|
1057
|
-
const resolvedDir = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1204
|
+
const outputPath = (0, import_core6.resolveOutputPath)(
|
|
1110
1205
|
userOutputFile,
|
|
1111
1206
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1112
1207
|
resolvedDir
|
|
1113
1208
|
);
|
|
1114
|
-
(0,
|
|
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(
|
|
1124
|
-
console.log(
|
|
1125
|
-
console.log(
|
|
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
|
-
|
|
1222
|
+
import_chalk6.default.white(`\u{1F4C1} Files analyzed: ${import_chalk6.default.bold(summary.totalFiles)}`)
|
|
1128
1223
|
);
|
|
1129
1224
|
console.log(
|
|
1130
|
-
|
|
1131
|
-
`\u{1F4CA} Total tokens: ${
|
|
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
|
-
|
|
1136
|
-
`\u{1F4B0} Avg context budget: ${
|
|
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
|
-
|
|
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(
|
|
1240
|
+
console.log(import_chalk6.default.bold("\u26A0\uFE0F Issues Found:\n"));
|
|
1146
1241
|
if (summary.criticalIssues > 0) {
|
|
1147
1242
|
console.log(
|
|
1148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1253
|
+
import_chalk6.default.blue(` \u{1F535} Minor: ${import_chalk6.default.bold(summary.minorIssues)}`)
|
|
1159
1254
|
);
|
|
1160
1255
|
}
|
|
1161
1256
|
console.log(
|
|
1162
|
-
|
|
1257
|
+
import_chalk6.default.green(
|
|
1163
1258
|
`
|
|
1164
|
-
\u{1F4A1} Potential savings: ${
|
|
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(
|
|
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(
|
|
1267
|
+
console.log(import_chalk6.default.bold("\u{1F4CF} Deep Import Chains:\n"));
|
|
1173
1268
|
console.log(
|
|
1174
|
-
|
|
1269
|
+
import_chalk6.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
|
|
1175
1270
|
);
|
|
1176
1271
|
console.log(
|
|
1177
|
-
|
|
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
|
-
` ${
|
|
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(
|
|
1284
|
+
console.log(import_chalk6.default.bold("\u{1F9E9} Fragmented Modules:\n"));
|
|
1190
1285
|
console.log(
|
|
1191
|
-
|
|
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
|
-
` ${
|
|
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
|
-
|
|
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(
|
|
1304
|
+
console.log(import_chalk6.default.bold("\u{1F500} Low Cohesion Files:\n"));
|
|
1210
1305
|
console.log(
|
|
1211
|
-
|
|
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 ?
|
|
1314
|
+
const color = item.score < 0.4 ? import_chalk6.default.red : import_chalk6.default.yellow;
|
|
1220
1315
|
console.log(
|
|
1221
|
-
` ${color("\u25CB")} ${
|
|
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(
|
|
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" ?
|
|
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")} ${
|
|
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(
|
|
1239
|
-
console.log(
|
|
1240
|
-
console.log(
|
|
1241
|
-
console.log((0,
|
|
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,
|
|
1341
|
+
(0, import_core6.handleCLIError)(error, "Context analysis");
|
|
1247
1342
|
}
|
|
1248
1343
|
}
|
|
1249
1344
|
|
|
1250
1345
|
// src/commands/consistency.ts
|
|
1251
|
-
var
|
|
1252
|
-
var
|
|
1253
|
-
var
|
|
1254
|
-
var
|
|
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(
|
|
1351
|
+
console.log(import_chalk7.default.blue("\u{1F50D} Analyzing consistency...\n"));
|
|
1257
1352
|
const startTime = Date.now();
|
|
1258
|
-
const resolvedDir = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
1395
|
+
const outputPath = (0, import_core7.resolveOutputPath)(
|
|
1301
1396
|
userOutputFile,
|
|
1302
1397
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
1303
1398
|
resolvedDir
|
|
1304
1399
|
);
|
|
1305
|
-
(0,
|
|
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,
|
|
1407
|
+
const outputPath = (0, import_core7.resolveOutputPath)(
|
|
1313
1408
|
userOutputFile,
|
|
1314
1409
|
`aiready-report-${getReportTimestamp()}.md`,
|
|
1315
1410
|
resolvedDir
|
|
1316
1411
|
);
|
|
1317
|
-
(0,
|
|
1318
|
-
console.log(
|
|
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(
|
|
1415
|
+
console.log(import_chalk7.default.bold("\n\u{1F4CA} Summary\n"));
|
|
1321
1416
|
console.log(
|
|
1322
|
-
`Files Analyzed: ${
|
|
1417
|
+
`Files Analyzed: ${import_chalk7.default.cyan(report.summary.filesAnalyzed)}`
|
|
1323
1418
|
);
|
|
1324
|
-
console.log(`Total Issues: ${
|
|
1325
|
-
console.log(` Naming: ${
|
|
1326
|
-
console.log(` Patterns: ${
|
|
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: ${
|
|
1423
|
+
` Architecture: ${import_chalk7.default.yellow(report.summary.architectureIssues || 0)}`
|
|
1329
1424
|
);
|
|
1330
|
-
console.log(`Analysis Time: ${
|
|
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
|
-
|
|
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(
|
|
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" ?
|
|
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())} ${
|
|
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
|
-
` ${
|
|
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(
|
|
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(
|
|
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" ?
|
|
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())} ${
|
|
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
|
-
` ${
|
|
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(
|
|
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(
|
|
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(
|
|
1409
|
-
console.log((0,
|
|
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,
|
|
1509
|
+
(0, import_core7.handleCLIError)(error, "Consistency analysis");
|
|
1415
1510
|
}
|
|
1416
1511
|
}
|
|
1417
1512
|
|
|
1418
1513
|
// src/commands/visualize.ts
|
|
1419
|
-
var
|
|
1420
|
-
var
|
|
1421
|
-
var
|
|
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,
|
|
1428
|
-
let reportPath = options.report ? (0,
|
|
1429
|
-
if (!reportPath || !(0,
|
|
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
|
-
|
|
1529
|
+
import_chalk8.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
|
|
1435
1530
|
);
|
|
1436
1531
|
} else {
|
|
1437
|
-
console.error(
|
|
1532
|
+
console.error(import_chalk8.default.red("\u274C No AI readiness report found"));
|
|
1438
1533
|
console.log(
|
|
1439
|
-
|
|
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,
|
|
1546
|
+
const raw = (0, import_fs6.readFileSync)(reportPath, "utf8");
|
|
1452
1547
|
const report = JSON.parse(raw);
|
|
1453
|
-
const configPath = (0,
|
|
1548
|
+
const configPath = (0, import_path8.resolve)(dirPath, "aiready.json");
|
|
1454
1549
|
let graphConfig = { maxNodes: 400, maxEdges: 600 };
|
|
1455
|
-
if ((0,
|
|
1550
|
+
if ((0, import_fs6.existsSync)(configPath)) {
|
|
1456
1551
|
try {
|
|
1457
|
-
const rawConfig = JSON.parse((0,
|
|
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,
|
|
1572
|
+
const localWebDir = (0, import_path8.resolve)(dirPath, "packages/visualizer");
|
|
1478
1573
|
let webDir = "";
|
|
1479
1574
|
let visualizerAvailable = false;
|
|
1480
|
-
if ((0,
|
|
1575
|
+
if ((0, import_fs6.existsSync)(localWebDir)) {
|
|
1481
1576
|
webDir = localWebDir;
|
|
1482
1577
|
visualizerAvailable = true;
|
|
1483
1578
|
} else {
|
|
1484
1579
|
const nodemodulesLocations = [
|
|
1485
|
-
(0,
|
|
1486
|
-
(0,
|
|
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,
|
|
1591
|
+
(0, import_path8.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
|
|
1497
1592
|
);
|
|
1498
|
-
const parent = (0,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
1526
|
-
(0,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
1682
|
+
const html = (0, import_core9.generateHTML)(graph);
|
|
1588
1683
|
const defaultOutput = "visualization.html";
|
|
1589
|
-
const outPath = (0,
|
|
1590
|
-
(0,
|
|
1591
|
-
console.log(
|
|
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
|
-
|
|
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,
|
|
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/
|
|
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,
|
|
1681
|
-
const merged = (0,
|
|
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:
|
|
1702
|
-
"moderate-risk":
|
|
1703
|
-
"high-risk":
|
|
1704
|
-
"blind-risk":
|
|
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] ??
|
|
1803
|
+
const color = safetyColors[safety] ?? import_chalk11.default.white;
|
|
1709
1804
|
console.log(
|
|
1710
|
-
` \u{1F9EA} Testability: ${
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
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(
|
|
1758
|
-
console.log(
|
|
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(
|
|
1856
|
+
console.error(import_chalk12.default.red("\n\u274C Failed to submit via gh CLI."));
|
|
1762
1857
|
console.log(
|
|
1763
|
-
|
|
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(
|
|
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(
|
|
1773
|
-
console.log(
|
|
1774
|
-
console.log(
|
|
1775
|
-
console.log(
|
|
1776
|
-
console.log(
|
|
1777
|
-
console.log(
|
|
1778
|
-
console.log(
|
|
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
|
-
|
|
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(
|
|
1790
|
-
console.log(` Report a Bug: ${
|
|
1791
|
-
console.log(` Request a Feature: ${
|
|
1792
|
-
console.log(` Suggest a Metric: ${
|
|
1793
|
-
console.log(
|
|
1794
|
-
console.log(
|
|
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
|
-
|
|
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,
|
|
1908
|
+
return (0, import_path9.dirname)((0, import_url.fileURLToPath)(import_meta.url));
|
|
1814
1909
|
};
|
|
1815
1910
|
var packageJson = JSON.parse(
|
|
1816
|
-
(0,
|
|
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)"
|