@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/.aiready/aiready-report-20260227-133806.json +7906 -0
- package/.aiready/aiready-report-20260227-133938.json +8052 -0
- package/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-test.log +5 -5
- package/README.md +27 -287
- package/dist/chunk-M7O2MEM5.mjs +211 -0
- package/dist/chunk-PDOONNSK.mjs +228 -0
- package/dist/cli.js +78 -25
- package/dist/cli.mjs +62 -22
- package/dist/index.js +24 -7
- package/dist/index.mjs +1 -1
- package/package.json +12 -11
- package/src/cli.ts +19 -5
- package/src/commands/{hallucination-risk.ts → ai-signal-clarity.ts} +5 -5
- package/src/commands/change-amplification.ts +3 -0
- package/src/commands/index.ts +3 -2
- package/src/commands/scan.ts +58 -16
- package/src/index.ts +30 -10
package/dist/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
__require,
|
|
4
4
|
analyzeUnified
|
|
5
|
-
} from "./chunk-
|
|
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", "
|
|
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: "
|
|
147
|
+
format: "console",
|
|
148
148
|
file: void 0
|
|
149
149
|
}
|
|
150
150
|
};
|
|
151
|
-
let profileTools = options.tools ? options.tools.split(",").map((t) =>
|
|
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 = ["
|
|
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
|
|
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
|
-
|
|
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.
|
|
364
|
-
const {
|
|
377
|
+
if (results.aiSignalClarity) {
|
|
378
|
+
const { calculateAiSignalClarityScore } = await import("@aiready/ai-signal-clarity");
|
|
365
379
|
try {
|
|
366
|
-
const hrScore =
|
|
367
|
-
toolScores.set("
|
|
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:
|
|
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/
|
|
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 #
|
|
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
|
|
1252
|
-
$ aiready scan --output 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,
|
|
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("
|
|
145
|
-
const {
|
|
146
|
-
const report = await
|
|
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: "
|
|
152
|
+
options.progressCallback({ tool: "aiSignalClarity", data: report });
|
|
153
153
|
}
|
|
154
|
-
result.
|
|
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.
|
|
221
|
-
output += `\u{1F9E0}
|
|
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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/cli",
|
|
3
|
-
"version": "0.9.
|
|
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/
|
|
15
|
-
"@aiready/
|
|
16
|
-
"@aiready/
|
|
17
|
-
"@aiready/
|
|
18
|
-
"@aiready/
|
|
19
|
-
"@aiready/
|
|
20
|
-
"@aiready/testability": "0.1.
|
|
21
|
-
"@aiready/
|
|
22
|
-
"@aiready/
|
|
23
|
-
"@aiready/doc-drift": "0.1.
|
|
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 #
|
|
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
|
|
43
|
-
$ aiready scan --output 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,
|
|
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', '
|
|
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
|
-
*
|
|
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
|
|
11
|
+
export async function aiSignalClarityAction(
|
|
12
12
|
directory: string,
|
|
13
13
|
options: any,
|
|
14
14
|
): Promise<ToolScoringOutput | undefined> {
|
|
15
|
-
const {
|
|
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
|
|
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(` 🧠
|
|
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`));
|
package/src/commands/index.ts
CHANGED
|
@@ -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 {
|
|
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';
|
package/src/commands/scan.ts
CHANGED
|
@@ -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', '
|
|
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: '
|
|
56
|
+
format: 'console',
|
|
57
57
|
file: undefined,
|
|
58
58
|
},
|
|
59
59
|
};
|
|
60
60
|
|
|
61
|
-
let profileTools = options.tools ? options.tools.split(',').map((t: string) =>
|
|
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 = ['
|
|
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
|
|
83
|
-
tools: profileTools as any,
|
|
86
|
+
const cliOverrides: any = {
|
|
84
87
|
include: options.include?.split(','),
|
|
85
88
|
exclude: options.exclude?.split(','),
|
|
86
|
-
}
|
|
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
|
-
|
|
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
|
-
//
|
|
322
|
-
if (results.
|
|
323
|
-
const {
|
|
336
|
+
// AI signal clarity score
|
|
337
|
+
if (results.aiSignalClarity) {
|
|
338
|
+
const { calculateAiSignalClarityScore } = await import('@aiready/ai-signal-clarity');
|
|
324
339
|
try {
|
|
325
|
-
const hrScore =
|
|
326
|
-
toolScores.set('
|
|
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:
|
|
617
|
+
agentic: aiSignalClarity, grounding, testability
|
|
576
618
|
cost: patterns, context
|
|
577
619
|
security: consistency, testability
|
|
578
620
|
onboarding: context, consistency, grounding
|