@aiready/cli 0.9.39 → 0.9.41
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-20260227-133806.json +7805 -0
- package/.aiready/aiready-report-20260227-133938.json +7951 -0
- package/.github/FUNDING.yml +2 -2
- package/.turbo/turbo-build.log +9 -9
- package/.turbo/turbo-test.log +5 -5
- package/CONTRIBUTING.md +11 -2
- package/dist/chunk-HLBKROD3.mjs +237 -0
- package/dist/cli.js +719 -179
- package/dist/cli.mjs +711 -180
- package/dist/index.js +12 -3
- package/dist/index.mjs +1 -1
- package/package.json +12 -12
- package/src/__tests__/cli.test.ts +1 -1
- package/src/cli.ts +118 -32
- package/src/commands/agent-grounding.ts +22 -7
- package/src/commands/ai-signal-clarity.ts +13 -8
- package/src/commands/consistency.ts +69 -29
- package/src/commands/context.ts +108 -38
- package/src/commands/deps-health.ts +15 -6
- package/src/commands/doc-drift.ts +10 -4
- package/src/commands/index.ts +6 -2
- package/src/commands/patterns.ts +67 -26
- package/src/commands/scan.ts +430 -119
- package/src/commands/testability.ts +22 -9
- package/src/commands/visualize.ts +102 -45
- package/src/index.ts +34 -10
- package/src/utils/helpers.ts +57 -32
package/dist/index.js
CHANGED
|
@@ -52,8 +52,14 @@ function sortBySeverity(results) {
|
|
|
52
52
|
});
|
|
53
53
|
return { ...file, issues: sortedIssues };
|
|
54
54
|
}).sort((a, b) => {
|
|
55
|
-
const aMaxSeverity = Math.max(
|
|
56
|
-
|
|
55
|
+
const aMaxSeverity = Math.max(
|
|
56
|
+
...a.issues.map((i) => severityOrder[i.severity] || 0),
|
|
57
|
+
0
|
|
58
|
+
);
|
|
59
|
+
const bMaxSeverity = Math.max(
|
|
60
|
+
...b.issues.map((i) => severityOrder[i.severity] || 0),
|
|
61
|
+
0
|
|
62
|
+
);
|
|
57
63
|
if (aMaxSeverity !== bMaxSeverity) {
|
|
58
64
|
return bMaxSeverity - aMaxSeverity;
|
|
59
65
|
}
|
|
@@ -152,7 +158,10 @@ async function analyzeUnified(options) {
|
|
|
152
158
|
options.progressCallback({ tool: "aiSignalClarity", data: report });
|
|
153
159
|
}
|
|
154
160
|
result.aiSignalClarity = report;
|
|
155
|
-
result.summary.totalIssues += report.results?.reduce(
|
|
161
|
+
result.summary.totalIssues += report.results?.reduce(
|
|
162
|
+
(sum, r) => sum + (r.issues?.length || 0),
|
|
163
|
+
0
|
|
164
|
+
) || 0;
|
|
156
165
|
}
|
|
157
166
|
if (tools.includes("grounding")) {
|
|
158
167
|
const { analyzeAgentGrounding } = await import("@aiready/agent-grounding");
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/cli",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.41",
|
|
4
4
|
"description": "Unified CLI for AIReady analysis tools",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -11,17 +11,17 @@
|
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"chalk": "^5.3.0",
|
|
13
13
|
"commander": "^14.0.0",
|
|
14
|
-
"@aiready/agent-grounding": "0.1.
|
|
15
|
-
"@aiready/
|
|
16
|
-
"@aiready/
|
|
17
|
-
"@aiready/consistency": "0.8.
|
|
18
|
-
"@aiready/
|
|
19
|
-
"@aiready/doc-drift": "0.1.
|
|
20
|
-
"@aiready/
|
|
21
|
-
"@aiready/
|
|
22
|
-
"@aiready/
|
|
23
|
-
"@aiready/
|
|
24
|
-
"@aiready/testability": "0.1.
|
|
14
|
+
"@aiready/agent-grounding": "0.1.6",
|
|
15
|
+
"@aiready/context-analyzer": "0.9.36",
|
|
16
|
+
"@aiready/core": "0.9.33",
|
|
17
|
+
"@aiready/consistency": "0.8.32",
|
|
18
|
+
"@aiready/deps": "0.1.6",
|
|
19
|
+
"@aiready/doc-drift": "0.1.6",
|
|
20
|
+
"@aiready/change-amplification": "0.1.6",
|
|
21
|
+
"@aiready/ai-signal-clarity": "0.1.6",
|
|
22
|
+
"@aiready/pattern-detect": "0.11.32",
|
|
23
|
+
"@aiready/visualizer": "0.1.38",
|
|
24
|
+
"@aiready/testability": "0.1.6"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"@types/node": "^24.0.0",
|
package/src/cli.ts
CHANGED
|
@@ -23,7 +23,9 @@ const getDirname = () => {
|
|
|
23
23
|
return dirname(fileURLToPath(import.meta.url));
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
const packageJson = JSON.parse(
|
|
26
|
+
const packageJson = JSON.parse(
|
|
27
|
+
readFileSync(join(getDirname(), '../package.json'), 'utf8')
|
|
28
|
+
);
|
|
27
29
|
|
|
28
30
|
const program = new Command();
|
|
29
31
|
|
|
@@ -31,17 +33,19 @@ program
|
|
|
31
33
|
.name('aiready')
|
|
32
34
|
.description('AIReady - Assess and improve AI-readiness of codebases')
|
|
33
35
|
.version(packageJson.version)
|
|
34
|
-
.addHelpText(
|
|
36
|
+
.addHelpText(
|
|
37
|
+
'after',
|
|
38
|
+
`
|
|
35
39
|
AI READINESS SCORING:
|
|
36
40
|
Get a 0-100 score indicating how AI-ready your codebase is.
|
|
37
41
|
Use --score flag with any analysis command for detailed breakdown.
|
|
38
42
|
|
|
39
43
|
EXAMPLES:
|
|
40
|
-
$ aiready scan #
|
|
44
|
+
$ aiready scan # Comprehensive analysis of current directory
|
|
41
45
|
$ aiready scan --score # Get AI Readiness Score (0-100)
|
|
42
46
|
$ aiready scan --tools patterns # Run only pattern detection
|
|
43
|
-
$ aiready
|
|
44
|
-
$ aiready scan --output json
|
|
47
|
+
$ npx @aiready/cli scan # Industry standard way to run standard scan
|
|
48
|
+
$ aiready scan --output json # Output raw JSON for piping
|
|
45
49
|
|
|
46
50
|
GETTING STARTED:
|
|
47
51
|
1. Run 'aiready scan' to analyze your codebase
|
|
@@ -66,25 +70,47 @@ CONFIGURATION:
|
|
|
66
70
|
VERSION: ${packageJson.version}
|
|
67
71
|
DOCUMENTATION: https://aiready.dev/docs/cli
|
|
68
72
|
GITHUB: https://github.com/caopengau/aiready-cli
|
|
69
|
-
LANDING: https://github.com/caopengau/aiready-landing`
|
|
73
|
+
LANDING: https://github.com/caopengau/aiready-landing`
|
|
74
|
+
);
|
|
70
75
|
|
|
71
76
|
// Scan command - Run comprehensive AI-readiness analysis
|
|
72
77
|
program
|
|
73
78
|
.command('scan')
|
|
74
|
-
.description(
|
|
79
|
+
.description(
|
|
80
|
+
'Run comprehensive AI-readiness analysis (patterns + context + consistency)'
|
|
81
|
+
)
|
|
75
82
|
.argument('[directory]', 'Directory to analyze', '.')
|
|
76
|
-
.option(
|
|
77
|
-
|
|
78
|
-
|
|
83
|
+
.option(
|
|
84
|
+
'-t, --tools <tools>',
|
|
85
|
+
'Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)'
|
|
86
|
+
)
|
|
87
|
+
.option(
|
|
88
|
+
'--profile <type>',
|
|
89
|
+
'Scan profile to use (agentic, cost, security, onboarding)'
|
|
90
|
+
)
|
|
91
|
+
.option(
|
|
92
|
+
'--compare-to <path>',
|
|
93
|
+
'Compare results against a previous AIReady report JSON'
|
|
94
|
+
)
|
|
79
95
|
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
80
96
|
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
81
|
-
.option('-o, --output <format>', 'Output format: console, json', '
|
|
97
|
+
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
82
98
|
.option('--output-file <path>', 'Output file path (for json)')
|
|
83
|
-
.option(
|
|
99
|
+
.option(
|
|
100
|
+
'--no-score',
|
|
101
|
+
'Disable calculating AI Readiness Score (enabled by default)'
|
|
102
|
+
)
|
|
84
103
|
.option('--weights <weights>', 'Custom scoring weights')
|
|
85
104
|
.option('--threshold <score>', 'Fail CI/CD if score below threshold (0-100)')
|
|
86
|
-
.option(
|
|
87
|
-
|
|
105
|
+
.option(
|
|
106
|
+
'--ci',
|
|
107
|
+
'CI mode: GitHub Actions annotations, no colors, fail on threshold'
|
|
108
|
+
)
|
|
109
|
+
.option(
|
|
110
|
+
'--fail-on <level>',
|
|
111
|
+
'Fail on issues: critical, major, any',
|
|
112
|
+
'critical'
|
|
113
|
+
)
|
|
88
114
|
.addHelpText('after', scanHelpText)
|
|
89
115
|
.action(async (directory, options) => {
|
|
90
116
|
await scanAction(directory, options);
|
|
@@ -97,14 +123,26 @@ program
|
|
|
97
123
|
.argument('[directory]', 'Directory to analyze', '.')
|
|
98
124
|
.option('-s, --similarity <number>', 'Minimum similarity score (0-1)', '0.40')
|
|
99
125
|
.option('-l, --min-lines <number>', 'Minimum lines to consider', '5')
|
|
100
|
-
.option(
|
|
101
|
-
|
|
102
|
-
|
|
126
|
+
.option(
|
|
127
|
+
'--max-candidates <number>',
|
|
128
|
+
'Maximum candidates per block (performance tuning)'
|
|
129
|
+
)
|
|
130
|
+
.option(
|
|
131
|
+
'--min-shared-tokens <number>',
|
|
132
|
+
'Minimum shared tokens for candidates (performance tuning)'
|
|
133
|
+
)
|
|
134
|
+
.option(
|
|
135
|
+
'--full-scan',
|
|
136
|
+
'Disable smart defaults for comprehensive analysis (slower)'
|
|
137
|
+
)
|
|
103
138
|
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
104
139
|
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
105
140
|
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
106
141
|
.option('--output-file <path>', 'Output file path (for json)')
|
|
107
|
-
.option(
|
|
142
|
+
.option(
|
|
143
|
+
'--score',
|
|
144
|
+
'Calculate and display AI Readiness Score for patterns (0-100)'
|
|
145
|
+
)
|
|
108
146
|
.addHelpText('after', patternsHelpText)
|
|
109
147
|
.action(async (directory, options) => {
|
|
110
148
|
await patternsAction(directory, options);
|
|
@@ -116,12 +154,19 @@ program
|
|
|
116
154
|
.description('Analyze context window costs and dependency fragmentation')
|
|
117
155
|
.argument('[directory]', 'Directory to analyze', '.')
|
|
118
156
|
.option('--max-depth <number>', 'Maximum acceptable import depth', '5')
|
|
119
|
-
.option(
|
|
157
|
+
.option(
|
|
158
|
+
'--max-context <number>',
|
|
159
|
+
'Maximum acceptable context budget (tokens)',
|
|
160
|
+
'10000'
|
|
161
|
+
)
|
|
120
162
|
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
121
163
|
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
122
164
|
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
123
165
|
.option('--output-file <path>', 'Output file path (for json)')
|
|
124
|
-
.option(
|
|
166
|
+
.option(
|
|
167
|
+
'--score',
|
|
168
|
+
'Calculate and display AI Readiness Score for context (0-100)'
|
|
169
|
+
)
|
|
125
170
|
.action(async (directory, options) => {
|
|
126
171
|
await contextAction(directory, options);
|
|
127
172
|
});
|
|
@@ -135,12 +180,23 @@ program
|
|
|
135
180
|
.option('--no-naming', 'Skip naming analysis')
|
|
136
181
|
.option('--patterns', 'Check code patterns (default: true)')
|
|
137
182
|
.option('--no-patterns', 'Skip pattern analysis')
|
|
138
|
-
.option(
|
|
183
|
+
.option(
|
|
184
|
+
'--min-severity <level>',
|
|
185
|
+
'Minimum severity: info|minor|major|critical',
|
|
186
|
+
'info'
|
|
187
|
+
)
|
|
139
188
|
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
140
189
|
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
141
|
-
.option(
|
|
190
|
+
.option(
|
|
191
|
+
'-o, --output <format>',
|
|
192
|
+
'Output format: console, json, markdown',
|
|
193
|
+
'console'
|
|
194
|
+
)
|
|
142
195
|
.option('--output-file <path>', 'Output file path (for json/markdown)')
|
|
143
|
-
.option(
|
|
196
|
+
.option(
|
|
197
|
+
'--score',
|
|
198
|
+
'Calculate and display AI Readiness Score for consistency (0-100)'
|
|
199
|
+
)
|
|
144
200
|
.action(async (directory, options) => {
|
|
145
201
|
await consistencyAction(directory, options);
|
|
146
202
|
});
|
|
@@ -150,11 +206,26 @@ program
|
|
|
150
206
|
.command('visualise')
|
|
151
207
|
.description('Alias for visualize (British spelling)')
|
|
152
208
|
.argument('[directory]', 'Directory to analyze', '.')
|
|
153
|
-
.option(
|
|
154
|
-
|
|
209
|
+
.option(
|
|
210
|
+
'--report <path>',
|
|
211
|
+
'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)'
|
|
212
|
+
)
|
|
213
|
+
.option(
|
|
214
|
+
'-o, --output <path>',
|
|
215
|
+
'Output HTML path (relative to directory)',
|
|
216
|
+
'packages/visualizer/visualization.html'
|
|
217
|
+
)
|
|
155
218
|
.option('--open', 'Open generated HTML in default browser')
|
|
156
|
-
.option(
|
|
157
|
-
|
|
219
|
+
.option(
|
|
220
|
+
'--serve [port]',
|
|
221
|
+
'Start a local static server to serve the visualization (optional port number)',
|
|
222
|
+
false
|
|
223
|
+
)
|
|
224
|
+
.option(
|
|
225
|
+
'--dev',
|
|
226
|
+
'Start Vite dev server (live reload) for interactive development',
|
|
227
|
+
true
|
|
228
|
+
)
|
|
158
229
|
.addHelpText('after', visualiseHelpText)
|
|
159
230
|
.action(async (directory, options) => {
|
|
160
231
|
await visualizeAction(directory, options);
|
|
@@ -165,11 +236,26 @@ program
|
|
|
165
236
|
.command('visualize')
|
|
166
237
|
.description('Generate interactive visualization from an AIReady report')
|
|
167
238
|
.argument('[directory]', 'Directory to analyze', '.')
|
|
168
|
-
.option(
|
|
169
|
-
|
|
239
|
+
.option(
|
|
240
|
+
'--report <path>',
|
|
241
|
+
'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)'
|
|
242
|
+
)
|
|
243
|
+
.option(
|
|
244
|
+
'-o, --output <path>',
|
|
245
|
+
'Output HTML path (relative to directory)',
|
|
246
|
+
'packages/visualizer/visualization.html'
|
|
247
|
+
)
|
|
170
248
|
.option('--open', 'Open generated HTML in default browser')
|
|
171
|
-
.option(
|
|
172
|
-
|
|
249
|
+
.option(
|
|
250
|
+
'--serve [port]',
|
|
251
|
+
'Start a local static server to serve the visualization (optional port number)',
|
|
252
|
+
false
|
|
253
|
+
)
|
|
254
|
+
.option(
|
|
255
|
+
'--dev',
|
|
256
|
+
'Start Vite dev server (live reload) for interactive development',
|
|
257
|
+
false
|
|
258
|
+
)
|
|
173
259
|
.addHelpText('after', visualizeHelpText)
|
|
174
260
|
.action(async (directory, options) => {
|
|
175
261
|
await visualizeAction(directory, options);
|
|
@@ -188,4 +274,4 @@ program
|
|
|
188
274
|
await changeAmplificationAction(directory, options);
|
|
189
275
|
});
|
|
190
276
|
|
|
191
|
-
program.parse();
|
|
277
|
+
program.parse();
|
|
@@ -8,9 +8,10 @@ import type { ToolScoringOutput } from '@aiready/core';
|
|
|
8
8
|
|
|
9
9
|
export async function agentGroundingAction(
|
|
10
10
|
directory: string,
|
|
11
|
-
options: any
|
|
11
|
+
options: any
|
|
12
12
|
): Promise<ToolScoringOutput | undefined> {
|
|
13
|
-
const { analyzeAgentGrounding, calculateGroundingScore } =
|
|
13
|
+
const { analyzeAgentGrounding, calculateGroundingScore } =
|
|
14
|
+
await import('@aiready/agent-grounding');
|
|
14
15
|
|
|
15
16
|
const config = await loadConfig(directory);
|
|
16
17
|
const merged = mergeConfigWithDefaults(config, {
|
|
@@ -33,14 +34,28 @@ export async function agentGroundingAction(
|
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
const scoreColor = (s: number) =>
|
|
36
|
-
s >= 85
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
s >= 85
|
|
38
|
+
? chalk.green
|
|
39
|
+
: s >= 70
|
|
40
|
+
? chalk.cyan
|
|
41
|
+
: s >= 50
|
|
42
|
+
? chalk.yellow
|
|
43
|
+
: chalk.red;
|
|
44
|
+
void scoreColor;
|
|
45
|
+
|
|
46
|
+
console.log(
|
|
47
|
+
` 🧭 Agent Grounding: ${chalk.bold(scoring.score + '/100')} (${report.summary.rating})`
|
|
48
|
+
);
|
|
39
49
|
const dims = report.summary.dimensions;
|
|
40
50
|
const worstDim = Object.entries(dims).sort(([, a], [, b]) => a - b)[0];
|
|
41
51
|
if (worstDim && worstDim[1] < 70) {
|
|
42
|
-
const name = worstDim[0]
|
|
43
|
-
|
|
52
|
+
const name = worstDim[0]
|
|
53
|
+
.replace(/([A-Z])/g, ' $1')
|
|
54
|
+
.replace('Score', '')
|
|
55
|
+
.trim();
|
|
56
|
+
console.log(
|
|
57
|
+
chalk.dim(` Weakest dimension: ${name} (${worstDim[1]}/100)`)
|
|
58
|
+
);
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
return scoring;
|
|
@@ -3,16 +3,15 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
-
import {
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import { resolveOutputPath, loadConfig, mergeConfigWithDefaults } from '@aiready/core';
|
|
6
|
+
import { loadConfig, mergeConfigWithDefaults } from '@aiready/core';
|
|
9
7
|
import type { ToolScoringOutput } from '@aiready/core';
|
|
10
8
|
|
|
11
9
|
export async function aiSignalClarityAction(
|
|
12
10
|
directory: string,
|
|
13
|
-
options: any
|
|
11
|
+
options: any
|
|
14
12
|
): Promise<ToolScoringOutput | undefined> {
|
|
15
|
-
const { analyzeAiSignalClarity, calculateHallucinationScore } =
|
|
13
|
+
const { analyzeAiSignalClarity, calculateHallucinationScore } =
|
|
14
|
+
await import('@aiready/ai-signal-clarity');
|
|
16
15
|
|
|
17
16
|
const config = await loadConfig(directory);
|
|
18
17
|
const merged = mergeConfigWithDefaults(config, {
|
|
@@ -33,7 +32,7 @@ export async function aiSignalClarityAction(
|
|
|
33
32
|
}
|
|
34
33
|
|
|
35
34
|
const { summary } = report;
|
|
36
|
-
const ratingColors: Record<string,
|
|
35
|
+
const ratingColors: Record<string, (s: string) => string> = {
|
|
37
36
|
minimal: chalk.green,
|
|
38
37
|
low: chalk.cyan,
|
|
39
38
|
moderate: chalk.yellow,
|
|
@@ -41,10 +40,16 @@ export async function aiSignalClarityAction(
|
|
|
41
40
|
severe: chalk.bgRed.white,
|
|
42
41
|
};
|
|
43
42
|
const color = ratingColors[summary.rating] ?? chalk.white;
|
|
44
|
-
console.log(
|
|
43
|
+
console.log(
|
|
44
|
+
` 🧠 AI Signal Clarity: ${chalk.bold(scoring.score + '/100')} (${color(summary.rating)})`
|
|
45
|
+
);
|
|
45
46
|
console.log(` Top Risk: ${chalk.italic(summary.topRisk)}`);
|
|
46
47
|
if (summary.totalSignals > 0) {
|
|
47
|
-
console.log(
|
|
48
|
+
console.log(
|
|
49
|
+
chalk.dim(
|
|
50
|
+
` ${summary.criticalSignals} critical ${summary.majorSignals} major ${summary.minorSignals} minor signals`
|
|
51
|
+
)
|
|
52
|
+
);
|
|
48
53
|
}
|
|
49
54
|
|
|
50
55
|
return scoring;
|
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { writeFileSync } from 'fs';
|
|
7
7
|
import { resolve as resolvePath } from 'path';
|
|
8
|
-
import {
|
|
9
|
-
loadMergedConfig,
|
|
10
|
-
handleJSONOutput,
|
|
11
|
-
handleCLIError,
|
|
12
|
-
getElapsedTime,
|
|
8
|
+
import {
|
|
9
|
+
loadMergedConfig,
|
|
10
|
+
handleJSONOutput,
|
|
11
|
+
handleCLIError,
|
|
12
|
+
getElapsedTime,
|
|
13
13
|
resolveOutputPath,
|
|
14
14
|
formatToolScore,
|
|
15
15
|
} from '@aiready/core';
|
|
@@ -27,7 +27,10 @@ interface ConsistencyOptions {
|
|
|
27
27
|
score?: boolean;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
export async function consistencyAction(
|
|
30
|
+
export async function consistencyAction(
|
|
31
|
+
directory: string,
|
|
32
|
+
options: ConsistencyOptions
|
|
33
|
+
) {
|
|
31
34
|
console.log(chalk.blue('🔍 Analyzing consistency...\n'));
|
|
32
35
|
|
|
33
36
|
const startTime = Date.now();
|
|
@@ -56,20 +59,25 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
56
59
|
exclude: options.exclude?.split(','),
|
|
57
60
|
});
|
|
58
61
|
|
|
59
|
-
const { analyzeConsistency, calculateConsistencyScore } =
|
|
62
|
+
const { analyzeConsistency, calculateConsistencyScore } =
|
|
63
|
+
await import('@aiready/consistency');
|
|
60
64
|
|
|
61
65
|
const report = await analyzeConsistency(finalOptions);
|
|
62
66
|
|
|
63
67
|
const elapsedTime = getElapsedTime(startTime);
|
|
64
|
-
|
|
68
|
+
|
|
65
69
|
// Calculate score if requested
|
|
66
70
|
let consistencyScore: ToolScoringOutput | undefined;
|
|
67
71
|
if (options.score) {
|
|
68
72
|
const issues = report.results?.flatMap((r: any) => r.issues) || [];
|
|
69
|
-
consistencyScore = calculateConsistencyScore(
|
|
73
|
+
consistencyScore = calculateConsistencyScore(
|
|
74
|
+
issues,
|
|
75
|
+
report.summary.filesAnalyzed
|
|
76
|
+
);
|
|
70
77
|
}
|
|
71
78
|
|
|
72
|
-
const outputFormat =
|
|
79
|
+
const outputFormat =
|
|
80
|
+
options.output || finalOptions.output?.format || 'console';
|
|
73
81
|
const userOutputFile = options.outputFile || finalOptions.output?.file;
|
|
74
82
|
|
|
75
83
|
if (outputFormat === 'json') {
|
|
@@ -87,8 +95,12 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
87
95
|
`aiready-report-${getReportTimestamp()}.json`,
|
|
88
96
|
resolvedDir
|
|
89
97
|
);
|
|
90
|
-
|
|
91
|
-
handleJSONOutput(
|
|
98
|
+
|
|
99
|
+
handleJSONOutput(
|
|
100
|
+
outputData,
|
|
101
|
+
outputPath,
|
|
102
|
+
`✅ Results saved to ${outputPath}`
|
|
103
|
+
);
|
|
92
104
|
} else if (outputFormat === 'markdown') {
|
|
93
105
|
// Markdown output
|
|
94
106
|
const markdown = generateMarkdownReport(report, elapsedTime);
|
|
@@ -102,15 +114,23 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
102
114
|
} else {
|
|
103
115
|
// Console output - format to match standalone CLI
|
|
104
116
|
console.log(chalk.bold('\n📊 Summary\n'));
|
|
105
|
-
console.log(
|
|
117
|
+
console.log(
|
|
118
|
+
`Files Analyzed: ${chalk.cyan(report.summary.filesAnalyzed)}`
|
|
119
|
+
);
|
|
106
120
|
console.log(`Total Issues: ${chalk.yellow(report.summary.totalIssues)}`);
|
|
107
121
|
console.log(` Naming: ${chalk.yellow(report.summary.namingIssues)}`);
|
|
108
122
|
console.log(` Patterns: ${chalk.yellow(report.summary.patternIssues)}`);
|
|
109
|
-
console.log(
|
|
123
|
+
console.log(
|
|
124
|
+
` Architecture: ${chalk.yellow(report.summary.architectureIssues || 0)}`
|
|
125
|
+
);
|
|
110
126
|
console.log(`Analysis Time: ${chalk.gray(elapsedTime + 's')}\n`);
|
|
111
127
|
|
|
112
128
|
if (report.summary.totalIssues === 0) {
|
|
113
|
-
console.log(
|
|
129
|
+
console.log(
|
|
130
|
+
chalk.green(
|
|
131
|
+
'✨ No consistency issues found! Your codebase is well-maintained.\n'
|
|
132
|
+
)
|
|
133
|
+
);
|
|
114
134
|
} else {
|
|
115
135
|
// Group and display issues by category
|
|
116
136
|
const namingResults = report.results.filter((r: any) =>
|
|
@@ -127,19 +147,29 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
127
147
|
if (shown >= 5) break;
|
|
128
148
|
for (const issue of result.issues) {
|
|
129
149
|
if (shown >= 5) break;
|
|
130
|
-
const severityColor =
|
|
131
|
-
issue.severity === '
|
|
132
|
-
|
|
133
|
-
|
|
150
|
+
const severityColor =
|
|
151
|
+
issue.severity === 'critical'
|
|
152
|
+
? chalk.red
|
|
153
|
+
: issue.severity === 'major'
|
|
154
|
+
? chalk.yellow
|
|
155
|
+
: issue.severity === 'minor'
|
|
156
|
+
? chalk.blue
|
|
157
|
+
: chalk.gray;
|
|
158
|
+
console.log(
|
|
159
|
+
`${severityColor(issue.severity.toUpperCase())} ${chalk.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
160
|
+
);
|
|
134
161
|
console.log(` ${issue.message}`);
|
|
135
162
|
if (issue.suggestion) {
|
|
136
|
-
console.log(
|
|
163
|
+
console.log(
|
|
164
|
+
` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`
|
|
165
|
+
);
|
|
137
166
|
}
|
|
138
167
|
console.log();
|
|
139
168
|
shown++;
|
|
140
169
|
}
|
|
141
170
|
}
|
|
142
|
-
const remaining =
|
|
171
|
+
const remaining =
|
|
172
|
+
namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
143
173
|
if (remaining > 0) {
|
|
144
174
|
console.log(chalk.dim(` ... and ${remaining} more issues\n`));
|
|
145
175
|
}
|
|
@@ -152,19 +182,29 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
152
182
|
if (shown >= 5) break;
|
|
153
183
|
for (const issue of result.issues) {
|
|
154
184
|
if (shown >= 5) break;
|
|
155
|
-
const severityColor =
|
|
156
|
-
issue.severity === '
|
|
157
|
-
|
|
158
|
-
|
|
185
|
+
const severityColor =
|
|
186
|
+
issue.severity === 'critical'
|
|
187
|
+
? chalk.red
|
|
188
|
+
: issue.severity === 'major'
|
|
189
|
+
? chalk.yellow
|
|
190
|
+
: issue.severity === 'minor'
|
|
191
|
+
? chalk.blue
|
|
192
|
+
: chalk.gray;
|
|
193
|
+
console.log(
|
|
194
|
+
`${severityColor(issue.severity.toUpperCase())} ${chalk.dim(`${issue.location.file}:${issue.location.line}`)}`
|
|
195
|
+
);
|
|
159
196
|
console.log(` ${issue.message}`);
|
|
160
197
|
if (issue.suggestion) {
|
|
161
|
-
console.log(
|
|
198
|
+
console.log(
|
|
199
|
+
` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`
|
|
200
|
+
);
|
|
162
201
|
}
|
|
163
202
|
console.log();
|
|
164
203
|
shown++;
|
|
165
204
|
}
|
|
166
205
|
}
|
|
167
|
-
const remaining =
|
|
206
|
+
const remaining =
|
|
207
|
+
patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
|
|
168
208
|
if (remaining > 0) {
|
|
169
209
|
console.log(chalk.dim(` ... and ${remaining} more issues\n`));
|
|
170
210
|
}
|
|
@@ -178,7 +218,7 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
178
218
|
console.log();
|
|
179
219
|
}
|
|
180
220
|
}
|
|
181
|
-
|
|
221
|
+
|
|
182
222
|
// Display score if calculated
|
|
183
223
|
if (consistencyScore) {
|
|
184
224
|
console.log(chalk.bold('\n📊 AI Readiness Score (Consistency)\n'));
|
|
@@ -189,4 +229,4 @@ export async function consistencyAction(directory: string, options: ConsistencyO
|
|
|
189
229
|
} catch (error) {
|
|
190
230
|
handleCLIError(error, 'Consistency analysis');
|
|
191
231
|
}
|
|
192
|
-
}
|
|
232
|
+
}
|