@aiready/cli 0.14.14 → 0.14.15
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/CONTRIBUTING.md +86 -1
- package/LICENSE +21 -0
- package/package.json +33 -12
- package/.aiready/aiready-report-20260227-133806.json +0 -7805
- package/.aiready/aiready-report-20260227-133938.json +0 -7951
- package/.aiready/aiready-report-20260228-003433.json +0 -7939
- package/.aiready/aiready-report-20260228-003613.json +0 -771
- package/.aiready/aiready-report-20260314-164626.json +0 -59
- package/.aiready/aiready-report-20260314-164741.json +0 -59
- package/.aiready/aiready-report-20260319-201106.json +0 -5566
- package/.aiready/aiready-report-20260319-201511.json +0 -5566
- package/.aiready/aiready-report-20260319-202017.json +0 -5708
- package/.github/FUNDING.yml +0 -5
- package/.turbo/turbo-build.log +0 -29
- package/.turbo/turbo-lint.log +0 -0
- package/.turbo/turbo-test.log +0 -76
- package/aiready-report.json +0 -30703
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -865
- package/coverage/coverage-final.json +0 -15
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -146
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/src/commands/agent-grounding.ts.html +0 -271
- package/coverage/src/commands/ai-signal-clarity.ts.html +0 -253
- package/coverage/src/commands/change-amplification.ts.html +0 -94
- package/coverage/src/commands/consistency.ts.html +0 -781
- package/coverage/src/commands/context.ts.html +0 -871
- package/coverage/src/commands/deps-health.ts.html +0 -280
- package/coverage/src/commands/doc-drift.ts.html +0 -271
- package/coverage/src/commands/index.html +0 -281
- package/coverage/src/commands/patterns.ts.html +0 -745
- package/coverage/src/commands/scan.ts.html +0 -1393
- package/coverage/src/commands/testability.ts.html +0 -304
- package/coverage/src/commands/upload.ts.html +0 -466
- package/coverage/src/commands/visualize.ts.html +0 -1027
- package/coverage/src/index.html +0 -116
- package/coverage/src/index.ts.html +0 -1372
- package/coverage/src/utils/helpers.ts.html +0 -559
- package/coverage/src/utils/index.html +0 -116
- package/docs/SPOKE_GUIDE.md +0 -184
- package/packages/core/src/.aiready/aiready-report-20260314-161145.json +0 -224
- package/packages/core/src/.aiready/aiready-report-20260314-161152.json +0 -235
- package/packages/pattern-detect/src/.aiready/aiready-report-20260314-161139.json +0 -224
- package/src/.aiready/aiready-report-20260312-103623.json +0 -32574
- package/src/.aiready/aiready-report-20260312-110843.json +0 -28740
- package/src/.aiready/aiready-report-20260312-110955.json +0 -28740
- package/src/.aiready/aiready-report-20260314-203209.json +0 -30713
- package/src/.aiready/aiready-report-20260314-203736.json +0 -30713
- package/src/.aiready/aiready-report-20260314-203857.json +0 -30713
- package/src/.aiready/aiready-report-20260314-204047.json +0 -30713
- package/src/.aiready/aiready-report-20260318-002110.json +0 -28782
- package/src/__tests__/cli.test.ts +0 -85
- package/src/__tests__/config-shape.test.ts +0 -105
- package/src/__tests__/unified.test.ts +0 -95
- package/src/cli.ts +0 -333
- package/src/commands/__tests__/agent-grounding.test.ts +0 -24
- package/src/commands/__tests__/ai-signal-clarity.test.ts +0 -32
- package/src/commands/__tests__/consistency.test.ts +0 -100
- package/src/commands/__tests__/deps-health.test.ts +0 -26
- package/src/commands/__tests__/doc-drift.test.ts +0 -26
- package/src/commands/__tests__/extra-commands.test.ts +0 -168
- package/src/commands/__tests__/init.test.ts +0 -51
- package/src/commands/__tests__/scan.test.ts +0 -153
- package/src/commands/__tests__/testability.test.ts +0 -36
- package/src/commands/__tests__/upload.test.ts +0 -50
- package/src/commands/__tests__/visualize.test.ts +0 -78
- package/src/commands/agent-grounding.ts +0 -62
- package/src/commands/ai-signal-clarity.ts +0 -1
- package/src/commands/bug.ts +0 -99
- package/src/commands/change-amplification.ts +0 -3
- package/src/commands/consistency.ts +0 -232
- package/src/commands/context.ts +0 -262
- package/src/commands/deps-health.ts +0 -1
- package/src/commands/doc-drift.ts +0 -1
- package/src/commands/index.ts +0 -20
- package/src/commands/init.ts +0 -199
- package/src/commands/patterns.ts +0 -222
- package/src/commands/report-formatter.ts +0 -267
- package/src/commands/scan.ts +0 -432
- package/src/commands/shared/configured-tool-action.ts +0 -35
- package/src/commands/shared/standard-tool-actions.ts +0 -126
- package/src/commands/testability.ts +0 -73
- package/src/commands/upload.ts +0 -129
- package/src/commands/visualize.ts +0 -321
- package/src/index.ts +0 -465
- package/src/utils/__tests__/helpers.test.ts +0 -35
- package/src/utils/helpers.ts +0 -234
- package/tsconfig.json +0 -11
- package/tsconfig.tsbuildinfo +0 -1
- package/vitest.config.ts +0 -13
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { analyzeUnified } from '../index';
|
|
3
|
-
import { ToolRegistry, ToolName, SpokeOutputSchema } from '@aiready/core';
|
|
4
|
-
|
|
5
|
-
describe('CLI Unified Analysis', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
ToolRegistry.clear();
|
|
8
|
-
|
|
9
|
-
// Register mock providers
|
|
10
|
-
ToolRegistry.register({
|
|
11
|
-
id: ToolName.PatternDetect,
|
|
12
|
-
alias: ['patterns'],
|
|
13
|
-
analyze: async () =>
|
|
14
|
-
SpokeOutputSchema.parse({
|
|
15
|
-
results: [],
|
|
16
|
-
summary: {},
|
|
17
|
-
metadata: { toolName: ToolName.PatternDetect, version: '1.0.0' },
|
|
18
|
-
}),
|
|
19
|
-
score: () => ({
|
|
20
|
-
toolName: ToolName.PatternDetect,
|
|
21
|
-
score: 80,
|
|
22
|
-
factors: [],
|
|
23
|
-
recommendations: [],
|
|
24
|
-
rawMetrics: {},
|
|
25
|
-
}),
|
|
26
|
-
defaultWeight: 10,
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
ToolRegistry.register({
|
|
30
|
-
id: ToolName.ContextAnalyzer,
|
|
31
|
-
alias: ['context'],
|
|
32
|
-
analyze: async () =>
|
|
33
|
-
SpokeOutputSchema.parse({
|
|
34
|
-
results: [],
|
|
35
|
-
summary: {},
|
|
36
|
-
metadata: { toolName: ToolName.ContextAnalyzer, version: '1.0.0' },
|
|
37
|
-
}),
|
|
38
|
-
score: () => ({
|
|
39
|
-
toolName: ToolName.ContextAnalyzer,
|
|
40
|
-
score: 70,
|
|
41
|
-
factors: [],
|
|
42
|
-
recommendations: [],
|
|
43
|
-
rawMetrics: {},
|
|
44
|
-
}),
|
|
45
|
-
defaultWeight: 10,
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
afterEach(() => {
|
|
50
|
-
ToolRegistry.clear();
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should run unified analysis with both tools', async () => {
|
|
54
|
-
const results = await analyzeUnified({
|
|
55
|
-
rootDir: '/test',
|
|
56
|
-
tools: ['patterns', 'context'],
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
expect(results).toHaveProperty(ToolName.PatternDetect);
|
|
60
|
-
expect(results).toHaveProperty(ToolName.ContextAnalyzer);
|
|
61
|
-
expect(results).toHaveProperty('summary');
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should run analysis with only patterns tool', async () => {
|
|
65
|
-
const results = await analyzeUnified({
|
|
66
|
-
rootDir: '/test',
|
|
67
|
-
tools: ['patterns'],
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
expect(results).toHaveProperty(ToolName.PatternDetect);
|
|
71
|
-
expect(results).not.toHaveProperty(ToolName.ContextAnalyzer);
|
|
72
|
-
expect(results).toHaveProperty('summary');
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it('should run analysis with only context tool', async () => {
|
|
76
|
-
const results = await analyzeUnified({
|
|
77
|
-
rootDir: '/test',
|
|
78
|
-
tools: ['context'],
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
expect(results).not.toHaveProperty(ToolName.PatternDetect);
|
|
82
|
-
expect(results).toHaveProperty(ToolName.ContextAnalyzer);
|
|
83
|
-
expect(results).toHaveProperty('summary');
|
|
84
|
-
});
|
|
85
|
-
});
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
-
import { analyzeUnified } from '../index';
|
|
3
|
-
import { ToolRegistry, ToolName, SpokeOutputSchema } from '@aiready/core';
|
|
4
|
-
|
|
5
|
-
describe('CLI Configuration Shape', () => {
|
|
6
|
-
beforeEach(() => {
|
|
7
|
-
ToolRegistry.clear();
|
|
8
|
-
|
|
9
|
-
// Register a mock provider that returns its input config in metadata
|
|
10
|
-
ToolRegistry.register({
|
|
11
|
-
id: ToolName.PatternDetect,
|
|
12
|
-
alias: ['patterns'],
|
|
13
|
-
analyze: async (options) =>
|
|
14
|
-
SpokeOutputSchema.parse({
|
|
15
|
-
results: [],
|
|
16
|
-
summary: { config: options },
|
|
17
|
-
metadata: {
|
|
18
|
-
toolName: ToolName.PatternDetect,
|
|
19
|
-
version: '1.0.0',
|
|
20
|
-
config: options,
|
|
21
|
-
},
|
|
22
|
-
}),
|
|
23
|
-
score: () => ({
|
|
24
|
-
toolName: ToolName.PatternDetect,
|
|
25
|
-
score: 80,
|
|
26
|
-
factors: [],
|
|
27
|
-
recommendations: [],
|
|
28
|
-
rawMetrics: {},
|
|
29
|
-
}),
|
|
30
|
-
defaultWeight: 10,
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
afterEach(() => {
|
|
35
|
-
ToolRegistry.clear();
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
it('should generate a strictly portable AIReadyConfig in summary', async () => {
|
|
39
|
-
const results = await analyzeUnified({
|
|
40
|
-
rootDir: '/tmp/fake-repo',
|
|
41
|
-
tools: [ToolName.PatternDetect],
|
|
42
|
-
exclude: ['**/node_modules/**'],
|
|
43
|
-
// Pass a tool-specific override
|
|
44
|
-
toolConfigs: {
|
|
45
|
-
[ToolName.PatternDetect]: {
|
|
46
|
-
minSimilarity: 0.9,
|
|
47
|
-
// This should be stripped
|
|
48
|
-
rootDir: '/tmp/fake-repo',
|
|
49
|
-
},
|
|
50
|
-
},
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
const config = results.summary.config;
|
|
54
|
-
|
|
55
|
-
// 1. Check top-level structure
|
|
56
|
-
expect(config).toHaveProperty('scan');
|
|
57
|
-
expect(config).toHaveProperty('tools');
|
|
58
|
-
|
|
59
|
-
// 2. Ensure rootDir is STRIPPED from top level
|
|
60
|
-
expect(config).not.toHaveProperty('rootDir');
|
|
61
|
-
|
|
62
|
-
// 3. Ensure internal keys are stripped from scan section
|
|
63
|
-
expect(config.scan).toHaveProperty('tools');
|
|
64
|
-
expect(config.scan).toHaveProperty('exclude');
|
|
65
|
-
expect(config.scan).not.toHaveProperty('rootDir');
|
|
66
|
-
|
|
67
|
-
// 4. Ensure recursive stripping in tools section
|
|
68
|
-
const patternConfig = config.tools[ToolName.PatternDetect];
|
|
69
|
-
expect(patternConfig).toHaveProperty('minSimilarity', 0.9);
|
|
70
|
-
expect(patternConfig).not.toHaveProperty('rootDir');
|
|
71
|
-
expect(patternConfig).not.toHaveProperty('onProgress');
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it('should strip internal keys like useSmartDefaults and batchSize', async () => {
|
|
75
|
-
const results = await analyzeUnified({
|
|
76
|
-
rootDir: '/test',
|
|
77
|
-
tools: [ToolName.PatternDetect],
|
|
78
|
-
useSmartDefaults: true,
|
|
79
|
-
batchSize: 50,
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const config = results.summary.config;
|
|
83
|
-
|
|
84
|
-
expect(config).not.toHaveProperty('useSmartDefaults');
|
|
85
|
-
expect(config.scan).not.toHaveProperty('useSmartDefaults');
|
|
86
|
-
|
|
87
|
-
// Check tool level too
|
|
88
|
-
const patternConfig = config.tools[ToolName.PatternDetect];
|
|
89
|
-
expect(patternConfig).not.toHaveProperty('useSmartDefaults');
|
|
90
|
-
expect(patternConfig).not.toHaveProperty('batchSize');
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
it('should produce a config that is compatible with tool specific collection', async () => {
|
|
94
|
-
// This test ensures that the toolConfigs collected from individual tools
|
|
95
|
-
// are also sanitized before being merged into the final report.
|
|
96
|
-
const results = await analyzeUnified({
|
|
97
|
-
rootDir: '/test',
|
|
98
|
-
tools: [ToolName.PatternDetect],
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const toolConfigs = results.summary.toolConfigs;
|
|
102
|
-
expect(toolConfigs).toBeDefined();
|
|
103
|
-
expect(toolConfigs![ToolName.PatternDetect]).not.toHaveProperty('rootDir');
|
|
104
|
-
});
|
|
105
|
-
});
|
|
@@ -1,95 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
-
import { analyzeUnified, scoreUnified, generateUnifiedSummary } from '../index';
|
|
3
|
-
import { ToolRegistry } from '@aiready/core';
|
|
4
|
-
|
|
5
|
-
vi.mock('@aiready/core', async () => {
|
|
6
|
-
const actual = await vi.importActual('@aiready/core');
|
|
7
|
-
return {
|
|
8
|
-
...actual,
|
|
9
|
-
initializeParsers: vi.fn().mockResolvedValue(undefined),
|
|
10
|
-
calculateOverallScore: vi
|
|
11
|
-
.fn()
|
|
12
|
-
.mockReturnValue({ overall: 85, breakdown: [] }),
|
|
13
|
-
calculateTokenBudget: vi.fn().mockReturnValue({}),
|
|
14
|
-
};
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
describe('Unified CLI logic', () => {
|
|
18
|
-
beforeEach(() => {
|
|
19
|
-
vi.clearAllMocks();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
describe('analyzeUnified', () => {
|
|
23
|
-
it('should run multiple tools and aggregate results', async () => {
|
|
24
|
-
const mockProvider1 = {
|
|
25
|
-
id: 'tool1',
|
|
26
|
-
analyze: vi.fn().mockResolvedValue({
|
|
27
|
-
results: [{ fileName: 'f1.ts', issues: [{}, {}] }],
|
|
28
|
-
summary: { totalFiles: 1 },
|
|
29
|
-
}),
|
|
30
|
-
score: vi.fn(),
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
vi.spyOn(ToolRegistry, 'find').mockImplementation((id) => {
|
|
34
|
-
if (id === 'tool1') return mockProvider1 as any;
|
|
35
|
-
return null;
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
const options = {
|
|
39
|
-
rootDir: '.',
|
|
40
|
-
tools: ['tool1'],
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const result = await analyzeUnified(options as any);
|
|
44
|
-
expect(result.summary.totalIssues).toBe(2);
|
|
45
|
-
expect(result.summary.toolsRun).toContain('tool1');
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
describe('scoreUnified', () => {
|
|
50
|
-
it('should score results from multiple tools', async () => {
|
|
51
|
-
const mockProvider = {
|
|
52
|
-
id: 'tool1',
|
|
53
|
-
score: vi.fn().mockReturnValue({ score: 80 }),
|
|
54
|
-
};
|
|
55
|
-
vi.spyOn(ToolRegistry, 'get').mockReturnValue(mockProvider as any);
|
|
56
|
-
|
|
57
|
-
const results = {
|
|
58
|
-
summary: { toolsRun: ['tool1'] },
|
|
59
|
-
tool1: { results: [] },
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
const score = await scoreUnified(results as any, { rootDir: '.' } as any);
|
|
63
|
-
expect(score.overall).toBe(85); // From mocked calculateOverallScore
|
|
64
|
-
expect(mockProvider.score).toHaveBeenCalled();
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it('should handle empty tools', async () => {
|
|
68
|
-
const results = { summary: { toolsRun: [] } };
|
|
69
|
-
const score = await scoreUnified(results as any, { rootDir: '.' } as any);
|
|
70
|
-
expect(score.overall).toBe(0);
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
describe('generateUnifiedSummary', () => {
|
|
75
|
-
it('should generate human-readable summary', () => {
|
|
76
|
-
const result = {
|
|
77
|
-
summary: {
|
|
78
|
-
toolsRun: ['tool1'],
|
|
79
|
-
totalIssues: 5,
|
|
80
|
-
executionTime: 1200,
|
|
81
|
-
},
|
|
82
|
-
tool1: { results: [{ issues: [{}, {}] }] },
|
|
83
|
-
};
|
|
84
|
-
|
|
85
|
-
vi.spyOn(ToolRegistry, 'getAll').mockReturnValue([
|
|
86
|
-
{ id: 'tool1' },
|
|
87
|
-
] as any);
|
|
88
|
-
|
|
89
|
-
const summary = generateUnifiedSummary(result as any);
|
|
90
|
-
expect(summary).toContain('AIReady Analysis Complete');
|
|
91
|
-
expect(summary).toContain('Total issues found: 5');
|
|
92
|
-
expect(summary).toContain('1.20s');
|
|
93
|
-
});
|
|
94
|
-
});
|
|
95
|
-
});
|
package/src/cli.ts
DELETED
|
@@ -1,333 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import { Command } from 'commander';
|
|
4
|
-
import { readFileSync } from 'fs';
|
|
5
|
-
import { join, dirname } from 'path';
|
|
6
|
-
import { fileURLToPath } from 'url';
|
|
7
|
-
|
|
8
|
-
import {
|
|
9
|
-
scanAction,
|
|
10
|
-
scanHelpText,
|
|
11
|
-
initAction,
|
|
12
|
-
patternsAction,
|
|
13
|
-
patternsHelpText,
|
|
14
|
-
contextAction,
|
|
15
|
-
consistencyAction,
|
|
16
|
-
visualizeAction,
|
|
17
|
-
visualizeHelpText,
|
|
18
|
-
visualiseHelpText,
|
|
19
|
-
changeAmplificationAction,
|
|
20
|
-
testabilityAction,
|
|
21
|
-
uploadAction,
|
|
22
|
-
uploadHelpText,
|
|
23
|
-
bugAction,
|
|
24
|
-
bugHelpText,
|
|
25
|
-
} from './commands';
|
|
26
|
-
|
|
27
|
-
const getDirname = () => {
|
|
28
|
-
if (typeof __dirname !== 'undefined') return __dirname;
|
|
29
|
-
return dirname(fileURLToPath(import.meta.url));
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const packageJson = JSON.parse(
|
|
33
|
-
readFileSync(join(getDirname(), '../package.json'), 'utf8')
|
|
34
|
-
);
|
|
35
|
-
|
|
36
|
-
const program = new Command();
|
|
37
|
-
|
|
38
|
-
program
|
|
39
|
-
.name('aiready')
|
|
40
|
-
.description('AIReady - Assess and improve AI-readiness of codebases')
|
|
41
|
-
.version(packageJson.version)
|
|
42
|
-
.addHelpText(
|
|
43
|
-
'after',
|
|
44
|
-
`
|
|
45
|
-
AI READINESS SCORING:
|
|
46
|
-
Get a 0-100 score indicating how AI-ready your codebase is.
|
|
47
|
-
Use --score flag with any analysis command for detailed breakdown.
|
|
48
|
-
|
|
49
|
-
EXAMPLES:
|
|
50
|
-
$ aiready scan # Comprehensive analysis with AI Readiness Score
|
|
51
|
-
$ aiready scan --no-score # Run scan without score calculation
|
|
52
|
-
$ aiready init # Create a default aiready.json configuration
|
|
53
|
-
$ aiready init --full # Create configuration with ALL available options
|
|
54
|
-
$ npx @aiready/cli scan # Industry standard way to run standard scan
|
|
55
|
-
$ aiready scan --output json # Output raw JSON for piping
|
|
56
|
-
|
|
57
|
-
GETTING STARTED:
|
|
58
|
-
1. Run 'aiready init' to create a persistent 'aiready.json' config file
|
|
59
|
-
2. Run 'aiready scan' to analyze your codebase and get an AI Readiness Score
|
|
60
|
-
3. Use 'aiready init --full' to see every fine-tuning parameter available
|
|
61
|
-
4. Use '--profile agentic' for agent-focused analysis
|
|
62
|
-
5. Set up CI/CD with '--threshold' for quality gates
|
|
63
|
-
|
|
64
|
-
CONFIGURATION:
|
|
65
|
-
Config files (searched upward): aiready.json, .aiready.json, aiready.config.*
|
|
66
|
-
CLI options override config file settings
|
|
67
|
-
|
|
68
|
-
Example aiready.json:
|
|
69
|
-
{
|
|
70
|
-
"scan": { "exclude": ["**/dist/**", "**/node_modules/**"] },
|
|
71
|
-
"tools": {
|
|
72
|
-
"pattern-detect": { "minSimilarity": 0.5 },
|
|
73
|
-
"context-analyzer": { "maxContextBudget": 15000 }
|
|
74
|
-
},
|
|
75
|
-
"output": { "format": "json", "directory": ".aiready" }
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
VERSION: ${packageJson.version}
|
|
79
|
-
DOCUMENTATION: https://aiready.dev/docs/cli
|
|
80
|
-
GITHUB: https://github.com/caopengau/aiready-cli
|
|
81
|
-
LANDING: https://github.com/caopengau/aiready-landing`
|
|
82
|
-
);
|
|
83
|
-
|
|
84
|
-
// Scan command - Run comprehensive AI-readiness analysis
|
|
85
|
-
program
|
|
86
|
-
.command('scan')
|
|
87
|
-
.description(
|
|
88
|
-
'Run comprehensive AI-readiness analysis (patterns + context + consistency)'
|
|
89
|
-
)
|
|
90
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
91
|
-
.option(
|
|
92
|
-
'-t, --tools <tools>',
|
|
93
|
-
'Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)'
|
|
94
|
-
)
|
|
95
|
-
.option(
|
|
96
|
-
'--profile <type>',
|
|
97
|
-
'Scan profile to use (agentic, cost, logic, ui, security, onboarding)'
|
|
98
|
-
)
|
|
99
|
-
.option(
|
|
100
|
-
'--compare-to <path>',
|
|
101
|
-
'Compare results against a previous AIReady report JSON'
|
|
102
|
-
)
|
|
103
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
104
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
105
|
-
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
106
|
-
.option('--output-file <path>', 'Output file path (for json)')
|
|
107
|
-
.option('--score', 'Calculate and display AI Readiness Score (0-100)', true)
|
|
108
|
-
.option('--no-score', 'Disable calculating AI Readiness Score')
|
|
109
|
-
.option('--weights <weights>', 'Custom scoring weights')
|
|
110
|
-
.option('--threshold <score>', 'Fail CI/CD if score below threshold (0-100)')
|
|
111
|
-
.option(
|
|
112
|
-
'--ci',
|
|
113
|
-
'CI mode: GitHub Actions annotations, no colors, fail on threshold'
|
|
114
|
-
)
|
|
115
|
-
.option(
|
|
116
|
-
'--fail-on <level>',
|
|
117
|
-
'Fail on issues: critical, major, any',
|
|
118
|
-
'critical'
|
|
119
|
-
)
|
|
120
|
-
.option('--api-key <key>', 'Platform API key for automatic upload')
|
|
121
|
-
.option('--upload', 'Automatically upload results to the platform')
|
|
122
|
-
.option('--server <url>', 'Custom platform URL')
|
|
123
|
-
.addHelpText('after', scanHelpText)
|
|
124
|
-
.action(async (directory, options) => {
|
|
125
|
-
await scanAction(directory, options);
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
// Init command - Generate default configuration
|
|
129
|
-
program
|
|
130
|
-
.command('init')
|
|
131
|
-
.description('Generate a default configuration (aiready.json)')
|
|
132
|
-
.option('-f, --force', 'Overwrite existing configuration file')
|
|
133
|
-
.option(
|
|
134
|
-
'--js',
|
|
135
|
-
'Generate configuration as a JavaScript file (aiready.config.js)'
|
|
136
|
-
)
|
|
137
|
-
.option('--full', 'Generate a full configuration with all available options')
|
|
138
|
-
.action(async (options) => {
|
|
139
|
-
const format = options.js ? 'js' : 'json';
|
|
140
|
-
await initAction({ force: options.force, format, full: options.full });
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
// Patterns command - Detect duplicate code patterns
|
|
144
|
-
program
|
|
145
|
-
.command('patterns')
|
|
146
|
-
.description('Detect duplicate code patterns that confuse AI models')
|
|
147
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
148
|
-
.option('-s, --similarity <number>', 'Minimum similarity score (0-1)', '0.40')
|
|
149
|
-
.option('-l, --min-lines <number>', 'Minimum lines to consider', '5')
|
|
150
|
-
.option(
|
|
151
|
-
'--max-candidates <number>',
|
|
152
|
-
'Maximum candidates per block (performance tuning)'
|
|
153
|
-
)
|
|
154
|
-
.option(
|
|
155
|
-
'--min-shared-tokens <number>',
|
|
156
|
-
'Minimum shared tokens for candidates (performance tuning)'
|
|
157
|
-
)
|
|
158
|
-
.option(
|
|
159
|
-
'--full-scan',
|
|
160
|
-
'Disable smart defaults for comprehensive analysis (slower)'
|
|
161
|
-
)
|
|
162
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
163
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
164
|
-
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
165
|
-
.option('--output-file <path>', 'Output file path (for json)')
|
|
166
|
-
.option('--score', 'Calculate and display AI Readiness Score (0-100)', true)
|
|
167
|
-
.option('--no-score', 'Disable calculating AI Readiness Score')
|
|
168
|
-
.addHelpText('after', patternsHelpText)
|
|
169
|
-
.action(async (directory, options) => {
|
|
170
|
-
await patternsAction(directory, options);
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
// Context command - Analyze context window costs
|
|
174
|
-
program
|
|
175
|
-
.command('context')
|
|
176
|
-
.description('Analyze context window costs and dependency fragmentation')
|
|
177
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
178
|
-
.option('--max-depth <number>', 'Maximum acceptable import depth', '5')
|
|
179
|
-
.option(
|
|
180
|
-
'--max-context <number>',
|
|
181
|
-
'Maximum acceptable context budget (tokens)',
|
|
182
|
-
'10000'
|
|
183
|
-
)
|
|
184
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
185
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
186
|
-
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
187
|
-
.option('--output-file <path>', 'Output file path (for json)')
|
|
188
|
-
.option('--score', 'Calculate and display AI Readiness Score (0-100)', true)
|
|
189
|
-
.option('--no-score', 'Disable calculating AI Readiness Score')
|
|
190
|
-
.action(async (directory, options) => {
|
|
191
|
-
await contextAction(directory, options);
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// Consistency command - Check naming conventions
|
|
195
|
-
program
|
|
196
|
-
.command('consistency')
|
|
197
|
-
.description('Check naming conventions and architectural consistency')
|
|
198
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
199
|
-
.option('--naming', 'Check naming conventions (default: true)')
|
|
200
|
-
.option('--no-naming', 'Skip naming analysis')
|
|
201
|
-
.option('--patterns', 'Check code patterns (default: true)')
|
|
202
|
-
.option('--no-patterns', 'Skip pattern analysis')
|
|
203
|
-
.option(
|
|
204
|
-
'--min-severity <level>',
|
|
205
|
-
'Minimum severity: info|minor|major|critical',
|
|
206
|
-
'info'
|
|
207
|
-
)
|
|
208
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
209
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
210
|
-
.option(
|
|
211
|
-
'-o, --output <format>',
|
|
212
|
-
'Output format: console, json, markdown',
|
|
213
|
-
'console'
|
|
214
|
-
)
|
|
215
|
-
.option('--output-file <path>', 'Output file path (for json/markdown)')
|
|
216
|
-
.option('--score', 'Calculate and display AI Readiness Score (0-100)', true)
|
|
217
|
-
.option('--no-score', 'Disable calculating AI Readiness Score')
|
|
218
|
-
.action(async (directory, options) => {
|
|
219
|
-
await consistencyAction(directory, options);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// Visualise command (British spelling alias)
|
|
223
|
-
program
|
|
224
|
-
.command('visualise')
|
|
225
|
-
.description('Alias for visualize (British spelling)')
|
|
226
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
227
|
-
.option(
|
|
228
|
-
'--report <path>',
|
|
229
|
-
'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)'
|
|
230
|
-
)
|
|
231
|
-
.option(
|
|
232
|
-
'-o, --output <path>',
|
|
233
|
-
'Output HTML path (relative to directory)',
|
|
234
|
-
'packages/visualizer/visualization.html'
|
|
235
|
-
)
|
|
236
|
-
.option('--open', 'Open generated HTML in default browser')
|
|
237
|
-
.option(
|
|
238
|
-
'--serve [port]',
|
|
239
|
-
'Start a local static server to serve the visualization (optional port number)',
|
|
240
|
-
false
|
|
241
|
-
)
|
|
242
|
-
.option(
|
|
243
|
-
'--dev',
|
|
244
|
-
'Start Vite dev server (live reload) for interactive development',
|
|
245
|
-
true
|
|
246
|
-
)
|
|
247
|
-
.addHelpText('after', visualiseHelpText)
|
|
248
|
-
.action(async (directory, options) => {
|
|
249
|
-
await visualizeAction(directory, options);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
// Visualize command - Generate interactive visualization
|
|
253
|
-
program
|
|
254
|
-
.command('visualize')
|
|
255
|
-
.description('Generate interactive visualization from an AIReady report')
|
|
256
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
257
|
-
.option(
|
|
258
|
-
'--report <path>',
|
|
259
|
-
'Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)'
|
|
260
|
-
)
|
|
261
|
-
.option(
|
|
262
|
-
'-o, --output <path>',
|
|
263
|
-
'Output HTML path (relative to directory)',
|
|
264
|
-
'packages/visualizer/visualization.html'
|
|
265
|
-
)
|
|
266
|
-
.option('--open', 'Open generated HTML in default browser')
|
|
267
|
-
.option(
|
|
268
|
-
'--serve [port]',
|
|
269
|
-
'Start a local static server to serve the visualization (optional port number)',
|
|
270
|
-
false
|
|
271
|
-
)
|
|
272
|
-
.option(
|
|
273
|
-
'--dev',
|
|
274
|
-
'Start Vite dev server (live reload) for interactive development',
|
|
275
|
-
false
|
|
276
|
-
)
|
|
277
|
-
.addHelpText('after', visualizeHelpText)
|
|
278
|
-
.action(async (directory, options) => {
|
|
279
|
-
await visualizeAction(directory, options);
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
// Change Amplification command
|
|
283
|
-
program
|
|
284
|
-
.command('change-amplification')
|
|
285
|
-
.description('Analyze graph metrics for change amplification')
|
|
286
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
287
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
288
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
289
|
-
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
290
|
-
.option('--output-file <path>', 'Output file path (for json)')
|
|
291
|
-
.action(async (directory, options) => {
|
|
292
|
-
await changeAmplificationAction(directory, options);
|
|
293
|
-
});
|
|
294
|
-
|
|
295
|
-
// Testability command
|
|
296
|
-
program
|
|
297
|
-
.command('testability')
|
|
298
|
-
.description('Analyze test coverage and AI readiness')
|
|
299
|
-
.argument('[directory]', 'Directory to analyze', '.')
|
|
300
|
-
.option('--min-coverage <ratio>', 'Minimum acceptable coverage ratio', '0.3')
|
|
301
|
-
.option('--include <patterns>', 'File patterns to include (comma-separated)')
|
|
302
|
-
.option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
|
|
303
|
-
.option('-o, --output <format>', 'Output format: console, json', 'console')
|
|
304
|
-
.option('--output-file <path>', 'Output file path (for json)')
|
|
305
|
-
.action(async (directory, options) => {
|
|
306
|
-
await testabilityAction(directory, options);
|
|
307
|
-
});
|
|
308
|
-
|
|
309
|
-
// Upload command - Upload report JSON to platform
|
|
310
|
-
program
|
|
311
|
-
.command('upload')
|
|
312
|
-
.description('Upload an AIReady report JSON to the platform')
|
|
313
|
-
.argument('<file>', 'Report JSON file to upload')
|
|
314
|
-
.option('--api-key <key>', 'Platform API key')
|
|
315
|
-
.option('--repo-id <id>', 'Platform repository ID (optional)')
|
|
316
|
-
.option('--server <url>', 'Custom platform URL')
|
|
317
|
-
.addHelpText('after', uploadHelpText)
|
|
318
|
-
.action(async (file, options) => {
|
|
319
|
-
await uploadAction(file, options);
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
program
|
|
323
|
-
.command('bug')
|
|
324
|
-
.description('Report a bug or provide feedback (Agent-friendly)')
|
|
325
|
-
.argument('[message]', 'Short description of the issue')
|
|
326
|
-
.option('-t, --type <type>', 'Issue type: bug, feature, metric', 'bug')
|
|
327
|
-
.option('--submit', 'Submit the issue directly using the GitHub CLI (gh)')
|
|
328
|
-
.addHelpText('after', bugHelpText)
|
|
329
|
-
.action(async (message, options) => {
|
|
330
|
-
await bugAction(message, options);
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
program.parse();
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { agentGroundingAction } from '../agent-grounding';
|
|
3
|
-
|
|
4
|
-
vi.mock('@aiready/agent-grounding', () => ({
|
|
5
|
-
analyzeAgentGrounding: vi.fn().mockResolvedValue({
|
|
6
|
-
summary: { score: 75, rating: 'good', dimensions: { apiClarityScore: 60 } },
|
|
7
|
-
results: [],
|
|
8
|
-
}),
|
|
9
|
-
calculateGroundingScore: vi.fn().mockReturnValue({ score: 75 }),
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
vi.mock('@aiready/core', () => ({
|
|
13
|
-
loadConfig: vi.fn().mockResolvedValue({}),
|
|
14
|
-
mergeConfigWithDefaults: vi
|
|
15
|
-
.fn()
|
|
16
|
-
.mockImplementation((c, d) => ({ ...d, ...c })),
|
|
17
|
-
}));
|
|
18
|
-
|
|
19
|
-
describe('Agent Grounding CLI Action', () => {
|
|
20
|
-
it('should run analysis and return scoring', async () => {
|
|
21
|
-
const result = await agentGroundingAction('.', { output: 'json' });
|
|
22
|
-
expect(result?.score).toBe(75);
|
|
23
|
-
});
|
|
24
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { aiSignalClarityAction } from '../ai-signal-clarity';
|
|
3
|
-
|
|
4
|
-
vi.mock('@aiready/ai-signal-clarity', () => ({
|
|
5
|
-
analyzeAiSignalClarity: vi.fn().mockResolvedValue({
|
|
6
|
-
summary: {
|
|
7
|
-
score: 85,
|
|
8
|
-
rating: 'low',
|
|
9
|
-
topRisk: 'none',
|
|
10
|
-
totalSignals: 0,
|
|
11
|
-
criticalSignals: 0,
|
|
12
|
-
majorSignals: 0,
|
|
13
|
-
minorSignals: 0,
|
|
14
|
-
},
|
|
15
|
-
results: [],
|
|
16
|
-
}),
|
|
17
|
-
calculateAiSignalClarityScore: vi.fn().mockReturnValue({ score: 85 }),
|
|
18
|
-
}));
|
|
19
|
-
|
|
20
|
-
vi.mock('@aiready/core', () => ({
|
|
21
|
-
loadConfig: vi.fn().mockResolvedValue({}),
|
|
22
|
-
mergeConfigWithDefaults: vi
|
|
23
|
-
.fn()
|
|
24
|
-
.mockImplementation((c, d) => ({ ...d, ...c })),
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
describe('AI Signal Clarity CLI Action', () => {
|
|
28
|
-
it('should run analysis and return scoring', async () => {
|
|
29
|
-
const result = await aiSignalClarityAction('.', { output: 'json' });
|
|
30
|
-
expect(result?.score).toBe(85);
|
|
31
|
-
});
|
|
32
|
-
});
|