@aiready/cli 0.9.40 → 0.9.43

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/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(...a.issues.map((i) => severityOrder[i.severity] || 0), 0);
56
- const bMaxSeverity = Math.max(...b.issues.map((i) => severityOrder[i.severity] || 0), 0);
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
  }
@@ -120,7 +126,8 @@ async function analyzeUnified(options) {
120
126
  const report = await analyzeDocDrift({
121
127
  rootDir: options.rootDir,
122
128
  include: options.include,
123
- exclude: options.exclude
129
+ exclude: options.exclude,
130
+ onProgress: options.onProgress
124
131
  });
125
132
  if (options.progressCallback) {
126
133
  options.progressCallback({ tool: "doc-drift", data: report });
@@ -133,7 +140,8 @@ async function analyzeUnified(options) {
133
140
  const report = await analyzeDeps({
134
141
  rootDir: options.rootDir,
135
142
  include: options.include,
136
- exclude: options.exclude
143
+ exclude: options.exclude,
144
+ onProgress: options.onProgress
137
145
  });
138
146
  if (options.progressCallback) {
139
147
  options.progressCallback({ tool: "deps-health", data: report });
@@ -146,20 +154,25 @@ async function analyzeUnified(options) {
146
154
  const report = await analyzeAiSignalClarity({
147
155
  rootDir: options.rootDir,
148
156
  include: options.include,
149
- exclude: options.exclude
157
+ exclude: options.exclude,
158
+ onProgress: options.onProgress
150
159
  });
151
160
  if (options.progressCallback) {
152
161
  options.progressCallback({ tool: "aiSignalClarity", data: report });
153
162
  }
154
163
  result.aiSignalClarity = report;
155
- result.summary.totalIssues += report.results?.reduce((sum, r) => sum + (r.issues?.length || 0), 0) || 0;
164
+ result.summary.totalIssues += report.results?.reduce(
165
+ (sum, r) => sum + (r.issues?.length || 0),
166
+ 0
167
+ ) || 0;
156
168
  }
157
169
  if (tools.includes("grounding")) {
158
170
  const { analyzeAgentGrounding } = await import("@aiready/agent-grounding");
159
171
  const report = await analyzeAgentGrounding({
160
172
  rootDir: options.rootDir,
161
173
  include: options.include,
162
- exclude: options.exclude
174
+ exclude: options.exclude,
175
+ onProgress: options.onProgress
163
176
  });
164
177
  if (options.progressCallback) {
165
178
  options.progressCallback({ tool: "grounding", data: report });
@@ -172,7 +185,8 @@ async function analyzeUnified(options) {
172
185
  const report = await analyzeTestability({
173
186
  rootDir: options.rootDir,
174
187
  include: options.include,
175
- exclude: options.exclude
188
+ exclude: options.exclude,
189
+ onProgress: options.onProgress
176
190
  });
177
191
  if (options.progressCallback) {
178
192
  options.progressCallback({ tool: "testability", data: report });
@@ -185,7 +199,8 @@ async function analyzeUnified(options) {
185
199
  const report = await analyzeChangeAmplification({
186
200
  rootDir: options.rootDir,
187
201
  include: options.include,
188
- exclude: options.exclude
202
+ exclude: options.exclude,
203
+ onProgress: options.onProgress
189
204
  });
190
205
  if (options.progressCallback) {
191
206
  options.progressCallback({ tool: "changeAmplification", data: report });
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  analyzeUnified,
3
3
  generateUnifiedSummary
4
- } from "./chunk-PDOONNSK.mjs";
4
+ } from "./chunk-LLJMKNBI.mjs";
5
5
  export {
6
6
  analyzeUnified,
7
7
  generateUnifiedSummary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.9.40",
3
+ "version": "0.9.43",
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.5",
15
- "@aiready/consistency": "0.8.31",
16
- "@aiready/core": "0.9.32",
17
- "@aiready/context-analyzer": "0.9.35",
18
- "@aiready/pattern-detect": "0.11.31",
19
- "@aiready/change-amplification": "0.1.5",
20
- "@aiready/testability": "0.1.5",
21
- "@aiready/visualizer": "0.1.37",
22
- "@aiready/deps": "0.1.5",
23
- "@aiready/doc-drift": "0.1.5",
24
- "@aiready/ai-signal-clarity": "0.1.5"
14
+ "@aiready/core": "0.9.35",
15
+ "@aiready/ai-signal-clarity": "0.1.8",
16
+ "@aiready/agent-grounding": "0.1.8",
17
+ "@aiready/pattern-detect": "0.11.34",
18
+ "@aiready/testability": "0.1.8",
19
+ "@aiready/context-analyzer": "0.9.38",
20
+ "@aiready/visualizer": "0.1.40",
21
+ "@aiready/consistency": "0.8.34",
22
+ "@aiready/deps": "0.1.8",
23
+ "@aiready/change-amplification": "0.1.8",
24
+ "@aiready/doc-drift": "0.1.8"
25
25
  },
26
26
  "devDependencies": {
27
27
  "@types/node": "^24.0.0",
@@ -56,4 +56,4 @@ describe('CLI Unified Analysis', () => {
56
56
  expect(results).toHaveProperty('context');
57
57
  expect(results).toHaveProperty('summary');
58
58
  });
59
- });
59
+ });
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(readFileSync(join(getDirname(), '../package.json'), 'utf8'));
26
+ const packageJson = JSON.parse(
27
+ readFileSync(join(getDirname(), '../package.json'), 'utf8')
28
+ );
27
29
 
28
30
  const program = new Command();
29
31
 
@@ -31,7 +33,9 @@ program
31
33
  .name('aiready')
32
34
  .description('AIReady - Assess and improve AI-readiness of codebases')
33
35
  .version(packageJson.version)
34
- .addHelpText('after', `
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.
@@ -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('Run comprehensive AI-readiness analysis (patterns + context + consistency)')
79
+ .description(
80
+ 'Run comprehensive AI-readiness analysis (patterns + context + consistency)'
81
+ )
75
82
  .argument('[directory]', 'Directory to analyze', '.')
76
- .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)')
77
- .option('--profile <type>', 'Scan profile to use (agentic, cost, security, onboarding)')
78
- .option('--compare-to <path>', 'Compare results against a previous AIReady report JSON')
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
97
  .option('-o, --output <format>', 'Output format: console, json', 'console')
82
98
  .option('--output-file <path>', 'Output file path (for json)')
83
- .option('--no-score', 'Disable calculating AI Readiness Score (enabled by default)')
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('--ci', 'CI mode: GitHub Actions annotations, no colors, fail on threshold')
87
- .option('--fail-on <level>', 'Fail on issues: critical, major, any', 'critical')
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('--max-candidates <number>', 'Maximum candidates per block (performance tuning)')
101
- .option('--min-shared-tokens <number>', 'Minimum shared tokens for candidates (performance tuning)')
102
- .option('--full-scan', 'Disable smart defaults for comprehensive analysis (slower)')
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('--score', 'Calculate and display AI Readiness Score for patterns (0-100)')
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('--max-context <number>', 'Maximum acceptable context budget (tokens)', '10000')
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('--score', 'Calculate and display AI Readiness Score for context (0-100)')
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('--min-severity <level>', 'Minimum severity: info|minor|major|critical', 'info')
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('-o, --output <format>', 'Output format: console, json, markdown', 'console')
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('--score', 'Calculate and display AI Readiness Score for consistency (0-100)')
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('--report <path>', 'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)')
154
- .option('-o, --output <path>', 'Output HTML path (relative to directory)', 'packages/visualizer/visualization.html')
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('--serve [port]', 'Start a local static server to serve the visualization (optional port number)', false)
157
- .option('--dev', 'Start Vite dev server (live reload) for interactive development', true)
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('--report <path>', 'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)')
169
- .option('-o, --output <path>', 'Output HTML path (relative to directory)', 'packages/visualizer/visualization.html')
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('--serve [port]', 'Start a local static server to serve the visualization (optional port number)', false)
172
- .option('--dev', 'Start Vite dev server (live reload) for interactive development', false)
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 } = await import('@aiready/agent-grounding');
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 ? chalk.green : s >= 70 ? chalk.cyan : s >= 50 ? chalk.yellow : chalk.red;
37
-
38
- console.log(` 🧭 Agent Grounding: ${chalk.bold(scoring.score + '/100')} (${report.summary.rating})`);
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].replace(/([A-Z])/g, ' $1').replace('Score', '').trim();
43
- console.log(chalk.dim(` Weakest dimension: ${name} (${worstDim[1]}/100)`));
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 { writeFileSync } from 'fs';
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 } = await import('@aiready/ai-signal-clarity');
13
+ const { analyzeAiSignalClarity, calculateAiSignalClarityScore } =
14
+ await import('@aiready/ai-signal-clarity');
16
15
 
17
16
  const config = await loadConfig(directory);
18
17
  const merged = mergeConfigWithDefaults(config, {
@@ -26,14 +25,14 @@ export async function aiSignalClarityAction(
26
25
  exclude: options.exclude,
27
26
  });
28
27
 
29
- const scoring = calculateHallucinationScore(report);
28
+ const scoring = calculateAiSignalClarityScore(report);
30
29
 
31
30
  if (options.output === 'json') {
32
31
  return scoring;
33
32
  }
34
33
 
35
34
  const { summary } = report;
36
- const ratingColors: Record<string, Function> = {
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(` 🧠 AI Signal Clarity: ${chalk.bold(scoring.score + '/100')} (${color(summary.rating)})`);
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(chalk.dim(` ${summary.criticalSignals} critical ${summary.majorSignals} major ${summary.minorSignals} minor signals`));
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(directory: string, options: ConsistencyOptions) {
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();
@@ -35,7 +38,7 @@ export async function consistencyAction(directory: string, options: ConsistencyO
35
38
 
36
39
  try {
37
40
  // Define defaults
38
- const defaults = {
41
+ const defaults: any = {
39
42
  checkNaming: true,
40
43
  checkPatterns: true,
41
44
  minSeverity: 'info' as const,
@@ -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 } = await import('@aiready/consistency');
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(issues, report.summary.filesAnalyzed);
73
+ consistencyScore = calculateConsistencyScore(
74
+ issues,
75
+ report.summary.filesAnalyzed
76
+ );
70
77
  }
71
78
 
72
- const outputFormat = options.output || finalOptions.output?.format || 'console';
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(outputData, outputPath, `✅ Results saved to ${outputPath}`);
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(`Files Analyzed: ${chalk.cyan(report.summary.filesAnalyzed)}`);
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(` Architecture: ${chalk.yellow(report.summary.architectureIssues || 0)}`);
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(chalk.green('✨ No consistency issues found! Your codebase is well-maintained.\n'));
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 = issue.severity === 'critical' ? chalk.red :
131
- issue.severity === 'major' ? chalk.yellow :
132
- issue.severity === 'minor' ? chalk.blue : chalk.gray;
133
- console.log(`${severityColor(issue.severity.toUpperCase())} ${chalk.dim(`${issue.location.file}:${issue.location.line}`)}`);
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(` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`);
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 = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
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 = issue.severity === 'critical' ? chalk.red :
156
- issue.severity === 'major' ? chalk.yellow :
157
- issue.severity === 'minor' ? chalk.blue : chalk.gray;
158
- console.log(`${severityColor(issue.severity.toUpperCase())} ${chalk.dim(`${issue.location.file}:${issue.location.line}`)}`);
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(` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`);
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 = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
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
+ }