@aiready/cli 0.9.33 → 0.9.36

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
@@ -1,16 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
- __require,
4
3
  analyzeUnified
5
- } from "./chunk-5GZDRZ3T.mjs";
4
+ } from "./chunk-N4SLON5K.mjs";
5
+ import "./chunk-RBWLQRKR.mjs";
6
+ import "./chunk-YIS6WTY5.mjs";
7
+ import "./chunk-XAF2EW5H.mjs";
8
+ import {
9
+ __require
10
+ } from "./chunk-Y6FXYEAI.mjs";
6
11
 
7
12
  // src/cli.ts
8
13
  import { Command } from "commander";
9
- import { readFileSync as readFileSync3 } from "fs";
10
- import { join } from "path";
14
+ import { readFileSync as readFileSync4 } from "fs";
15
+ import { join, dirname } from "path";
16
+ import { fileURLToPath } from "url";
11
17
 
12
18
  // src/commands/scan.ts
13
19
  import chalk2 from "chalk";
20
+ import { readFileSync as readFileSync2 } from "fs";
14
21
  import { resolve as resolvePath2 } from "path";
15
22
  import {
16
23
  loadMergedConfig,
@@ -138,7 +145,7 @@ async function scanAction(directory, options) {
138
145
  const resolvedDir = resolvePath2(process.cwd(), directory || ".");
139
146
  try {
140
147
  const defaults = {
141
- tools: ["patterns", "context", "consistency"],
148
+ tools: ["patterns", "context", "consistency", "hallucination", "grounding", "testability", "doc-drift", "deps-health"],
142
149
  include: void 0,
143
150
  exclude: void 0,
144
151
  output: {
@@ -146,8 +153,28 @@ async function scanAction(directory, options) {
146
153
  file: void 0
147
154
  }
148
155
  };
156
+ let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
157
+ if (options.profile) {
158
+ switch (options.profile.toLowerCase()) {
159
+ case "agentic":
160
+ profileTools = ["hallucination", "grounding", "testability"];
161
+ break;
162
+ case "cost":
163
+ profileTools = ["patterns", "context"];
164
+ break;
165
+ case "security":
166
+ profileTools = ["consistency", "testability"];
167
+ break;
168
+ case "onboarding":
169
+ profileTools = ["context", "consistency", "grounding"];
170
+ break;
171
+ default:
172
+ console.log(chalk2.yellow(`
173
+ \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`));
174
+ }
175
+ }
149
176
  const baseOptions = await loadMergedConfig(resolvedDir, defaults, {
150
- tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0,
177
+ tools: profileTools,
151
178
  include: options.include?.split(","),
152
179
  exclude: options.exclude?.split(",")
153
180
  });
@@ -279,6 +306,20 @@ async function scanAction(directory, options) {
279
306
  console.log(chalk2.dim(` ... and ${remaining} more files with issues (use --output json for full details)`));
280
307
  }
281
308
  }
309
+ } else if (event.tool === "doc-drift") {
310
+ const dr = event.data;
311
+ console.log(` Issues found: ${chalk2.bold(String(dr.issues?.length || 0))}`);
312
+ if (dr.rawData) {
313
+ console.log(` Signature Mismatches: ${chalk2.bold(dr.rawData.outdatedComments || 0)}`);
314
+ console.log(` Undocumented Complexity: ${chalk2.bold(dr.rawData.undocumentedComplexity || 0)}`);
315
+ }
316
+ } else if (event.tool === "deps-health") {
317
+ const dr = event.data;
318
+ console.log(` Packages Analyzed: ${chalk2.bold(String(dr.summary?.packagesAnalyzed || 0))}`);
319
+ if (dr.rawData) {
320
+ console.log(` Deprecated Packages: ${chalk2.bold(dr.rawData.deprecatedPackages || 0)}`);
321
+ console.log(` AI Cutoff Skew Score: ${chalk2.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`);
322
+ }
282
323
  }
283
324
  } catch (err) {
284
325
  }
@@ -324,11 +365,82 @@ async function scanAction(directory, options) {
324
365
  } catch (err) {
325
366
  }
326
367
  }
368
+ if (finalOptions.tools.includes("hallucination") || finalOptions.tools.includes("hallucination-risk")) {
369
+ try {
370
+ const { hallucinationRiskAction: hallucinationRiskAction2 } = await import("./hallucination-risk-XU6E7IGN.mjs");
371
+ const hrScore = await hallucinationRiskAction2(resolvedDir, { ...finalOptions, output: "json" });
372
+ if (hrScore) toolScores.set("hallucination-risk", hrScore);
373
+ } catch (err) {
374
+ }
375
+ }
376
+ if (finalOptions.tools.includes("grounding") || finalOptions.tools.includes("agent-grounding")) {
377
+ try {
378
+ const { agentGroundingAction: agentGroundingAction2 } = await import("./agent-grounding-DAOSU4MF.mjs");
379
+ const agScore = await agentGroundingAction2(resolvedDir, { ...finalOptions, output: "json" });
380
+ if (agScore) toolScores.set("agent-grounding", agScore);
381
+ } catch (err) {
382
+ }
383
+ }
384
+ if (finalOptions.tools.includes("testability")) {
385
+ try {
386
+ const { testabilityAction: testabilityAction2 } = await import("./testability-VDZJZ4MF.mjs");
387
+ const tbScore = await testabilityAction2(resolvedDir, { ...finalOptions, output: "json" });
388
+ if (tbScore) toolScores.set("testability", tbScore);
389
+ } catch (err) {
390
+ }
391
+ }
392
+ if (results.docDrift) {
393
+ toolScores.set("doc-drift", {
394
+ toolName: "doc-drift",
395
+ score: results.docDrift.summary.score,
396
+ rawMetrics: results.docDrift.rawData,
397
+ factors: [],
398
+ recommendations: results.docDrift.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
399
+ });
400
+ }
401
+ if (results.deps) {
402
+ toolScores.set("dependency-health", {
403
+ toolName: "dependency-health",
404
+ score: results.deps.summary.score,
405
+ rawMetrics: results.deps.rawData,
406
+ factors: [],
407
+ recommendations: results.deps.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
408
+ });
409
+ }
327
410
  const cliWeights = parseWeightString(options.weights);
328
411
  if (toolScores.size > 0) {
329
412
  scoringResult = calculateOverallScore(toolScores, finalOptions, cliWeights.size ? cliWeights : void 0);
330
413
  console.log(chalk2.bold("\n\u{1F4CA} AI Readiness Overall Score"));
331
414
  console.log(` ${formatScore(scoringResult)}`);
415
+ if (options.compareTo) {
416
+ try {
417
+ const prevReportStr = readFileSync2(resolvePath2(process.cwd(), options.compareTo), "utf8");
418
+ const prevReport = JSON.parse(prevReportStr);
419
+ const prevScore = prevReport.scoring?.score || prevReport.scoring?.overallScore;
420
+ if (typeof prevScore === "number") {
421
+ const diff = scoringResult.overall - prevScore;
422
+ const diffStr = diff > 0 ? `+${diff}` : String(diff);
423
+ console.log();
424
+ if (diff > 0) {
425
+ console.log(chalk2.green(` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
426
+ } else if (diff < 0) {
427
+ console.log(chalk2.red(` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
428
+ } else {
429
+ console.log(chalk2.blue(` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
430
+ }
431
+ scoringResult.trend = {
432
+ previousScore: prevScore,
433
+ difference: diff
434
+ };
435
+ } else {
436
+ console.log(chalk2.yellow(`
437
+ \u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`));
438
+ }
439
+ } catch (e) {
440
+ console.log(chalk2.yellow(`
441
+ \u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`));
442
+ }
443
+ }
332
444
  if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
333
445
  console.log(chalk2.bold("\nTool breakdown:"));
334
446
  scoringResult.breakdown.forEach((tool) => {
@@ -364,17 +476,17 @@ async function scanAction(directory, options) {
364
476
  if (process.env.GITHUB_ACTIONS === "true") {
365
477
  console.log(`
366
478
  ::group::AI Readiness Score`);
367
- console.log(`score=${scoringResult.overallScore}`);
479
+ console.log(`score=${scoringResult.overall}`);
368
480
  if (scoringResult.breakdown) {
369
481
  scoringResult.breakdown.forEach((tool) => {
370
482
  console.log(`${tool.toolName}=${tool.score}`);
371
483
  });
372
484
  }
373
485
  console.log("::endgroup::");
374
- if (threshold && scoringResult.overallScore < threshold) {
375
- console.log(`::error::AI Readiness Score ${scoringResult.overallScore} is below threshold ${threshold}`);
486
+ if (threshold && scoringResult.overall < threshold) {
487
+ console.log(`::error::AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`);
376
488
  } else if (threshold) {
377
- console.log(`::notice::AI Readiness Score: ${scoringResult.overallScore}/100 (threshold: ${threshold})`);
489
+ console.log(`::notice::AI Readiness Score: ${scoringResult.overall}/100 (threshold: ${threshold})`);
378
490
  }
379
491
  if (results.patterns) {
380
492
  const criticalPatterns = results.patterns.flatMap(
@@ -387,9 +499,9 @@ async function scanAction(directory, options) {
387
499
  }
388
500
  let shouldFail = false;
389
501
  let failReason = "";
390
- if (threshold && scoringResult.overallScore < threshold) {
502
+ if (threshold && scoringResult.overall < threshold) {
391
503
  shouldFail = true;
392
- failReason = `AI Readiness Score ${scoringResult.overallScore} is below threshold ${threshold}`;
504
+ failReason = `AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`;
393
505
  }
394
506
  if (failOnLevel !== "none") {
395
507
  const severityLevels = { critical: 4, major: 3, minor: 2, any: 1 };
@@ -437,7 +549,7 @@ async function scanAction(directory, options) {
437
549
  } else {
438
550
  console.log(chalk2.green("\n\u2705 PR PASSED: AI Readiness Check"));
439
551
  if (threshold) {
440
- console.log(chalk2.green(` Score: ${scoringResult.overallScore}/100 (threshold: ${threshold})`));
552
+ console.log(chalk2.green(` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`));
441
553
  }
442
554
  console.log(chalk2.dim("\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"));
443
555
  }
@@ -450,11 +562,20 @@ var scanHelpText = `
450
562
  EXAMPLES:
451
563
  $ aiready scan # Analyze all tools
452
564
  $ aiready scan --tools patterns,context # Skip consistency
565
+ $ aiready scan --profile agentic # Optimize for AI agent execution
566
+ $ aiready scan --profile security # Optimize for secure coding (testability)
567
+ $ aiready scan --compare-to prev-report.json # Compare trends against previous run
453
568
  $ aiready scan --score --threshold 75 # CI/CD with threshold
454
569
  $ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
455
570
  $ aiready scan --ci --fail-on major # Fail on major+ issues
456
571
  $ aiready scan --output json --output-file report.json
457
572
 
573
+ PROFILES:
574
+ agentic: hallucination, grounding, testability
575
+ cost: patterns, context
576
+ security: consistency, testability
577
+ onboarding: context, consistency, grounding
578
+
458
579
  CI/CD INTEGRATION (Gatekeeper Mode):
459
580
  Use --ci for GitHub Actions integration:
460
581
  - Outputs GitHub Actions annotations for PR checks
@@ -741,7 +862,7 @@ async function contextAction(directory, options) {
741
862
 
742
863
  // src/commands/consistency.ts
743
864
  import chalk5 from "chalk";
744
- import { writeFileSync } from "fs";
865
+ import { writeFileSync as writeFileSync2 } from "fs";
745
866
  import { resolve as resolvePath5 } from "path";
746
867
  import {
747
868
  loadMergedConfig as loadMergedConfig4,
@@ -806,7 +927,7 @@ async function consistencyAction(directory, options) {
806
927
  `aiready-report-${getReportTimestamp()}.md`,
807
928
  resolvedDir
808
929
  );
809
- writeFileSync(outputPath, markdown);
930
+ writeFileSync2(outputPath, markdown);
810
931
  console.log(chalk5.green(`\u2705 Report saved to ${outputPath}`));
811
932
  } else {
812
933
  console.log(chalk5.bold("\n\u{1F4CA} Summary\n"));
@@ -893,7 +1014,7 @@ async function consistencyAction(directory, options) {
893
1014
 
894
1015
  // src/commands/visualize.ts
895
1016
  import chalk6 from "chalk";
896
- import { writeFileSync as writeFileSync2, readFileSync as readFileSync2, existsSync as existsSync2, copyFileSync as copyFileSync2 } from "fs";
1017
+ import { writeFileSync as writeFileSync3, readFileSync as readFileSync3, existsSync as existsSync2, copyFileSync as copyFileSync2 } from "fs";
897
1018
  import { resolve as resolvePath6 } from "path";
898
1019
  import { spawn } from "child_process";
899
1020
  import { handleCLIError as handleCLIError5 } from "@aiready/core";
@@ -918,13 +1039,13 @@ Or specify a custom report:
918
1039
  return;
919
1040
  }
920
1041
  }
921
- const raw = readFileSync2(reportPath, "utf8");
1042
+ const raw = readFileSync3(reportPath, "utf8");
922
1043
  const report = JSON.parse(raw);
923
1044
  const configPath = resolvePath6(dirPath, "aiready.json");
924
1045
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
925
1046
  if (existsSync2(configPath)) {
926
1047
  try {
927
- const rawConfig = JSON.parse(readFileSync2(configPath, "utf8"));
1048
+ const rawConfig = JSON.parse(readFileSync3(configPath, "utf8"));
928
1049
  if (rawConfig.visualizer?.graph) {
929
1050
  graphConfig = {
930
1051
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1032,7 +1153,7 @@ Or specify a custom report:
1032
1153
  const html = generateHTML(graph);
1033
1154
  const defaultOutput = "visualization.html";
1034
1155
  const outPath = resolvePath6(dirPath, options.output || defaultOutput);
1035
- writeFileSync2(outPath, html, "utf8");
1156
+ writeFileSync3(outPath, html, "utf8");
1036
1157
  console.log(chalk6.green(`\u2705 Visualization written to: ${outPath}`));
1037
1158
  if (options.open || options.serve) {
1038
1159
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
@@ -1105,7 +1226,11 @@ NOTES:
1105
1226
  `;
1106
1227
 
1107
1228
  // src/cli.ts
1108
- var packageJson = JSON.parse(readFileSync3(join(__dirname, "../package.json"), "utf8"));
1229
+ var getDirname = () => {
1230
+ if (typeof __dirname !== "undefined") return __dirname;
1231
+ return dirname(fileURLToPath(import.meta.url));
1232
+ };
1233
+ var packageJson = JSON.parse(readFileSync4(join(getDirname(), "../package.json"), "utf8"));
1109
1234
  var program = new Command();
1110
1235
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText("after", `
1111
1236
  AI READINESS SCORING:
@@ -1143,7 +1268,7 @@ VERSION: ${packageJson.version}
1143
1268
  DOCUMENTATION: https://aiready.dev/docs/cli
1144
1269
  GITHUB: https://github.com/caopengau/aiready-cli
1145
1270
  LANDING: https://github.com/caopengau/aiready-landing`);
1146
- 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)", "patterns,context,consistency").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 (patterns:40,context:35,consistency:25)").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) => {
1271
+ 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) => {
1147
1272
  await scanAction(directory, options);
1148
1273
  });
1149
1274
  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) => {
@@ -0,0 +1,47 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
3
+ // src/commands/deps-health.ts
4
+ import chalk from "chalk";
5
+ import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
6
+ async function depsHealthAction(directory, options) {
7
+ const { analyzeDeps } = await import("@aiready/deps");
8
+ const config = await loadConfig(directory);
9
+ const merged = mergeConfigWithDefaults(config, {
10
+ trainingCutoffYear: 2023
11
+ });
12
+ const report = await analyzeDeps({
13
+ rootDir: directory,
14
+ include: options.include,
15
+ exclude: options.exclude,
16
+ trainingCutoffYear: options.trainingCutoffYear ?? merged.trainingCutoffYear ?? 2023
17
+ });
18
+ const scoring = {
19
+ toolName: "dependency-health",
20
+ score: report.summary.score,
21
+ rawMetrics: report.rawData,
22
+ factors: [],
23
+ recommendations: report.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
24
+ };
25
+ if (options.output === "json") {
26
+ return scoring;
27
+ }
28
+ const { summary } = report;
29
+ const ratingColors = {
30
+ excellent: chalk.green,
31
+ good: chalk.blueBright,
32
+ moderate: chalk.yellow,
33
+ poor: chalk.red,
34
+ hazardous: chalk.bgRed.white
35
+ };
36
+ const color = ratingColors[summary.rating] ?? chalk.white;
37
+ console.log(` \u{1F4E6} Dependency Health: ${chalk.bold(scoring.score + "/100 health")} (${color(summary.rating)})`);
38
+ if (report.issues.length > 0) {
39
+ console.log(chalk.dim(` Found ${report.issues.length} dependency issues.`));
40
+ } else {
41
+ console.log(chalk.dim(` Dependencies look healthy for AI assistance.`));
42
+ }
43
+ return scoring;
44
+ }
45
+ export {
46
+ depsHealthAction
47
+ };
@@ -0,0 +1,47 @@
1
+ import "./chunk-Y6FXYEAI.mjs";
2
+
3
+ // src/commands/doc-drift.ts
4
+ import chalk from "chalk";
5
+ import { loadConfig, mergeConfigWithDefaults } from "@aiready/core";
6
+ async function docDriftAction(directory, options) {
7
+ const { analyzeDocDrift } = await import("@aiready/doc-drift");
8
+ const config = await loadConfig(directory);
9
+ const merged = mergeConfigWithDefaults(config, {
10
+ staleMonths: 6
11
+ });
12
+ const report = await analyzeDocDrift({
13
+ rootDir: directory,
14
+ include: options.include,
15
+ exclude: options.exclude,
16
+ staleMonths: options.staleMonths ?? merged.staleMonths ?? 6
17
+ });
18
+ const scoring = {
19
+ toolName: "doc-drift",
20
+ score: report.summary.score,
21
+ rawMetrics: report.rawData,
22
+ factors: [],
23
+ recommendations: report.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
24
+ };
25
+ if (options.output === "json") {
26
+ return scoring;
27
+ }
28
+ const { summary } = report;
29
+ const ratingColors = {
30
+ minimal: chalk.green,
31
+ low: chalk.cyan,
32
+ moderate: chalk.yellow,
33
+ high: chalk.red,
34
+ severe: chalk.bgRed.white
35
+ };
36
+ const color = ratingColors[summary.rating] ?? chalk.white;
37
+ console.log(` \u{1F4DD} Documentation Drift: ${chalk.bold(100 - scoring.score + "/100 health")} (${color(summary.rating)} risk)`);
38
+ if (report.issues.length > 0) {
39
+ console.log(chalk.dim(` Found ${report.issues.length} drift issues.`));
40
+ } else {
41
+ console.log(chalk.dim(` No documentation drift detected.`));
42
+ }
43
+ return scoring;
44
+ }
45
+ export {
46
+ docDriftAction
47
+ };
@@ -0,0 +1,7 @@
1
+ import {
2
+ hallucinationRiskAction
3
+ } from "./chunk-RBWLQRKR.mjs";
4
+ import "./chunk-Y6FXYEAI.mjs";
5
+ export {
6
+ hallucinationRiskAction
7
+ };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
@@ -105,6 +115,32 @@ async function analyzeUnified(options) {
105
115
  result.consistency = report;
106
116
  result.summary.totalIssues += report.summary.totalIssues;
107
117
  }
118
+ if (tools.includes("doc-drift")) {
119
+ const { analyzeDocDrift } = await import("@aiready/doc-drift");
120
+ const report = await analyzeDocDrift({
121
+ rootDir: options.rootDir,
122
+ include: options.include,
123
+ exclude: options.exclude
124
+ });
125
+ if (options.progressCallback) {
126
+ options.progressCallback({ tool: "doc-drift", data: report });
127
+ }
128
+ result.docDrift = report;
129
+ result.summary.totalIssues += report.issues?.length || 0;
130
+ }
131
+ if (tools.includes("deps-health")) {
132
+ const { analyzeDeps } = await import("@aiready/deps");
133
+ const report = await analyzeDeps({
134
+ rootDir: options.rootDir,
135
+ include: options.include,
136
+ exclude: options.exclude
137
+ });
138
+ if (options.progressCallback) {
139
+ options.progressCallback({ tool: "deps-health", data: report });
140
+ }
141
+ result.deps = report;
142
+ result.summary.totalIssues += report.issues?.length || 0;
143
+ }
108
144
  result.summary.executionTime = Date.now() - startTime;
109
145
  return result;
110
146
  }
@@ -132,6 +168,14 @@ function generateUnifiedSummary(result) {
132
168
  }
133
169
  if (result.consistency) {
134
170
  output += `\u{1F3F7}\uFE0F Consistency Analysis: ${result.consistency.summary.totalIssues} issues
171
+ `;
172
+ }
173
+ if (result.docDrift) {
174
+ output += `\u{1F4DD} Doc Drift Analysis: ${result.docDrift.issues?.length || 0} issues
175
+ `;
176
+ }
177
+ if (result.deps) {
178
+ output += `\u{1F4E6} Dependency Health: ${result.deps.issues?.length || 0} issues
135
179
  `;
136
180
  }
137
181
  return output;
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
1
  import {
2
2
  analyzeUnified,
3
3
  generateUnifiedSummary
4
- } from "./chunk-5GZDRZ3T.mjs";
4
+ } from "./chunk-N4SLON5K.mjs";
5
+ import "./chunk-Y6FXYEAI.mjs";
5
6
  export {
6
7
  analyzeUnified,
7
8
  generateUnifiedSummary
@@ -0,0 +1,7 @@
1
+ import {
2
+ testabilityAction
3
+ } from "./chunk-XAF2EW5H.mjs";
4
+ import "./chunk-Y6FXYEAI.mjs";
5
+ export {
6
+ testabilityAction
7
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.9.33",
3
+ "version": "0.9.36",
4
4
  "description": "Unified CLI for AIReady analysis tools",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -9,17 +9,22 @@
9
9
  "aiready": "./dist/cli.js"
10
10
  },
11
11
  "dependencies": {
12
- "commander": "^14.0.0",
13
12
  "chalk": "^5.3.0",
14
- "@aiready/context-analyzer": "0.9.28",
15
- "@aiready/core": "0.9.25",
16
- "@aiready/visualizer": "0.1.30",
17
- "@aiready/pattern-detect": "0.11.24",
18
- "@aiready/consistency": "0.8.24"
13
+ "commander": "^14.0.0",
14
+ "@aiready/consistency": "0.8.27",
15
+ "@aiready/context-analyzer": "0.9.31",
16
+ "@aiready/core": "0.9.28",
17
+ "@aiready/deps": "0.1.1",
18
+ "@aiready/agent-grounding": "0.1.1",
19
+ "@aiready/doc-drift": "0.1.1",
20
+ "@aiready/pattern-detect": "0.11.27",
21
+ "@aiready/testability": "0.1.1",
22
+ "@aiready/visualizer": "0.1.33",
23
+ "@aiready/hallucination-risk": "0.1.1"
19
24
  },
20
25
  "devDependencies": {
21
- "tsup": "^8.3.5",
22
- "@types/node": "^24.0.0"
26
+ "@types/node": "^24.0.0",
27
+ "tsup": "^8.3.5"
23
28
  },
24
29
  "keywords": [
25
30
  "aiready",
package/src/cli.ts CHANGED
@@ -2,7 +2,8 @@
2
2
 
3
3
  import { Command } from 'commander';
4
4
  import { readFileSync } from 'fs';
5
- import { join } from 'path';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
6
7
 
7
8
  import {
8
9
  scanAction,
@@ -16,7 +17,12 @@ import {
16
17
  visualiseHelpText,
17
18
  } from './commands';
18
19
 
19
- const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
20
+ const getDirname = () => {
21
+ if (typeof __dirname !== 'undefined') return __dirname;
22
+ return dirname(fileURLToPath(import.meta.url));
23
+ };
24
+
25
+ const packageJson = JSON.parse(readFileSync(join(getDirname(), '../package.json'), 'utf8'));
20
26
 
21
27
  const program = new Command();
22
28
 
@@ -66,13 +72,15 @@ program
66
72
  .command('scan')
67
73
  .description('Run comprehensive AI-readiness analysis (patterns + context + consistency)')
68
74
  .argument('[directory]', 'Directory to analyze', '.')
69
- .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context,consistency)', 'patterns,context,consistency')
75
+ .option('-t, --tools <tools>', 'Tools to run (comma-separated: patterns,context,consistency,hallucination,grounding,testability)')
76
+ .option('--profile <type>', 'Scan profile to use (agentic, cost, security, onboarding)')
77
+ .option('--compare-to <path>', 'Compare results against a previous AIReady report JSON')
70
78
  .option('--include <patterns>', 'File patterns to include (comma-separated)')
71
79
  .option('--exclude <patterns>', 'File patterns to exclude (comma-separated)')
72
80
  .option('-o, --output <format>', 'Output format: console, json', 'json')
73
81
  .option('--output-file <path>', 'Output file path (for json)')
74
82
  .option('--no-score', 'Disable calculating AI Readiness Score (enabled by default)')
75
- .option('--weights <weights>', 'Custom scoring weights (patterns:40,context:35,consistency:25)')
83
+ .option('--weights <weights>', 'Custom scoring weights')
76
84
  .option('--threshold <score>', 'Fail CI/CD if score below threshold (0-100)')
77
85
  .option('--ci', 'CI mode: GitHub Actions annotations, no colors, fail on threshold')
78
86
  .option('--fail-on <level>', 'Fail on issues: critical, major, any', 'critical')
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Agent grounding command for unified CLI
3
+ */
4
+
5
+ import chalk from 'chalk';
6
+ import { loadConfig, mergeConfigWithDefaults } from '@aiready/core';
7
+ import type { ToolScoringOutput } from '@aiready/core';
8
+
9
+ export async function agentGroundingAction(
10
+ directory: string,
11
+ options: any,
12
+ ): Promise<ToolScoringOutput | undefined> {
13
+ const { analyzeAgentGrounding, calculateGroundingScore } = await import('@aiready/agent-grounding');
14
+
15
+ const config = await loadConfig(directory);
16
+ const merged = mergeConfigWithDefaults(config, {
17
+ maxRecommendedDepth: 4,
18
+ readmeStaleDays: 90,
19
+ });
20
+
21
+ const report = await analyzeAgentGrounding({
22
+ rootDir: directory,
23
+ maxRecommendedDepth: options.maxDepth ?? merged.maxRecommendedDepth,
24
+ readmeStaleDays: options.readmeStaleDays ?? merged.readmeStaleDays,
25
+ include: options.include,
26
+ exclude: options.exclude,
27
+ });
28
+
29
+ const scoring = calculateGroundingScore(report);
30
+
31
+ if (options.output === 'json') {
32
+ return scoring;
33
+ }
34
+
35
+ const scoreColor = (s: number) =>
36
+ s >= 85 ? chalk.green : s >= 70 ? chalk.cyan : s >= 50 ? chalk.yellow : chalk.red;
37
+
38
+ console.log(` 🧭 Agent Grounding: ${chalk.bold(scoring.score + '/100')} (${report.summary.rating})`);
39
+ const dims = report.summary.dimensions;
40
+ const worstDim = Object.entries(dims).sort(([, a], [, b]) => a - b)[0];
41
+ if (worstDim && worstDim[1] < 70) {
42
+ const name = worstDim[0].replace(/([A-Z])/g, ' $1').replace('Score', '').trim();
43
+ console.log(chalk.dim(` Weakest dimension: ${name} (${worstDim[1]}/100)`));
44
+ }
45
+
46
+ return scoring;
47
+ }