@aiready/cli 0.15.1 → 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/cli.js +185 -273
  2. package/dist/cli.mjs +174 -266
  3. package/package.json +13 -13
package/dist/cli.js CHANGED
@@ -25,7 +25,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
 
26
26
  // src/cli.ts
27
27
  var import_commander = require("commander");
28
- var import_fs9 = require("fs");
28
+ var import_fs8 = require("fs");
29
29
  var import_path8 = require("path");
30
30
  var import_url = require("url");
31
31
 
@@ -96,38 +96,6 @@ async function warnIfGraphCapExceeded(report, dirPath) {
96
96
  void err;
97
97
  }
98
98
  }
99
- function generateMarkdownReport(report, elapsedTime) {
100
- let markdown = `# Consistency Analysis Report
101
-
102
- `;
103
- markdown += `**Generated:** ${(/* @__PURE__ */ new Date()).toISOString()}
104
- `;
105
- markdown += `**Analysis Time:** ${elapsedTime}s
106
-
107
- `;
108
- markdown += `## Summary
109
-
110
- `;
111
- markdown += `- **Files Analyzed:** ${report.summary.filesAnalyzed}
112
- `;
113
- markdown += `- **Total Issues:** ${report.summary.totalIssues}
114
- `;
115
- markdown += ` - Naming: ${report.summary.namingIssues}
116
- `;
117
- markdown += ` - Patterns: ${report.summary.patternIssues}
118
-
119
- `;
120
- if (report.recommendations.length > 0) {
121
- markdown += `## Recommendations
122
-
123
- `;
124
- report.recommendations.forEach((rec, i) => {
125
- markdown += `${i + 1}. ${rec}
126
- `;
127
- });
128
- }
129
- return markdown;
130
- }
131
99
 
132
100
  // src/commands/report-formatter.ts
133
101
  var import_chalk2 = __toESM(require("chalk"));
@@ -1170,6 +1138,38 @@ ${import_chalk6.default.bold("CI/CD Integration:")}
1170
1138
  Use --threshold and --fail-on to use AIReady as a quality gate in your CI pipelines.
1171
1139
  When running in GitHub Actions, it will automatically emit annotations for found issues.
1172
1140
  `;
1141
+ function defineScanCommand(program2) {
1142
+ program2.command("scan").description(
1143
+ "Run comprehensive AI-readiness analysis (patterns + context + consistency)"
1144
+ ).argument("[directory]", "Directory to analyze", ".").option(
1145
+ "-t, --tools <tools>",
1146
+ "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
1147
+ ).option(
1148
+ "--profile <type>",
1149
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
1150
+ ).option(
1151
+ "--compare-to <path>",
1152
+ "Compare results against a previous AIReady report JSON"
1153
+ ).option(
1154
+ "--include <patterns>",
1155
+ "File patterns to include (comma-separated)"
1156
+ ).option(
1157
+ "--exclude <patterns>",
1158
+ "File patterns to exclude (comma-separated)"
1159
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
1160
+ "--threshold <score>",
1161
+ "Fail CI/CD if score below threshold (0-100)"
1162
+ ).option(
1163
+ "--ci",
1164
+ "CI mode: GitHub Actions annotations, no colors, fail on threshold"
1165
+ ).option(
1166
+ "--fail-on <level>",
1167
+ "Fail on issues: critical, major, any",
1168
+ "critical"
1169
+ ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", SCAN_HELP_TEXT).action(async (directory, options) => {
1170
+ await scanAction(directory, options);
1171
+ });
1172
+ }
1173
1173
 
1174
1174
  // src/commands/init.ts
1175
1175
  var import_fs5 = require("fs");
@@ -1449,33 +1449,6 @@ function renderSafetyRating(safety) {
1449
1449
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
1450
1450
  );
1451
1451
  }
1452
- function renderIssueSummaryBlock(summary) {
1453
- const total = (summary.criticalIssues || 0) + (summary.majorIssues || 0) + (summary.minorIssues || 0);
1454
- if (total === 0) {
1455
- console.log(import_chalk8.default.green("\u2705 No significant issues found!\n"));
1456
- return;
1457
- }
1458
- console.log(import_chalk8.default.bold("\u26A0\uFE0F Issues Found:\n"));
1459
- if (summary.criticalIssues > 0)
1460
- console.log(
1461
- import_chalk8.default.red(` \u{1F534} Critical: ${import_chalk8.default.bold(summary.criticalIssues)}`)
1462
- );
1463
- if (summary.majorIssues > 0)
1464
- console.log(
1465
- import_chalk8.default.yellow(` \u{1F7E1} Major: ${import_chalk8.default.bold(summary.majorIssues)}`)
1466
- );
1467
- if (summary.minorIssues > 0)
1468
- console.log(import_chalk8.default.blue(` \u{1F535} Minor: ${import_chalk8.default.bold(summary.minorIssues)}`));
1469
- if (summary.totalPotentialSavings) {
1470
- console.log(
1471
- import_chalk8.default.green(
1472
- `
1473
- \u{1F4A1} Potential savings: ${import_chalk8.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1474
- `
1475
- )
1476
- );
1477
- }
1478
- }
1479
1452
  function renderSubSection(title) {
1480
1453
  console.log("\n" + (0, import_core12.getTerminalDivider)());
1481
1454
  console.log(import_chalk8.default.bold.white(` ${title.toUpperCase()}`));
@@ -1492,6 +1465,36 @@ function renderToolScoreFooter(score) {
1492
1465
  }
1493
1466
 
1494
1467
  // src/commands/patterns.ts
1468
+ var PATTERNS_HELP_TEXT = `
1469
+ EXAMPLES:
1470
+ $ aiready patterns # Default analysis
1471
+ $ aiready patterns --similarity 0.6 # Stricter matching
1472
+ $ aiready patterns --min-lines 10 # Larger patterns only
1473
+ `;
1474
+ function definePatternsCommand(program2) {
1475
+ program2.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option(
1476
+ "-s, --similarity <number>",
1477
+ "Minimum similarity score (0-1)",
1478
+ "0.40"
1479
+ ).option("-l, --min-lines <number>", "Minimum lines to consider", "5").option(
1480
+ "--max-candidates <number>",
1481
+ "Maximum candidates per block (performance tuning)"
1482
+ ).option(
1483
+ "--min-shared-tokens <number>",
1484
+ "Minimum shared tokens for candidates (performance tuning)"
1485
+ ).option(
1486
+ "--full-scan",
1487
+ "Disable smart defaults for comprehensive analysis (slower)"
1488
+ ).option(
1489
+ "--include <patterns>",
1490
+ "File patterns to include (comma-separated)"
1491
+ ).option(
1492
+ "--exclude <patterns>",
1493
+ "File patterns to exclude (comma-separated)"
1494
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1495
+ await patternsAction(directory, options);
1496
+ });
1497
+ }
1495
1498
  async function patternsAction(directory, options) {
1496
1499
  return await executeToolAction(directory, options, {
1497
1500
  toolName: "pattern-detect",
@@ -1571,21 +1574,30 @@ async function patternsAction(directory, options) {
1571
1574
  }
1572
1575
  });
1573
1576
  }
1574
- var PATTERNS_HELP_TEXT = `
1575
- EXAMPLES:
1576
- $ aiready patterns # Default analysis
1577
- $ aiready patterns --similarity 0.6 # Stricter matching
1578
- $ aiready patterns --min-lines 10 # Larger patterns only
1579
- `;
1580
1577
 
1581
1578
  // src/commands/context.ts
1582
1579
  var import_chalk10 = __toESM(require("chalk"));
1583
1580
  var import_core14 = require("@aiready/core");
1581
+ function defineContextCommand(program2) {
1582
+ program2.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
1583
+ "--max-context <number>",
1584
+ "Maximum acceptable context budget (tokens)",
1585
+ "10000"
1586
+ ).option(
1587
+ "--include <patterns>",
1588
+ "File patterns to include (comma-separated)"
1589
+ ).option(
1590
+ "--exclude <patterns>",
1591
+ "File patterns to exclude (comma-separated)"
1592
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
1593
+ await contextAction(directory, options);
1594
+ });
1595
+ }
1584
1596
  async function contextAction(directory, options) {
1585
1597
  return await executeToolAction(directory, options, {
1586
1598
  toolName: "context-analyzer",
1587
1599
  label: "Context analysis",
1588
- emoji: "\u{1F9E0}",
1600
+ emoji: "\u{1F9E9}",
1589
1601
  defaults: {
1590
1602
  maxDepth: 5,
1591
1603
  maxContextBudget: 1e4,
@@ -1597,11 +1609,6 @@ async function contextAction(directory, options) {
1597
1609
  maxDepth: opts.maxDepth ? parseInt(opts.maxDepth) : void 0,
1598
1610
  maxContextBudget: opts.maxContext ? parseInt(opts.maxContext) : void 0
1599
1611
  }),
1600
- preAnalyze: async (resolvedDir, baseOptions) => {
1601
- const { getSmartDefaults } = await import("@aiready/context-analyzer");
1602
- const smartDefaults = await getSmartDefaults(resolvedDir, baseOptions);
1603
- return { ...smartDefaults, ...baseOptions };
1604
- },
1605
1612
  importTool: async () => {
1606
1613
  const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1607
1614
  return {
@@ -1610,45 +1617,40 @@ async function contextAction(directory, options) {
1610
1617
  calculateScore: calculateContextScore
1611
1618
  };
1612
1619
  },
1613
- renderConsole: ({ summary, elapsedTime, score }) => {
1620
+ renderConsole: ({ results: _results, summary, elapsedTime, score }) => {
1614
1621
  (0, import_core14.printTerminalHeader)("CONTEXT ANALYSIS SUMMARY");
1615
1622
  console.log(
1616
- import_chalk10.default.white(`\u{1F4C1} Files analyzed: ${import_chalk10.default.bold(summary.totalFiles)}`)
1623
+ import_chalk10.default.white(`\u{1F4C1} Total files: ${import_chalk10.default.bold(summary.totalFiles)}`)
1617
1624
  );
1618
1625
  console.log(
1619
1626
  import_chalk10.default.white(
1620
- `\u{1F4CA} Total tokens: ${import_chalk10.default.bold(summary.totalTokens.toLocaleString())}`
1627
+ `\u{1F4B8} Total tokens (context budget): ${import_chalk10.default.bold(summary.totalTokens.toLocaleString())}`
1621
1628
  )
1622
1629
  );
1623
1630
  console.log(
1624
- import_chalk10.default.yellow(
1625
- `\u{1F4B0} Avg context budget: ${import_chalk10.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1631
+ import_chalk10.default.cyan(
1632
+ `\u{1F4CA} Average context budget: ${import_chalk10.default.bold(summary.avgContextBudget.toFixed(0))} tokens`
1626
1633
  )
1627
1634
  );
1628
1635
  console.log(
1629
- import_chalk10.default.white(`\u23F1 Analysis time: ${import_chalk10.default.bold(elapsedTime + "s")}
1630
- `)
1636
+ import_chalk10.default.gray(`\u23F1 Analysis time: ${import_chalk10.default.bold(elapsedTime + "s")}`)
1631
1637
  );
1632
- renderIssueSummaryBlock(summary);
1633
- if (summary.deepFiles && summary.deepFiles.length > 0) {
1634
- renderSubSection("Deep Import Chains");
1635
- summary.deepFiles.slice(0, 10).forEach((item) => {
1636
- const fileName = item.file.split("/").slice(-2).join("/");
1638
+ if (summary.fragmentedModules.length > 0) {
1639
+ renderSubSection("Top Fragmented Modules");
1640
+ summary.fragmentedModules.slice(0, 5).forEach((mod) => {
1641
+ const scoreColor = mod.fragmentationScore > 0.7 ? import_chalk10.default.red : mod.fragmentationScore > 0.4 ? import_chalk10.default.yellow : import_chalk10.default.green;
1637
1642
  console.log(
1638
- ` ${import_chalk10.default.cyan("\u2192")} ${import_chalk10.default.white(fileName)} ${import_chalk10.default.dim(`(depth: ${item.depth})`)}`
1643
+ ` ${scoreColor("\u25A0")} ${import_chalk10.default.white(mod.domain.padEnd(20))} ${import_chalk10.default.bold((mod.fragmentationScore * 100).toFixed(0) + "%")} fragmentation`
1639
1644
  );
1640
1645
  });
1641
1646
  }
1642
- if (summary.fragmentedModules && summary.fragmentedModules.length > 0) {
1643
- renderSubSection("Fragmented Modules");
1644
- summary.fragmentedModules.slice(0, 10).forEach((module2) => {
1647
+ if (summary.topExpensiveFiles.length > 0) {
1648
+ renderSubSection("Top Context-Expensive Files");
1649
+ summary.topExpensiveFiles.slice(0, 5).forEach((item) => {
1650
+ const icon = item.severity === "critical" ? "\u{1F534}" : item.severity === "major" ? "\u{1F7E1}" : "\u{1F535}";
1651
+ const color = item.severity === "critical" ? import_chalk10.default.red : item.severity === "major" ? import_chalk10.default.yellow : import_chalk10.default.blue;
1645
1652
  console.log(
1646
- ` ${import_chalk10.default.yellow("\u25CF")} ${import_chalk10.default.white(module2.domain)} - ${import_chalk10.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1647
- );
1648
- console.log(
1649
- import_chalk10.default.dim(
1650
- ` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
1651
- )
1653
+ ` ${icon} ${color(item.severity.toUpperCase())}: ${import_chalk10.default.white(item.file.split("/").pop())} ${import_chalk10.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1652
1654
  );
1653
1655
  });
1654
1656
  }
@@ -1659,17 +1661,35 @@ async function contextAction(directory, options) {
1659
1661
 
1660
1662
  // src/commands/consistency.ts
1661
1663
  var import_chalk11 = __toESM(require("chalk"));
1662
- var import_fs6 = require("fs");
1663
1664
  var import_core15 = require("@aiready/core");
1665
+ function defineConsistencyCommand(program2) {
1666
+ program2.command("consistency").description("Check naming conventions and architectural consistency").argument("[directory]", "Directory to analyze", ".").option("--naming", "Check naming conventions (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code patterns (default: true)").option("--no-patterns", "Skip pattern analysis").option(
1667
+ "--min-severity <level>",
1668
+ "Minimum severity: info|minor|major|critical",
1669
+ "info"
1670
+ ).option(
1671
+ "--include <patterns>",
1672
+ "File patterns to include (comma-separated)"
1673
+ ).option(
1674
+ "--exclude <patterns>",
1675
+ "File patterns to exclude (comma-separated)"
1676
+ ).option(
1677
+ "-o, --output <format>",
1678
+ "Output format: console, json, markdown",
1679
+ "console"
1680
+ ).option("--output-file <path>", "Output file path (for json/markdown)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
1681
+ await consistencyAction(directory, options);
1682
+ });
1683
+ }
1664
1684
  async function consistencyAction(directory, options) {
1665
1685
  return await executeToolAction(directory, options, {
1666
1686
  toolName: "naming-consistency",
1667
1687
  label: "Consistency analysis",
1668
- emoji: "\u{1F50D}",
1688
+ emoji: "\u{1F4CF}",
1669
1689
  defaults: {
1670
- checkNaming: true,
1671
- checkPatterns: true,
1672
- minSeverity: "info",
1690
+ checkNaming: options.naming !== false,
1691
+ checkPatterns: options.patterns !== false,
1692
+ minSeverity: options.minSeverity || "info",
1673
1693
  include: void 0,
1674
1694
  exclude: void 0,
1675
1695
  output: { format: "console", file: void 0 }
@@ -1680,119 +1700,68 @@ async function consistencyAction(directory, options) {
1680
1700
  minSeverity: opts.minSeverity
1681
1701
  }),
1682
1702
  importTool: async () => {
1683
- const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1703
+ const { analyzeConsistency, generateSummary, calculateConsistencyScore } = await import("@aiready/consistency");
1684
1704
  return {
1685
- analyze: analyzeConsistency,
1686
- generateSummary: (report) => report.summary,
1687
- calculateScore: (summary, _resultsCount) => {
1688
- return calculateConsistencyScore(
1689
- summary.results?.flatMap((r) => r.issues) ?? [],
1690
- summary.summary.filesAnalyzed
1691
- );
1692
- }
1705
+ analyze: async (opts) => {
1706
+ const report = await analyzeConsistency(opts);
1707
+ return report;
1708
+ },
1709
+ generateSummary,
1710
+ calculateScore: calculateConsistencyScore
1693
1711
  };
1694
1712
  },
1695
- renderConsole: ({ results, summary, elapsedTime, score, finalOptions }) => {
1696
- const report = results;
1697
- const { format: outputFormat, file: userOutputFile } = (0, import_core15.resolveOutputFormat)(options, finalOptions);
1698
- if (outputFormat === "markdown") {
1699
- const markdown = generateMarkdownReport(report, elapsedTime);
1700
- const outputPath = (0, import_core15.resolveOutputPath)(
1701
- userOutputFile,
1702
- `aiready-report-${(0, import_core2.getReportTimestamp)()}.md`,
1703
- directory
1704
- );
1705
- (0, import_fs6.writeFileSync)(outputPath, markdown);
1706
- console.log(import_chalk11.default.green(`\u2705 Report saved to ${outputPath}`));
1707
- return;
1708
- }
1709
- console.log(import_chalk11.default.bold("\n\u{1F4CA} Summary\n"));
1710
- console.log(`Files Analyzed: ${import_chalk11.default.cyan(summary.filesAnalyzed)}`);
1711
- console.log(`Total Issues: ${import_chalk11.default.yellow(summary.totalIssues)}`);
1712
- console.log(` Naming: ${import_chalk11.default.yellow(summary.namingIssues)}`);
1713
- console.log(` Patterns: ${import_chalk11.default.yellow(summary.patternIssues)}`);
1713
+ renderConsole: ({ results: report, summary, elapsedTime, score }) => {
1714
+ (0, import_core15.printTerminalHeader)("CONSISTENCY ANALYSIS SUMMARY");
1714
1715
  console.log(
1715
- ` Architecture: ${import_chalk11.default.yellow(summary.architectureIssues ?? 0)}`
1716
+ import_chalk11.default.white(`\u{1F4C1} Files analyzed: ${import_chalk11.default.bold(summary.filesAnalyzed)}`)
1716
1717
  );
1717
- console.log(`Analysis Time: ${import_chalk11.default.gray(elapsedTime + "s")}
1718
- `);
1719
- if (summary.totalIssues === 0) {
1720
- console.log(
1721
- import_chalk11.default.green(
1722
- "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1723
- )
1724
- );
1725
- } else {
1726
- const namingResults = report.results.filter(
1727
- (r) => r.issues.some((i) => i.category === "naming")
1728
- );
1729
- const patternResults = report.results.filter(
1730
- (r) => r.issues.some((i) => i.category === "patterns")
1731
- );
1732
- if (namingResults.length > 0) {
1733
- console.log(import_chalk11.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1734
- let shown = 0;
1735
- for (const namingFileResult of namingResults) {
1736
- if (shown >= 5) break;
1737
- for (const issue of namingFileResult.issues) {
1738
- if (shown >= 5) break;
1739
- const severityColor = issue.severity === "critical" ? import_chalk11.default.red : issue.severity === "major" ? import_chalk11.default.yellow : issue.severity === "minor" ? import_chalk11.default.blue : import_chalk11.default.gray;
1740
- console.log(
1741
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk11.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1742
- );
1743
- console.log(` ${issue.message}`);
1744
- if (issue.suggestion) {
1745
- console.log(
1746
- ` ${import_chalk11.default.dim("\u2192")} ${import_chalk11.default.italic(issue.suggestion)}`
1747
- );
1748
- }
1749
- console.log();
1750
- shown++;
1751
- }
1752
- }
1753
- }
1754
- if (patternResults.length > 0) {
1755
- console.log(import_chalk11.default.bold("\u{1F504} Pattern Issues\n"));
1756
- let shown = 0;
1757
- for (const patternFileResult of patternResults) {
1758
- if (shown >= 5) break;
1759
- for (const issue of patternFileResult.issues) {
1760
- if (shown >= 5) break;
1761
- const severityColor = issue.severity === "critical" ? import_chalk11.default.red : issue.severity === "major" ? import_chalk11.default.yellow : issue.severity === "minor" ? import_chalk11.default.blue : import_chalk11.default.gray;
1762
- console.log(
1763
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk11.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1764
- );
1765
- console.log(` ${issue.message}`);
1766
- if (issue.suggestion) {
1767
- console.log(
1768
- ` ${import_chalk11.default.dim("\u2192")} ${import_chalk11.default.italic(issue.suggestion)}`
1769
- );
1770
- }
1771
- console.log();
1772
- shown++;
1773
- }
1718
+ console.log(
1719
+ import_chalk11.default.white(`\u26A0 Total issues: ${import_chalk11.default.bold(summary.totalIssues)}`)
1720
+ );
1721
+ console.log(
1722
+ import_chalk11.default.gray(`\u23F1 Analysis time: ${import_chalk11.default.bold(elapsedTime + "s")}`)
1723
+ );
1724
+ if (summary.totalIssues > 0 && report.results) {
1725
+ renderSubSection("Issues Breakdown");
1726
+ const sortedIssues = [...report.results].flatMap(
1727
+ (file) => (file.issues || []).map((issue) => ({
1728
+ ...issue,
1729
+ file: file.fileName
1730
+ }))
1731
+ ).sort((a, b) => {
1732
+ const levels = {
1733
+ critical: 4,
1734
+ major: 3,
1735
+ minor: 2,
1736
+ info: 1
1737
+ };
1738
+ return (levels[b.severity] || 0) - (levels[a.severity] || 0);
1739
+ }).slice(0, 10);
1740
+ sortedIssues.forEach((issue) => {
1741
+ const icon = issue.severity === "critical" ? "\u{1F534}" : issue.severity === "major" ? "\u{1F7E1}" : "\u{1F535}";
1742
+ const color = issue.severity === "critical" ? import_chalk11.default.red : issue.severity === "major" ? import_chalk11.default.yellow : import_chalk11.default.blue;
1743
+ console.log(
1744
+ ` ${icon} ${color(issue.severity.toUpperCase())}: ${import_chalk11.default.white(issue.file)}${issue.line ? `:${issue.line}` : ""}`
1745
+ );
1746
+ console.log(` ${issue.message}`);
1747
+ if (issue.suggestion) {
1748
+ console.log(import_chalk11.default.dim(` \u{1F4A1} ${issue.suggestion}`));
1774
1749
  }
1775
- }
1776
- if (report.recommendations?.length > 0) {
1777
- console.log(import_chalk11.default.bold("\u{1F4A1} Recommendations\n"));
1778
- report.recommendations.forEach((rec, i) => {
1779
- console.log(`${i + 1}. ${rec}`);
1780
- });
1781
1750
  console.log();
1782
- }
1783
- }
1784
- if (score) {
1785
- console.log(import_chalk11.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1786
- console.log((0, import_core15.formatToolScore)(score));
1787
- console.log();
1751
+ });
1752
+ } else {
1753
+ console.log(
1754
+ import_chalk11.default.green("\n\u2728 Great! No consistency issues detected.\n")
1755
+ );
1788
1756
  }
1757
+ renderToolScoreFooter(score);
1789
1758
  }
1790
1759
  });
1791
1760
  }
1792
1761
 
1793
1762
  // src/commands/visualize.ts
1794
1763
  var import_chalk12 = __toESM(require("chalk"));
1795
- var import_fs7 = require("fs");
1764
+ var import_fs6 = require("fs");
1796
1765
  var import_path6 = require("path");
1797
1766
  var import_child_process = require("child_process");
1798
1767
  var import_core16 = require("@aiready/core");
@@ -1801,7 +1770,7 @@ async function visualizeAction(directory, options) {
1801
1770
  try {
1802
1771
  const dirPath = (0, import_path6.resolve)(process.cwd(), directory ?? ".");
1803
1772
  let reportPath = options.report ? (0, import_path6.resolve)(dirPath, options.report) : null;
1804
- if (!reportPath || !(0, import_fs7.existsSync)(reportPath)) {
1773
+ if (!reportPath || !(0, import_fs6.existsSync)(reportPath)) {
1805
1774
  const latestScan = (0, import_core17.findLatestReport)(dirPath);
1806
1775
  if (latestScan) {
1807
1776
  reportPath = latestScan;
@@ -1823,13 +1792,13 @@ Or specify a custom report:
1823
1792
  return;
1824
1793
  }
1825
1794
  }
1826
- const raw = (0, import_fs7.readFileSync)(reportPath, "utf8");
1795
+ const raw = (0, import_fs6.readFileSync)(reportPath, "utf8");
1827
1796
  const report = JSON.parse(raw);
1828
1797
  const configPath = (0, import_path6.resolve)(dirPath, "aiready.json");
1829
1798
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1830
- if ((0, import_fs7.existsSync)(configPath)) {
1799
+ if ((0, import_fs6.existsSync)(configPath)) {
1831
1800
  try {
1832
- const rawConfig = JSON.parse((0, import_fs7.readFileSync)(configPath, "utf8"));
1801
+ const rawConfig = JSON.parse((0, import_fs6.readFileSync)(configPath, "utf8"));
1833
1802
  if (rawConfig.visualizer?.graph) {
1834
1803
  graphConfig = {
1835
1804
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1852,7 +1821,7 @@ Or specify a custom report:
1852
1821
  const localWebDir = (0, import_path6.resolve)(dirPath, "packages/visualizer");
1853
1822
  let webDir = "";
1854
1823
  let visualizerAvailable = false;
1855
- if ((0, import_fs7.existsSync)(localWebDir)) {
1824
+ if ((0, import_fs6.existsSync)(localWebDir)) {
1856
1825
  webDir = localWebDir;
1857
1826
  visualizerAvailable = true;
1858
1827
  } else {
@@ -1875,7 +1844,7 @@ Or specify a custom report:
1875
1844
  currentDir = parent;
1876
1845
  }
1877
1846
  for (const location of nodemodulesLocations) {
1878
- if ((0, import_fs7.existsSync)(location) && (0, import_fs7.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1847
+ if ((0, import_fs6.existsSync)(location) && (0, import_fs6.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1879
1848
  webDir = location;
1880
1849
  visualizerAvailable = true;
1881
1850
  break;
@@ -1891,14 +1860,14 @@ Or specify a custom report:
1891
1860
  }
1892
1861
  }
1893
1862
  }
1894
- const webViteConfigExists = webDir && (0, import_fs7.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1863
+ const webViteConfigExists = webDir && (0, import_fs6.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1895
1864
  if (visualizerAvailable && webViteConfigExists) {
1896
1865
  const spawnCwd = webDir;
1897
1866
  const { watch } = await import("fs");
1898
1867
  const copyReportToViz = () => {
1899
1868
  try {
1900
1869
  const destPath = (0, import_path6.resolve)(spawnCwd, "web", "report-data.json");
1901
- (0, import_fs7.copyFileSync)(reportPath, destPath);
1870
+ (0, import_fs6.copyFileSync)(reportPath, destPath);
1902
1871
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1903
1872
  } catch (e) {
1904
1873
  console.error("Failed to sync report:", e);
@@ -1962,7 +1931,7 @@ Or specify a custom report:
1962
1931
  const html = (0, import_core17.generateHTML)(graph);
1963
1932
  const defaultOutput = "visualization.html";
1964
1933
  const outPath = (0, import_path6.resolve)(dirPath, options.output ?? defaultOutput);
1965
- (0, import_fs7.writeFileSync)(outPath, html, "utf8");
1934
+ (0, import_fs6.writeFileSync)(outPath, html, "utf8");
1966
1935
  console.log(import_chalk12.default.green(`\u2705 Visualization written to: ${outPath}`));
1967
1936
  if (options.open || options.serve) {
1968
1937
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
@@ -2245,7 +2214,7 @@ EXAMPLES:
2245
2214
  // src/commands/remediate.ts
2246
2215
  var import_chalk18 = __toESM(require("chalk"));
2247
2216
  var import_path7 = require("path");
2248
- var import_fs8 = require("fs");
2217
+ var import_fs7 = require("fs");
2249
2218
  var import_core18 = require("@aiready/core");
2250
2219
  async function remediateAction(directory, options) {
2251
2220
  const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory || ".");
@@ -2255,15 +2224,15 @@ async function remediateAction(directory, options) {
2255
2224
  let reportPath = options.report;
2256
2225
  if (!reportPath) {
2257
2226
  const aireadyDir = (0, import_path7.resolve)(resolvedDir, ".aiready");
2258
- if ((0, import_fs8.existsSync)(aireadyDir)) {
2259
- const files = (0, import_fs8.readdirSync)(aireadyDir).filter((f) => f.startsWith("aiready-report-") && f.endsWith(".json")).sort().reverse();
2227
+ if ((0, import_fs7.existsSync)(aireadyDir)) {
2228
+ const files = (0, import_fs7.readdirSync)(aireadyDir).filter((f) => f.startsWith("aiready-report-") && f.endsWith(".json")).sort().reverse();
2260
2229
  if (files.length > 0) {
2261
2230
  reportPath = (0, import_path7.resolve)(aireadyDir, files[0]);
2262
2231
  console.log(import_chalk18.default.dim(`\u{1F4C2} Using latest report: ${files[0]}`));
2263
2232
  }
2264
2233
  }
2265
2234
  }
2266
- if (!reportPath || !(0, import_fs8.existsSync)(reportPath)) {
2235
+ if (!reportPath || !(0, import_fs7.existsSync)(reportPath)) {
2267
2236
  console.log(import_chalk18.default.yellow("\n\u26A0\uFE0F No AIReady report found."));
2268
2237
  console.log(
2269
2238
  import_chalk18.default.dim(
@@ -2340,7 +2309,7 @@ var getDirname = () => {
2340
2309
  return (0, import_path8.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2341
2310
  };
2342
2311
  var packageJson = JSON.parse(
2343
- (0, import_fs9.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
2312
+ (0, import_fs8.readFileSync)((0, import_path8.join)(getDirname(), "../package.json"), "utf8")
2344
2313
  );
2345
2314
  var program = new import_commander.Command();
2346
2315
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -2369,42 +2338,15 @@ CONFIGURATION:
2369
2338
  Config files (searched upward): aiready.json, .aiready.json, aiready.config.*
2370
2339
  CLI options override config file settings
2371
2340
 
2372
- Example aiready.json:
2373
- {
2374
- "scan": { "exclude": ["**/dist/**", "**/node_modules/**"] },
2375
- "tools": {
2376
- "pattern-detect": { "minSimilarity": 0.5 },
2377
- "context-analyzer": { "maxContextBudget": 15000 }
2378
- },
2379
- "output": { "format": "json", "directory": ".aiready" }
2380
- }
2381
-
2382
2341
  VERSION: ${packageJson.version}
2383
2342
  DOCUMENTATION: https://aiready.dev/docs/cli
2384
2343
  GITHUB: https://github.com/caopengau/aiready-cli
2385
2344
  LANDING: https://github.com/caopengau/aiready-landing`
2386
2345
  );
2387
- program.command("scan").description(
2388
- "Run comprehensive AI-readiness analysis (patterns + context + consistency)"
2389
- ).argument("[directory]", "Directory to analyze", ".").option(
2390
- "-t, --tools <tools>",
2391
- "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
2392
- ).option(
2393
- "--profile <type>",
2394
- "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
2395
- ).option(
2396
- "--compare-to <path>",
2397
- "Compare results against a previous AIReady report JSON"
2398
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
2399
- "--ci",
2400
- "CI mode: GitHub Actions annotations, no colors, fail on threshold"
2401
- ).option(
2402
- "--fail-on <level>",
2403
- "Fail on issues: critical, major, any",
2404
- "critical"
2405
- ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", SCAN_HELP_TEXT).action(async (directory, options) => {
2406
- await scanAction(directory, options);
2407
- });
2346
+ defineScanCommand(program);
2347
+ definePatternsCommand(program);
2348
+ defineContextCommand(program);
2349
+ defineConsistencyCommand(program);
2408
2350
  program.command("init").description("Generate a default configuration (aiready.json)").option("-f, --force", "Overwrite existing configuration file").option(
2409
2351
  "--js",
2410
2352
  "Generate configuration as a JavaScript file (aiready.config.js)"
@@ -2412,36 +2354,6 @@ program.command("init").description("Generate a default configuration (aiready.j
2412
2354
  const format = options.js ? "js" : "json";
2413
2355
  await initAction({ force: options.force, format, full: options.full });
2414
2356
  });
2415
- 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(
2416
- "--max-candidates <number>",
2417
- "Maximum candidates per block (performance tuning)"
2418
- ).option(
2419
- "--min-shared-tokens <number>",
2420
- "Minimum shared tokens for candidates (performance tuning)"
2421
- ).option(
2422
- "--full-scan",
2423
- "Disable smart defaults for comprehensive analysis (slower)"
2424
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
2425
- await patternsAction(directory, options);
2426
- });
2427
- program.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
2428
- "--max-context <number>",
2429
- "Maximum acceptable context budget (tokens)",
2430
- "10000"
2431
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2432
- await contextAction(directory, options);
2433
- });
2434
- program.command("consistency").description("Check naming conventions and architectural consistency").argument("[directory]", "Directory to analyze", ".").option("--naming", "Check naming conventions (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code patterns (default: true)").option("--no-patterns", "Skip pattern analysis").option(
2435
- "--min-severity <level>",
2436
- "Minimum severity: info|minor|major|critical",
2437
- "info"
2438
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option(
2439
- "-o, --output <format>",
2440
- "Output format: console, json, markdown",
2441
- "console"
2442
- ).option("--output-file <path>", "Output file path (for json/markdown)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2443
- await consistencyAction(directory, options);
2444
- });
2445
2357
  program.command("visualise").description("Alias for visualize (British spelling)").argument("[directory]", "Directory to analyze", ".").option(
2446
2358
  "--report <path>",
2447
2359
  "Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)"
package/dist/cli.mjs CHANGED
@@ -88,38 +88,6 @@ async function warnIfGraphCapExceeded(report, dirPath) {
88
88
  void err;
89
89
  }
90
90
  }
91
- function generateMarkdownReport(report, elapsedTime) {
92
- let markdown = `# Consistency Analysis Report
93
-
94
- `;
95
- markdown += `**Generated:** ${(/* @__PURE__ */ new Date()).toISOString()}
96
- `;
97
- markdown += `**Analysis Time:** ${elapsedTime}s
98
-
99
- `;
100
- markdown += `## Summary
101
-
102
- `;
103
- markdown += `- **Files Analyzed:** ${report.summary.filesAnalyzed}
104
- `;
105
- markdown += `- **Total Issues:** ${report.summary.totalIssues}
106
- `;
107
- markdown += ` - Naming: ${report.summary.namingIssues}
108
- `;
109
- markdown += ` - Patterns: ${report.summary.patternIssues}
110
-
111
- `;
112
- if (report.recommendations.length > 0) {
113
- markdown += `## Recommendations
114
-
115
- `;
116
- report.recommendations.forEach((rec, i) => {
117
- markdown += `${i + 1}. ${rec}
118
- `;
119
- });
120
- }
121
- return markdown;
122
- }
123
91
 
124
92
  // src/commands/report-formatter.ts
125
93
  import chalk2 from "chalk";
@@ -876,6 +844,38 @@ ${chalk6.bold("CI/CD Integration:")}
876
844
  Use --threshold and --fail-on to use AIReady as a quality gate in your CI pipelines.
877
845
  When running in GitHub Actions, it will automatically emit annotations for found issues.
878
846
  `;
847
+ function defineScanCommand(program2) {
848
+ program2.command("scan").description(
849
+ "Run comprehensive AI-readiness analysis (patterns + context + consistency)"
850
+ ).argument("[directory]", "Directory to analyze", ".").option(
851
+ "-t, --tools <tools>",
852
+ "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
853
+ ).option(
854
+ "--profile <type>",
855
+ "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
856
+ ).option(
857
+ "--compare-to <path>",
858
+ "Compare results against a previous AIReady report JSON"
859
+ ).option(
860
+ "--include <patterns>",
861
+ "File patterns to include (comma-separated)"
862
+ ).option(
863
+ "--exclude <patterns>",
864
+ "File patterns to exclude (comma-separated)"
865
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option(
866
+ "--threshold <score>",
867
+ "Fail CI/CD if score below threshold (0-100)"
868
+ ).option(
869
+ "--ci",
870
+ "CI mode: GitHub Actions annotations, no colors, fail on threshold"
871
+ ).option(
872
+ "--fail-on <level>",
873
+ "Fail on issues: critical, major, any",
874
+ "critical"
875
+ ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", SCAN_HELP_TEXT).action(async (directory, options) => {
876
+ await scanAction(directory, options);
877
+ });
878
+ }
879
879
 
880
880
  // src/commands/init.ts
881
881
  import { writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
@@ -1158,33 +1158,6 @@ function renderSafetyRating(safety) {
1158
1158
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
1159
1159
  );
1160
1160
  }
1161
- function renderIssueSummaryBlock(summary) {
1162
- const total = (summary.criticalIssues || 0) + (summary.majorIssues || 0) + (summary.minorIssues || 0);
1163
- if (total === 0) {
1164
- console.log(chalk8.green("\u2705 No significant issues found!\n"));
1165
- return;
1166
- }
1167
- console.log(chalk8.bold("\u26A0\uFE0F Issues Found:\n"));
1168
- if (summary.criticalIssues > 0)
1169
- console.log(
1170
- chalk8.red(` \u{1F534} Critical: ${chalk8.bold(summary.criticalIssues)}`)
1171
- );
1172
- if (summary.majorIssues > 0)
1173
- console.log(
1174
- chalk8.yellow(` \u{1F7E1} Major: ${chalk8.bold(summary.majorIssues)}`)
1175
- );
1176
- if (summary.minorIssues > 0)
1177
- console.log(chalk8.blue(` \u{1F535} Minor: ${chalk8.bold(summary.minorIssues)}`));
1178
- if (summary.totalPotentialSavings) {
1179
- console.log(
1180
- chalk8.green(
1181
- `
1182
- \u{1F4A1} Potential savings: ${chalk8.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1183
- `
1184
- )
1185
- );
1186
- }
1187
- }
1188
1161
  function renderSubSection(title) {
1189
1162
  console.log("\n" + coreGetDivider());
1190
1163
  console.log(chalk8.bold.white(` ${title.toUpperCase()}`));
@@ -1201,6 +1174,36 @@ function renderToolScoreFooter(score) {
1201
1174
  }
1202
1175
 
1203
1176
  // src/commands/patterns.ts
1177
+ var PATTERNS_HELP_TEXT = `
1178
+ EXAMPLES:
1179
+ $ aiready patterns # Default analysis
1180
+ $ aiready patterns --similarity 0.6 # Stricter matching
1181
+ $ aiready patterns --min-lines 10 # Larger patterns only
1182
+ `;
1183
+ function definePatternsCommand(program2) {
1184
+ program2.command("patterns").description("Detect duplicate code patterns that confuse AI models").argument("[directory]", "Directory to analyze", ".").option(
1185
+ "-s, --similarity <number>",
1186
+ "Minimum similarity score (0-1)",
1187
+ "0.40"
1188
+ ).option("-l, --min-lines <number>", "Minimum lines to consider", "5").option(
1189
+ "--max-candidates <number>",
1190
+ "Maximum candidates per block (performance tuning)"
1191
+ ).option(
1192
+ "--min-shared-tokens <number>",
1193
+ "Minimum shared tokens for candidates (performance tuning)"
1194
+ ).option(
1195
+ "--full-scan",
1196
+ "Disable smart defaults for comprehensive analysis (slower)"
1197
+ ).option(
1198
+ "--include <patterns>",
1199
+ "File patterns to include (comma-separated)"
1200
+ ).option(
1201
+ "--exclude <patterns>",
1202
+ "File patterns to exclude (comma-separated)"
1203
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
1204
+ await patternsAction(directory, options);
1205
+ });
1206
+ }
1204
1207
  async function patternsAction(directory, options) {
1205
1208
  return await executeToolAction(directory, options, {
1206
1209
  toolName: "pattern-detect",
@@ -1280,21 +1283,30 @@ async function patternsAction(directory, options) {
1280
1283
  }
1281
1284
  });
1282
1285
  }
1283
- var PATTERNS_HELP_TEXT = `
1284
- EXAMPLES:
1285
- $ aiready patterns # Default analysis
1286
- $ aiready patterns --similarity 0.6 # Stricter matching
1287
- $ aiready patterns --min-lines 10 # Larger patterns only
1288
- `;
1289
1286
 
1290
1287
  // src/commands/context.ts
1291
1288
  import chalk10 from "chalk";
1292
1289
  import { printTerminalHeader as printTerminalHeader2 } from "@aiready/core";
1290
+ function defineContextCommand(program2) {
1291
+ program2.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
1292
+ "--max-context <number>",
1293
+ "Maximum acceptable context budget (tokens)",
1294
+ "10000"
1295
+ ).option(
1296
+ "--include <patterns>",
1297
+ "File patterns to include (comma-separated)"
1298
+ ).option(
1299
+ "--exclude <patterns>",
1300
+ "File patterns to exclude (comma-separated)"
1301
+ ).option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
1302
+ await contextAction(directory, options);
1303
+ });
1304
+ }
1293
1305
  async function contextAction(directory, options) {
1294
1306
  return await executeToolAction(directory, options, {
1295
1307
  toolName: "context-analyzer",
1296
1308
  label: "Context analysis",
1297
- emoji: "\u{1F9E0}",
1309
+ emoji: "\u{1F9E9}",
1298
1310
  defaults: {
1299
1311
  maxDepth: 5,
1300
1312
  maxContextBudget: 1e4,
@@ -1306,11 +1318,6 @@ async function contextAction(directory, options) {
1306
1318
  maxDepth: opts.maxDepth ? parseInt(opts.maxDepth) : void 0,
1307
1319
  maxContextBudget: opts.maxContext ? parseInt(opts.maxContext) : void 0
1308
1320
  }),
1309
- preAnalyze: async (resolvedDir, baseOptions) => {
1310
- const { getSmartDefaults } = await import("@aiready/context-analyzer");
1311
- const smartDefaults = await getSmartDefaults(resolvedDir, baseOptions);
1312
- return { ...smartDefaults, ...baseOptions };
1313
- },
1314
1321
  importTool: async () => {
1315
1322
  const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1316
1323
  return {
@@ -1319,45 +1326,40 @@ async function contextAction(directory, options) {
1319
1326
  calculateScore: calculateContextScore
1320
1327
  };
1321
1328
  },
1322
- renderConsole: ({ summary, elapsedTime, score }) => {
1329
+ renderConsole: ({ results: _results, summary, elapsedTime, score }) => {
1323
1330
  printTerminalHeader2("CONTEXT ANALYSIS SUMMARY");
1324
1331
  console.log(
1325
- chalk10.white(`\u{1F4C1} Files analyzed: ${chalk10.bold(summary.totalFiles)}`)
1332
+ chalk10.white(`\u{1F4C1} Total files: ${chalk10.bold(summary.totalFiles)}`)
1326
1333
  );
1327
1334
  console.log(
1328
1335
  chalk10.white(
1329
- `\u{1F4CA} Total tokens: ${chalk10.bold(summary.totalTokens.toLocaleString())}`
1336
+ `\u{1F4B8} Total tokens (context budget): ${chalk10.bold(summary.totalTokens.toLocaleString())}`
1330
1337
  )
1331
1338
  );
1332
1339
  console.log(
1333
- chalk10.yellow(
1334
- `\u{1F4B0} Avg context budget: ${chalk10.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1340
+ chalk10.cyan(
1341
+ `\u{1F4CA} Average context budget: ${chalk10.bold(summary.avgContextBudget.toFixed(0))} tokens`
1335
1342
  )
1336
1343
  );
1337
1344
  console.log(
1338
- chalk10.white(`\u23F1 Analysis time: ${chalk10.bold(elapsedTime + "s")}
1339
- `)
1345
+ chalk10.gray(`\u23F1 Analysis time: ${chalk10.bold(elapsedTime + "s")}`)
1340
1346
  );
1341
- renderIssueSummaryBlock(summary);
1342
- if (summary.deepFiles && summary.deepFiles.length > 0) {
1343
- renderSubSection("Deep Import Chains");
1344
- summary.deepFiles.slice(0, 10).forEach((item) => {
1345
- const fileName = item.file.split("/").slice(-2).join("/");
1347
+ if (summary.fragmentedModules.length > 0) {
1348
+ renderSubSection("Top Fragmented Modules");
1349
+ summary.fragmentedModules.slice(0, 5).forEach((mod) => {
1350
+ const scoreColor = mod.fragmentationScore > 0.7 ? chalk10.red : mod.fragmentationScore > 0.4 ? chalk10.yellow : chalk10.green;
1346
1351
  console.log(
1347
- ` ${chalk10.cyan("\u2192")} ${chalk10.white(fileName)} ${chalk10.dim(`(depth: ${item.depth})`)}`
1352
+ ` ${scoreColor("\u25A0")} ${chalk10.white(mod.domain.padEnd(20))} ${chalk10.bold((mod.fragmentationScore * 100).toFixed(0) + "%")} fragmentation`
1348
1353
  );
1349
1354
  });
1350
1355
  }
1351
- if (summary.fragmentedModules && summary.fragmentedModules.length > 0) {
1352
- renderSubSection("Fragmented Modules");
1353
- summary.fragmentedModules.slice(0, 10).forEach((module) => {
1354
- console.log(
1355
- ` ${chalk10.yellow("\u25CF")} ${chalk10.white(module.domain)} - ${chalk10.dim(`${module.files.length} files, ${(module.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1356
- );
1356
+ if (summary.topExpensiveFiles.length > 0) {
1357
+ renderSubSection("Top Context-Expensive Files");
1358
+ summary.topExpensiveFiles.slice(0, 5).forEach((item) => {
1359
+ const icon = item.severity === "critical" ? "\u{1F534}" : item.severity === "major" ? "\u{1F7E1}" : "\u{1F535}";
1360
+ const color = item.severity === "critical" ? chalk10.red : item.severity === "major" ? chalk10.yellow : chalk10.blue;
1357
1361
  console.log(
1358
- chalk10.dim(
1359
- ` Token cost: ${module.totalTokens.toLocaleString()}, Cohesion: ${(module.avgCohesion * 100).toFixed(0)}%`
1360
- )
1362
+ ` ${icon} ${color(item.severity.toUpperCase())}: ${chalk10.white(item.file.split("/").pop())} ${chalk10.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1361
1363
  );
1362
1364
  });
1363
1365
  }
@@ -1368,21 +1370,35 @@ async function contextAction(directory, options) {
1368
1370
 
1369
1371
  // src/commands/consistency.ts
1370
1372
  import chalk11 from "chalk";
1371
- import { writeFileSync as writeFileSync3 } from "fs";
1372
- import {
1373
- resolveOutputPath as resolveOutputPath2,
1374
- formatToolScore as formatToolScore2,
1375
- resolveOutputFormat as resolveOutputFormat2
1376
- } from "@aiready/core";
1373
+ import { printTerminalHeader as printTerminalHeader3 } from "@aiready/core";
1374
+ function defineConsistencyCommand(program2) {
1375
+ program2.command("consistency").description("Check naming conventions and architectural consistency").argument("[directory]", "Directory to analyze", ".").option("--naming", "Check naming conventions (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code patterns (default: true)").option("--no-patterns", "Skip pattern analysis").option(
1376
+ "--min-severity <level>",
1377
+ "Minimum severity: info|minor|major|critical",
1378
+ "info"
1379
+ ).option(
1380
+ "--include <patterns>",
1381
+ "File patterns to include (comma-separated)"
1382
+ ).option(
1383
+ "--exclude <patterns>",
1384
+ "File patterns to exclude (comma-separated)"
1385
+ ).option(
1386
+ "-o, --output <format>",
1387
+ "Output format: console, json, markdown",
1388
+ "console"
1389
+ ).option("--output-file <path>", "Output file path (for json/markdown)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
1390
+ await consistencyAction(directory, options);
1391
+ });
1392
+ }
1377
1393
  async function consistencyAction(directory, options) {
1378
1394
  return await executeToolAction(directory, options, {
1379
1395
  toolName: "naming-consistency",
1380
1396
  label: "Consistency analysis",
1381
- emoji: "\u{1F50D}",
1397
+ emoji: "\u{1F4CF}",
1382
1398
  defaults: {
1383
- checkNaming: true,
1384
- checkPatterns: true,
1385
- minSeverity: "info",
1399
+ checkNaming: options.naming !== false,
1400
+ checkPatterns: options.patterns !== false,
1401
+ minSeverity: options.minSeverity || "info",
1386
1402
  include: void 0,
1387
1403
  exclude: void 0,
1388
1404
  output: { format: "console", file: void 0 }
@@ -1393,119 +1409,68 @@ async function consistencyAction(directory, options) {
1393
1409
  minSeverity: opts.minSeverity
1394
1410
  }),
1395
1411
  importTool: async () => {
1396
- const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1412
+ const { analyzeConsistency, generateSummary, calculateConsistencyScore } = await import("@aiready/consistency");
1397
1413
  return {
1398
- analyze: analyzeConsistency,
1399
- generateSummary: (report) => report.summary,
1400
- calculateScore: (summary, _resultsCount) => {
1401
- return calculateConsistencyScore(
1402
- summary.results?.flatMap((r) => r.issues) ?? [],
1403
- summary.summary.filesAnalyzed
1404
- );
1405
- }
1414
+ analyze: async (opts) => {
1415
+ const report = await analyzeConsistency(opts);
1416
+ return report;
1417
+ },
1418
+ generateSummary,
1419
+ calculateScore: calculateConsistencyScore
1406
1420
  };
1407
1421
  },
1408
- renderConsole: ({ results, summary, elapsedTime, score, finalOptions }) => {
1409
- const report = results;
1410
- const { format: outputFormat, file: userOutputFile } = resolveOutputFormat2(options, finalOptions);
1411
- if (outputFormat === "markdown") {
1412
- const markdown = generateMarkdownReport(report, elapsedTime);
1413
- const outputPath = resolveOutputPath2(
1414
- userOutputFile,
1415
- `aiready-report-${getReportTimestamp()}.md`,
1416
- directory
1417
- );
1418
- writeFileSync3(outputPath, markdown);
1419
- console.log(chalk11.green(`\u2705 Report saved to ${outputPath}`));
1420
- return;
1421
- }
1422
- console.log(chalk11.bold("\n\u{1F4CA} Summary\n"));
1423
- console.log(`Files Analyzed: ${chalk11.cyan(summary.filesAnalyzed)}`);
1424
- console.log(`Total Issues: ${chalk11.yellow(summary.totalIssues)}`);
1425
- console.log(` Naming: ${chalk11.yellow(summary.namingIssues)}`);
1426
- console.log(` Patterns: ${chalk11.yellow(summary.patternIssues)}`);
1422
+ renderConsole: ({ results: report, summary, elapsedTime, score }) => {
1423
+ printTerminalHeader3("CONSISTENCY ANALYSIS SUMMARY");
1427
1424
  console.log(
1428
- ` Architecture: ${chalk11.yellow(summary.architectureIssues ?? 0)}`
1425
+ chalk11.white(`\u{1F4C1} Files analyzed: ${chalk11.bold(summary.filesAnalyzed)}`)
1429
1426
  );
1430
- console.log(`Analysis Time: ${chalk11.gray(elapsedTime + "s")}
1431
- `);
1432
- if (summary.totalIssues === 0) {
1433
- console.log(
1434
- chalk11.green(
1435
- "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1436
- )
1437
- );
1438
- } else {
1439
- const namingResults = report.results.filter(
1440
- (r) => r.issues.some((i) => i.category === "naming")
1441
- );
1442
- const patternResults = report.results.filter(
1443
- (r) => r.issues.some((i) => i.category === "patterns")
1444
- );
1445
- if (namingResults.length > 0) {
1446
- console.log(chalk11.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1447
- let shown = 0;
1448
- for (const namingFileResult of namingResults) {
1449
- if (shown >= 5) break;
1450
- for (const issue of namingFileResult.issues) {
1451
- if (shown >= 5) break;
1452
- const severityColor = issue.severity === "critical" ? chalk11.red : issue.severity === "major" ? chalk11.yellow : issue.severity === "minor" ? chalk11.blue : chalk11.gray;
1453
- console.log(
1454
- `${severityColor(issue.severity.toUpperCase())} ${chalk11.dim(`${issue.location.file}:${issue.location.line}`)}`
1455
- );
1456
- console.log(` ${issue.message}`);
1457
- if (issue.suggestion) {
1458
- console.log(
1459
- ` ${chalk11.dim("\u2192")} ${chalk11.italic(issue.suggestion)}`
1460
- );
1461
- }
1462
- console.log();
1463
- shown++;
1464
- }
1465
- }
1466
- }
1467
- if (patternResults.length > 0) {
1468
- console.log(chalk11.bold("\u{1F504} Pattern Issues\n"));
1469
- let shown = 0;
1470
- for (const patternFileResult of patternResults) {
1471
- if (shown >= 5) break;
1472
- for (const issue of patternFileResult.issues) {
1473
- if (shown >= 5) break;
1474
- const severityColor = issue.severity === "critical" ? chalk11.red : issue.severity === "major" ? chalk11.yellow : issue.severity === "minor" ? chalk11.blue : chalk11.gray;
1475
- console.log(
1476
- `${severityColor(issue.severity.toUpperCase())} ${chalk11.dim(`${issue.location.file}:${issue.location.line}`)}`
1477
- );
1478
- console.log(` ${issue.message}`);
1479
- if (issue.suggestion) {
1480
- console.log(
1481
- ` ${chalk11.dim("\u2192")} ${chalk11.italic(issue.suggestion)}`
1482
- );
1483
- }
1484
- console.log();
1485
- shown++;
1486
- }
1427
+ console.log(
1428
+ chalk11.white(`\u26A0 Total issues: ${chalk11.bold(summary.totalIssues)}`)
1429
+ );
1430
+ console.log(
1431
+ chalk11.gray(`\u23F1 Analysis time: ${chalk11.bold(elapsedTime + "s")}`)
1432
+ );
1433
+ if (summary.totalIssues > 0 && report.results) {
1434
+ renderSubSection("Issues Breakdown");
1435
+ const sortedIssues = [...report.results].flatMap(
1436
+ (file) => (file.issues || []).map((issue) => ({
1437
+ ...issue,
1438
+ file: file.fileName
1439
+ }))
1440
+ ).sort((a, b) => {
1441
+ const levels = {
1442
+ critical: 4,
1443
+ major: 3,
1444
+ minor: 2,
1445
+ info: 1
1446
+ };
1447
+ return (levels[b.severity] || 0) - (levels[a.severity] || 0);
1448
+ }).slice(0, 10);
1449
+ sortedIssues.forEach((issue) => {
1450
+ const icon = issue.severity === "critical" ? "\u{1F534}" : issue.severity === "major" ? "\u{1F7E1}" : "\u{1F535}";
1451
+ const color = issue.severity === "critical" ? chalk11.red : issue.severity === "major" ? chalk11.yellow : chalk11.blue;
1452
+ console.log(
1453
+ ` ${icon} ${color(issue.severity.toUpperCase())}: ${chalk11.white(issue.file)}${issue.line ? `:${issue.line}` : ""}`
1454
+ );
1455
+ console.log(` ${issue.message}`);
1456
+ if (issue.suggestion) {
1457
+ console.log(chalk11.dim(` \u{1F4A1} ${issue.suggestion}`));
1487
1458
  }
1488
- }
1489
- if (report.recommendations?.length > 0) {
1490
- console.log(chalk11.bold("\u{1F4A1} Recommendations\n"));
1491
- report.recommendations.forEach((rec, i) => {
1492
- console.log(`${i + 1}. ${rec}`);
1493
- });
1494
1459
  console.log();
1495
- }
1496
- }
1497
- if (score) {
1498
- console.log(chalk11.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1499
- console.log(formatToolScore2(score));
1500
- console.log();
1460
+ });
1461
+ } else {
1462
+ console.log(
1463
+ chalk11.green("\n\u2728 Great! No consistency issues detected.\n")
1464
+ );
1501
1465
  }
1466
+ renderToolScoreFooter(score);
1502
1467
  }
1503
1468
  });
1504
1469
  }
1505
1470
 
1506
1471
  // src/commands/visualize.ts
1507
1472
  import chalk12 from "chalk";
1508
- import { writeFileSync as writeFileSync4, readFileSync as readFileSync3, existsSync as existsSync3, copyFileSync } from "fs";
1473
+ import { writeFileSync as writeFileSync3, readFileSync as readFileSync3, existsSync as existsSync3, copyFileSync } from "fs";
1509
1474
  import { resolve as resolvePath5 } from "path";
1510
1475
  import { spawn } from "child_process";
1511
1476
  import { handleCLIError as handleCLIError4 } from "@aiready/core";
@@ -1675,7 +1640,7 @@ Or specify a custom report:
1675
1640
  const html = generateHTML(graph);
1676
1641
  const defaultOutput = "visualization.html";
1677
1642
  const outPath = resolvePath5(dirPath, options.output ?? defaultOutput);
1678
- writeFileSync4(outPath, html, "utf8");
1643
+ writeFileSync3(outPath, html, "utf8");
1679
1644
  console.log(chalk12.green(`\u2705 Visualization written to: ${outPath}`));
1680
1645
  if (options.open || options.serve) {
1681
1646
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
@@ -1959,11 +1924,11 @@ EXAMPLES:
1959
1924
  import chalk18 from "chalk";
1960
1925
  import { resolve as resolvePath6 } from "path";
1961
1926
  import { existsSync as existsSync4, readdirSync } from "fs";
1962
- import { printTerminalHeader as printTerminalHeader3 } from "@aiready/core";
1927
+ import { printTerminalHeader as printTerminalHeader4 } from "@aiready/core";
1963
1928
  async function remediateAction(directory, options) {
1964
1929
  const resolvedDir = resolvePath6(process.cwd(), directory || ".");
1965
1930
  const serverUrl = options.server || "https://platform.getaiready.dev";
1966
- printTerminalHeader3("AIREADY REMEDIATION SWARM");
1931
+ printTerminalHeader4("AIREADY REMEDIATION SWARM");
1967
1932
  console.log(chalk18.cyan("\u{1F916} Initializing local remediation agent..."));
1968
1933
  let reportPath = options.report;
1969
1934
  if (!reportPath) {
@@ -2081,42 +2046,15 @@ CONFIGURATION:
2081
2046
  Config files (searched upward): aiready.json, .aiready.json, aiready.config.*
2082
2047
  CLI options override config file settings
2083
2048
 
2084
- Example aiready.json:
2085
- {
2086
- "scan": { "exclude": ["**/dist/**", "**/node_modules/**"] },
2087
- "tools": {
2088
- "pattern-detect": { "minSimilarity": 0.5 },
2089
- "context-analyzer": { "maxContextBudget": 15000 }
2090
- },
2091
- "output": { "format": "json", "directory": ".aiready" }
2092
- }
2093
-
2094
2049
  VERSION: ${packageJson.version}
2095
2050
  DOCUMENTATION: https://aiready.dev/docs/cli
2096
2051
  GITHUB: https://github.com/caopengau/aiready-cli
2097
2052
  LANDING: https://github.com/caopengau/aiready-landing`
2098
2053
  );
2099
- program.command("scan").description(
2100
- "Run comprehensive AI-readiness analysis (patterns + context + consistency)"
2101
- ).argument("[directory]", "Directory to analyze", ".").option(
2102
- "-t, --tools <tools>",
2103
- "Tools to run (comma-separated: patterns,context,consistency,doc-drift,deps-health,aiSignalClarity,grounding,testability,changeAmplification)"
2104
- ).option(
2105
- "--profile <type>",
2106
- "Scan profile to use (agentic, cost, logic, ui, security, onboarding)"
2107
- ).option(
2108
- "--compare-to <path>",
2109
- "Compare results against a previous AIReady report JSON"
2110
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
2111
- "--ci",
2112
- "CI mode: GitHub Actions annotations, no colors, fail on threshold"
2113
- ).option(
2114
- "--fail-on <level>",
2115
- "Fail on issues: critical, major, any",
2116
- "critical"
2117
- ).option("--api-key <key>", "Platform API key for automatic upload").option("--upload", "Automatically upload results to the platform").option("--server <url>", "Custom platform URL").addHelpText("after", SCAN_HELP_TEXT).action(async (directory, options) => {
2118
- await scanAction(directory, options);
2119
- });
2054
+ defineScanCommand(program);
2055
+ definePatternsCommand(program);
2056
+ defineContextCommand(program);
2057
+ defineConsistencyCommand(program);
2120
2058
  program.command("init").description("Generate a default configuration (aiready.json)").option("-f, --force", "Overwrite existing configuration file").option(
2121
2059
  "--js",
2122
2060
  "Generate configuration as a JavaScript file (aiready.config.js)"
@@ -2124,36 +2062,6 @@ program.command("init").description("Generate a default configuration (aiready.j
2124
2062
  const format = options.js ? "js" : "json";
2125
2063
  await initAction({ force: options.force, format, full: options.full });
2126
2064
  });
2127
- 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(
2128
- "--max-candidates <number>",
2129
- "Maximum candidates per block (performance tuning)"
2130
- ).option(
2131
- "--min-shared-tokens <number>",
2132
- "Minimum shared tokens for candidates (performance tuning)"
2133
- ).option(
2134
- "--full-scan",
2135
- "Disable smart defaults for comprehensive analysis (slower)"
2136
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)").option("--no-score", "Disable calculating AI Readiness Score").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
2137
- await patternsAction(directory, options);
2138
- });
2139
- program.command("context").description("Analyze context window costs and dependency fragmentation").argument("[directory]", "Directory to analyze", ".").option("--max-depth <number>", "Maximum acceptable import depth", "5").option(
2140
- "--max-context <number>",
2141
- "Maximum acceptable context budget (tokens)",
2142
- "10000"
2143
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option("-o, --output <format>", "Output format: console, json", "console").option("--output-file <path>", "Output file path (for json)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2144
- await contextAction(directory, options);
2145
- });
2146
- program.command("consistency").description("Check naming conventions and architectural consistency").argument("[directory]", "Directory to analyze", ".").option("--naming", "Check naming conventions (default: true)").option("--no-naming", "Skip naming analysis").option("--patterns", "Check code patterns (default: true)").option("--no-patterns", "Skip pattern analysis").option(
2147
- "--min-severity <level>",
2148
- "Minimum severity: info|minor|major|critical",
2149
- "info"
2150
- ).option("--include <patterns>", "File patterns to include (comma-separated)").option("--exclude <patterns>", "File patterns to exclude (comma-separated)").option(
2151
- "-o, --output <format>",
2152
- "Output format: console, json, markdown",
2153
- "console"
2154
- ).option("--output-file <path>", "Output file path (for json/markdown)").option("--score", "Calculate and display AI Readiness Score (0-100)", true).option("--no-score", "Disable calculating AI Readiness Score").action(async (directory, options) => {
2155
- await consistencyAction(directory, options);
2156
- });
2157
2065
  program.command("visualise").description("Alias for visualize (British spelling)").argument("[directory]", "Directory to analyze", ".").option(
2158
2066
  "--report <path>",
2159
2067
  "Report path (auto-detects latest .aiready/aiready-report-*.json if not provided)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/cli",
3
- "version": "0.15.1",
3
+ "version": "0.15.2",
4
4
  "description": "Assess and improve your codebase's AI-readiness. Get an AI Readiness Score (0-100) and detect semantic duplicates, context fragmentation, and naming inconsistencies.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -24,18 +24,18 @@
24
24
  "dependencies": {
25
25
  "chalk": "^5.3.0",
26
26
  "commander": "^14.0.0",
27
- "@aiready/agent-grounding": "0.14.1",
28
- "@aiready/consistency": "0.21.1",
29
- "@aiready/context-analyzer": "0.22.1",
30
- "@aiready/core": "0.24.1",
31
- "@aiready/deps": "0.14.1",
32
- "@aiready/doc-drift": "0.14.1",
33
- "@aiready/ai-signal-clarity": "0.14.1",
34
- "@aiready/change-amplification": "0.14.1",
35
- "@aiready/pattern-detect": "0.17.1",
36
- "@aiready/visualizer": "0.7.1",
37
- "@aiready/testability": "0.7.1",
38
- "@aiready/contract-enforcement": "0.2.1"
27
+ "@aiready/agent-grounding": "0.14.2",
28
+ "@aiready/consistency": "0.21.2",
29
+ "@aiready/context-analyzer": "0.22.2",
30
+ "@aiready/core": "0.24.2",
31
+ "@aiready/deps": "0.14.2",
32
+ "@aiready/doc-drift": "0.14.2",
33
+ "@aiready/change-amplification": "0.14.2",
34
+ "@aiready/contract-enforcement": "0.2.2",
35
+ "@aiready/ai-signal-clarity": "0.14.2",
36
+ "@aiready/pattern-detect": "0.17.2",
37
+ "@aiready/testability": "0.7.2",
38
+ "@aiready/visualizer": "0.7.2"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@types/node": "^24.0.0",