@aiready/cli 0.13.1 → 0.13.2

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.13.1 build /Users/pengcao/projects/aiready/packages/cli
3
+ > @aiready/cli@0.13.2 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
-  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta] 7:38:32 pm
13
+  WARN  ▲ [WARNING] "import.meta" is not available with the "cjs" output format and will be empty [empty-import-meta] 7:51:15 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
- CJS dist/cli.js 80.29 KB
24
- CJS dist/index.js 10.62 KB
25
- CJS ⚡️ Build success in 77ms
26
- ESM dist/cli.mjs 66.94 KB
27
- ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
28
23
  ESM dist/index.mjs 170.00 B
29
- ESM ⚡️ Build success in 77ms
24
+ ESM dist/chunk-VOKP7FGM.mjs 9.52 KB
25
+ ESM dist/cli.mjs 68.68 KB
26
+ ESM ⚡️ Build success in 30ms
27
+ CJS dist/index.js 10.62 KB
28
+ CJS dist/cli.js 82.21 KB
29
+ CJS ⚡️ Build success in 30ms
package/dist/cli.js CHANGED
@@ -550,6 +550,24 @@ async function scanAction(directory, options) {
550
550
  case "cost":
551
551
  profileTools = [import_core3.ToolName.PatternDetect, import_core3.ToolName.ContextAnalyzer];
552
552
  break;
553
+ case "logic":
554
+ profileTools = [
555
+ import_core3.ToolName.TestabilityIndex,
556
+ import_core3.ToolName.NamingConsistency,
557
+ import_core3.ToolName.ContextAnalyzer,
558
+ import_core3.ToolName.PatternDetect,
559
+ import_core3.ToolName.ChangeAmplification
560
+ ];
561
+ break;
562
+ case "ui":
563
+ profileTools = [
564
+ import_core3.ToolName.NamingConsistency,
565
+ import_core3.ToolName.ContextAnalyzer,
566
+ import_core3.ToolName.PatternDetect,
567
+ import_core3.ToolName.DocDrift,
568
+ import_core3.ToolName.AiSignalClarity
569
+ ];
570
+ break;
553
571
  case "security":
554
572
  profileTools = [
555
573
  import_core3.ToolName.NamingConsistency,
@@ -619,6 +637,7 @@ async function scanAction(directory, options) {
619
637
  );
620
638
  }
621
639
  };
640
+ const scoringProfile = options.profile || baseOptions.scoring?.profile || "default";
622
641
  const results = await analyzeUnified({
623
642
  ...finalOptions,
624
643
  progressCallback,
@@ -635,9 +654,16 @@ async function scanAction(directory, options) {
635
654
  );
636
655
  let scoringResult;
637
656
  if (options.score || finalOptions.scoring?.showBreakdown) {
638
- scoringResult = await scoreUnified(results, finalOptions);
657
+ scoringResult = await scoreUnified(results, {
658
+ ...finalOptions,
659
+ scoring: {
660
+ ...finalOptions.scoring,
661
+ profile: scoringProfile
662
+ }
663
+ });
639
664
  console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
640
665
  console.log(` ${(0, import_core3.formatScore)(scoringResult)}`);
666
+ console.log(import_chalk3.default.dim(` (Scoring Profile: ${scoringProfile})`));
641
667
  if (options.compareTo) {
642
668
  try {
643
669
  const prevReport = JSON.parse(
@@ -735,8 +761,26 @@ async function scanAction(directory, options) {
735
761
  console.log(import_chalk3.default.bold("\nTool breakdown:"));
736
762
  scoringResult.breakdown.forEach((tool) => {
737
763
  const rating = (0, import_core3.getRating)(tool.score);
738
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
764
+ const emoji = (0, import_core3.getRatingDisplay)(rating).emoji;
765
+ console.log(
766
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
767
+ );
739
768
  });
769
+ const allRecs = scoringResult.breakdown.flatMap(
770
+ (t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
771
+ ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
772
+ if (allRecs.length > 0) {
773
+ console.log(import_chalk3.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
774
+ allRecs.forEach((rec, i) => {
775
+ const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
776
+ console.log(
777
+ ` ${i + 1}. ${priorityIcon} ${import_chalk3.default.bold(rec.action)}`
778
+ );
779
+ console.log(
780
+ ` Impact: ${import_chalk3.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
781
+ );
782
+ });
783
+ }
740
784
  }
741
785
  }
742
786
  const mapToUnifiedReport = (res, scoring) => {
@@ -1869,11 +1913,11 @@ program.command("scan").description(
1869
1913
  "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
1870
1914
  ).option(
1871
1915
  "--profile <type>",
1872
- "Scan profile to use (agentic, cost, security, onboarding)"
1916
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
1873
1917
  ).option(
1874
1918
  "--compare-to <path>",
1875
1919
  "Compare results against a previous AIReady report JSON"
1876
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option(
1920
+ ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option(
1877
1921
  "--no-score",
1878
1922
  "Disable calculating AI Readiness Score (enabled by default)"
1879
1923
  ).option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
package/dist/cli.mjs CHANGED
@@ -23,6 +23,7 @@ import {
23
23
  formatScore,
24
24
  calculateTokenBudget,
25
25
  getRating,
26
+ getRatingDisplay,
26
27
  getRepoMetadata,
27
28
  Severity,
28
29
  ToolName,
@@ -289,6 +290,24 @@ async function scanAction(directory, options) {
289
290
  case "cost":
290
291
  profileTools = [ToolName.PatternDetect, ToolName.ContextAnalyzer];
291
292
  break;
293
+ case "logic":
294
+ profileTools = [
295
+ ToolName.TestabilityIndex,
296
+ ToolName.NamingConsistency,
297
+ ToolName.ContextAnalyzer,
298
+ ToolName.PatternDetect,
299
+ ToolName.ChangeAmplification
300
+ ];
301
+ break;
302
+ case "ui":
303
+ profileTools = [
304
+ ToolName.NamingConsistency,
305
+ ToolName.ContextAnalyzer,
306
+ ToolName.PatternDetect,
307
+ ToolName.DocDrift,
308
+ ToolName.AiSignalClarity
309
+ ];
310
+ break;
292
311
  case "security":
293
312
  profileTools = [
294
313
  ToolName.NamingConsistency,
@@ -358,6 +377,7 @@ async function scanAction(directory, options) {
358
377
  );
359
378
  }
360
379
  };
380
+ const scoringProfile = options.profile || baseOptions.scoring?.profile || "default";
361
381
  const results = await analyzeUnified({
362
382
  ...finalOptions,
363
383
  progressCallback,
@@ -374,9 +394,16 @@ async function scanAction(directory, options) {
374
394
  );
375
395
  let scoringResult;
376
396
  if (options.score || finalOptions.scoring?.showBreakdown) {
377
- scoringResult = await scoreUnified(results, finalOptions);
397
+ scoringResult = await scoreUnified(results, {
398
+ ...finalOptions,
399
+ scoring: {
400
+ ...finalOptions.scoring,
401
+ profile: scoringProfile
402
+ }
403
+ });
378
404
  console.log(chalk3.bold("\n\u{1F4CA} AI Readiness Overall Score"));
379
405
  console.log(` ${formatScore(scoringResult)}`);
406
+ console.log(chalk3.dim(` (Scoring Profile: ${scoringProfile})`));
380
407
  if (options.compareTo) {
381
408
  try {
382
409
  const prevReport = JSON.parse(
@@ -474,8 +501,26 @@ async function scanAction(directory, options) {
474
501
  console.log(chalk3.bold("\nTool breakdown:"));
475
502
  scoringResult.breakdown.forEach((tool) => {
476
503
  const rating = getRating(tool.score);
477
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
504
+ const emoji = getRatingDisplay(rating).emoji;
505
+ console.log(
506
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
507
+ );
478
508
  });
509
+ const allRecs = scoringResult.breakdown.flatMap(
510
+ (t) => (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
511
+ ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 3);
512
+ if (allRecs.length > 0) {
513
+ console.log(chalk3.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
514
+ allRecs.forEach((rec, i) => {
515
+ const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
516
+ console.log(
517
+ ` ${i + 1}. ${priorityIcon} ${chalk3.bold(rec.action)}`
518
+ );
519
+ console.log(
520
+ ` Impact: ${chalk3.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
521
+ );
522
+ });
523
+ }
479
524
  }
480
525
  }
481
526
  const mapToUnifiedReport = (res, scoring) => {
@@ -1630,11 +1675,11 @@ program.command("scan").description(
1630
1675
  "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
1631
1676
  ).option(
1632
1677
  "--profile <type>",
1633
- "Scan profile to use (agentic, cost, security, onboarding)"
1678
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
1634
1679
  ).option(
1635
1680
  "--compare-to <path>",
1636
1681
  "Compare results against a previous AIReady report JSON"
1637
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option(
1682
+ ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option(
1638
1683
  "--no-score",
1639
1684
  "Disable calculating AI Readiness Score (enabled by default)"
1640
1685
  ).option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.13.1",
3
+ "version": "0.13.2",
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.12.0",
15
- "@aiready/context-analyzer": "0.20.0",
16
- "@aiready/core": "0.22.0",
17
- "@aiready/deps": "0.12.0",
18
14
  "@aiready/consistency": "0.19.0",
19
15
  "@aiready/clawmart": "0.1.2",
16
+ "@aiready/context-analyzer": "0.20.0",
17
+ "@aiready/agent-grounding": "0.12.0",
18
+ "@aiready/core": "0.22.1",
20
19
  "@aiready/doc-drift": "0.12.0",
21
20
  "@aiready/change-amplification": "0.12.0",
22
- "@aiready/testability": "0.5.0",
23
- "@aiready/pattern-detect": "0.15.0",
21
+ "@aiready/deps": "0.12.0",
24
22
  "@aiready/ai-signal-clarity": "0.12.0",
25
- "@aiready/visualizer": "0.5.0"
23
+ "@aiready/visualizer": "0.5.0",
24
+ "@aiready/testability": "0.5.0",
25
+ "@aiready/pattern-detect": "0.15.0"
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^24.0.0",
package/src/cli.ts CHANGED
@@ -95,7 +95,7 @@ program
95
95
  )
96
96
  .option(
97
97
  '--profile <type>',
98
- 'Scan profile to use (agentic, cost, security, onboarding)'
98
+ 'Scan profile to use (agentic, cost, logic, ui, security, onboarding)'
99
99
  )
100
100
  .option(
101
101
  '--compare-to <path>',
@@ -105,6 +105,7 @@ program
105
105
  .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
106
106
  .option('-o, --output <format>', 'Output format: console, json', 'console')
107
107
  .option('--output-file <path>', 'Output file path (for json)')
108
+ .option('--score', 'Calculate and display AI Readiness Score (0-100)')
108
109
  .option(
109
110
  '--no-score',
110
111
  'Disable calculating AI Readiness Score (enabled by default)'
@@ -98,6 +98,24 @@ export async function scanAction(directory: string, options: ScanOptions) {
98
98
  case 'cost':
99
99
  profileTools = [ToolName.PatternDetect, ToolName.ContextAnalyzer];
100
100
  break;
101
+ case 'logic':
102
+ profileTools = [
103
+ ToolName.TestabilityIndex,
104
+ ToolName.NamingConsistency,
105
+ ToolName.ContextAnalyzer,
106
+ ToolName.PatternDetect,
107
+ ToolName.ChangeAmplification,
108
+ ];
109
+ break;
110
+ case 'ui':
111
+ profileTools = [
112
+ ToolName.NamingConsistency,
113
+ ToolName.ContextAnalyzer,
114
+ ToolName.PatternDetect,
115
+ ToolName.DocDrift,
116
+ ToolName.AiSignalClarity,
117
+ ];
118
+ break;
101
119
  case 'security':
102
120
  profileTools = [
103
121
  ToolName.NamingConsistency,
@@ -182,6 +200,10 @@ export async function scanAction(directory: string, options: ScanOptions) {
182
200
  }
183
201
  };
184
202
 
203
+ // Determine scoring profile for project-type-aware weighting
204
+ const scoringProfile =
205
+ options.profile || baseOptions.scoring?.profile || 'default';
206
+
185
207
  const results = await analyzeUnified({
186
208
  ...finalOptions,
187
209
  progressCallback,
@@ -199,10 +221,18 @@ export async function scanAction(directory: string, options: ScanOptions) {
199
221
 
200
222
  let scoringResult: ScoringResult | undefined;
201
223
  if (options.score || finalOptions.scoring?.showBreakdown) {
202
- scoringResult = await scoreUnified(results, finalOptions);
224
+ // Pass the profile to scoreUnified
225
+ scoringResult = await scoreUnified(results, {
226
+ ...finalOptions,
227
+ scoring: {
228
+ ...finalOptions.scoring,
229
+ profile: scoringProfile,
230
+ },
231
+ });
203
232
 
204
233
  console.log(chalk.bold('\n📊 AI Readiness Overall Score'));
205
234
  console.log(` ${formatScore(scoringResult)}`);
235
+ console.log(chalk.dim(` (Scoring Profile: ${scoringProfile})`));
206
236
 
207
237
  // Trend comparison logic
208
238
  if (options.compareTo) {
@@ -313,8 +343,37 @@ export async function scanAction(directory: string, options: ScanOptions) {
313
343
  console.log(chalk.bold('\nTool breakdown:'));
314
344
  scoringResult.breakdown.forEach((tool) => {
315
345
  const rating = getRating(tool.score);
316
- console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
346
+ const emoji = getRatingDisplay(rating).emoji;
347
+ console.log(
348
+ ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${emoji}`
349
+ );
317
350
  });
351
+
352
+ // Top Actionable Recommendations
353
+ const allRecs = scoringResult.breakdown
354
+ .flatMap((t) =>
355
+ (t.recommendations || []).map((r) => ({ ...r, tool: t.toolName }))
356
+ )
357
+ .sort((a, b) => b.estimatedImpact - a.estimatedImpact)
358
+ .slice(0, 3);
359
+
360
+ if (allRecs.length > 0) {
361
+ console.log(chalk.bold('\n🎯 Top Actionable Recommendations:'));
362
+ allRecs.forEach((rec, i) => {
363
+ const priorityIcon =
364
+ rec.priority === 'high'
365
+ ? '🔴'
366
+ : rec.priority === 'medium'
367
+ ? '🟡'
368
+ : '🔵';
369
+ console.log(
370
+ ` ${i + 1}. ${priorityIcon} ${chalk.bold(rec.action)}`
371
+ );
372
+ console.log(
373
+ ` Impact: ${chalk.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
374
+ );
375
+ });
376
+ }
318
377
  }
319
378
  }
320
379