@aiready/cli 0.9.35 → 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.js CHANGED
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
9
16
  var __copyProps = (to, from, except, desc) => {
10
17
  if (from && typeof from === "object" || typeof from === "function") {
11
18
  for (let key of __getOwnPropNames(from))
@@ -23,15 +30,158 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
30
  mod
24
31
  ));
25
32
 
33
+ // src/commands/hallucination-risk.ts
34
+ var hallucination_risk_exports = {};
35
+ __export(hallucination_risk_exports, {
36
+ hallucinationRiskAction: () => hallucinationRiskAction
37
+ });
38
+ async function hallucinationRiskAction(directory, options) {
39
+ const { analyzeHallucinationRisk, calculateHallucinationScore } = await import("@aiready/hallucination-risk");
40
+ const config = await (0, import_core.loadConfig)(directory);
41
+ const merged = (0, import_core.mergeConfigWithDefaults)(config, {
42
+ minSeverity: "info"
43
+ });
44
+ const report = await analyzeHallucinationRisk({
45
+ rootDir: directory,
46
+ minSeverity: options.minSeverity ?? merged.minSeverity ?? "info",
47
+ include: options.include,
48
+ exclude: options.exclude
49
+ });
50
+ const scoring = calculateHallucinationScore(report);
51
+ if (options.output === "json") {
52
+ return scoring;
53
+ }
54
+ const { summary } = report;
55
+ const ratingColors = {
56
+ minimal: import_chalk2.default.green,
57
+ low: import_chalk2.default.cyan,
58
+ moderate: import_chalk2.default.yellow,
59
+ high: import_chalk2.default.red,
60
+ severe: import_chalk2.default.bgRed.white
61
+ };
62
+ const color = ratingColors[summary.rating] ?? import_chalk2.default.white;
63
+ console.log(` \u{1F9E0} Hallucination Risk: ${import_chalk2.default.bold(scoring.score + "/100")} (${color(summary.rating)})`);
64
+ console.log(` Top Risk: ${import_chalk2.default.italic(summary.topRisk)}`);
65
+ if (summary.totalSignals > 0) {
66
+ console.log(import_chalk2.default.dim(` ${summary.criticalSignals} critical ${summary.majorSignals} major ${summary.minorSignals} minor signals`));
67
+ }
68
+ return scoring;
69
+ }
70
+ var import_chalk2, import_core;
71
+ var init_hallucination_risk = __esm({
72
+ "src/commands/hallucination-risk.ts"() {
73
+ "use strict";
74
+ import_chalk2 = __toESM(require("chalk"));
75
+ import_core = require("@aiready/core");
76
+ }
77
+ });
78
+
79
+ // src/commands/agent-grounding.ts
80
+ var agent_grounding_exports = {};
81
+ __export(agent_grounding_exports, {
82
+ agentGroundingAction: () => agentGroundingAction
83
+ });
84
+ async function agentGroundingAction(directory, options) {
85
+ const { analyzeAgentGrounding, calculateGroundingScore } = await import("@aiready/agent-grounding");
86
+ const config = await (0, import_core2.loadConfig)(directory);
87
+ const merged = (0, import_core2.mergeConfigWithDefaults)(config, {
88
+ maxRecommendedDepth: 4,
89
+ readmeStaleDays: 90
90
+ });
91
+ const report = await analyzeAgentGrounding({
92
+ rootDir: directory,
93
+ maxRecommendedDepth: options.maxDepth ?? merged.maxRecommendedDepth,
94
+ readmeStaleDays: options.readmeStaleDays ?? merged.readmeStaleDays,
95
+ include: options.include,
96
+ exclude: options.exclude
97
+ });
98
+ const scoring = calculateGroundingScore(report);
99
+ if (options.output === "json") {
100
+ return scoring;
101
+ }
102
+ const scoreColor = (s) => s >= 85 ? import_chalk3.default.green : s >= 70 ? import_chalk3.default.cyan : s >= 50 ? import_chalk3.default.yellow : import_chalk3.default.red;
103
+ console.log(` \u{1F9ED} Agent Grounding: ${import_chalk3.default.bold(scoring.score + "/100")} (${report.summary.rating})`);
104
+ const dims = report.summary.dimensions;
105
+ const worstDim = Object.entries(dims).sort(([, a], [, b]) => a - b)[0];
106
+ if (worstDim && worstDim[1] < 70) {
107
+ const name = worstDim[0].replace(/([A-Z])/g, " $1").replace("Score", "").trim();
108
+ console.log(import_chalk3.default.dim(` Weakest dimension: ${name} (${worstDim[1]}/100)`));
109
+ }
110
+ return scoring;
111
+ }
112
+ var import_chalk3, import_core2;
113
+ var init_agent_grounding = __esm({
114
+ "src/commands/agent-grounding.ts"() {
115
+ "use strict";
116
+ import_chalk3 = __toESM(require("chalk"));
117
+ import_core2 = require("@aiready/core");
118
+ }
119
+ });
120
+
121
+ // src/commands/testability.ts
122
+ var testability_exports = {};
123
+ __export(testability_exports, {
124
+ testabilityAction: () => testabilityAction
125
+ });
126
+ async function testabilityAction(directory, options) {
127
+ const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
128
+ const config = await (0, import_core3.loadConfig)(directory);
129
+ const merged = (0, import_core3.mergeConfigWithDefaults)(config, {
130
+ minCoverageRatio: 0.3
131
+ });
132
+ const report = await analyzeTestability({
133
+ rootDir: directory,
134
+ minCoverageRatio: options.minCoverageRatio ?? merged.minCoverageRatio,
135
+ include: options.include,
136
+ exclude: options.exclude
137
+ });
138
+ const scoring = calculateTestabilityScore(report);
139
+ if (options.output === "json") {
140
+ return scoring;
141
+ }
142
+ const safetyIcons = {
143
+ "safe": "\u2705",
144
+ "moderate-risk": "\u26A0\uFE0F ",
145
+ "high-risk": "\u{1F534}",
146
+ "blind-risk": "\u{1F480}"
147
+ };
148
+ const safetyColors = {
149
+ "safe": import_chalk4.default.green,
150
+ "moderate-risk": import_chalk4.default.yellow,
151
+ "high-risk": import_chalk4.default.red,
152
+ "blind-risk": import_chalk4.default.bgRed.white
153
+ };
154
+ const safety = report.summary.aiChangeSafetyRating;
155
+ const icon = safetyIcons[safety] ?? "\u2753";
156
+ const color = safetyColors[safety] ?? import_chalk4.default.white;
157
+ console.log(` \u{1F9EA} Testability: ${import_chalk4.default.bold(scoring.score + "/100")} (${report.summary.rating})`);
158
+ console.log(` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`);
159
+ console.log(import_chalk4.default.dim(` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`));
160
+ if (safety === "blind-risk") {
161
+ console.log(import_chalk4.default.red.bold("\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"));
162
+ }
163
+ return scoring;
164
+ }
165
+ var import_chalk4, import_core3;
166
+ var init_testability = __esm({
167
+ "src/commands/testability.ts"() {
168
+ "use strict";
169
+ import_chalk4 = __toESM(require("chalk"));
170
+ import_core3 = require("@aiready/core");
171
+ }
172
+ });
173
+
26
174
  // src/cli.ts
27
175
  var import_commander = require("commander");
28
- var import_fs4 = require("fs");
176
+ var import_fs5 = require("fs");
29
177
  var import_path7 = require("path");
178
+ var import_url = require("url");
30
179
 
31
180
  // src/commands/scan.ts
32
- var import_chalk2 = __toESM(require("chalk"));
181
+ var import_chalk5 = __toESM(require("chalk"));
182
+ var import_fs2 = require("fs");
33
183
  var import_path2 = require("path");
34
- var import_core = require("@aiready/core");
184
+ var import_core4 = require("@aiready/core");
35
185
 
36
186
  // src/index.ts
37
187
  var import_pattern_detect = require("@aiready/pattern-detect");
@@ -115,6 +265,32 @@ async function analyzeUnified(options) {
115
265
  result.consistency = report;
116
266
  result.summary.totalIssues += report.summary.totalIssues;
117
267
  }
268
+ if (tools.includes("doc-drift")) {
269
+ const { analyzeDocDrift } = await import("@aiready/doc-drift");
270
+ const report = await analyzeDocDrift({
271
+ rootDir: options.rootDir,
272
+ include: options.include,
273
+ exclude: options.exclude
274
+ });
275
+ if (options.progressCallback) {
276
+ options.progressCallback({ tool: "doc-drift", data: report });
277
+ }
278
+ result.docDrift = report;
279
+ result.summary.totalIssues += report.issues?.length || 0;
280
+ }
281
+ if (tools.includes("deps-health")) {
282
+ const { analyzeDeps } = await import("@aiready/deps");
283
+ const report = await analyzeDeps({
284
+ rootDir: options.rootDir,
285
+ include: options.include,
286
+ exclude: options.exclude
287
+ });
288
+ if (options.progressCallback) {
289
+ options.progressCallback({ tool: "deps-health", data: report });
290
+ }
291
+ result.deps = report;
292
+ result.summary.totalIssues += report.issues?.length || 0;
293
+ }
118
294
  result.summary.executionTime = Date.now() - startTime;
119
295
  return result;
120
296
  }
@@ -145,7 +321,7 @@ function findLatestScanReport(dirPath) {
145
321
  }
146
322
  function warnIfGraphCapExceeded(report, dirPath) {
147
323
  try {
148
- const { loadConfig } = require("@aiready/core");
324
+ const { loadConfig: loadConfig4 } = require("@aiready/core");
149
325
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
150
326
  const configPath = (0, import_path.resolve)(dirPath, "aiready.json");
151
327
  if ((0, import_fs.existsSync)(configPath)) {
@@ -226,12 +402,12 @@ function truncateArray(arr, cap = 8) {
226
402
 
227
403
  // src/commands/scan.ts
228
404
  async function scanAction(directory, options) {
229
- console.log(import_chalk2.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
405
+ console.log(import_chalk5.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
230
406
  const startTime = Date.now();
231
407
  const resolvedDir = (0, import_path2.resolve)(process.cwd(), directory || ".");
232
408
  try {
233
409
  const defaults = {
234
- tools: ["patterns", "context", "consistency"],
410
+ tools: ["patterns", "context", "consistency", "hallucination", "grounding", "testability", "doc-drift", "deps-health"],
235
411
  include: void 0,
236
412
  exclude: void 0,
237
413
  output: {
@@ -239,8 +415,28 @@ async function scanAction(directory, options) {
239
415
  file: void 0
240
416
  }
241
417
  };
242
- const baseOptions = await (0, import_core.loadMergedConfig)(resolvedDir, defaults, {
243
- tools: options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0,
418
+ let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
419
+ if (options.profile) {
420
+ switch (options.profile.toLowerCase()) {
421
+ case "agentic":
422
+ profileTools = ["hallucination", "grounding", "testability"];
423
+ break;
424
+ case "cost":
425
+ profileTools = ["patterns", "context"];
426
+ break;
427
+ case "security":
428
+ profileTools = ["consistency", "testability"];
429
+ break;
430
+ case "onboarding":
431
+ profileTools = ["context", "consistency", "grounding"];
432
+ break;
433
+ default:
434
+ console.log(import_chalk5.default.yellow(`
435
+ \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`));
436
+ }
437
+ }
438
+ const baseOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
439
+ tools: profileTools,
244
440
  include: options.include?.split(","),
245
441
  exclude: options.exclude?.split(",")
246
442
  });
@@ -250,13 +446,13 @@ async function scanAction(directory, options) {
250
446
  const patternSmartDefaults = await getSmartDefaults(resolvedDir, baseOptions);
251
447
  finalOptions = { ...patternSmartDefaults, ...finalOptions, ...baseOptions };
252
448
  }
253
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Preview ==="));
254
- console.log(import_chalk2.default.white("Tools to run:"), (finalOptions.tools || ["patterns", "context", "consistency"]).join(", "));
255
- console.log(import_chalk2.default.white("Will use settings from config and defaults."));
256
- console.log(import_chalk2.default.white("\nGeneral settings:"));
257
- if (finalOptions.rootDir) console.log(` rootDir: ${import_chalk2.default.bold(String(finalOptions.rootDir))}`);
258
- if (finalOptions.include) console.log(` include: ${import_chalk2.default.bold(truncateArray(finalOptions.include, 6))}`);
259
- if (finalOptions.exclude) console.log(` exclude: ${import_chalk2.default.bold(truncateArray(finalOptions.exclude, 6))}`);
449
+ console.log(import_chalk5.default.cyan("\n=== AIReady Run Preview ==="));
450
+ console.log(import_chalk5.default.white("Tools to run:"), (finalOptions.tools || ["patterns", "context", "consistency"]).join(", "));
451
+ console.log(import_chalk5.default.white("Will use settings from config and defaults."));
452
+ console.log(import_chalk5.default.white("\nGeneral settings:"));
453
+ if (finalOptions.rootDir) console.log(` rootDir: ${import_chalk5.default.bold(String(finalOptions.rootDir))}`);
454
+ if (finalOptions.include) console.log(` include: ${import_chalk5.default.bold(truncateArray(finalOptions.include, 6))}`);
455
+ if (finalOptions.exclude) console.log(` exclude: ${import_chalk5.default.bold(truncateArray(finalOptions.exclude, 6))}`);
260
456
  if (finalOptions["pattern-detect"] || finalOptions.minSimilarity) {
261
457
  const patternDetectConfig = finalOptions["pattern-detect"] || {
262
458
  minSimilarity: finalOptions.minSimilarity,
@@ -269,16 +465,16 @@ async function scanAction(directory, options) {
269
465
  severity: finalOptions.severity,
270
466
  includeTests: finalOptions.includeTests
271
467
  };
272
- console.log(import_chalk2.default.white("\nPattern-detect settings:"));
273
- console.log(` minSimilarity: ${import_chalk2.default.bold(patternDetectConfig.minSimilarity ?? "default")}`);
274
- console.log(` minLines: ${import_chalk2.default.bold(patternDetectConfig.minLines ?? "default")}`);
275
- if (patternDetectConfig.approx !== void 0) console.log(` approx: ${import_chalk2.default.bold(String(patternDetectConfig.approx))}`);
276
- if (patternDetectConfig.minSharedTokens !== void 0) console.log(` minSharedTokens: ${import_chalk2.default.bold(String(patternDetectConfig.minSharedTokens))}`);
277
- if (patternDetectConfig.maxCandidatesPerBlock !== void 0) console.log(` maxCandidatesPerBlock: ${import_chalk2.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`);
278
- if (patternDetectConfig.batchSize !== void 0) console.log(` batchSize: ${import_chalk2.default.bold(String(patternDetectConfig.batchSize))}`);
279
- if (patternDetectConfig.streamResults !== void 0) console.log(` streamResults: ${import_chalk2.default.bold(String(patternDetectConfig.streamResults))}`);
280
- if (patternDetectConfig.severity !== void 0) console.log(` severity: ${import_chalk2.default.bold(String(patternDetectConfig.severity))}`);
281
- if (patternDetectConfig.includeTests !== void 0) console.log(` includeTests: ${import_chalk2.default.bold(String(patternDetectConfig.includeTests))}`);
468
+ console.log(import_chalk5.default.white("\nPattern-detect settings:"));
469
+ console.log(` minSimilarity: ${import_chalk5.default.bold(patternDetectConfig.minSimilarity ?? "default")}`);
470
+ console.log(` minLines: ${import_chalk5.default.bold(patternDetectConfig.minLines ?? "default")}`);
471
+ if (patternDetectConfig.approx !== void 0) console.log(` approx: ${import_chalk5.default.bold(String(patternDetectConfig.approx))}`);
472
+ if (patternDetectConfig.minSharedTokens !== void 0) console.log(` minSharedTokens: ${import_chalk5.default.bold(String(patternDetectConfig.minSharedTokens))}`);
473
+ if (patternDetectConfig.maxCandidatesPerBlock !== void 0) console.log(` maxCandidatesPerBlock: ${import_chalk5.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`);
474
+ if (patternDetectConfig.batchSize !== void 0) console.log(` batchSize: ${import_chalk5.default.bold(String(patternDetectConfig.batchSize))}`);
475
+ if (patternDetectConfig.streamResults !== void 0) console.log(` streamResults: ${import_chalk5.default.bold(String(patternDetectConfig.streamResults))}`);
476
+ if (patternDetectConfig.severity !== void 0) console.log(` severity: ${import_chalk5.default.bold(String(patternDetectConfig.severity))}`);
477
+ if (patternDetectConfig.includeTests !== void 0) console.log(` includeTests: ${import_chalk5.default.bold(String(patternDetectConfig.includeTests))}`);
282
478
  }
283
479
  if (finalOptions["context-analyzer"] || finalOptions.maxDepth) {
284
480
  const ca = finalOptions["context-analyzer"] || {
@@ -288,32 +484,32 @@ async function scanAction(directory, options) {
288
484
  maxFragmentation: finalOptions.maxFragmentation,
289
485
  includeNodeModules: finalOptions.includeNodeModules
290
486
  };
291
- console.log(import_chalk2.default.white("\nContext-analyzer settings:"));
292
- console.log(` maxDepth: ${import_chalk2.default.bold(ca.maxDepth ?? "default")}`);
293
- console.log(` maxContextBudget: ${import_chalk2.default.bold(ca.maxContextBudget ?? "default")}`);
294
- if (ca.minCohesion !== void 0) console.log(` minCohesion: ${import_chalk2.default.bold(String(ca.minCohesion))}`);
295
- if (ca.maxFragmentation !== void 0) console.log(` maxFragmentation: ${import_chalk2.default.bold(String(ca.maxFragmentation))}`);
296
- if (ca.includeNodeModules !== void 0) console.log(` includeNodeModules: ${import_chalk2.default.bold(String(ca.includeNodeModules))}`);
487
+ console.log(import_chalk5.default.white("\nContext-analyzer settings:"));
488
+ console.log(` maxDepth: ${import_chalk5.default.bold(ca.maxDepth ?? "default")}`);
489
+ console.log(` maxContextBudget: ${import_chalk5.default.bold(ca.maxContextBudget ?? "default")}`);
490
+ if (ca.minCohesion !== void 0) console.log(` minCohesion: ${import_chalk5.default.bold(String(ca.minCohesion))}`);
491
+ if (ca.maxFragmentation !== void 0) console.log(` maxFragmentation: ${import_chalk5.default.bold(String(ca.maxFragmentation))}`);
492
+ if (ca.includeNodeModules !== void 0) console.log(` includeNodeModules: ${import_chalk5.default.bold(String(ca.includeNodeModules))}`);
297
493
  }
298
494
  if (finalOptions.consistency) {
299
495
  const c = finalOptions.consistency;
300
- console.log(import_chalk2.default.white("\nConsistency settings:"));
301
- console.log(` checkNaming: ${import_chalk2.default.bold(String(c.checkNaming ?? true))}`);
302
- console.log(` checkPatterns: ${import_chalk2.default.bold(String(c.checkPatterns ?? true))}`);
303
- console.log(` checkArchitecture: ${import_chalk2.default.bold(String(c.checkArchitecture ?? false))}`);
304
- if (c.minSeverity) console.log(` minSeverity: ${import_chalk2.default.bold(c.minSeverity)}`);
305
- if (c.acceptedAbbreviations) console.log(` acceptedAbbreviations: ${import_chalk2.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`);
306
- if (c.shortWords) console.log(` shortWords: ${import_chalk2.default.bold(truncateArray(c.shortWords, 8))}`);
496
+ console.log(import_chalk5.default.white("\nConsistency settings:"));
497
+ console.log(` checkNaming: ${import_chalk5.default.bold(String(c.checkNaming ?? true))}`);
498
+ console.log(` checkPatterns: ${import_chalk5.default.bold(String(c.checkPatterns ?? true))}`);
499
+ console.log(` checkArchitecture: ${import_chalk5.default.bold(String(c.checkArchitecture ?? false))}`);
500
+ if (c.minSeverity) console.log(` minSeverity: ${import_chalk5.default.bold(c.minSeverity)}`);
501
+ if (c.acceptedAbbreviations) console.log(` acceptedAbbreviations: ${import_chalk5.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`);
502
+ if (c.shortWords) console.log(` shortWords: ${import_chalk5.default.bold(truncateArray(c.shortWords, 8))}`);
307
503
  }
308
- console.log(import_chalk2.default.white("\nStarting analysis..."));
504
+ console.log(import_chalk5.default.white("\nStarting analysis..."));
309
505
  const progressCallback = (event) => {
310
- console.log(import_chalk2.default.cyan(`
506
+ console.log(import_chalk5.default.cyan(`
311
507
  --- ${event.tool.toUpperCase()} RESULTS ---`));
312
508
  try {
313
509
  if (event.tool === "patterns") {
314
510
  const pr = event.data;
315
- console.log(` Duplicate patterns: ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))}`);
316
- console.log(` Files with pattern issues: ${import_chalk2.default.bold(String(pr.results?.length || 0))}`);
511
+ console.log(` Duplicate patterns: ${import_chalk5.default.bold(String(pr.duplicates?.length || 0))}`);
512
+ console.log(` Files with pattern issues: ${import_chalk5.default.bold(String(pr.results?.length || 0))}`);
317
513
  if (pr.duplicates && pr.duplicates.length > 0) {
318
514
  pr.duplicates.slice(0, 5).forEach((d, i) => {
319
515
  console.log(` ${i + 1}. ${d.file1.split("/").pop()} \u2194 ${d.file2.split("/").pop()} (sim=${(d.similarity * 100).toFixed(1)}%)`);
@@ -327,10 +523,10 @@ async function scanAction(directory, options) {
327
523
  });
328
524
  }
329
525
  if (pr.groups && pr.groups.length >= 0) {
330
- console.log(` \u2705 Grouped ${import_chalk2.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk2.default.bold(String(pr.groups.length))} file pairs`);
526
+ console.log(` \u2705 Grouped ${import_chalk5.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk5.default.bold(String(pr.groups.length))} file pairs`);
331
527
  }
332
528
  if (pr.clusters && pr.clusters.length >= 0) {
333
- console.log(` \u2705 Created ${import_chalk2.default.bold(String(pr.clusters.length))} refactor clusters`);
529
+ console.log(` \u2705 Created ${import_chalk5.default.bold(String(pr.clusters.length))} refactor clusters`);
334
530
  pr.clusters.slice(0, 3).forEach((cl, idx) => {
335
531
  const files = (cl.files || []).map((f) => f.path.split("/").pop()).join(", ");
336
532
  console.log(` ${idx + 1}. ${files} (${cl.tokenCost || "n/a"} tokens)`);
@@ -338,14 +534,14 @@ async function scanAction(directory, options) {
338
534
  }
339
535
  } else if (event.tool === "context") {
340
536
  const cr = event.data;
341
- console.log(` Context issues found: ${import_chalk2.default.bold(String(cr.length || 0))}`);
537
+ console.log(` Context issues found: ${import_chalk5.default.bold(String(cr.length || 0))}`);
342
538
  cr.slice(0, 5).forEach((c, i) => {
343
539
  const msg = c.message ? ` - ${c.message}` : "";
344
540
  console.log(` ${i + 1}. ${c.file} (${c.severity || "n/a"})${msg}`);
345
541
  });
346
542
  } else if (event.tool === "consistency") {
347
543
  const rep = event.data;
348
- console.log(` Consistency totalIssues: ${import_chalk2.default.bold(String(rep.summary?.totalIssues || 0))}`);
544
+ console.log(` Consistency totalIssues: ${import_chalk5.default.bold(String(rep.summary?.totalIssues || 0))}`);
349
545
  if (rep.results && rep.results.length > 0) {
350
546
  const fileMap = /* @__PURE__ */ new Map();
351
547
  rep.results.forEach((r) => {
@@ -369,24 +565,38 @@ async function scanAction(directory, options) {
369
565
  });
370
566
  const remaining = files.length - topFiles.length;
371
567
  if (remaining > 0) {
372
- console.log(import_chalk2.default.dim(` ... and ${remaining} more files with issues (use --output json for full details)`));
568
+ console.log(import_chalk5.default.dim(` ... and ${remaining} more files with issues (use --output json for full details)`));
373
569
  }
374
570
  }
571
+ } else if (event.tool === "doc-drift") {
572
+ const dr = event.data;
573
+ console.log(` Issues found: ${import_chalk5.default.bold(String(dr.issues?.length || 0))}`);
574
+ if (dr.rawData) {
575
+ console.log(` Signature Mismatches: ${import_chalk5.default.bold(dr.rawData.outdatedComments || 0)}`);
576
+ console.log(` Undocumented Complexity: ${import_chalk5.default.bold(dr.rawData.undocumentedComplexity || 0)}`);
577
+ }
578
+ } else if (event.tool === "deps-health") {
579
+ const dr = event.data;
580
+ console.log(` Packages Analyzed: ${import_chalk5.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`);
581
+ if (dr.rawData) {
582
+ console.log(` Deprecated Packages: ${import_chalk5.default.bold(dr.rawData.deprecatedPackages || 0)}`);
583
+ console.log(` AI Cutoff Skew Score: ${import_chalk5.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`);
584
+ }
375
585
  }
376
586
  } catch (err) {
377
587
  }
378
588
  };
379
589
  const results = await analyzeUnified({ ...finalOptions, progressCallback, suppressToolConfig: true });
380
- console.log(import_chalk2.default.cyan("\n=== AIReady Run Summary ==="));
381
- console.log(import_chalk2.default.white("Tools run:"), (finalOptions.tools || ["patterns", "context", "consistency"]).join(", "));
382
- console.log(import_chalk2.default.cyan("\nResults summary:"));
383
- console.log(` Total issues (all tools): ${import_chalk2.default.bold(String(results.summary.totalIssues || 0))}`);
384
- if (results.duplicates) console.log(` Duplicate patterns found: ${import_chalk2.default.bold(String(results.duplicates.length || 0))}`);
385
- if (results.patterns) console.log(` Pattern files with issues: ${import_chalk2.default.bold(String(results.patterns.length || 0))}`);
386
- if (results.context) console.log(` Context issues: ${import_chalk2.default.bold(String(results.context.length || 0))}`);
387
- if (results.consistency) console.log(` Consistency issues: ${import_chalk2.default.bold(String(results.consistency.summary.totalIssues || 0))}`);
388
- console.log(import_chalk2.default.cyan("===========================\n"));
389
- const elapsedTime = (0, import_core.getElapsedTime)(startTime);
590
+ console.log(import_chalk5.default.cyan("\n=== AIReady Run Summary ==="));
591
+ console.log(import_chalk5.default.white("Tools run:"), (finalOptions.tools || ["patterns", "context", "consistency"]).join(", "));
592
+ console.log(import_chalk5.default.cyan("\nResults summary:"));
593
+ console.log(` Total issues (all tools): ${import_chalk5.default.bold(String(results.summary.totalIssues || 0))}`);
594
+ if (results.duplicates) console.log(` Duplicate patterns found: ${import_chalk5.default.bold(String(results.duplicates.length || 0))}`);
595
+ if (results.patterns) console.log(` Pattern files with issues: ${import_chalk5.default.bold(String(results.patterns.length || 0))}`);
596
+ if (results.context) console.log(` Context issues: ${import_chalk5.default.bold(String(results.context.length || 0))}`);
597
+ if (results.consistency) console.log(` Consistency issues: ${import_chalk5.default.bold(String(results.consistency.summary.totalIssues || 0))}`);
598
+ console.log(import_chalk5.default.cyan("===========================\n"));
599
+ const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
390
600
  let scoringResult;
391
601
  if (options.score || finalOptions.scoring?.showBreakdown) {
392
602
  const toolScores = /* @__PURE__ */ new Map();
@@ -417,23 +627,94 @@ async function scanAction(directory, options) {
417
627
  } catch (err) {
418
628
  }
419
629
  }
420
- const cliWeights = (0, import_core.parseWeightString)(options.weights);
630
+ if (finalOptions.tools.includes("hallucination") || finalOptions.tools.includes("hallucination-risk")) {
631
+ try {
632
+ const { hallucinationRiskAction: hallucinationRiskAction2 } = await Promise.resolve().then(() => (init_hallucination_risk(), hallucination_risk_exports));
633
+ const hrScore = await hallucinationRiskAction2(resolvedDir, { ...finalOptions, output: "json" });
634
+ if (hrScore) toolScores.set("hallucination-risk", hrScore);
635
+ } catch (err) {
636
+ }
637
+ }
638
+ if (finalOptions.tools.includes("grounding") || finalOptions.tools.includes("agent-grounding")) {
639
+ try {
640
+ const { agentGroundingAction: agentGroundingAction2 } = await Promise.resolve().then(() => (init_agent_grounding(), agent_grounding_exports));
641
+ const agScore = await agentGroundingAction2(resolvedDir, { ...finalOptions, output: "json" });
642
+ if (agScore) toolScores.set("agent-grounding", agScore);
643
+ } catch (err) {
644
+ }
645
+ }
646
+ if (finalOptions.tools.includes("testability")) {
647
+ try {
648
+ const { testabilityAction: testabilityAction2 } = await Promise.resolve().then(() => (init_testability(), testability_exports));
649
+ const tbScore = await testabilityAction2(resolvedDir, { ...finalOptions, output: "json" });
650
+ if (tbScore) toolScores.set("testability", tbScore);
651
+ } catch (err) {
652
+ }
653
+ }
654
+ if (results.docDrift) {
655
+ toolScores.set("doc-drift", {
656
+ toolName: "doc-drift",
657
+ score: results.docDrift.summary.score,
658
+ rawMetrics: results.docDrift.rawData,
659
+ factors: [],
660
+ recommendations: results.docDrift.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
661
+ });
662
+ }
663
+ if (results.deps) {
664
+ toolScores.set("dependency-health", {
665
+ toolName: "dependency-health",
666
+ score: results.deps.summary.score,
667
+ rawMetrics: results.deps.rawData,
668
+ factors: [],
669
+ recommendations: results.deps.recommendations.map((action) => ({ action, estimatedImpact: 5, priority: "medium" }))
670
+ });
671
+ }
672
+ const cliWeights = (0, import_core4.parseWeightString)(options.weights);
421
673
  if (toolScores.size > 0) {
422
- scoringResult = (0, import_core.calculateOverallScore)(toolScores, finalOptions, cliWeights.size ? cliWeights : void 0);
423
- console.log(import_chalk2.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
424
- console.log(` ${(0, import_core.formatScore)(scoringResult)}`);
674
+ scoringResult = (0, import_core4.calculateOverallScore)(toolScores, finalOptions, cliWeights.size ? cliWeights : void 0);
675
+ console.log(import_chalk5.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
676
+ console.log(` ${(0, import_core4.formatScore)(scoringResult)}`);
677
+ if (options.compareTo) {
678
+ try {
679
+ const prevReportStr = (0, import_fs2.readFileSync)((0, import_path2.resolve)(process.cwd(), options.compareTo), "utf8");
680
+ const prevReport = JSON.parse(prevReportStr);
681
+ const prevScore = prevReport.scoring?.score || prevReport.scoring?.overallScore;
682
+ if (typeof prevScore === "number") {
683
+ const diff = scoringResult.overall - prevScore;
684
+ const diffStr = diff > 0 ? `+${diff}` : String(diff);
685
+ console.log();
686
+ if (diff > 0) {
687
+ console.log(import_chalk5.default.green(` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
688
+ } else if (diff < 0) {
689
+ console.log(import_chalk5.default.red(` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
690
+ } else {
691
+ console.log(import_chalk5.default.blue(` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`));
692
+ }
693
+ scoringResult.trend = {
694
+ previousScore: prevScore,
695
+ difference: diff
696
+ };
697
+ } else {
698
+ console.log(import_chalk5.default.yellow(`
699
+ \u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`));
700
+ }
701
+ } catch (e) {
702
+ console.log(import_chalk5.default.yellow(`
703
+ \u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`));
704
+ }
705
+ }
425
706
  if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
426
- console.log(import_chalk2.default.bold("\nTool breakdown:"));
707
+ console.log(import_chalk5.default.bold("\nTool breakdown:"));
427
708
  scoringResult.breakdown.forEach((tool) => {
428
- const rating = (0, import_core.getRating)(tool.score);
429
- const rd = (0, import_core.getRatingDisplay)(rating);
709
+ const rating = (0, import_core4.getRating)(tool.score);
710
+ const rd = (0, import_core4.getRatingDisplay)(rating);
430
711
  console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${rd.emoji}`);
431
712
  });
432
713
  console.log();
433
714
  if (finalOptions.scoring?.showBreakdown) {
434
- console.log(import_chalk2.default.bold("Detailed tool breakdown:"));
715
+ console.log(import_chalk5.default.bold("Detailed tool breakdown:"));
435
716
  scoringResult.breakdown.forEach((tool) => {
436
- console.log((0, import_core.formatToolScore)(tool));
717
+ console.log((0, import_core4.formatToolScore)(tool));
437
718
  });
438
719
  console.log();
439
720
  }
@@ -445,9 +726,9 @@ async function scanAction(directory, options) {
445
726
  if (outputFormat === "json") {
446
727
  const timestamp = getReportTimestamp();
447
728
  const defaultFilename = `aiready-report-${timestamp}.json`;
448
- const outputPath = (0, import_core.resolveOutputPath)(userOutputFile, defaultFilename, resolvedDir);
729
+ const outputPath = (0, import_core4.resolveOutputPath)(userOutputFile, defaultFilename, resolvedDir);
449
730
  const outputData = { ...results, scoring: scoringResult };
450
- (0, import_core.handleJSONOutput)(outputData, outputPath, `\u2705 Report saved to ${outputPath}`);
731
+ (0, import_core4.handleJSONOutput)(outputData, outputPath, `\u2705 Report saved to ${outputPath}`);
451
732
  warnIfGraphCapExceeded(outputData, resolvedDir);
452
733
  }
453
734
  const isCI = options.ci || process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
@@ -457,17 +738,17 @@ async function scanAction(directory, options) {
457
738
  if (process.env.GITHUB_ACTIONS === "true") {
458
739
  console.log(`
459
740
  ::group::AI Readiness Score`);
460
- console.log(`score=${scoringResult.overallScore}`);
741
+ console.log(`score=${scoringResult.overall}`);
461
742
  if (scoringResult.breakdown) {
462
743
  scoringResult.breakdown.forEach((tool) => {
463
744
  console.log(`${tool.toolName}=${tool.score}`);
464
745
  });
465
746
  }
466
747
  console.log("::endgroup::");
467
- if (threshold && scoringResult.overallScore < threshold) {
468
- console.log(`::error::AI Readiness Score ${scoringResult.overallScore} is below threshold ${threshold}`);
748
+ if (threshold && scoringResult.overall < threshold) {
749
+ console.log(`::error::AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`);
469
750
  } else if (threshold) {
470
- console.log(`::notice::AI Readiness Score: ${scoringResult.overallScore}/100 (threshold: ${threshold})`);
751
+ console.log(`::notice::AI Readiness Score: ${scoringResult.overall}/100 (threshold: ${threshold})`);
471
752
  }
472
753
  if (results.patterns) {
473
754
  const criticalPatterns = results.patterns.flatMap(
@@ -480,9 +761,9 @@ async function scanAction(directory, options) {
480
761
  }
481
762
  let shouldFail = false;
482
763
  let failReason = "";
483
- if (threshold && scoringResult.overallScore < threshold) {
764
+ if (threshold && scoringResult.overall < threshold) {
484
765
  shouldFail = true;
485
- failReason = `AI Readiness Score ${scoringResult.overallScore} is below threshold ${threshold}`;
766
+ failReason = `AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`;
486
767
  }
487
768
  if (failOnLevel !== "none") {
488
769
  const severityLevels = { critical: 4, major: 3, minor: 2, any: 1 };
@@ -520,34 +801,43 @@ async function scanAction(directory, options) {
520
801
  }
521
802
  }
522
803
  if (shouldFail) {
523
- console.log(import_chalk2.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
524
- console.log(import_chalk2.default.red(` Reason: ${failReason}`));
525
- console.log(import_chalk2.default.dim("\n Remediation steps:"));
526
- console.log(import_chalk2.default.dim(" 1. Run `aiready scan` locally to see detailed issues"));
527
- console.log(import_chalk2.default.dim(" 2. Fix the critical issues before merging"));
528
- console.log(import_chalk2.default.dim(" 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"));
804
+ console.log(import_chalk5.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
805
+ console.log(import_chalk5.default.red(` Reason: ${failReason}`));
806
+ console.log(import_chalk5.default.dim("\n Remediation steps:"));
807
+ console.log(import_chalk5.default.dim(" 1. Run `aiready scan` locally to see detailed issues"));
808
+ console.log(import_chalk5.default.dim(" 2. Fix the critical issues before merging"));
809
+ console.log(import_chalk5.default.dim(" 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"));
529
810
  process.exit(1);
530
811
  } else {
531
- console.log(import_chalk2.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
812
+ console.log(import_chalk5.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
532
813
  if (threshold) {
533
- console.log(import_chalk2.default.green(` Score: ${scoringResult.overallScore}/100 (threshold: ${threshold})`));
814
+ console.log(import_chalk5.default.green(` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`));
534
815
  }
535
- console.log(import_chalk2.default.dim("\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"));
816
+ console.log(import_chalk5.default.dim("\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"));
536
817
  }
537
818
  }
538
819
  } catch (error) {
539
- (0, import_core.handleCLIError)(error, "Analysis");
820
+ (0, import_core4.handleCLIError)(error, "Analysis");
540
821
  }
541
822
  }
542
823
  var scanHelpText = `
543
824
  EXAMPLES:
544
825
  $ aiready scan # Analyze all tools
545
826
  $ aiready scan --tools patterns,context # Skip consistency
827
+ $ aiready scan --profile agentic # Optimize for AI agent execution
828
+ $ aiready scan --profile security # Optimize for secure coding (testability)
829
+ $ aiready scan --compare-to prev-report.json # Compare trends against previous run
546
830
  $ aiready scan --score --threshold 75 # CI/CD with threshold
547
831
  $ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
548
832
  $ aiready scan --ci --fail-on major # Fail on major+ issues
549
833
  $ aiready scan --output json --output-file report.json
550
834
 
835
+ PROFILES:
836
+ agentic: hallucination, grounding, testability
837
+ cost: patterns, context
838
+ security: consistency, testability
839
+ onboarding: context, consistency, grounding
840
+
551
841
  CI/CD INTEGRATION (Gatekeeper Mode):
552
842
  Use --ci for GitHub Actions integration:
553
843
  - Outputs GitHub Actions annotations for PR checks
@@ -560,11 +850,11 @@ CI/CD INTEGRATION (Gatekeeper Mode):
560
850
  `;
561
851
 
562
852
  // src/commands/patterns.ts
563
- var import_chalk3 = __toESM(require("chalk"));
853
+ var import_chalk6 = __toESM(require("chalk"));
564
854
  var import_path3 = require("path");
565
- var import_core2 = require("@aiready/core");
855
+ var import_core5 = require("@aiready/core");
566
856
  async function patternsAction(directory, options) {
567
- console.log(import_chalk3.default.blue("\u{1F50D} Analyzing patterns...\n"));
857
+ console.log(import_chalk6.default.blue("\u{1F50D} Analyzing patterns...\n"));
568
858
  const startTime = Date.now();
569
859
  const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory || ".");
570
860
  try {
@@ -595,10 +885,10 @@ async function patternsAction(directory, options) {
595
885
  if (options.minSharedTokens) {
596
886
  cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
597
887
  }
598
- const finalOptions = await (0, import_core2.loadMergedConfig)(resolvedDir, defaults, cliOptions);
888
+ const finalOptions = await (0, import_core5.loadMergedConfig)(resolvedDir, defaults, cliOptions);
599
889
  const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
600
890
  const { results, duplicates } = await analyzePatterns2(finalOptions);
601
- const elapsedTime = (0, import_core2.getElapsedTime)(startTime);
891
+ const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
602
892
  const summary = generateSummary(results);
603
893
  let patternScore;
604
894
  if (options.score) {
@@ -612,60 +902,60 @@ async function patternsAction(directory, options) {
612
902
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
613
903
  ...patternScore && { scoring: patternScore }
614
904
  };
615
- const outputPath = (0, import_core2.resolveOutputPath)(
905
+ const outputPath = (0, import_core5.resolveOutputPath)(
616
906
  userOutputFile,
617
907
  `aiready-report-${getReportTimestamp()}.json`,
618
908
  resolvedDir
619
909
  );
620
- (0, import_core2.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
910
+ (0, import_core5.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
621
911
  } else {
622
912
  const terminalWidth = process.stdout.columns || 80;
623
913
  const dividerWidth = Math.min(60, terminalWidth - 2);
624
914
  const divider = "\u2501".repeat(dividerWidth);
625
- console.log(import_chalk3.default.cyan(divider));
626
- console.log(import_chalk3.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
627
- console.log(import_chalk3.default.cyan(divider) + "\n");
628
- console.log(import_chalk3.default.white(`\u{1F4C1} Files analyzed: ${import_chalk3.default.bold(results.length)}`));
629
- console.log(import_chalk3.default.yellow(`\u26A0 Duplicate patterns found: ${import_chalk3.default.bold(summary.totalPatterns)}`));
630
- console.log(import_chalk3.default.red(`\u{1F4B0} Token cost (wasted): ${import_chalk3.default.bold(summary.totalTokenCost.toLocaleString())}`));
631
- console.log(import_chalk3.default.gray(`\u23F1 Analysis time: ${import_chalk3.default.bold(elapsedTime + "s")}`));
915
+ console.log(import_chalk6.default.cyan(divider));
916
+ console.log(import_chalk6.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
917
+ console.log(import_chalk6.default.cyan(divider) + "\n");
918
+ console.log(import_chalk6.default.white(`\u{1F4C1} Files analyzed: ${import_chalk6.default.bold(results.length)}`));
919
+ console.log(import_chalk6.default.yellow(`\u26A0 Duplicate patterns found: ${import_chalk6.default.bold(summary.totalPatterns)}`));
920
+ console.log(import_chalk6.default.red(`\u{1F4B0} Token cost (wasted): ${import_chalk6.default.bold(summary.totalTokenCost.toLocaleString())}`));
921
+ console.log(import_chalk6.default.gray(`\u23F1 Analysis time: ${import_chalk6.default.bold(elapsedTime + "s")}`));
632
922
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
633
923
  if (sortedTypes.length > 0) {
634
- console.log(import_chalk3.default.cyan("\n" + divider));
635
- console.log(import_chalk3.default.bold.white(" PATTERNS BY TYPE"));
636
- console.log(import_chalk3.default.cyan(divider) + "\n");
924
+ console.log(import_chalk6.default.cyan("\n" + divider));
925
+ console.log(import_chalk6.default.bold.white(" PATTERNS BY TYPE"));
926
+ console.log(import_chalk6.default.cyan(divider) + "\n");
637
927
  sortedTypes.forEach(([type, count]) => {
638
- console.log(` ${import_chalk3.default.white(type.padEnd(15))} ${import_chalk3.default.bold(count)}`);
928
+ console.log(` ${import_chalk6.default.white(type.padEnd(15))} ${import_chalk6.default.bold(count)}`);
639
929
  });
640
930
  }
641
931
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
642
- console.log(import_chalk3.default.cyan("\n" + divider));
643
- console.log(import_chalk3.default.bold.white(" TOP DUPLICATE PATTERNS"));
644
- console.log(import_chalk3.default.cyan(divider) + "\n");
932
+ console.log(import_chalk6.default.cyan("\n" + divider));
933
+ console.log(import_chalk6.default.bold.white(" TOP DUPLICATE PATTERNS"));
934
+ console.log(import_chalk6.default.cyan(divider) + "\n");
645
935
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
646
936
  topDuplicates.forEach((dup) => {
647
937
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
648
938
  const severityIcon = dup.similarity > 0.95 ? "\u{1F534}" : dup.similarity > 0.9 ? "\u{1F7E1}" : "\u{1F535}";
649
939
  const file1Name = dup.file1.split("/").pop() || dup.file1;
650
940
  const file2Name = dup.file2.split("/").pop() || dup.file2;
651
- console.log(`${severityIcon} ${severity}: ${import_chalk3.default.bold(file1Name)} \u2194 ${import_chalk3.default.bold(file2Name)}`);
652
- console.log(` Similarity: ${import_chalk3.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk3.default.bold(dup.tokenCost.toLocaleString())} tokens each`);
653
- console.log(` Lines: ${import_chalk3.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk3.default.cyan(dup.line2 + "-" + dup.endLine2)}
941
+ console.log(`${severityIcon} ${severity}: ${import_chalk6.default.bold(file1Name)} \u2194 ${import_chalk6.default.bold(file2Name)}`);
942
+ console.log(` Similarity: ${import_chalk6.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk6.default.bold(dup.tokenCost.toLocaleString())} tokens each`);
943
+ console.log(` Lines: ${import_chalk6.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk6.default.cyan(dup.line2 + "-" + dup.endLine2)}
654
944
  `);
655
945
  });
656
946
  } else {
657
- console.log(import_chalk3.default.green("\n\u2728 Great! No duplicate patterns detected.\n"));
947
+ console.log(import_chalk6.default.green("\n\u2728 Great! No duplicate patterns detected.\n"));
658
948
  }
659
949
  if (patternScore) {
660
- console.log(import_chalk3.default.cyan(divider));
661
- console.log(import_chalk3.default.bold.white(" AI READINESS SCORE (Patterns)"));
662
- console.log(import_chalk3.default.cyan(divider) + "\n");
663
- console.log((0, import_core2.formatToolScore)(patternScore));
950
+ console.log(import_chalk6.default.cyan(divider));
951
+ console.log(import_chalk6.default.bold.white(" AI READINESS SCORE (Patterns)"));
952
+ console.log(import_chalk6.default.cyan(divider) + "\n");
953
+ console.log((0, import_core5.formatToolScore)(patternScore));
664
954
  console.log();
665
955
  }
666
956
  }
667
957
  } catch (error) {
668
- (0, import_core2.handleCLIError)(error, "Pattern analysis");
958
+ (0, import_core5.handleCLIError)(error, "Pattern analysis");
669
959
  }
670
960
  }
671
961
  var patternsHelpText = `
@@ -676,11 +966,11 @@ EXAMPLES:
676
966
  `;
677
967
 
678
968
  // src/commands/context.ts
679
- var import_chalk4 = __toESM(require("chalk"));
969
+ var import_chalk7 = __toESM(require("chalk"));
680
970
  var import_path4 = require("path");
681
- var import_core3 = require("@aiready/core");
971
+ var import_core6 = require("@aiready/core");
682
972
  async function contextAction(directory, options) {
683
- console.log(import_chalk4.default.blue("\u{1F9E0} Analyzing context costs...\n"));
973
+ console.log(import_chalk7.default.blue("\u{1F9E0} Analyzing context costs...\n"));
684
974
  const startTime = Date.now();
685
975
  const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory || ".");
686
976
  try {
@@ -694,7 +984,7 @@ async function contextAction(directory, options) {
694
984
  file: void 0
695
985
  }
696
986
  };
697
- let baseOptions = await (0, import_core3.loadMergedConfig)(resolvedDir, defaults, {
987
+ let baseOptions = await (0, import_core6.loadMergedConfig)(resolvedDir, defaults, {
698
988
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
699
989
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
700
990
  include: options.include?.split(","),
@@ -713,7 +1003,7 @@ async function contextAction(directory, options) {
713
1003
  console.log("");
714
1004
  const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
715
1005
  const results = await analyzeContext2(finalOptions);
716
- const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
1006
+ const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
717
1007
  const summary = generateSummary(results);
718
1008
  let contextScore;
719
1009
  if (options.score) {
@@ -727,104 +1017,104 @@ async function contextAction(directory, options) {
727
1017
  summary: { ...summary, executionTime: parseFloat(elapsedTime) },
728
1018
  ...contextScore && { scoring: contextScore }
729
1019
  };
730
- const outputPath = (0, import_core3.resolveOutputPath)(
1020
+ const outputPath = (0, import_core6.resolveOutputPath)(
731
1021
  userOutputFile,
732
1022
  `aiready-report-${getReportTimestamp()}.json`,
733
1023
  resolvedDir
734
1024
  );
735
- (0, import_core3.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
1025
+ (0, import_core6.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
736
1026
  } else {
737
1027
  const terminalWidth = process.stdout.columns || 80;
738
1028
  const dividerWidth = Math.min(60, terminalWidth - 2);
739
1029
  const divider = "\u2501".repeat(dividerWidth);
740
- console.log(import_chalk4.default.cyan(divider));
741
- console.log(import_chalk4.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
742
- console.log(import_chalk4.default.cyan(divider) + "\n");
743
- console.log(import_chalk4.default.white(`\u{1F4C1} Files analyzed: ${import_chalk4.default.bold(summary.totalFiles)}`));
744
- console.log(import_chalk4.default.white(`\u{1F4CA} Total tokens: ${import_chalk4.default.bold(summary.totalTokens.toLocaleString())}`));
745
- console.log(import_chalk4.default.yellow(`\u{1F4B0} Avg context budget: ${import_chalk4.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`));
746
- console.log(import_chalk4.default.white(`\u23F1 Analysis time: ${import_chalk4.default.bold(elapsedTime + "s")}
1030
+ console.log(import_chalk7.default.cyan(divider));
1031
+ console.log(import_chalk7.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1032
+ console.log(import_chalk7.default.cyan(divider) + "\n");
1033
+ console.log(import_chalk7.default.white(`\u{1F4C1} Files analyzed: ${import_chalk7.default.bold(summary.totalFiles)}`));
1034
+ console.log(import_chalk7.default.white(`\u{1F4CA} Total tokens: ${import_chalk7.default.bold(summary.totalTokens.toLocaleString())}`));
1035
+ console.log(import_chalk7.default.yellow(`\u{1F4B0} Avg context budget: ${import_chalk7.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`));
1036
+ console.log(import_chalk7.default.white(`\u23F1 Analysis time: ${import_chalk7.default.bold(elapsedTime + "s")}
747
1037
  `));
748
1038
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
749
1039
  if (totalIssues > 0) {
750
- console.log(import_chalk4.default.bold("\u26A0\uFE0F Issues Found:\n"));
1040
+ console.log(import_chalk7.default.bold("\u26A0\uFE0F Issues Found:\n"));
751
1041
  if (summary.criticalIssues > 0) {
752
- console.log(import_chalk4.default.red(` \u{1F534} Critical: ${import_chalk4.default.bold(summary.criticalIssues)}`));
1042
+ console.log(import_chalk7.default.red(` \u{1F534} Critical: ${import_chalk7.default.bold(summary.criticalIssues)}`));
753
1043
  }
754
1044
  if (summary.majorIssues > 0) {
755
- console.log(import_chalk4.default.yellow(` \u{1F7E1} Major: ${import_chalk4.default.bold(summary.majorIssues)}`));
1045
+ console.log(import_chalk7.default.yellow(` \u{1F7E1} Major: ${import_chalk7.default.bold(summary.majorIssues)}`));
756
1046
  }
757
1047
  if (summary.minorIssues > 0) {
758
- console.log(import_chalk4.default.blue(` \u{1F535} Minor: ${import_chalk4.default.bold(summary.minorIssues)}`));
1048
+ console.log(import_chalk7.default.blue(` \u{1F535} Minor: ${import_chalk7.default.bold(summary.minorIssues)}`));
759
1049
  }
760
- console.log(import_chalk4.default.green(`
761
- \u{1F4A1} Potential savings: ${import_chalk4.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1050
+ console.log(import_chalk7.default.green(`
1051
+ \u{1F4A1} Potential savings: ${import_chalk7.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
762
1052
  `));
763
1053
  } else {
764
- console.log(import_chalk4.default.green("\u2705 No significant issues found!\n"));
1054
+ console.log(import_chalk7.default.green("\u2705 No significant issues found!\n"));
765
1055
  }
766
1056
  if (summary.deepFiles.length > 0) {
767
- console.log(import_chalk4.default.bold("\u{1F4CF} Deep Import Chains:\n"));
768
- console.log(import_chalk4.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`));
769
- console.log(import_chalk4.default.gray(` Maximum depth: ${summary.maxImportDepth}
1057
+ console.log(import_chalk7.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1058
+ console.log(import_chalk7.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`));
1059
+ console.log(import_chalk7.default.gray(` Maximum depth: ${summary.maxImportDepth}
770
1060
  `));
771
1061
  summary.deepFiles.slice(0, 10).forEach((item) => {
772
1062
  const fileName = item.file.split("/").slice(-2).join("/");
773
- console.log(` ${import_chalk4.default.cyan("\u2192")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(depth: ${item.depth})`)}`);
1063
+ console.log(` ${import_chalk7.default.cyan("\u2192")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(depth: ${item.depth})`)}`);
774
1064
  });
775
1065
  console.log();
776
1066
  }
777
1067
  if (summary.fragmentedModules.length > 0) {
778
- console.log(import_chalk4.default.bold("\u{1F9E9} Fragmented Modules:\n"));
779
- console.log(import_chalk4.default.gray(` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1068
+ console.log(import_chalk7.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1069
+ console.log(import_chalk7.default.gray(` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
780
1070
  `));
781
1071
  summary.fragmentedModules.slice(0, 10).forEach((module2) => {
782
- console.log(` ${import_chalk4.default.yellow("\u25CF")} ${import_chalk4.default.white(module2.domain)} - ${import_chalk4.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`);
783
- console.log(import_chalk4.default.dim(` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`));
1072
+ console.log(` ${import_chalk7.default.yellow("\u25CF")} ${import_chalk7.default.white(module2.domain)} - ${import_chalk7.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`);
1073
+ console.log(import_chalk7.default.dim(` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`));
784
1074
  });
785
1075
  console.log();
786
1076
  }
787
1077
  if (summary.lowCohesionFiles.length > 0) {
788
- console.log(import_chalk4.default.bold("\u{1F500} Low Cohesion Files:\n"));
789
- console.log(import_chalk4.default.gray(` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1078
+ console.log(import_chalk7.default.bold("\u{1F500} Low Cohesion Files:\n"));
1079
+ console.log(import_chalk7.default.gray(` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
790
1080
  `));
791
1081
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
792
1082
  const fileName = item.file.split("/").slice(-2).join("/");
793
1083
  const scorePercent = (item.score * 100).toFixed(0);
794
- const color = item.score < 0.4 ? import_chalk4.default.red : import_chalk4.default.yellow;
795
- console.log(` ${color("\u25CB")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${scorePercent}% cohesion)`)}`);
1084
+ const color = item.score < 0.4 ? import_chalk7.default.red : import_chalk7.default.yellow;
1085
+ console.log(` ${color("\u25CB")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(${scorePercent}% cohesion)`)}`);
796
1086
  });
797
1087
  console.log();
798
1088
  }
799
1089
  if (summary.topExpensiveFiles.length > 0) {
800
- console.log(import_chalk4.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1090
+ console.log(import_chalk7.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
801
1091
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
802
1092
  const fileName = item.file.split("/").slice(-2).join("/");
803
- const severityColor = item.severity === "critical" ? import_chalk4.default.red : item.severity === "major" ? import_chalk4.default.yellow : import_chalk4.default.blue;
804
- console.log(` ${severityColor("\u25CF")} ${import_chalk4.default.white(fileName)} ${import_chalk4.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`);
1093
+ const severityColor = item.severity === "critical" ? import_chalk7.default.red : item.severity === "major" ? import_chalk7.default.yellow : import_chalk7.default.blue;
1094
+ console.log(` ${severityColor("\u25CF")} ${import_chalk7.default.white(fileName)} ${import_chalk7.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`);
805
1095
  });
806
1096
  console.log();
807
1097
  }
808
1098
  if (contextScore) {
809
- console.log(import_chalk4.default.cyan(divider));
810
- console.log(import_chalk4.default.bold.white(" AI READINESS SCORE (Context)"));
811
- console.log(import_chalk4.default.cyan(divider) + "\n");
812
- console.log((0, import_core3.formatToolScore)(contextScore));
1099
+ console.log(import_chalk7.default.cyan(divider));
1100
+ console.log(import_chalk7.default.bold.white(" AI READINESS SCORE (Context)"));
1101
+ console.log(import_chalk7.default.cyan(divider) + "\n");
1102
+ console.log((0, import_core6.formatToolScore)(contextScore));
813
1103
  console.log();
814
1104
  }
815
1105
  }
816
1106
  } catch (error) {
817
- (0, import_core3.handleCLIError)(error, "Context analysis");
1107
+ (0, import_core6.handleCLIError)(error, "Context analysis");
818
1108
  }
819
1109
  }
820
1110
 
821
1111
  // src/commands/consistency.ts
822
- var import_chalk5 = __toESM(require("chalk"));
823
- var import_fs2 = require("fs");
1112
+ var import_chalk8 = __toESM(require("chalk"));
1113
+ var import_fs3 = require("fs");
824
1114
  var import_path5 = require("path");
825
- var import_core4 = require("@aiready/core");
1115
+ var import_core7 = require("@aiready/core");
826
1116
  async function consistencyAction(directory, options) {
827
- console.log(import_chalk5.default.blue("\u{1F50D} Analyzing consistency...\n"));
1117
+ console.log(import_chalk8.default.blue("\u{1F50D} Analyzing consistency...\n"));
828
1118
  const startTime = Date.now();
829
1119
  const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory || ".");
830
1120
  try {
@@ -839,7 +1129,7 @@ async function consistencyAction(directory, options) {
839
1129
  file: void 0
840
1130
  }
841
1131
  };
842
- const finalOptions = await (0, import_core4.loadMergedConfig)(resolvedDir, defaults, {
1132
+ const finalOptions = await (0, import_core7.loadMergedConfig)(resolvedDir, defaults, {
843
1133
  checkNaming: options.naming !== false,
844
1134
  checkPatterns: options.patterns !== false,
845
1135
  minSeverity: options.minSeverity,
@@ -848,7 +1138,7 @@ async function consistencyAction(directory, options) {
848
1138
  });
849
1139
  const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
850
1140
  const report = await analyzeConsistency2(finalOptions);
851
- const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1141
+ const elapsedTime = (0, import_core7.getElapsedTime)(startTime);
852
1142
  let consistencyScore;
853
1143
  if (options.score) {
854
1144
  const issues = report.results?.flatMap((r) => r.issues) || [];
@@ -865,32 +1155,32 @@ async function consistencyAction(directory, options) {
865
1155
  },
866
1156
  ...consistencyScore && { scoring: consistencyScore }
867
1157
  };
868
- const outputPath = (0, import_core4.resolveOutputPath)(
1158
+ const outputPath = (0, import_core7.resolveOutputPath)(
869
1159
  userOutputFile,
870
1160
  `aiready-report-${getReportTimestamp()}.json`,
871
1161
  resolvedDir
872
1162
  );
873
- (0, import_core4.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
1163
+ (0, import_core7.handleJSONOutput)(outputData, outputPath, `\u2705 Results saved to ${outputPath}`);
874
1164
  } else if (outputFormat === "markdown") {
875
1165
  const markdown = generateMarkdownReport(report, elapsedTime);
876
- const outputPath = (0, import_core4.resolveOutputPath)(
1166
+ const outputPath = (0, import_core7.resolveOutputPath)(
877
1167
  userOutputFile,
878
1168
  `aiready-report-${getReportTimestamp()}.md`,
879
1169
  resolvedDir
880
1170
  );
881
- (0, import_fs2.writeFileSync)(outputPath, markdown);
882
- console.log(import_chalk5.default.green(`\u2705 Report saved to ${outputPath}`));
1171
+ (0, import_fs3.writeFileSync)(outputPath, markdown);
1172
+ console.log(import_chalk8.default.green(`\u2705 Report saved to ${outputPath}`));
883
1173
  } else {
884
- console.log(import_chalk5.default.bold("\n\u{1F4CA} Summary\n"));
885
- console.log(`Files Analyzed: ${import_chalk5.default.cyan(report.summary.filesAnalyzed)}`);
886
- console.log(`Total Issues: ${import_chalk5.default.yellow(report.summary.totalIssues)}`);
887
- console.log(` Naming: ${import_chalk5.default.yellow(report.summary.namingIssues)}`);
888
- console.log(` Patterns: ${import_chalk5.default.yellow(report.summary.patternIssues)}`);
889
- console.log(` Architecture: ${import_chalk5.default.yellow(report.summary.architectureIssues || 0)}`);
890
- console.log(`Analysis Time: ${import_chalk5.default.gray(elapsedTime + "s")}
1174
+ console.log(import_chalk8.default.bold("\n\u{1F4CA} Summary\n"));
1175
+ console.log(`Files Analyzed: ${import_chalk8.default.cyan(report.summary.filesAnalyzed)}`);
1176
+ console.log(`Total Issues: ${import_chalk8.default.yellow(report.summary.totalIssues)}`);
1177
+ console.log(` Naming: ${import_chalk8.default.yellow(report.summary.namingIssues)}`);
1178
+ console.log(` Patterns: ${import_chalk8.default.yellow(report.summary.patternIssues)}`);
1179
+ console.log(` Architecture: ${import_chalk8.default.yellow(report.summary.architectureIssues || 0)}`);
1180
+ console.log(`Analysis Time: ${import_chalk8.default.gray(elapsedTime + "s")}
891
1181
  `);
892
1182
  if (report.summary.totalIssues === 0) {
893
- console.log(import_chalk5.default.green("\u2728 No consistency issues found! Your codebase is well-maintained.\n"));
1183
+ console.log(import_chalk8.default.green("\u2728 No consistency issues found! Your codebase is well-maintained.\n"));
894
1184
  } else {
895
1185
  const namingResults = report.results.filter(
896
1186
  (r) => r.issues.some((i) => i.category === "naming")
@@ -899,17 +1189,17 @@ async function consistencyAction(directory, options) {
899
1189
  (r) => r.issues.some((i) => i.category === "patterns")
900
1190
  );
901
1191
  if (namingResults.length > 0) {
902
- console.log(import_chalk5.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1192
+ console.log(import_chalk8.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
903
1193
  let shown = 0;
904
1194
  for (const result of namingResults) {
905
1195
  if (shown >= 5) break;
906
1196
  for (const issue of result.issues) {
907
1197
  if (shown >= 5) break;
908
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
909
- console.log(`${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`);
1198
+ const severityColor = issue.severity === "critical" ? import_chalk8.default.red : issue.severity === "major" ? import_chalk8.default.yellow : issue.severity === "minor" ? import_chalk8.default.blue : import_chalk8.default.gray;
1199
+ console.log(`${severityColor(issue.severity.toUpperCase())} ${import_chalk8.default.dim(`${issue.location.file}:${issue.location.line}`)}`);
910
1200
  console.log(` ${issue.message}`);
911
1201
  if (issue.suggestion) {
912
- console.log(` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`);
1202
+ console.log(` ${import_chalk8.default.dim("\u2192")} ${import_chalk8.default.italic(issue.suggestion)}`);
913
1203
  }
914
1204
  console.log();
915
1205
  shown++;
@@ -917,22 +1207,22 @@ async function consistencyAction(directory, options) {
917
1207
  }
918
1208
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
919
1209
  if (remaining > 0) {
920
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1210
+ console.log(import_chalk8.default.dim(` ... and ${remaining} more issues
921
1211
  `));
922
1212
  }
923
1213
  }
924
1214
  if (patternResults.length > 0) {
925
- console.log(import_chalk5.default.bold("\u{1F504} Pattern Issues\n"));
1215
+ console.log(import_chalk8.default.bold("\u{1F504} Pattern Issues\n"));
926
1216
  let shown = 0;
927
1217
  for (const result of patternResults) {
928
1218
  if (shown >= 5) break;
929
1219
  for (const issue of result.issues) {
930
1220
  if (shown >= 5) break;
931
- const severityColor = issue.severity === "critical" ? import_chalk5.default.red : issue.severity === "major" ? import_chalk5.default.yellow : issue.severity === "minor" ? import_chalk5.default.blue : import_chalk5.default.gray;
932
- console.log(`${severityColor(issue.severity.toUpperCase())} ${import_chalk5.default.dim(`${issue.location.file}:${issue.location.line}`)}`);
1221
+ const severityColor = issue.severity === "critical" ? import_chalk8.default.red : issue.severity === "major" ? import_chalk8.default.yellow : issue.severity === "minor" ? import_chalk8.default.blue : import_chalk8.default.gray;
1222
+ console.log(`${severityColor(issue.severity.toUpperCase())} ${import_chalk8.default.dim(`${issue.location.file}:${issue.location.line}`)}`);
933
1223
  console.log(` ${issue.message}`);
934
1224
  if (issue.suggestion) {
935
- console.log(` ${import_chalk5.default.dim("\u2192")} ${import_chalk5.default.italic(issue.suggestion)}`);
1225
+ console.log(` ${import_chalk8.default.dim("\u2192")} ${import_chalk8.default.italic(issue.suggestion)}`);
936
1226
  }
937
1227
  console.log();
938
1228
  shown++;
@@ -940,12 +1230,12 @@ async function consistencyAction(directory, options) {
940
1230
  }
941
1231
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
942
1232
  if (remaining > 0) {
943
- console.log(import_chalk5.default.dim(` ... and ${remaining} more issues
1233
+ console.log(import_chalk8.default.dim(` ... and ${remaining} more issues
944
1234
  `));
945
1235
  }
946
1236
  }
947
1237
  if (report.recommendations.length > 0) {
948
- console.log(import_chalk5.default.bold("\u{1F4A1} Recommendations\n"));
1238
+ console.log(import_chalk8.default.bold("\u{1F4A1} Recommendations\n"));
949
1239
  report.recommendations.forEach((rec, i) => {
950
1240
  console.log(`${i + 1}. ${rec}`);
951
1241
  });
@@ -953,35 +1243,35 @@ async function consistencyAction(directory, options) {
953
1243
  }
954
1244
  }
955
1245
  if (consistencyScore) {
956
- console.log(import_chalk5.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
957
- console.log((0, import_core4.formatToolScore)(consistencyScore));
1246
+ console.log(import_chalk8.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1247
+ console.log((0, import_core7.formatToolScore)(consistencyScore));
958
1248
  console.log();
959
1249
  }
960
1250
  }
961
1251
  } catch (error) {
962
- (0, import_core4.handleCLIError)(error, "Consistency analysis");
1252
+ (0, import_core7.handleCLIError)(error, "Consistency analysis");
963
1253
  }
964
1254
  }
965
1255
 
966
1256
  // src/commands/visualize.ts
967
- var import_chalk6 = __toESM(require("chalk"));
968
- var import_fs3 = require("fs");
1257
+ var import_chalk9 = __toESM(require("chalk"));
1258
+ var import_fs4 = require("fs");
969
1259
  var import_path6 = require("path");
970
1260
  var import_child_process = require("child_process");
971
- var import_core5 = require("@aiready/core");
972
- var import_core6 = require("@aiready/core");
1261
+ var import_core8 = require("@aiready/core");
1262
+ var import_core9 = require("@aiready/core");
973
1263
  async function visualizeAction(directory, options) {
974
1264
  try {
975
1265
  const dirPath = (0, import_path6.resolve)(process.cwd(), directory || ".");
976
1266
  let reportPath = options.report ? (0, import_path6.resolve)(dirPath, options.report) : null;
977
- if (!reportPath || !(0, import_fs3.existsSync)(reportPath)) {
1267
+ if (!reportPath || !(0, import_fs4.existsSync)(reportPath)) {
978
1268
  const latestScan = findLatestScanReport(dirPath);
979
1269
  if (latestScan) {
980
1270
  reportPath = latestScan;
981
- console.log(import_chalk6.default.dim(`Found latest report: ${latestScan.split("/").pop()}`));
1271
+ console.log(import_chalk9.default.dim(`Found latest report: ${latestScan.split("/").pop()}`));
982
1272
  } else {
983
- console.error(import_chalk6.default.red("\u274C No AI readiness report found"));
984
- console.log(import_chalk6.default.dim(`
1273
+ console.error(import_chalk9.default.red("\u274C No AI readiness report found"));
1274
+ console.log(import_chalk9.default.dim(`
985
1275
  Generate a report with:
986
1276
  aiready scan --output json
987
1277
 
@@ -990,13 +1280,13 @@ Or specify a custom report:
990
1280
  return;
991
1281
  }
992
1282
  }
993
- const raw = (0, import_fs3.readFileSync)(reportPath, "utf8");
1283
+ const raw = (0, import_fs4.readFileSync)(reportPath, "utf8");
994
1284
  const report = JSON.parse(raw);
995
1285
  const configPath = (0, import_path6.resolve)(dirPath, "aiready.json");
996
1286
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
997
- if ((0, import_fs3.existsSync)(configPath)) {
1287
+ if ((0, import_fs4.existsSync)(configPath)) {
998
1288
  try {
999
- const rawConfig = JSON.parse((0, import_fs3.readFileSync)(configPath, "utf8"));
1289
+ const rawConfig = JSON.parse((0, import_fs4.readFileSync)(configPath, "utf8"));
1000
1290
  if (rawConfig.visualizer?.graph) {
1001
1291
  graphConfig = {
1002
1292
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1018,7 +1308,7 @@ Or specify a custom report:
1018
1308
  const monorepoWebDir = (0, import_path6.resolve)(dirPath, "packages/visualizer");
1019
1309
  let webDir = "";
1020
1310
  let visualizerAvailable = false;
1021
- if ((0, import_fs3.existsSync)(monorepoWebDir)) {
1311
+ if ((0, import_fs4.existsSync)(monorepoWebDir)) {
1022
1312
  webDir = monorepoWebDir;
1023
1313
  visualizerAvailable = true;
1024
1314
  } else {
@@ -1034,7 +1324,7 @@ Or specify a custom report:
1034
1324
  currentDir = parent;
1035
1325
  }
1036
1326
  for (const location of nodemodulesLocations) {
1037
- if ((0, import_fs3.existsSync)(location) && (0, import_fs3.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1327
+ if ((0, import_fs4.existsSync)(location) && (0, import_fs4.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1038
1328
  webDir = location;
1039
1329
  visualizerAvailable = true;
1040
1330
  break;
@@ -1049,14 +1339,14 @@ Or specify a custom report:
1049
1339
  }
1050
1340
  }
1051
1341
  }
1052
- const webViteConfigExists = webDir && (0, import_fs3.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1342
+ const webViteConfigExists = webDir && (0, import_fs4.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1053
1343
  if (visualizerAvailable && webViteConfigExists) {
1054
1344
  const spawnCwd = webDir;
1055
1345
  const { watch } = await import("fs");
1056
1346
  const copyReportToViz = () => {
1057
1347
  try {
1058
1348
  const destPath = (0, import_path6.resolve)(spawnCwd, "web", "report-data.json");
1059
- (0, import_fs3.copyFileSync)(reportPath, destPath);
1349
+ (0, import_fs4.copyFileSync)(reportPath, destPath);
1060
1350
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1061
1351
  } catch (e) {
1062
1352
  console.error("Failed to sync report:", e);
@@ -1090,22 +1380,22 @@ Or specify a custom report:
1090
1380
  devServerStarted = true;
1091
1381
  return;
1092
1382
  } else {
1093
- console.log(import_chalk6.default.yellow("\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."));
1094
- console.log(import_chalk6.default.cyan(" Falling back to static HTML generation...\n"));
1383
+ console.log(import_chalk9.default.yellow("\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."));
1384
+ console.log(import_chalk9.default.cyan(" Falling back to static HTML generation...\n"));
1095
1385
  useDevMode = false;
1096
1386
  }
1097
1387
  } catch (err) {
1098
1388
  console.error("Failed to start dev server:", err);
1099
- console.log(import_chalk6.default.cyan(" Falling back to static HTML generation...\n"));
1389
+ console.log(import_chalk9.default.cyan(" Falling back to static HTML generation...\n"));
1100
1390
  useDevMode = false;
1101
1391
  }
1102
1392
  }
1103
1393
  console.log("Generating HTML...");
1104
- const html = (0, import_core6.generateHTML)(graph);
1394
+ const html = (0, import_core9.generateHTML)(graph);
1105
1395
  const defaultOutput = "visualization.html";
1106
1396
  const outPath = (0, import_path6.resolve)(dirPath, options.output || defaultOutput);
1107
- (0, import_fs3.writeFileSync)(outPath, html, "utf8");
1108
- console.log(import_chalk6.default.green(`\u2705 Visualization written to: ${outPath}`));
1397
+ (0, import_fs4.writeFileSync)(outPath, html, "utf8");
1398
+ console.log(import_chalk9.default.green(`\u2705 Visualization written to: ${outPath}`));
1109
1399
  if (options.open || options.serve) {
1110
1400
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1111
1401
  if (options.serve) {
@@ -1131,7 +1421,7 @@ Or specify a custom report:
1131
1421
  });
1132
1422
  server.listen(port, () => {
1133
1423
  const addr = `http://localhost:${port}/`;
1134
- console.log(import_chalk6.default.cyan(`\u{1F310} Local visualization server running at ${addr}`));
1424
+ console.log(import_chalk9.default.cyan(`\u{1F310} Local visualization server running at ${addr}`));
1135
1425
  (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
1136
1426
  });
1137
1427
  process.on("SIGINT", () => {
@@ -1146,7 +1436,7 @@ Or specify a custom report:
1146
1436
  }
1147
1437
  }
1148
1438
  } catch (err) {
1149
- (0, import_core5.handleCLIError)(err, "Visualization");
1439
+ (0, import_core8.handleCLIError)(err, "Visualization");
1150
1440
  }
1151
1441
  }
1152
1442
  var visualizeHelpText = `
@@ -1176,8 +1466,18 @@ NOTES:
1176
1466
  - Same options as 'visualize'. Use --serve to host the static HTML, or --dev for live reload.
1177
1467
  `;
1178
1468
 
1469
+ // src/commands/index.ts
1470
+ init_hallucination_risk();
1471
+ init_agent_grounding();
1472
+ init_testability();
1473
+
1179
1474
  // src/cli.ts
1180
- var packageJson = JSON.parse((0, import_fs4.readFileSync)((0, import_path7.join)(__dirname, "../package.json"), "utf8"));
1475
+ var import_meta = {};
1476
+ var getDirname = () => {
1477
+ if (typeof __dirname !== "undefined") return __dirname;
1478
+ return (0, import_path7.dirname)((0, import_url.fileURLToPath)(import_meta.url));
1479
+ };
1480
+ var packageJson = JSON.parse((0, import_fs5.readFileSync)((0, import_path7.join)(getDirname(), "../package.json"), "utf8"));
1181
1481
  var program = new import_commander.Command();
1182
1482
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText("after", `
1183
1483
  AI READINESS SCORING:
@@ -1215,7 +1515,7 @@ VERSION: ${packageJson.version}
1215
1515
  DOCUMENTATION: https://aiready.dev/docs/cli
1216
1516
  GITHUB: https://github.com/caopengau/aiready-cli
1217
1517
  LANDING: https://github.com/caopengau/aiready-landing`);
1218
- 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) => {
1518
+ 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) => {
1219
1519
  await scanAction(directory, options);
1220
1520
  });
1221
1521
  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) => {