@aiready/cli 0.14.10 → 0.14.12
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/.aiready/aiready-report-20260319-201106.json +5566 -0
- package/.aiready/aiready-report-20260319-201511.json +5566 -0
- package/.aiready/aiready-report-20260319-202017.json +5708 -0
- package/.turbo/turbo-build.log +29 -28
- package/.turbo/turbo-test.log +76 -74
- package/dist/cli.js +181 -54
- package/dist/cli.mjs +181 -54
- package/package.json +12 -12
- package/src/commands/__tests__/init.test.ts +6 -11
- package/src/commands/init.ts +101 -57
- package/src/commands/report-formatter.ts +133 -7
|
@@ -7,6 +7,95 @@ import {
|
|
|
7
7
|
getRatingDisplay,
|
|
8
8
|
} from '@aiready/core';
|
|
9
9
|
|
|
10
|
+
/**
|
|
11
|
+
* Generate a visual progress bar for a score.
|
|
12
|
+
*
|
|
13
|
+
* @param score - The score value (0-100)
|
|
14
|
+
* @param width - The width of the progress bar
|
|
15
|
+
* @returns A colored progress bar string
|
|
16
|
+
*/
|
|
17
|
+
function generateProgressBar(score: number, width: number = 20): string {
|
|
18
|
+
const filled = Math.round((score / 100) * width);
|
|
19
|
+
const empty = width - filled;
|
|
20
|
+
|
|
21
|
+
let color = chalk.red;
|
|
22
|
+
if (score >= 90) color = chalk.green;
|
|
23
|
+
else if (score >= 75) color = chalk.cyan;
|
|
24
|
+
else if (score >= 60) color = chalk.yellow;
|
|
25
|
+
|
|
26
|
+
const bar = '█'.repeat(filled) + '░'.repeat(empty);
|
|
27
|
+
return color(bar);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Count issues by severity level from all tool results.
|
|
32
|
+
*
|
|
33
|
+
* @param results - The unified results object
|
|
34
|
+
* @returns Object with counts for each severity level
|
|
35
|
+
*/
|
|
36
|
+
function countIssuesBySeverity(results: any): {
|
|
37
|
+
critical: number;
|
|
38
|
+
major: number;
|
|
39
|
+
minor: number;
|
|
40
|
+
} {
|
|
41
|
+
let critical = 0;
|
|
42
|
+
let major = 0;
|
|
43
|
+
let minor = 0;
|
|
44
|
+
|
|
45
|
+
if (results.summary?.toolsRun) {
|
|
46
|
+
for (const toolId of results.summary.toolsRun) {
|
|
47
|
+
const toolRes = results[toolId];
|
|
48
|
+
if (toolRes?.results) {
|
|
49
|
+
for (const fileRes of toolRes.results) {
|
|
50
|
+
if (fileRes.issues) {
|
|
51
|
+
for (const issue of fileRes.issues) {
|
|
52
|
+
const sev = issue.severity?.toLowerCase();
|
|
53
|
+
if (sev === 'critical') critical++;
|
|
54
|
+
else if (sev === 'major') major++;
|
|
55
|
+
else minor++;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { critical, major, minor };
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Get top files with most issues.
|
|
68
|
+
*
|
|
69
|
+
* @param results - The unified results object
|
|
70
|
+
* @param limit - Maximum number of files to return
|
|
71
|
+
* @returns Array of files with issue counts
|
|
72
|
+
*/
|
|
73
|
+
function getTopFilesWithIssues(
|
|
74
|
+
results: any,
|
|
75
|
+
limit: number = 5
|
|
76
|
+
): Array<{ file: string; count: number }> {
|
|
77
|
+
const fileCounts = new Map<string, number>();
|
|
78
|
+
|
|
79
|
+
if (results.summary?.toolsRun) {
|
|
80
|
+
for (const toolId of results.summary.toolsRun) {
|
|
81
|
+
const toolRes = results[toolId];
|
|
82
|
+
if (toolRes?.results) {
|
|
83
|
+
for (const fileRes of toolRes.results) {
|
|
84
|
+
if (fileRes.issues?.length > 0) {
|
|
85
|
+
const current = fileCounts.get(fileRes.fileName) || 0;
|
|
86
|
+
fileCounts.set(fileRes.fileName, current + fileRes.issues.length);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return Array.from(fileCounts.entries())
|
|
94
|
+
.map(([file, count]) => ({ file, count }))
|
|
95
|
+
.sort((a, b) => b.count - a.count)
|
|
96
|
+
.slice(0, limit);
|
|
97
|
+
}
|
|
98
|
+
|
|
10
99
|
/**
|
|
11
100
|
* Handle console output for the scan results.
|
|
12
101
|
*
|
|
@@ -14,12 +103,48 @@ import {
|
|
|
14
103
|
* @param startTime - The timestamp when the scan started.
|
|
15
104
|
*/
|
|
16
105
|
export function printScanSummary(results: any, startTime: number) {
|
|
106
|
+
// Count issues by severity
|
|
107
|
+
const severity = countIssuesBySeverity(results);
|
|
108
|
+
const totalIssues = severity.critical + severity.major + severity.minor;
|
|
109
|
+
|
|
110
|
+
// Get top files with issues
|
|
111
|
+
const topFiles = getTopFilesWithIssues(results);
|
|
112
|
+
|
|
17
113
|
console.log(chalk.cyan('\n=== AIReady Run Summary ==='));
|
|
114
|
+
console.log(` Total issues: ${chalk.bold(String(totalIssues))}`);
|
|
115
|
+
|
|
116
|
+
// Severity breakdown
|
|
117
|
+
if (totalIssues > 0) {
|
|
118
|
+
console.log(chalk.dim(' Severity breakdown:'));
|
|
119
|
+
if (severity.critical > 0) {
|
|
120
|
+
console.log(
|
|
121
|
+
` ${chalk.red('●')} Critical: ${chalk.bold(severity.critical)}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
if (severity.major > 0) {
|
|
125
|
+
console.log(
|
|
126
|
+
` ${chalk.yellow('●')} Major: ${chalk.bold(severity.major)}`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
if (severity.minor > 0) {
|
|
130
|
+
console.log(
|
|
131
|
+
` ${chalk.blue('●')} Minor: ${chalk.bold(severity.minor)}`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// Top files with issues
|
|
137
|
+
if (topFiles.length > 0) {
|
|
138
|
+
console.log(chalk.dim('\n Top files with issues:'));
|
|
139
|
+
topFiles.forEach((item) => {
|
|
140
|
+
console.log(
|
|
141
|
+
` ${chalk.yellow('→')} ${item.file}: ${chalk.bold(item.count)} issues`
|
|
142
|
+
);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
18
146
|
console.log(
|
|
19
|
-
|
|
20
|
-
);
|
|
21
|
-
console.log(
|
|
22
|
-
` Execution time: ${chalk.bold(((Date.now() - startTime) / 1000).toFixed(2) + 's')}`
|
|
147
|
+
`\n Execution time: ${chalk.bold(((Date.now() - startTime) / 1000).toFixed(2) + 's')}`
|
|
23
148
|
);
|
|
24
149
|
}
|
|
25
150
|
|
|
@@ -64,18 +189,19 @@ export function printScoring(
|
|
|
64
189
|
scoringResult.breakdown.forEach((tool: any) => {
|
|
65
190
|
const rating = getRating(tool.score);
|
|
66
191
|
const emoji = getRatingDisplay(rating).emoji;
|
|
192
|
+
const progressBar = generateProgressBar(tool.score, 15);
|
|
67
193
|
console.log(
|
|
68
|
-
`
|
|
194
|
+
` ${progressBar} ${tool.score}/100 (${rating}) ${emoji} ${tool.toolName}`
|
|
69
195
|
);
|
|
70
196
|
});
|
|
71
197
|
|
|
72
|
-
// Top Actionable Recommendations
|
|
198
|
+
// Top Actionable Recommendations - increased from 3 to 5
|
|
73
199
|
const allRecs = scoringResult.breakdown
|
|
74
200
|
.flatMap((t: any) =>
|
|
75
201
|
(t.recommendations ?? []).map((r: any) => ({ ...r, tool: t.toolName }))
|
|
76
202
|
)
|
|
77
203
|
.sort((a: any, b: any) => b.estimatedImpact - a.estimatedImpact)
|
|
78
|
-
.slice(0,
|
|
204
|
+
.slice(0, 5); // Increased from 3 to 5
|
|
79
205
|
|
|
80
206
|
if (allRecs.length > 0) {
|
|
81
207
|
console.log(chalk.bold('\n🎯 Top Actionable Recommendations:'));
|