@aiready/cli 0.9.38 → 0.9.40

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  __require,
4
4
  analyzeUnified
5
- } from "./chunk-JQG7ZATX.mjs";
5
+ } from "./chunk-PDOONNSK.mjs";
6
6
 
7
7
  // src/cli.ts
8
8
  import { Command } from "commander";
@@ -12,7 +12,7 @@ import { fileURLToPath } from "url";
12
12
 
13
13
  // src/commands/scan.ts
14
14
  import chalk2 from "chalk";
15
- import { readFileSync as readFileSync2 } from "fs";
15
+ import { writeFileSync, readFileSync as readFileSync2 } from "fs";
16
16
  import { resolve as resolvePath2 } from "path";
17
17
  import {
18
18
  loadMergedConfig,
@@ -140,19 +140,23 @@ async function scanAction(directory, options) {
140
140
  const resolvedDir = resolvePath2(process.cwd(), directory || ".");
141
141
  try {
142
142
  const defaults = {
143
- tools: ["patterns", "context", "consistency", "hallucination", "grounding", "testability", "doc-drift", "deps-health"],
143
+ tools: ["patterns", "context", "consistency", "aiSignalClarity", "grounding", "testability", "doc-drift", "deps-health", "changeAmplification"],
144
144
  include: void 0,
145
145
  exclude: void 0,
146
146
  output: {
147
- format: "json",
147
+ format: "console",
148
148
  file: void 0
149
149
  }
150
150
  };
151
- let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
151
+ let profileTools = options.tools ? options.tools.split(",").map((t) => {
152
+ const tool = t.trim();
153
+ if (tool === "hallucination" || tool === "hallucination-risk") return "aiSignalClarity";
154
+ return tool;
155
+ }) : void 0;
152
156
  if (options.profile) {
153
157
  switch (options.profile.toLowerCase()) {
154
158
  case "agentic":
155
- profileTools = ["hallucination", "grounding", "testability"];
159
+ profileTools = ["aiSignalClarity", "grounding", "testability"];
156
160
  break;
157
161
  case "cost":
158
162
  profileTools = ["patterns", "context"];
@@ -168,11 +172,14 @@ async function scanAction(directory, options) {
168
172
  \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`));
169
173
  }
170
174
  }
171
- const baseOptions = await loadMergedConfig(resolvedDir, defaults, {
172
- tools: profileTools,
175
+ const cliOverrides = {
173
176
  include: options.include?.split(","),
174
177
  exclude: options.exclude?.split(",")
175
- });
178
+ };
179
+ if (profileTools) {
180
+ cliOverrides.tools = profileTools;
181
+ }
182
+ const baseOptions = await loadMergedConfig(resolvedDir, defaults, cliOverrides);
176
183
  let finalOptions = { ...baseOptions };
177
184
  if (baseOptions.tools.includes("patterns")) {
178
185
  const { getSmartDefaults } = await import("@aiready/pattern-detect");
@@ -315,6 +322,12 @@ async function scanAction(directory, options) {
315
322
  console.log(` Deprecated Packages: ${chalk2.bold(dr.rawData.deprecatedPackages || 0)}`);
316
323
  console.log(` AI Cutoff Skew Score: ${chalk2.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`);
317
324
  }
325
+ } else if (event.tool === "change-amplification" || event.tool === "changeAmplification") {
326
+ const dr = event.data;
327
+ console.log(` Coupling issues: ${chalk2.bold(String(dr.issues?.length || 0))}`);
328
+ if (dr.summary) {
329
+ console.log(` Complexity Score: ${chalk2.bold(dr.summary.score || 0)}/100`);
330
+ }
318
331
  }
319
332
  } catch (err) {
320
333
  }
@@ -327,7 +340,8 @@ async function scanAction(directory, options) {
327
340
  if (results.duplicates) console.log(` Duplicate patterns found: ${chalk2.bold(String(results.duplicates.length || 0))}`);
328
341
  if (results.patterns) console.log(` Pattern files with issues: ${chalk2.bold(String(results.patterns.length || 0))}`);
329
342
  if (results.context) console.log(` Context issues: ${chalk2.bold(String(results.context.length || 0))}`);
330
- if (results.consistency) console.log(` Consistency issues: ${chalk2.bold(String(results.consistency.summary.totalIssues || 0))}`);
343
+ console.log(` Consistency issues: ${chalk2.bold(String(results.consistency?.summary?.totalIssues || 0))}`);
344
+ if (results.changeAmplification) console.log(` Change amplification: ${chalk2.bold(String(results.changeAmplification.summary?.score || 0))}/100`);
331
345
  console.log(chalk2.cyan("===========================\n"));
332
346
  const elapsedTime = getElapsedTime(startTime);
333
347
  let scoringResult;
@@ -360,11 +374,11 @@ async function scanAction(directory, options) {
360
374
  } catch (err) {
361
375
  }
362
376
  }
363
- if (results.hallucination) {
364
- const { calculateHallucinationScore } = await import("@aiready/hallucination-risk");
377
+ if (results.aiSignalClarity) {
378
+ const { calculateAiSignalClarityScore } = await import("@aiready/ai-signal-clarity");
365
379
  try {
366
- const hrScore = calculateHallucinationScore(results.hallucination);
367
- toolScores.set("hallucination-risk", hrScore);
380
+ const hrScore = calculateAiSignalClarityScore(results.aiSignalClarity);
381
+ toolScores.set("ai-signal-clarity", hrScore);
368
382
  } catch (err) {
369
383
  }
370
384
  }
@@ -390,7 +404,7 @@ async function scanAction(directory, options) {
390
404
  score: results.docDrift.summary.score,
391
405
  rawMetrics: results.docDrift.rawData,
392
406
  factors: [],
393
- recommendations: results.docDrift.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
407
+ recommendations: (results.docDrift.recommendations || []).map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
394
408
  });
395
409
  }
396
410
  if (results.deps) {
@@ -399,7 +413,16 @@ async function scanAction(directory, options) {
399
413
  score: results.deps.summary.score,
400
414
  rawMetrics: results.deps.rawData,
401
415
  factors: [],
402
- recommendations: results.deps.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
416
+ recommendations: (results.deps.recommendations || []).map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
417
+ });
418
+ }
419
+ if (results.changeAmplification) {
420
+ toolScores.set("change-amplification", {
421
+ toolName: "change-amplification",
422
+ score: results.changeAmplification.summary.score,
423
+ rawMetrics: results.changeAmplification.rawData,
424
+ factors: [],
425
+ recommendations: (results.changeAmplification.recommendations || []).map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
403
426
  });
404
427
  }
405
428
  const cliWeights = parseWeightString(options.weights);
@@ -463,6 +486,17 @@ async function scanAction(directory, options) {
463
486
  const outputData = { ...results, scoring: scoringResult };
464
487
  handleJSONOutput(outputData, outputPath, `\u2705 Report saved to ${outputPath}`);
465
488
  warnIfGraphCapExceeded(outputData, resolvedDir);
489
+ } else {
490
+ const timestamp = getReportTimestamp();
491
+ const defaultFilename = `aiready-report-${timestamp}.json`;
492
+ const outputPath = resolveOutputPath(userOutputFile, defaultFilename, resolvedDir);
493
+ const outputData = { ...results, scoring: scoringResult };
494
+ try {
495
+ writeFileSync(outputPath, JSON.stringify(outputData, null, 2));
496
+ console.log(chalk2.dim(`\u2705 Report auto-persisted to ${outputPath}`));
497
+ warnIfGraphCapExceeded(outputData, resolvedDir);
498
+ } catch (err) {
499
+ }
466
500
  }
467
501
  const isCI = options.ci || process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
468
502
  if (isCI && scoringResult) {
@@ -566,7 +600,7 @@ EXAMPLES:
566
600
  $ aiready scan --output json --output-file report.json
567
601
 
568
602
  PROFILES:
569
- agentic: hallucination, grounding, testability
603
+ agentic: aiSignalClarity, grounding, testability
570
604
  cost: patterns, context
571
605
  security: consistency, testability
572
606
  onboarding: context, consistency, grounding
@@ -1220,7 +1254,7 @@ NOTES:
1220
1254
  - Same options as 'visualize'. Use --serve to host the static HTML, or --dev for live reload.
1221
1255
  `;
1222
1256
 
1223
- // src/commands/hallucination-risk.ts
1257
+ // src/commands/ai-signal-clarity.ts
1224
1258
  import chalk7 from "chalk";
1225
1259
  import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
1226
1260
 
@@ -1232,6 +1266,9 @@ import { loadConfig as loadConfig2, mergeConfigWithDefaults as mergeConfigWithDe
1232
1266
  import chalk9 from "chalk";
1233
1267
  import { loadConfig as loadConfig3, mergeConfigWithDefaults as mergeConfigWithDefaults3 } from "@aiready/core";
1234
1268
 
1269
+ // src/commands/change-amplification.ts
1270
+ import { changeAmplificationAction } from "@aiready/change-amplification/dist/cli.js";
1271
+
1235
1272
  // src/cli.ts
1236
1273
  var getDirname = () => {
1237
1274
  if (typeof __dirname !== "undefined") return __dirname;
@@ -1245,11 +1282,11 @@ AI READINESS SCORING:
1245
1282
  Use --score flag with any analysis command for detailed breakdown.
1246
1283
 
1247
1284
  EXAMPLES:
1248
- $ aiready scan # Quick analysis of current directory
1285
+ $ aiready scan # Comprehensive analysis of current directory
1249
1286
  $ aiready scan --score # Get AI Readiness Score (0-100)
1250
1287
  $ aiready scan --tools patterns # Run only pattern detection
1251
- $ aiready patterns --similarity 0.6 # Custom similarity threshold
1252
- $ aiready scan --output json --output-file results.json
1288
+ $ npx @aiready/cli scan # Industry standard way to run standard scan
1289
+ $ aiready scan --output json # Output raw JSON for piping
1253
1290
 
1254
1291
  GETTING STARTED:
1255
1292
  1. Run 'aiready scan' to analyze your codebase
@@ -1275,7 +1312,7 @@ VERSION: ${packageJson.version}
1275
1312
  DOCUMENTATION: https://aiready.dev/docs/cli
1276
1313
  GITHUB: https://github.com/caopengau/aiready-cli
1277
1314
  LANDING: https://github.com/caopengau/aiready-landing`);
1278
- program.command("scan").description("Run comprehensive AI-readiness analysis (patterns + context + consistency)").argument("[directory]", "Directory to analyze", ".").option("-t, --tools <tools>", "Tools to run (comma-separated: patterns,context,consistency,hallucination,grounding,testability)").option("--profile <type>", "Scan profile to use (agentic, cost, security, onboarding)").option("--compare-to <path>", "Compare results against a previous AIReady report JSON").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", "json").option("--output-file <path>", "Output file path (for json)").option("--no-score", "Disable calculating AI Readiness Score (enabled by default)").option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option("--ci", "CI mode: GitHub Actions annotations, no colors, fail on threshold").option("--fail-on <level>", "Fail on issues: critical, major, any", "critical").addHelpText("after", scanHelpText).action(async (directory, options) => {
1315
+ program.command("scan").description("Run comprehensive AI-readiness analysis (patterns + context + consistency)").argument("[directory]", "Directory to analyze", ".").option("-t, --tools <tools>", "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)").option("--profile <type>", "Scan profile to use (agentic, cost, security, onboarding)").option("--compare-to <path>", "Compare results against a previous AIReady report JSON").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("--no-score", "Disable calculating AI Readiness Score (enabled by default)").option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option("--ci", "CI mode: GitHub Actions annotations, no colors, fail on threshold").option("--fail-on <level>", "Fail on issues: critical, major, any", "critical").addHelpText("after", scanHelpText).action(async (directory, options) => {
1279
1316
  await scanAction(directory, options);
1280
1317
  });
1281
1318
  program.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option("-s, --similarity <number>", "Minimum similarity score (0-1)", "0.40").option("-l, --min-lines <number>", "Minimum lines to consider", "5").option("--max-candidates <number>", "Maximum candidates per block (performance tuning)").option("--min-shared-tokens <number>", "Minimum shared tokens for candidates (performance tuning)").option("--full-scan", "Disable smart defaults for comprehensive analysis (slower)").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 for patterns (0-100)").addHelpText("after", patternsHelpText).action(async (directory, options) => {
@@ -1293,4 +1330,7 @@ program.command("visualise").description("Alias for visualize (British spelling)
1293
1330
  program.command("visualize").description("Generate interactive visualization from an AIReady report").argument("[directory]", "Directory to analyze", ".").option("--report <path>", "Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)").option("-o, --output <path>", "Output HTML path (relative to directory)", "packages/visualizer/visualization.html").option("--open", "Open generated HTML in default browser").option("--serve [port]", "Start a local static server to serve the visualization (optional port number)", false).option("--dev", "Start Vite dev server (live reload) for interactive development", false).addHelpText("after", visualizeHelpText).action(async (directory, options) => {
1294
1331
  await visualizeAction(directory, options);
1295
1332
  });
1333
+ program.command("change-amplification").description("Analyze graph metrics for change amplification").argument("[directory]", "Directory to analyze", ".").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)").action(async (directory, options) => {
1334
+ await changeAmplificationAction(directory, options);
1335
+ });
1296
1336
  program.parse();
package/dist/index.js CHANGED
@@ -141,17 +141,17 @@ async function analyzeUnified(options) {
141
141
  result.deps = report;
142
142
  result.summary.totalIssues += report.issues?.length || 0;
143
143
  }
144
- if (tools.includes("hallucination")) {
145
- const { analyzeHallucinationRisk } = await import("@aiready/hallucination-risk");
146
- const report = await analyzeHallucinationRisk({
144
+ if (tools.includes("aiSignalClarity")) {
145
+ const { analyzeAiSignalClarity } = await import("@aiready/ai-signal-clarity");
146
+ const report = await analyzeAiSignalClarity({
147
147
  rootDir: options.rootDir,
148
148
  include: options.include,
149
149
  exclude: options.exclude
150
150
  });
151
151
  if (options.progressCallback) {
152
- options.progressCallback({ tool: "hallucination", data: report });
152
+ options.progressCallback({ tool: "aiSignalClarity", data: report });
153
153
  }
154
- result.hallucination = report;
154
+ result.aiSignalClarity = report;
155
155
  result.summary.totalIssues += report.results?.reduce((sum, r) => sum + (r.issues?.length || 0), 0) || 0;
156
156
  }
157
157
  if (tools.includes("grounding")) {
@@ -180,6 +180,19 @@ async function analyzeUnified(options) {
180
180
  result.testability = report;
181
181
  result.summary.totalIssues += report.issues?.length || 0;
182
182
  }
183
+ if (tools.includes("changeAmplification")) {
184
+ const { analyzeChangeAmplification } = await import("@aiready/change-amplification");
185
+ const report = await analyzeChangeAmplification({
186
+ rootDir: options.rootDir,
187
+ include: options.include,
188
+ exclude: options.exclude
189
+ });
190
+ if (options.progressCallback) {
191
+ options.progressCallback({ tool: "changeAmplification", data: report });
192
+ }
193
+ result.changeAmplification = report;
194
+ result.summary.totalIssues += report.summary?.totalIssues || 0;
195
+ }
183
196
  result.summary.executionTime = Date.now() - startTime;
184
197
  return result;
185
198
  }
@@ -217,8 +230,8 @@ function generateUnifiedSummary(result) {
217
230
  output += `\u{1F4E6} Dependency Health: ${result.deps.issues?.length || 0} issues
218
231
  `;
219
232
  }
220
- if (result.hallucination) {
221
- output += `\u{1F9E0} Hallucination Risk: ${result.hallucination.summary?.totalSignals || 0} signals
233
+ if (result.aiSignalClarity) {
234
+ output += `\u{1F9E0} AI Signal Clarity: ${result.aiSignalClarity.summary?.totalSignals || 0} signals
222
235
  `;
223
236
  }
224
237
  if (result.grounding) {
@@ -227,6 +240,10 @@ function generateUnifiedSummary(result) {
227
240
  }
228
241
  if (result.testability) {
229
242
  output += `\u{1F9EA} Testability Index: ${result.testability.issues?.length || 0} issues
243
+ `;
244
+ }
245
+ if (result.changeAmplification) {
246
+ output += `\u{1F4A5} Change Amplification: ${result.changeAmplification.summary?.totalIssues || 0} cascading risks
230
247
  `;
231
248
  }
232
249
  return output;
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  analyzeUnified,
3
3
  generateUnifiedSummary
4
- } from "./chunk-JQG7ZATX.mjs";
4
+ } from "./chunk-PDOONNSK.mjs";
5
5
  export {
6
6
  analyzeUnified,
7
7
  generateUnifiedSummary
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.9.38",
3
+ "version": "0.9.40",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -11,16 +11,17 @@
11
11
  "dependencies": {
12
12
  "chalk": "^5.3.0",
13
13
  "commander": "^14.0.0",
14
- "@aiready/core": "0.9.30",
15
- "@aiready/context-analyzer": "0.9.33",
16
- "@aiready/deps": "0.1.3",
17
- "@aiready/agent-grounding": "0.1.3",
18
- "@aiready/consistency": "0.8.29",
19
- "@aiready/visualizer": "0.1.35",
20
- "@aiready/testability": "0.1.3",
21
- "@aiready/pattern-detect": "0.11.29",
22
- "@aiready/hallucination-risk": "0.1.3",
23
- "@aiready/doc-drift": "0.1.3"
14
+ "@aiready/agent-grounding": "0.1.5",
15
+ "@aiready/consistency": "0.8.31",
16
+ "@aiready/core": "0.9.32",
17
+ "@aiready/context-analyzer": "0.9.35",
18
+ "@aiready/pattern-detect": "0.11.31",
19
+ "@aiready/change-amplification": "0.1.5",
20
+ "@aiready/testability": "0.1.5",
21
+ "@aiready/visualizer": "0.1.37",
22
+ "@aiready/deps": "0.1.5",
23
+ "@aiready/doc-drift": "0.1.5",
24
+ "@aiready/ai-signal-clarity": "0.1.5"
24
25
  },
25
26
  "devDependencies": {
26
27
  "@types/node": "^24.0.0",
package/src/cli.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  visualizeAction,
16
16
  visualizeHelpText,
17
17
  visualiseHelpText,
18
+ changeAmplificationAction,
18
19
  } from './commands';
19
20
 
20
21
  const getDirname = () => {
@@ -36,11 +37,11 @@ AI READINESS SCORING:
36
37
  Use --score flag with any analysis command for detailed breakdown.
37
38
 
38
39
  EXAMPLES:
39
- $ aiready scan # Quick analysis of current directory
40
+ $ aiready scan # Comprehensive analysis of current directory
40
41
  $ aiready scan --score # Get AI Readiness Score (0-100)
41
42
  $ aiready scan --tools patterns # Run only pattern detection
42
- $ aiready patterns --similarity 0.6 # Custom similarity threshold
43
- $ aiready scan --output json --output-file results.json
43
+ $ npx @aiready/cli scan # Industry standard way to run standard scan
44
+ $ aiready scan --output json # Output raw JSON for piping
44
45
 
45
46
  GETTING STARTED:
46
47
  1. Run 'aiready scan' to analyze your codebase
@@ -72,12 +73,12 @@ program
72
73
  .command('scan')
73
74
  .description('Run comprehensive AI-readiness analysis (patterns + context + consistency)')
74
75
  .argument('[directory]', 'Directory to analyze', '.')
75
- .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context,consistency,hallucination,grounding,testability)')
76
+ .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)')
76
77
  .option('--profile <type>', 'Scan profile to use (agentic, cost, security, onboarding)')
77
78
  .option('--compare-to <path>', 'Compare results against a previous AIReady report JSON')
78
79
  .option('--include <patterns>', 'File patterns to include (comma-separated)')
79
80
  .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
80
- .option('-o, --output <format>', 'Output format: console, json', 'json')
81
+ .option('-o, --output <format>', 'Output format: console, json', 'console')
81
82
  .option('--output-file <path>', 'Output file path (for json)')
82
83
  .option('--no-score', 'Disable calculating AI Readiness Score (enabled by default)')
83
84
  .option('--weights <weights>', 'Custom scoring weights')
@@ -174,4 +175,17 @@ program
174
175
  await visualizeAction(directory, options);
175
176
  });
176
177
 
178
+ // Change Amplification command
179
+ program
180
+ .command('change-amplification')
181
+ .description('Analyze graph metrics for change amplification')
182
+ .argument('[directory]', 'Directory to analyze', '.')
183
+ .option('--include <patterns>', 'File patterns to include (comma-separated)')
184
+ .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
185
+ .option('-o, --output <format>', 'Output format: console, json', 'console')
186
+ .option('--output-file <path>', 'Output file path (for json)')
187
+ .action(async (directory, options) => {
188
+ await changeAmplificationAction(directory, options);
189
+ });
190
+
177
191
  program.parse();
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Hallucination risk command for unified CLI
2
+ * AI signal clarity command for unified CLI
3
3
  */
4
4
 
5
5
  import chalk from 'chalk';
@@ -8,18 +8,18 @@ import { join } from 'path';
8
8
  import { resolveOutputPath, loadConfig, mergeConfigWithDefaults } from '@aiready/core';
9
9
  import type { ToolScoringOutput } from '@aiready/core';
10
10
 
11
- export async function hallucinationRiskAction(
11
+ export async function aiSignalClarityAction(
12
12
  directory: string,
13
13
  options: any,
14
14
  ): Promise<ToolScoringOutput | undefined> {
15
- const { analyzeHallucinationRisk, calculateHallucinationScore } = await import('@aiready/hallucination-risk');
15
+ const { analyzeAiSignalClarity, calculateHallucinationScore } = await import('@aiready/ai-signal-clarity');
16
16
 
17
17
  const config = await loadConfig(directory);
18
18
  const merged = mergeConfigWithDefaults(config, {
19
19
  minSeverity: 'info',
20
20
  });
21
21
 
22
- const report = await analyzeHallucinationRisk({
22
+ const report = await analyzeAiSignalClarity({
23
23
  rootDir: directory,
24
24
  minSeverity: options.minSeverity ?? merged.minSeverity ?? 'info',
25
25
  include: options.include,
@@ -41,7 +41,7 @@ export async function hallucinationRiskAction(
41
41
  severe: chalk.bgRed.white,
42
42
  };
43
43
  const color = ratingColors[summary.rating] ?? chalk.white;
44
- console.log(` 🧠 Hallucination Risk: ${chalk.bold(scoring.score + '/100')} (${color(summary.rating)})`);
44
+ console.log(` 🧠 AI Signal Clarity: ${chalk.bold(scoring.score + '/100')} (${color(summary.rating)})`);
45
45
  console.log(` Top Risk: ${chalk.italic(summary.topRisk)}`);
46
46
  if (summary.totalSignals > 0) {
47
47
  console.log(chalk.dim(` ${summary.criticalSignals} critical ${summary.majorSignals} major ${summary.minorSignals} minor signals`));
@@ -0,0 +1,3 @@
1
+ import { changeAmplificationAction } from '@aiready/change-amplification/dist/cli.js';
2
+
3
+ export { changeAmplificationAction };
@@ -7,6 +7,7 @@ export { patternsAction, patternsHelpText } from './patterns';
7
7
  export { contextAction } from './context';
8
8
  export { consistencyAction } from './consistency';
9
9
  export { visualizeAction, visualizeHelpText, visualiseHelpText } from './visualize';
10
- export { hallucinationRiskAction } from './hallucination-risk';
10
+ export { aiSignalClarityAction } from './ai-signal-clarity';
11
11
  export { agentGroundingAction } from './agent-grounding';
12
- export { testabilityAction } from './testability';
12
+ export { testabilityAction } from './testability';
13
+ export { changeAmplificationAction } from './change-amplification';
@@ -49,20 +49,24 @@ export async function scanAction(directory: string, options: ScanOptions) {
49
49
  try {
50
50
  // Define defaults
51
51
  const defaults = {
52
- tools: ['patterns', 'context', 'consistency', 'hallucination', 'grounding', 'testability', 'doc-drift', 'deps-health'],
52
+ tools: ['patterns', 'context', 'consistency', 'aiSignalClarity', 'grounding', 'testability', 'doc-drift', 'deps-health', 'changeAmplification'],
53
53
  include: undefined,
54
54
  exclude: undefined,
55
55
  output: {
56
- format: 'json',
56
+ format: 'console',
57
57
  file: undefined,
58
58
  },
59
59
  };
60
60
 
61
- let profileTools = options.tools ? options.tools.split(',').map((t: string) => t.trim()) : undefined;
61
+ let profileTools = options.tools ? options.tools.split(',').map((t: string) => {
62
+ const tool = t.trim();
63
+ if (tool === 'hallucination' || tool === 'hallucination-risk') return 'aiSignalClarity';
64
+ return tool;
65
+ }) : undefined;
62
66
  if (options.profile) {
63
67
  switch (options.profile.toLowerCase()) {
64
68
  case 'agentic':
65
- profileTools = ['hallucination', 'grounding', 'testability'];
69
+ profileTools = ['aiSignalClarity', 'grounding', 'testability'];
66
70
  break;
67
71
  case 'cost':
68
72
  profileTools = ['patterns', 'context'];
@@ -79,11 +83,15 @@ export async function scanAction(directory: string, options: ScanOptions) {
79
83
  }
80
84
 
81
85
  // Load and merge config with CLI options
82
- const baseOptions = await loadMergedConfig(resolvedDir, defaults, {
83
- tools: profileTools as any,
86
+ const cliOverrides: any = {
84
87
  include: options.include?.split(','),
85
88
  exclude: options.exclude?.split(','),
86
- }) as any;
89
+ };
90
+ if (profileTools) {
91
+ cliOverrides.tools = profileTools;
92
+ }
93
+
94
+ const baseOptions = await loadMergedConfig(resolvedDir, defaults, cliOverrides) as any;
87
95
 
88
96
 
89
97
  // Apply smart defaults for pattern detection if patterns tool is enabled
@@ -254,6 +262,12 @@ export async function scanAction(directory: string, options: ScanOptions) {
254
262
  console.log(` Deprecated Packages: ${chalk.bold(dr.rawData.deprecatedPackages || 0)}`);
255
263
  console.log(` AI Cutoff Skew Score: ${chalk.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`);
256
264
  }
265
+ } else if (event.tool === 'change-amplification' || event.tool === 'changeAmplification') {
266
+ const dr = event.data as any;
267
+ console.log(` Coupling issues: ${chalk.bold(String(dr.issues?.length || 0))}`);
268
+ if (dr.summary) {
269
+ console.log(` Complexity Score: ${chalk.bold(dr.summary.score || 0)}/100`);
270
+ }
257
271
  }
258
272
  } catch (err) {
259
273
  // don't crash the run for progress printing errors
@@ -272,7 +286,8 @@ export async function scanAction(directory: string, options: ScanOptions) {
272
286
  if (results.duplicates) console.log(` Duplicate patterns found: ${chalk.bold(String(results.duplicates.length || 0))}`);
273
287
  if (results.patterns) console.log(` Pattern files with issues: ${chalk.bold(String(results.patterns.length || 0))}`);
274
288
  if (results.context) console.log(` Context issues: ${chalk.bold(String(results.context.length || 0))}`);
275
- if (results.consistency) console.log(` Consistency issues: ${chalk.bold(String(results.consistency.summary.totalIssues || 0))}`);
289
+ console.log(` Consistency issues: ${chalk.bold(String(results.consistency?.summary?.totalIssues || 0))}`);
290
+ if (results.changeAmplification) console.log(` Change amplification: ${chalk.bold(String(results.changeAmplification.summary?.score || 0))}/100`);
276
291
  console.log(chalk.cyan('===========================\n'));
277
292
 
278
293
  const elapsedTime = getElapsedTime(startTime);
@@ -318,12 +333,12 @@ export async function scanAction(directory: string, options: ScanOptions) {
318
333
  }
319
334
  }
320
335
 
321
- // Hallucination risk score
322
- if (results.hallucination) {
323
- const { calculateHallucinationScore } = await import('@aiready/hallucination-risk');
336
+ // AI signal clarity score
337
+ if (results.aiSignalClarity) {
338
+ const { calculateAiSignalClarityScore } = await import('@aiready/ai-signal-clarity');
324
339
  try {
325
- const hrScore = calculateHallucinationScore(results.hallucination);
326
- toolScores.set('hallucination-risk', hrScore);
340
+ const hrScore = calculateAiSignalClarityScore(results.aiSignalClarity);
341
+ toolScores.set('ai-signal-clarity', hrScore);
327
342
  } catch (err) {
328
343
  // ignore
329
344
  }
@@ -358,7 +373,7 @@ export async function scanAction(directory: string, options: ScanOptions) {
358
373
  score: results.docDrift.summary.score,
359
374
  rawMetrics: results.docDrift.rawData,
360
375
  factors: [],
361
- recommendations: results.docDrift.recommendations.map((action: string) => ({ action, estimatedImpact: 5, priority: 'medium' }))
376
+ recommendations: (results.docDrift.recommendations || []).map((action: string) => ({ action, estimatedImpact: 5, priority: 'medium' }))
362
377
  });
363
378
  }
364
379
 
@@ -369,10 +384,22 @@ export async function scanAction(directory: string, options: ScanOptions) {
369
384
  score: results.deps.summary.score,
370
385
  rawMetrics: results.deps.rawData,
371
386
  factors: [],
372
- recommendations: results.deps.recommendations.map((action: string) => ({ action, estimatedImpact: 5, priority: 'medium' }))
387
+ recommendations: (results.deps.recommendations || []).map((action: string) => ({ action, estimatedImpact: 5, priority: 'medium' }))
388
+ });
389
+ }
390
+
391
+ // Change Amplification score
392
+ if (results.changeAmplification) {
393
+ toolScores.set('change-amplification', {
394
+ toolName: 'change-amplification',
395
+ score: results.changeAmplification.summary.score,
396
+ rawMetrics: results.changeAmplification.rawData,
397
+ factors: [],
398
+ recommendations: (results.changeAmplification.recommendations || []).map((action: string) => ({ action, estimatedImpact: 5, priority: 'medium' }))
373
399
  });
374
400
  }
375
401
 
402
+
376
403
  // Parse CLI weight overrides (if any)
377
404
  const cliWeights = parseWeightString((options as any).weights);
378
405
 
@@ -450,6 +477,21 @@ export async function scanAction(directory: string, options: ScanOptions) {
450
477
 
451
478
  // Warn if graph caps may be exceeded
452
479
  warnIfGraphCapExceeded(outputData, resolvedDir);
480
+ } else {
481
+ // Auto-persist report even in console mode for downstream tools
482
+ const timestamp = getReportTimestamp();
483
+ const defaultFilename = `aiready-report-${timestamp}.json`;
484
+ const outputPath = resolveOutputPath(userOutputFile, defaultFilename, resolvedDir);
485
+ const outputData = { ...results, scoring: scoringResult };
486
+
487
+ try {
488
+ writeFileSync(outputPath, JSON.stringify(outputData, null, 2));
489
+ console.log(chalk.dim(`✅ Report auto-persisted to ${outputPath}`));
490
+ // Warn if graph caps may be exceeded
491
+ warnIfGraphCapExceeded(outputData, resolvedDir);
492
+ } catch (err) {
493
+ // failed to save report, but don't fail the command
494
+ }
453
495
  }
454
496
 
455
497
  // CI/CD Gatekeeper Mode
@@ -572,7 +614,7 @@ EXAMPLES:
572
614
  $ aiready scan --output json --output-file report.json
573
615
 
574
616
  PROFILES:
575
- agentic: hallucination, grounding, testability
617
+ agentic: aiSignalClarity, grounding, testability
576
618
  cost: patterns, context
577
619
  security: consistency, testability
578
620
  onboarding: context, consistency, grounding