@aiready/cli 0.12.23 → 0.13.1

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.
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.12.22 build /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.13.1 build /Users/pengcao/projects/aiready/packages/cli
4
4
  > tsup src/index.ts src/cli.ts --format cjs,esm
5
5
 
6
6
  CLI Building entry: src/cli.ts, src/index.ts
@@ -10,7 +10,7 @@
10
10
  CJS Build start
11
11
  ESM Build start
12
12
 
13
- [3:18:55 pm]  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta]
13
+  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta] 7:38:32 pm
14
14
 
15
15
  src/cli.ts:32:31:
16
16
   32 │ return dirname(fileURLToPath(import.meta.url));
@@ -20,10 +20,10 @@
20
20
 
21
21
 
22
22
 
23
- ESM dist/index.mjs 170.00 B
24
- ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
25
- ESM dist/cli.mjs 66.64 KB
26
- ESM ⚡️ Build success in 28ms
23
+ CJS dist/cli.js 80.29 KB
27
24
  CJS dist/index.js 10.62 KB
28
- CJS dist/cli.js 79.99 KB
29
- CJS ⚡️ Build success in 28ms
25
+ CJS ⚡️ Build success in 77ms
26
+ ESM dist/cli.mjs 66.94 KB
27
+ ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
28
+ ESM dist/index.mjs 170.00 B
29
+ ESM ⚡️ Build success in 77ms
@@ -1,19 +1,20 @@
1
1
 
2
2
  
3
- > @aiready/cli@0.12.22 test /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.13.0 test /Users/pengcao/projects/aiready/packages/cli
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/cli
8
8
 
9
- ✓ src/commands/__tests__/testability.test.ts (2 tests) 9ms
10
- ✓ src/commands/__tests__/ai-signal-clarity.test.ts (1 test) 8ms
11
- ✓ src/commands/__tests__/deps-health.test.ts (1 test) 9ms
12
- ✓ src/commands/__tests__/doc-drift.test.ts (1 test) 9ms
9
+ ✓ src/utils/__tests__/helpers.test.ts (3 tests) 5ms
13
10
  stdout | src/commands/__tests__/visualize.test.ts > Visualize CLI Action > should generate HTML from specified report
14
11
  Building graph from report...
15
12
 
16
- ✓ src/commands/__tests__/agent-grounding.test.ts (1 test) 8ms
13
+ ✓ src/commands/__tests__/testability.test.ts (2 tests) 14ms
14
+ ✓ src/commands/__tests__/ai-signal-clarity.test.ts (1 test) 13ms
15
+ ✓ src/commands/__tests__/deps-health.test.ts (1 test) 12ms
16
+ ✓ src/commands/__tests__/doc-drift.test.ts (1 test) 25ms
17
+ ✓ src/commands/__tests__/agent-grounding.test.ts (1 test) 25ms
17
18
  stdout | src/commands/__tests__/visualize.test.ts > Visualize CLI Action > should generate HTML from specified report
18
19
  Generating HTML...
19
20
  ✅ Visualization written to: /Users/pengcao/projects/aiready/packages/cli/visualization.html
@@ -41,8 +42,7 @@ Or specify a custom report:
41
42
  Generating HTML...
42
43
  ✅ Visualization written to: /Users/pengcao/projects/aiready/packages/cli/visualization.html
43
44
 
44
- ✓ src/commands/__tests__/visualize.test.ts (4 tests) 27ms
45
- ✓ src/utils/__tests__/helpers.test.ts (3 tests) 3ms
45
+ ✓ src/commands/__tests__/visualize.test.ts (4 tests) 34ms
46
46
  stdout | src/commands/__tests__/upload.test.ts > Upload CLI Action > should fail if API key is missing
47
47
   Set AIREADY_API_KEY environment variable or use --api-key flag.
48
48
  Get an API key from https://platform.getaiready.dev/dashboard
@@ -59,17 +59,17 @@ Or specify a custom report:
59
59
 
60
60
  ✓ src/commands/__tests__/upload.test.ts (2 tests) 5ms
61
61
  ✓ src/commands/__tests__/consistency.test.ts (4 tests) 4ms
62
- ✓ src/commands/__tests__/scan.test.ts (6 tests) 74ms
63
- ✓ src/__tests__/unified.test.ts (4 tests) 4ms
64
- ✓ src/commands/__tests__/extra-commands.test.ts (8 tests) 95ms
65
- ✓ src/__tests__/cli.test.ts (3 tests) 2501ms
66
- ✓ should run unified analysis with both tools  2499ms
67
- ✓ src/__tests__/config-shape.test.ts (3 tests) 2500ms
68
- ✓ should generate a strictly portable AIReadyConfig in summary  2499ms
62
+ ✓ src/commands/__tests__/scan.test.ts (6 tests) 77ms
63
+ ✓ src/__tests__/unified.test.ts (4 tests) 3ms
64
+ ✓ src/commands/__tests__/extra-commands.test.ts (8 tests) 93ms
65
+ ✓ src/__tests__/cli.test.ts (3 tests) 3317ms
66
+ ✓ should run unified analysis with both tools  3316ms
67
+ ✓ src/__tests__/config-shape.test.ts (3 tests) 3318ms
68
+ ✓ should generate a strictly portable AIReadyConfig in summary  3316ms
69
69
 
70
70
   Test Files  14 passed (14)
71
71
   Tests  43 passed (43)
72
-  Start at  15:19:20
73
-  Duration  3.27s (transform 1.67s, setup 0ms, import 3.49s, tests 5.26s, environment 1ms)
72
+  Start at  00:58:55
73
+  Duration  4.20s (transform 1.99s, setup 0ms, import 4.11s, tests 6.94s, environment 1ms)
74
74
 
75
75
  [?25h
package/CONTRIBUTING.md CHANGED
@@ -196,7 +196,7 @@ src/
196
196
  Great places to start:
197
197
 
198
198
  - **New commands**: Add new CLI commands
199
- - **Tool integration**: Integrate new analysis tools
199
+ - **Tool integration**: Integrate new analysis tools. Follow the [Spoke Development Guide](./docs/SPOKE_GUIDE.md) for more details.
200
200
  - **Output formats**: Add new output options (XML, CSV, HTML)
201
201
  - **Configuration**: Improve config file handling
202
202
  - **Performance**: Optimize for large codebases
package/README.md CHANGED
@@ -50,10 +50,15 @@ aiready scan .
50
50
 
51
51
  # Run a specific tool
52
52
  aiready patterns . --similarity 0.6
53
- ````
53
+ ```
54
+
55
+ ## 🛠️ Building Your Own Tool (Spokes)
56
+
57
+ Want to build your own analysis tool that integrates with the AIReady ecosystem? Check out our [Spoke Development Guide](./docs/SPOKE_GUIDE.md).
54
58
 
55
59
  ## 🌐 Platform Integration
56
60
 
61
+
57
62
  Connect your local scans to the [AIReady Dashboard](https://platform.getaiready.dev/dashboard).
58
63
 
59
64
  ### Automatic Upload
@@ -85,3 +90,4 @@ MIT
85
90
  ```
86
91
 
87
92
  ```
93
+ ````
package/dist/cli.js CHANGED
@@ -805,11 +805,20 @@ async function scanAction(directory, options) {
805
805
  const failOnLevel = options.failOn || "critical";
806
806
  let shouldFail = false;
807
807
  let failReason = "";
808
+ const report = mapToUnifiedReport(results, scoringResult);
809
+ if (report.results && report.results.length > 0) {
810
+ console.log(
811
+ import_chalk3.default.cyan(
812
+ `
813
+ \u{1F4DD} Emitting GitHub Action annotations for ${report.results.length} issues...`
814
+ )
815
+ );
816
+ (0, import_core3.emitIssuesAsAnnotations)(report.results);
817
+ }
808
818
  if (threshold && scoringResult.overall < threshold) {
809
819
  shouldFail = true;
810
820
  failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
811
821
  }
812
- const report = mapToUnifiedReport(results, scoringResult);
813
822
  if (failOnLevel !== "none") {
814
823
  if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
815
824
  shouldFail = true;
package/dist/cli.mjs CHANGED
@@ -25,7 +25,8 @@ import {
25
25
  getRating,
26
26
  getRepoMetadata,
27
27
  Severity,
28
- ToolName
28
+ ToolName,
29
+ emitIssuesAsAnnotations
29
30
  } from "@aiready/core";
30
31
 
31
32
  // src/utils/helpers.ts
@@ -543,11 +544,20 @@ async function scanAction(directory, options) {
543
544
  const failOnLevel = options.failOn || "critical";
544
545
  let shouldFail = false;
545
546
  let failReason = "";
547
+ const report = mapToUnifiedReport(results, scoringResult);
548
+ if (report.results && report.results.length > 0) {
549
+ console.log(
550
+ chalk3.cyan(
551
+ `
552
+ \u{1F4DD} Emitting GitHub Action annotations for ${report.results.length} issues...`
553
+ )
554
+ );
555
+ emitIssuesAsAnnotations(report.results);
556
+ }
546
557
  if (threshold && scoringResult.overall < threshold) {
547
558
  shouldFail = true;
548
559
  failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
549
560
  }
550
- const report = mapToUnifiedReport(results, scoringResult);
551
561
  if (failOnLevel !== "none") {
552
562
  if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
553
563
  shouldFail = true;
@@ -0,0 +1,184 @@
1
+ # Building a New AIReady Spoke
2
+
3
+ This guide explains how to build a new analysis tool ("spoke") and integrate it into the AIReady ecosystem. AIReady uses a hub-and-spoke architecture where independent tools are coordinated by a central CLI and Hub (@aiready/core).
4
+
5
+ ## 🚀 Getting Started
6
+
7
+ ### 1. Create Package Structure
8
+
9
+ If you are contributing to the monorepo:
10
+
11
+ ```bash
12
+ mkdir -p packages/your-tool/src
13
+ cd packages/your-tool
14
+ ```
15
+
16
+ ### 2. Create `package.json`
17
+
18
+ Your tool should depend on `@aiready/core` for shared types and utilities.
19
+
20
+ ```json
21
+ {
22
+ "name": "@aiready/your-tool",
23
+ "version": "0.1.0",
24
+ "description": "Brief description of what this tool does",
25
+ "main": "./dist/index.js",
26
+ "module": "./dist/index.mjs",
27
+ "types": "./dist/index.d.ts",
28
+ "bin": {
29
+ "aiready-yourtool": "./dist/cli.js"
30
+ },
31
+ "scripts": {
32
+ "build": "tsup src/index.ts src/cli.ts --format cjs,esm --dts",
33
+ "dev": "tsup src/index.ts src/cli.ts --format cjs,esm --dts --watch",
34
+ "test": "vitest run",
35
+ "lint": "eslint src",
36
+ "clean": "rm -rf dist"
37
+ },
38
+ "dependencies": {
39
+ "@aiready/core": "workspace:*",
40
+ "commander": "^12.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "tsup": "^8.3.5"
44
+ },
45
+ "keywords": ["aiready", "your-keywords"],
46
+ "license": "MIT"
47
+ }
48
+ ```
49
+
50
+ ### 3. Implement the Analysis Logic
51
+
52
+ Create `src/analyzer.ts` to contain your core logic.
53
+
54
+ ```typescript
55
+ import { scanFiles, readFileContent } from '@aiready/core';
56
+ import type {
57
+ AnalysisResult,
58
+ Issue,
59
+ ScanOptions,
60
+ SpokeOutput,
61
+ } from '@aiready/core';
62
+
63
+ export async function analyzeYourTool(
64
+ options: ScanOptions
65
+ ): Promise<SpokeOutput> {
66
+ const files = await scanFiles(options);
67
+ const results: AnalysisResult[] = [];
68
+
69
+ // Your analysis logic here
70
+ // 1. Iterate through files
71
+ // 2. Detect issues
72
+ // 3. Return standardized AnalysisResult[]
73
+
74
+ return {
75
+ results,
76
+ summary: {
77
+ totalFiles: files.length,
78
+ totalIssues: results.reduce((acc, r) => acc + r.issues.length, 0),
79
+ // ... other summary stats
80
+ },
81
+ };
82
+ }
83
+ ```
84
+
85
+ ### 4. Implement ToolProvider and Register
86
+
87
+ Every spoke must implement the `ToolProvider` interface and register with the global `ToolRegistry` so that it is automatically discovered by the unified CLI.
88
+
89
+ 1. **Create `src/provider.ts`**:
90
+
91
+ ```typescript
92
+ import {
93
+ ToolProvider,
94
+ ToolName,
95
+ SpokeOutput,
96
+ ScanOptions,
97
+ ToolScoringOutput,
98
+ } from '@aiready/core';
99
+ import { analyzeYourTool } from './analyzer';
100
+
101
+ export const YourToolProvider: ToolProvider = {
102
+ id: ToolName.YourToolID, // Use an existing ToolName or request a new one
103
+ alias: ['your-alias'],
104
+
105
+ async analyze(options: ScanOptions): Promise<SpokeOutput> {
106
+ const output = await analyzeYourTool(options);
107
+ return {
108
+ ...output,
109
+ metadata: { toolName: ToolName.YourToolID, version: '0.1.0' },
110
+ };
111
+ },
112
+
113
+ score(output: SpokeOutput, options: ScanOptions): ToolScoringOutput {
114
+ // Implement scoring logic (0-100)
115
+ return {
116
+ score: 100, // Example
117
+ metrics: output.summary,
118
+ };
119
+ },
120
+
121
+ defaultWeight: 10,
122
+ };
123
+ ```
124
+
125
+ 2. **Register in `src/index.ts`**:
126
+
127
+ ```typescript
128
+ import { ToolRegistry } from '@aiready/core';
129
+ import { YourToolProvider } from './provider';
130
+
131
+ // Register with global registry for automatic CLI discovery
132
+ ToolRegistry.register(YourToolProvider);
133
+
134
+ export { YourToolProvider };
135
+ export * from './analyzer';
136
+ ```
137
+
138
+ ### 5. Create Standalone CLI (`src/cli.ts`)
139
+
140
+ ```typescript
141
+ #!/usr/bin/env node
142
+ import { Command } from 'commander';
143
+ import { analyzeYourTool } from './analyzer';
144
+ import chalk from 'chalk';
145
+
146
+ const program = new Command();
147
+
148
+ program
149
+ .name('aiready-yourtool')
150
+ .description('Description of your tool')
151
+ .version('0.1.0')
152
+ .argument('<directory>', 'Directory to analyze')
153
+ .action(async (directory, options) => {
154
+ console.log(chalk.blue('🔍 Analyzing...\n'));
155
+ const output = await analyzeYourTool({ rootDir: directory });
156
+ console.log(JSON.stringify(output, null, 2));
157
+ });
158
+
159
+ program.parse();
160
+ ```
161
+
162
+ ## 📋 Standard Specs to Follow
163
+
164
+ To ensure your tool integrates perfectly with the AIReady ecosystem, it must follow these rules:
165
+
166
+ 1. **Standard Options**: Support `--include`, `--exclude`, and `--output` (standardized via `ScanOptions`).
167
+ 2. **No Direct Dependencies**: Spokes should never depend on other spokes. Only depend on `@aiready/core`.
168
+ 3. **Standard Issue Types**: Use `IssueType` from `@aiready/core` whenever possible.
169
+ 4. **Severity Levels**: Use `critical`, `major`, `minor`, and `info`.
170
+ 5. **Non-Blocking**: The `analyze` function should be asynchronous and handle large codebases efficiently.
171
+
172
+ ## 🧪 Testing
173
+
174
+ Use `vitest` for unit and integration tests. Ensure you test your `ToolProvider` implementation using the `validateSpokeOutput` utility from `@aiready/core`.
175
+
176
+ ```typescript
177
+ import { validateSpokeOutput } from '@aiready/core/types/contract';
178
+
179
+ test('output matches AIReady contract', async () => {
180
+ const output = await analyzeYourTool({ rootDir: './test' });
181
+ const validation = validateSpokeOutput('your-tool', output);
182
+ expect(validation.valid).toBe(true);
183
+ });
184
+ ```
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.12.23",
3
+ "version": "0.13.1",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,18 +11,18 @@
11
11
  "dependencies": {
12
12
  "chalk": "^5.3.0",
13
13
  "commander": "^14.0.0",
14
- "@aiready/agent-grounding": "0.11.21",
14
+ "@aiready/agent-grounding": "0.12.0",
15
+ "@aiready/context-analyzer": "0.20.0",
16
+ "@aiready/core": "0.22.0",
17
+ "@aiready/deps": "0.12.0",
18
+ "@aiready/consistency": "0.19.0",
15
19
  "@aiready/clawmart": "0.1.2",
16
- "@aiready/context-analyzer": "0.19.21",
17
- "@aiready/core": "0.21.21",
18
- "@aiready/consistency": "0.18.21",
19
- "@aiready/doc-drift": "0.11.21",
20
- "@aiready/ai-signal-clarity": "0.11.21",
21
- "@aiready/pattern-detect": "0.14.21",
22
- "@aiready/change-amplification": "0.11.21",
23
- "@aiready/visualizer": "0.4.22",
24
- "@aiready/deps": "0.11.21",
25
- "@aiready/testability": "0.4.21"
20
+ "@aiready/doc-drift": "0.12.0",
21
+ "@aiready/change-amplification": "0.12.0",
22
+ "@aiready/testability": "0.5.0",
23
+ "@aiready/pattern-detect": "0.15.0",
24
+ "@aiready/ai-signal-clarity": "0.12.0",
25
+ "@aiready/visualizer": "0.5.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^24.0.0",