@aiready/cli 0.14.14 → 0.14.16

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.
Files changed (98) hide show
  1. package/CONTRIBUTING.md +86 -1
  2. package/LICENSE +21 -0
  3. package/README.md +152 -52
  4. package/dist/cli.js +73 -12
  5. package/dist/cli.mjs +73 -12
  6. package/package.json +44 -14
  7. package/.aiready/aiready-report-20260227-133806.json +0 -7805
  8. package/.aiready/aiready-report-20260227-133938.json +0 -7951
  9. package/.aiready/aiready-report-20260228-003433.json +0 -7939
  10. package/.aiready/aiready-report-20260228-003613.json +0 -771
  11. package/.aiready/aiready-report-20260314-164626.json +0 -59
  12. package/.aiready/aiready-report-20260314-164741.json +0 -59
  13. package/.aiready/aiready-report-20260319-201106.json +0 -5566
  14. package/.aiready/aiready-report-20260319-201511.json +0 -5566
  15. package/.aiready/aiready-report-20260319-202017.json +0 -5708
  16. package/.github/FUNDING.yml +0 -5
  17. package/.turbo/turbo-build.log +0 -29
  18. package/.turbo/turbo-lint.log +0 -0
  19. package/.turbo/turbo-test.log +0 -76
  20. package/aiready-report.json +0 -30703
  21. package/coverage/base.css +0 -224
  22. package/coverage/block-navigation.js +0 -87
  23. package/coverage/clover.xml +0 -865
  24. package/coverage/coverage-final.json +0 -15
  25. package/coverage/favicon.png +0 -0
  26. package/coverage/index.html +0 -146
  27. package/coverage/prettify.css +0 -1
  28. package/coverage/prettify.js +0 -2
  29. package/coverage/sort-arrow-sprite.png +0 -0
  30. package/coverage/sorter.js +0 -210
  31. package/coverage/src/commands/agent-grounding.ts.html +0 -271
  32. package/coverage/src/commands/ai-signal-clarity.ts.html +0 -253
  33. package/coverage/src/commands/change-amplification.ts.html +0 -94
  34. package/coverage/src/commands/consistency.ts.html +0 -781
  35. package/coverage/src/commands/context.ts.html +0 -871
  36. package/coverage/src/commands/deps-health.ts.html +0 -280
  37. package/coverage/src/commands/doc-drift.ts.html +0 -271
  38. package/coverage/src/commands/index.html +0 -281
  39. package/coverage/src/commands/patterns.ts.html +0 -745
  40. package/coverage/src/commands/scan.ts.html +0 -1393
  41. package/coverage/src/commands/testability.ts.html +0 -304
  42. package/coverage/src/commands/upload.ts.html +0 -466
  43. package/coverage/src/commands/visualize.ts.html +0 -1027
  44. package/coverage/src/index.html +0 -116
  45. package/coverage/src/index.ts.html +0 -1372
  46. package/coverage/src/utils/helpers.ts.html +0 -559
  47. package/coverage/src/utils/index.html +0 -116
  48. package/docs/SPOKE_GUIDE.md +0 -184
  49. package/packages/core/src/.aiready/aiready-report-20260314-161145.json +0 -224
  50. package/packages/core/src/.aiready/aiready-report-20260314-161152.json +0 -235
  51. package/packages/pattern-detect/src/.aiready/aiready-report-20260314-161139.json +0 -224
  52. package/src/.aiready/aiready-report-20260312-103623.json +0 -32574
  53. package/src/.aiready/aiready-report-20260312-110843.json +0 -28740
  54. package/src/.aiready/aiready-report-20260312-110955.json +0 -28740
  55. package/src/.aiready/aiready-report-20260314-203209.json +0 -30713
  56. package/src/.aiready/aiready-report-20260314-203736.json +0 -30713
  57. package/src/.aiready/aiready-report-20260314-203857.json +0 -30713
  58. package/src/.aiready/aiready-report-20260314-204047.json +0 -30713
  59. package/src/.aiready/aiready-report-20260318-002110.json +0 -28782
  60. package/src/__tests__/cli.test.ts +0 -85
  61. package/src/__tests__/config-shape.test.ts +0 -105
  62. package/src/__tests__/unified.test.ts +0 -95
  63. package/src/cli.ts +0 -333
  64. package/src/commands/__tests__/agent-grounding.test.ts +0 -24
  65. package/src/commands/__tests__/ai-signal-clarity.test.ts +0 -32
  66. package/src/commands/__tests__/consistency.test.ts +0 -100
  67. package/src/commands/__tests__/deps-health.test.ts +0 -26
  68. package/src/commands/__tests__/doc-drift.test.ts +0 -26
  69. package/src/commands/__tests__/extra-commands.test.ts +0 -168
  70. package/src/commands/__tests__/init.test.ts +0 -51
  71. package/src/commands/__tests__/scan.test.ts +0 -153
  72. package/src/commands/__tests__/testability.test.ts +0 -36
  73. package/src/commands/__tests__/upload.test.ts +0 -50
  74. package/src/commands/__tests__/visualize.test.ts +0 -78
  75. package/src/commands/agent-grounding.ts +0 -62
  76. package/src/commands/ai-signal-clarity.ts +0 -1
  77. package/src/commands/bug.ts +0 -99
  78. package/src/commands/change-amplification.ts +0 -3
  79. package/src/commands/consistency.ts +0 -232
  80. package/src/commands/context.ts +0 -262
  81. package/src/commands/deps-health.ts +0 -1
  82. package/src/commands/doc-drift.ts +0 -1
  83. package/src/commands/index.ts +0 -20
  84. package/src/commands/init.ts +0 -199
  85. package/src/commands/patterns.ts +0 -222
  86. package/src/commands/report-formatter.ts +0 -267
  87. package/src/commands/scan.ts +0 -432
  88. package/src/commands/shared/configured-tool-action.ts +0 -35
  89. package/src/commands/shared/standard-tool-actions.ts +0 -126
  90. package/src/commands/testability.ts +0 -73
  91. package/src/commands/upload.ts +0 -129
  92. package/src/commands/visualize.ts +0 -321
  93. package/src/index.ts +0 -465
  94. package/src/utils/__tests__/helpers.test.ts +0 -35
  95. package/src/utils/helpers.ts +0 -234
  96. package/tsconfig.json +0 -11
  97. package/tsconfig.tsbuildinfo +0 -1
  98. package/vitest.config.ts +0 -13
@@ -1,62 +0,0 @@
1
- /**
2
- * Agent grounding command for unified CLI
3
- */
4
-
5
- import chalk from 'chalk';
6
- import { loadConfig, mergeConfigWithDefaults } from '@aiready/core';
7
- import type { ToolScoringOutput } from '@aiready/core';
8
-
9
- export async function agentGroundingAction(
10
- directory: string,
11
- options: any
12
- ): Promise<ToolScoringOutput | undefined> {
13
- const { analyzeAgentGrounding, calculateGroundingScore } =
14
- await import('@aiready/agent-grounding');
15
-
16
- const config = await loadConfig(directory);
17
- const merged = mergeConfigWithDefaults(config, {
18
- maxRecommendedDepth: 4,
19
- readmeStaleDays: 90,
20
- });
21
-
22
- const report = await analyzeAgentGrounding({
23
- rootDir: directory,
24
- maxRecommendedDepth: options.maxDepth ?? merged.maxRecommendedDepth,
25
- readmeStaleDays: options.readmeStaleDays ?? merged.readmeStaleDays,
26
- include: options.include,
27
- exclude: options.exclude,
28
- });
29
-
30
- const scoring = calculateGroundingScore(report);
31
-
32
- if (options.output === 'json') {
33
- return scoring;
34
- }
35
-
36
- const scoreColor = (s: number) =>
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
- );
49
- const dims = report.summary.dimensions;
50
- const worstDim = Object.entries(dims).sort(([, a], [, b]) => a - b)[0];
51
- if (worstDim && worstDim[1] < 70) {
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
- );
59
- }
60
-
61
- return scoring;
62
- }
@@ -1 +0,0 @@
1
- export { aiSignalClarityAction } from './shared/standard-tool-actions';
@@ -1,99 +0,0 @@
1
- import chalk from 'chalk';
2
-
3
- import { execSync } from 'child_process';
4
-
5
- /**
6
- * Handle bug and feedback reporting
7
- */
8
- export async function bugAction(message: string | undefined, options: any) {
9
- const repoUrl = 'https://github.com/caopengau/aiready-cli';
10
- const repoSlug = 'caopengau/aiready-cli';
11
-
12
- if (message) {
13
- // Agent-assisted pre-filled issue
14
- const type = options.type ?? 'bug';
15
- const title = `[${type.toUpperCase()}] ${message}`;
16
- const label =
17
- type === 'bug' ? 'bug' : type === 'feature' ? 'enhancement' : 'metric';
18
-
19
- const body = `
20
- ## Description
21
- ${message}
22
-
23
- ## Context
24
- Generated via AIReady CLI 'bug' command.
25
- Type: ${type}
26
- `.trim();
27
-
28
- if (options.submit) {
29
- console.log(chalk.blue('🚀 Submitting issue via GitHub CLI...\n'));
30
- try {
31
- // Check if gh is authenticated
32
- execSync('gh auth status', { stdio: 'ignore' });
33
-
34
- const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
35
- const output = execSync(command, { encoding: 'utf8' }).trim();
36
-
37
- console.log(chalk.green('✅ Issue Created Successfully!'));
38
- console.log(chalk.cyan(output));
39
- return;
40
- } catch {
41
- console.error(chalk.red('\n❌ Failed to submit via gh CLI.'));
42
- console.log(
43
- chalk.yellow(
44
- ' Make sure gh is installed and run "gh auth login".\n'
45
- )
46
- );
47
- console.log(chalk.dim(' Falling back to URL generation...'));
48
- }
49
- }
50
-
51
- const template =
52
- type === 'bug'
53
- ? 'bug_report.md'
54
- : type === 'feature'
55
- ? 'feature_request.md'
56
- : 'new_metric_idea.md';
57
- const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
58
-
59
- console.log(chalk.green('🚀 Issue Draft Prepared!\n'));
60
- console.log(chalk.bold('Title: ') + title);
61
- console.log(chalk.bold('Type: ') + type);
62
- console.log(chalk.bold('\nClick the link below to submit this issue:'));
63
- console.log(chalk.cyan(fullUrl));
64
-
65
- console.log(chalk.bold('\n🤖 [FOR AI AGENTS]:'));
66
- console.log(chalk.dim(' You have successfully prepared a report.'));
67
- console.log(
68
- chalk.dim(
69
- ' Please present the URL above to the user so they can finalize the submission.'
70
- )
71
- );
72
- return;
73
- }
74
-
75
- const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
76
- const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
77
- const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
78
-
79
- console.log(chalk.blue('💬 Feedback & Bug Reports\n'));
80
- console.log(` Report a Bug: ${chalk.cyan(bugUrl)}`);
81
- console.log(` Request a Feature: ${chalk.cyan(featureUrl)}`);
82
- console.log(` Suggest a Metric: ${chalk.cyan(metricUrl)}`);
83
-
84
- console.log(chalk.bold('\n🤖 [FOR AI AGENTS]:'));
85
- console.log(chalk.dim(' To prepare a specific report, run:'));
86
- console.log(
87
- chalk.cyan(
88
- ' aiready bug "your description here" --type bug|feature|metric'
89
- )
90
- );
91
- }
92
-
93
- export const bugHelpText = `
94
- EXAMPLES:
95
- $ aiready bug # Show general links
96
- $ aiready bug "Naming check is too slow" # Prepare a pre-filled bug report
97
- $ aiready bug "Add CO2 impact metric" --type metric # Prepare a metric suggestion
98
- $ aiready bug "Fix typo in scan output" --submit # Submit directly via gh CLI
99
- `;
@@ -1,3 +0,0 @@
1
- import { changeAmplificationAction } from '@aiready/change-amplification/dist/cli.js';
2
-
3
- export { changeAmplificationAction };
@@ -1,232 +0,0 @@
1
- /**
2
- * Consistency command - Check naming conventions and architectural consistency
3
- */
4
-
5
- import chalk from 'chalk';
6
- import { writeFileSync } from 'fs';
7
- import { resolve as resolvePath } from 'path';
8
- import {
9
- loadMergedConfig,
10
- handleJSONOutput,
11
- handleCLIError,
12
- getElapsedTime,
13
- resolveOutputPath,
14
- formatToolScore,
15
- } from '@aiready/core';
16
- import type { ToolScoringOutput } from '@aiready/core';
17
- import { getReportTimestamp, generateMarkdownReport } from '../utils/helpers';
18
-
19
- interface ConsistencyOptions {
20
- naming?: boolean;
21
- patterns?: boolean;
22
- minSeverity?: string;
23
- include?: string;
24
- exclude?: string;
25
- output?: string;
26
- outputFile?: string;
27
- score?: boolean;
28
- }
29
-
30
- export async function consistencyAction(
31
- directory: string,
32
- options: ConsistencyOptions
33
- ) {
34
- console.log(chalk.blue('🔍 Analyzing consistency...\n'));
35
-
36
- const startTime = Date.now();
37
- const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
38
-
39
- try {
40
- // Define defaults
41
- const defaults: any = {
42
- checkNaming: true,
43
- checkPatterns: true,
44
- minSeverity: 'info' as const,
45
- include: undefined,
46
- exclude: undefined,
47
- output: {
48
- format: 'console',
49
- file: undefined,
50
- },
51
- };
52
-
53
- // Load and merge config with CLI options
54
- const finalOptions = await loadMergedConfig(resolvedDir, defaults, {
55
- checkNaming: options.naming !== false,
56
- checkPatterns: options.patterns !== false,
57
- minSeverity: options.minSeverity,
58
- include: options.include?.split(','),
59
- exclude: options.exclude?.split(','),
60
- });
61
-
62
- const { analyzeConsistency, calculateConsistencyScore } =
63
- await import('@aiready/consistency');
64
-
65
- const report = await analyzeConsistency(finalOptions);
66
-
67
- const elapsedTime = getElapsedTime(startTime);
68
-
69
- // Calculate score if requested
70
- let consistencyScore: ToolScoringOutput | undefined;
71
- if (options.score) {
72
- const issues = report.results?.flatMap((r: any) => r.issues) ?? [];
73
- consistencyScore = calculateConsistencyScore(
74
- issues,
75
- report.summary.filesAnalyzed
76
- );
77
- }
78
-
79
- const outputFormat =
80
- options.output ?? finalOptions.output?.format ?? 'console';
81
- const userOutputFile = options.outputFile ?? finalOptions.output?.file;
82
-
83
- if (outputFormat === 'json') {
84
- const outputData = {
85
- ...report,
86
- summary: {
87
- ...report.summary,
88
- executionTime: parseFloat(elapsedTime),
89
- },
90
- ...(consistencyScore && { scoring: consistencyScore }),
91
- };
92
-
93
- const outputPath = resolveOutputPath(
94
- userOutputFile,
95
- `aiready-report-${getReportTimestamp()}.json`,
96
- resolvedDir
97
- );
98
-
99
- handleJSONOutput(
100
- outputData,
101
- outputPath,
102
- `✅ Results saved to ${outputPath}`
103
- );
104
- } else if (outputFormat === 'markdown') {
105
- // Markdown output
106
- const markdown = generateMarkdownReport(report, elapsedTime);
107
- const outputPath = resolveOutputPath(
108
- userOutputFile,
109
- `aiready-report-${getReportTimestamp()}.md`,
110
- resolvedDir
111
- );
112
- writeFileSync(outputPath, markdown);
113
- console.log(chalk.green(`✅ Report saved to ${outputPath}`));
114
- } else {
115
- // Console output - format to match standalone CLI
116
- console.log(chalk.bold('\n📊 Summary\n'));
117
- console.log(
118
- `Files Analyzed: ${chalk.cyan(report.summary.filesAnalyzed)}`
119
- );
120
- console.log(`Total Issues: ${chalk.yellow(report.summary.totalIssues)}`);
121
- console.log(` Naming: ${chalk.yellow(report.summary.namingIssues)}`);
122
- console.log(` Patterns: ${chalk.yellow(report.summary.patternIssues)}`);
123
- console.log(
124
- ` Architecture: ${chalk.yellow(report.summary.architectureIssues ?? 0)}`
125
- );
126
- console.log(`Analysis Time: ${chalk.gray(elapsedTime + 's')}\n`);
127
-
128
- if (report.summary.totalIssues === 0) {
129
- console.log(
130
- chalk.green(
131
- '✨ No consistency issues found! Your codebase is well-maintained.\n'
132
- )
133
- );
134
- } else {
135
- // Group and display issues by category
136
- const namingResults = report.results.filter((r: any) =>
137
- r.issues.some((i: any) => i.category === 'naming')
138
- );
139
- const patternResults = report.results.filter((r: any) =>
140
- r.issues.some((i: any) => i.category === 'patterns')
141
- );
142
-
143
- if (namingResults.length > 0) {
144
- console.log(chalk.bold('🏷️ Naming Issues\n'));
145
- let shown = 0;
146
- for (const result of namingResults) {
147
- if (shown >= 5) break;
148
- for (const issue of result.issues) {
149
- if (shown >= 5) break;
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
- );
161
- console.log(` ${issue.message}`);
162
- if (issue.suggestion) {
163
- console.log(
164
- ` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`
165
- );
166
- }
167
- console.log();
168
- shown++;
169
- }
170
- }
171
- const remaining =
172
- namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
173
- if (remaining > 0) {
174
- console.log(chalk.dim(` ... and ${remaining} more issues\n`));
175
- }
176
- }
177
-
178
- if (patternResults.length > 0) {
179
- console.log(chalk.bold('🔄 Pattern Issues\n'));
180
- let shown = 0;
181
- for (const result of patternResults) {
182
- if (shown >= 5) break;
183
- for (const issue of result.issues) {
184
- if (shown >= 5) break;
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
- );
196
- console.log(` ${issue.message}`);
197
- if (issue.suggestion) {
198
- console.log(
199
- ` ${chalk.dim('→')} ${chalk.italic(issue.suggestion)}`
200
- );
201
- }
202
- console.log();
203
- shown++;
204
- }
205
- }
206
- const remaining =
207
- patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
208
- if (remaining > 0) {
209
- console.log(chalk.dim(` ... and ${remaining} more issues\n`));
210
- }
211
- }
212
-
213
- if (report.recommendations.length > 0) {
214
- console.log(chalk.bold('💡 Recommendations\n'));
215
- report.recommendations.forEach((rec: string, i: number) => {
216
- console.log(`${i + 1}. ${rec}`);
217
- });
218
- console.log();
219
- }
220
- }
221
-
222
- // Display score if calculated
223
- if (consistencyScore) {
224
- console.log(chalk.bold('\n📊 AI Readiness Score (Consistency)\n'));
225
- console.log(formatToolScore(consistencyScore));
226
- console.log();
227
- }
228
- }
229
- } catch (error) {
230
- handleCLIError(error, 'Consistency analysis');
231
- }
232
- }
@@ -1,262 +0,0 @@
1
- /**
2
- * Context command - Analyze context window costs and dependency fragmentation
3
- */
4
-
5
- import chalk from 'chalk';
6
- import { resolve as resolvePath } from 'path';
7
- import {
8
- loadMergedConfig,
9
- handleJSONOutput,
10
- handleCLIError,
11
- getElapsedTime,
12
- resolveOutputPath,
13
- formatToolScore,
14
- } from '@aiready/core';
15
- import type { ToolScoringOutput } from '@aiready/core';
16
- import { getReportTimestamp } from '../utils/helpers';
17
-
18
- interface ContextOptions {
19
- maxDepth?: string;
20
- maxContext?: string;
21
- include?: string;
22
- exclude?: string;
23
- output?: string;
24
- outputFile?: string;
25
- score?: boolean;
26
- }
27
-
28
- export async function contextAction(
29
- directory: string,
30
- options: ContextOptions
31
- ) {
32
- console.log(chalk.blue('🧠 Analyzing context costs...\n'));
33
-
34
- const startTime = Date.now();
35
- const resolvedDir = resolvePath(process.cwd(), directory ?? '.');
36
-
37
- try {
38
- // Define defaults
39
- const defaults: any = {
40
- maxDepth: 5,
41
- maxContextBudget: 10000,
42
- include: undefined,
43
- exclude: undefined,
44
- output: {
45
- format: 'console',
46
- file: undefined,
47
- },
48
- };
49
-
50
- // Load and merge config with CLI options
51
- const baseOptions = await loadMergedConfig(resolvedDir, defaults, {
52
- maxDepth: options.maxDepth ? parseInt(options.maxDepth) : undefined,
53
- maxContextBudget: options.maxContext
54
- ? parseInt(options.maxContext)
55
- : undefined,
56
- include: options.include?.split(','),
57
- exclude: options.exclude?.split(','),
58
- });
59
-
60
- // Apply smart defaults for context analysis (always for individual context command)
61
- let finalOptions: any = { ...baseOptions };
62
- const { getSmartDefaults } = await import('@aiready/context-analyzer');
63
- const contextSmartDefaults = await getSmartDefaults(
64
- resolvedDir,
65
- baseOptions
66
- );
67
- finalOptions = { ...contextSmartDefaults, ...finalOptions };
68
-
69
- // Display configuration
70
- console.log('📋 Configuration:');
71
- console.log(` Max depth: ${finalOptions.maxDepth}`);
72
- console.log(` Max context budget: ${finalOptions.maxContextBudget}`);
73
- console.log(
74
- ` Min cohesion: ${(finalOptions.minCohesion * 100).toFixed(1)}%`
75
- );
76
- console.log(
77
- ` Max fragmentation: ${(finalOptions.maxFragmentation * 100).toFixed(1)}%`
78
- );
79
- console.log(` Analysis focus: ${finalOptions.focus}`);
80
- console.log('');
81
-
82
- const { analyzeContext, generateSummary, calculateContextScore } =
83
- await import('@aiready/context-analyzer');
84
-
85
- const results = await analyzeContext(finalOptions);
86
-
87
- const elapsedTime = getElapsedTime(startTime);
88
- const summary = generateSummary(results);
89
-
90
- // Calculate score if requested
91
- let contextScore: ToolScoringOutput | undefined;
92
- if (options.score) {
93
- contextScore = calculateContextScore(summary as any);
94
- }
95
-
96
- const outputFormat =
97
- options.output ?? finalOptions.output?.format ?? 'console';
98
- const userOutputFile = options.outputFile ?? finalOptions.output?.file;
99
-
100
- if (outputFormat === 'json') {
101
- const outputData = {
102
- results,
103
- summary: { ...summary, executionTime: parseFloat(elapsedTime) },
104
- ...(contextScore && { scoring: contextScore }),
105
- };
106
-
107
- const outputPath = resolveOutputPath(
108
- userOutputFile,
109
- `aiready-report-${getReportTimestamp()}.json`,
110
- resolvedDir
111
- );
112
-
113
- handleJSONOutput(
114
- outputData,
115
- outputPath,
116
- `✅ Results saved to ${outputPath}`
117
- );
118
- } else {
119
- // Console output - format the results nicely
120
- const terminalWidth = process.stdout.columns ?? 80;
121
- const dividerWidth = Math.min(60, terminalWidth - 2);
122
- const divider = '━'.repeat(dividerWidth);
123
-
124
- console.log(chalk.cyan(divider));
125
- console.log(chalk.bold.white(' CONTEXT ANALYSIS SUMMARY'));
126
- console.log(chalk.cyan(divider) + '\n');
127
-
128
- console.log(
129
- chalk.white(`📁 Files analyzed: ${chalk.bold(summary.totalFiles)}`)
130
- );
131
- console.log(
132
- chalk.white(
133
- `📊 Total tokens: ${chalk.bold(summary.totalTokens.toLocaleString())}`
134
- )
135
- );
136
- console.log(
137
- chalk.yellow(
138
- `💰 Avg context budget: ${chalk.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
139
- )
140
- );
141
- console.log(
142
- chalk.white(`⏱ Analysis time: ${chalk.bold(elapsedTime + 's')}\n`)
143
- );
144
-
145
- // Issues summary
146
- const totalIssues =
147
- summary.criticalIssues + summary.majorIssues + summary.minorIssues;
148
- if (totalIssues > 0) {
149
- console.log(chalk.bold('⚠️ Issues Found:\n'));
150
- if (summary.criticalIssues > 0) {
151
- console.log(
152
- chalk.red(` 🔴 Critical: ${chalk.bold(summary.criticalIssues)}`)
153
- );
154
- }
155
- if (summary.majorIssues > 0) {
156
- console.log(
157
- chalk.yellow(` 🟡 Major: ${chalk.bold(summary.majorIssues)}`)
158
- );
159
- }
160
- if (summary.minorIssues > 0) {
161
- console.log(
162
- chalk.blue(` 🔵 Minor: ${chalk.bold(summary.minorIssues)}`)
163
- );
164
- }
165
- console.log(
166
- chalk.green(
167
- `\n 💡 Potential savings: ${chalk.bold(summary.totalPotentialSavings.toLocaleString())} tokens\n`
168
- )
169
- );
170
- } else {
171
- console.log(chalk.green('✅ No significant issues found!\n'));
172
- }
173
-
174
- // Deep import chains
175
- if (summary.deepFiles.length > 0) {
176
- console.log(chalk.bold('📏 Deep Import Chains:\n'));
177
- console.log(
178
- chalk.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
179
- );
180
- console.log(
181
- chalk.gray(` Maximum depth: ${summary.maxImportDepth}\n`)
182
- );
183
- summary.deepFiles.slice(0, 10).forEach((item) => {
184
- const fileName = item.file.split('/').slice(-2).join('/');
185
- console.log(
186
- ` ${chalk.cyan('→')} ${chalk.white(fileName)} ${chalk.dim(`(depth: ${item.depth})`)}`
187
- );
188
- });
189
- console.log();
190
- }
191
-
192
- // Fragmented modules
193
- if (summary.fragmentedModules.length > 0) {
194
- console.log(chalk.bold('🧩 Fragmented Modules:\n'));
195
- console.log(
196
- chalk.gray(
197
- ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%\n`
198
- )
199
- );
200
- summary.fragmentedModules.slice(0, 10).forEach((module) => {
201
- console.log(
202
- ` ${chalk.yellow('●')} ${chalk.white(module.domain)} - ${chalk.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
203
- );
204
- console.log(
205
- chalk.dim(
206
- ` Token cost: ${module.totalTokens.toLocaleString()}, Cohesion: ${(module.avgCohesion * 100).toFixed(0)}%`
207
- )
208
- );
209
- });
210
- console.log();
211
- }
212
-
213
- // Low cohesion files
214
- if (summary.lowCohesionFiles.length > 0) {
215
- console.log(chalk.bold('🔀 Low Cohesion Files:\n'));
216
- console.log(
217
- chalk.gray(
218
- ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%\n`
219
- )
220
- );
221
- summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
222
- const fileName = item.file.split('/').slice(-2).join('/');
223
- const scorePercent = (item.score * 100).toFixed(0);
224
- const color = item.score < 0.4 ? chalk.red : chalk.yellow;
225
- console.log(
226
- ` ${color('○')} ${chalk.white(fileName)} ${chalk.dim(`(${scorePercent}% cohesion)`)}`
227
- );
228
- });
229
- console.log();
230
- }
231
-
232
- // Top expensive files
233
- if (summary.topExpensiveFiles.length > 0) {
234
- console.log(chalk.bold('💸 Most Expensive Files (Context Budget):\n'));
235
- summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
236
- const fileName = item.file.split('/').slice(-2).join('/');
237
- const severityColor =
238
- item.severity === 'critical'
239
- ? chalk.red
240
- : item.severity === 'major'
241
- ? chalk.yellow
242
- : chalk.blue;
243
- console.log(
244
- ` ${severityColor('●')} ${chalk.white(fileName)} ${chalk.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
245
- );
246
- });
247
- console.log();
248
- }
249
-
250
- // Display score if calculated
251
- if (contextScore) {
252
- console.log(chalk.cyan(divider));
253
- console.log(chalk.bold.white(' AI READINESS SCORE (Context)'));
254
- console.log(chalk.cyan(divider) + '\n');
255
- console.log(formatToolScore(contextScore));
256
- console.log();
257
- }
258
- }
259
- } catch (error) {
260
- handleCLIError(error, 'Context analysis');
261
- }
262
- }
@@ -1 +0,0 @@
1
- export { depsHealthAction } from './shared/standard-tool-actions';
@@ -1 +0,0 @@
1
- export { docDriftAction } from './shared/standard-tool-actions';
@@ -1,20 +0,0 @@
1
- /**
2
- * Command exports for CLI
3
- */
4
-
5
- export { scanAction, scanHelpText } from './scan';
6
- export { initAction } from './init';
7
- export { patternsAction, patternsHelpText } from './patterns';
8
- export { contextAction } from './context';
9
- export { consistencyAction } from './consistency';
10
- export {
11
- visualizeAction,
12
- visualizeHelpText,
13
- visualiseHelpText,
14
- } from './visualize';
15
- export { aiSignalClarityAction } from './ai-signal-clarity';
16
- export { agentGroundingAction } from './agent-grounding';
17
- export { testabilityAction } from './testability';
18
- export { changeAmplificationAction } from './change-amplification';
19
- export { uploadAction, uploadHelpText } from './upload';
20
- export { bugAction, bugHelpText } from './bug';