@aiready/cli 0.14.22 → 0.14.24

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
@@ -25,286 +25,24 @@ 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_fs7 = require("fs");
29
- var import_path9 = require("path");
28
+ var import_fs8 = require("fs");
29
+ var import_path7 = require("path");
30
30
  var import_url = require("url");
31
31
 
32
32
  // src/commands/scan.ts
33
- var import_chalk5 = __toESM(require("chalk"));
34
- var import_fs3 = require("fs");
35
- var import_path3 = require("path");
36
- var import_core7 = require("@aiready/core");
33
+ var import_chalk6 = __toESM(require("chalk"));
34
+ var import_fs4 = require("fs");
35
+ var import_path4 = require("path");
36
+ var import_core9 = require("@aiready/core");
37
37
 
38
- // src/index.ts
39
- var import_core = require("@aiready/core");
40
- var import_pattern_detect = require("@aiready/pattern-detect");
41
- var import_context_analyzer = require("@aiready/context-analyzer");
42
- var import_consistency = require("@aiready/consistency");
43
- var import_ai_signal_clarity = require("@aiready/ai-signal-clarity");
44
- var import_agent_grounding = require("@aiready/agent-grounding");
45
- var import_testability = require("@aiready/testability");
46
- var import_doc_drift = require("@aiready/doc-drift");
47
- var import_deps = require("@aiready/deps");
48
- var import_change_amplification = require("@aiready/change-amplification");
49
- var TOOL_PACKAGE_MAP = {
50
- [import_core.ToolName.PatternDetect]: "@aiready/pattern-detect",
51
- [import_core.ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
52
- [import_core.ToolName.NamingConsistency]: "@aiready/consistency",
53
- [import_core.ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
54
- [import_core.ToolName.AgentGrounding]: "@aiready/agent-grounding",
55
- [import_core.ToolName.TestabilityIndex]: "@aiready/testability",
56
- [import_core.ToolName.DocDrift]: "@aiready/doc-drift",
57
- [import_core.ToolName.DependencyHealth]: "@aiready/deps",
58
- [import_core.ToolName.ChangeAmplification]: "@aiready/change-amplification",
59
- // Aliases handled by registry
60
- patterns: "@aiready/pattern-detect",
61
- duplicates: "@aiready/pattern-detect",
62
- context: "@aiready/context-analyzer",
63
- fragmentation: "@aiready/context-analyzer",
64
- consistency: "@aiready/consistency",
65
- "ai-signal": "@aiready/ai-signal-clarity",
66
- grounding: "@aiready/agent-grounding",
67
- testability: "@aiready/testability",
68
- "deps-health": "@aiready/deps",
69
- "change-amp": "@aiready/change-amplification"
70
- };
71
- function sanitizeConfigRecursive(obj) {
72
- if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
73
- const sanitized = {};
74
- const infraToStrip = [
75
- "rootDir",
76
- "onProgress",
77
- "progressCallback",
78
- "streamResults",
79
- "batchSize",
80
- "useSmartDefaults"
81
- ];
82
- for (const [key, value] of Object.entries(obj)) {
83
- if (infraToStrip.includes(key)) continue;
84
- if (typeof value === "object" && value !== null && !Array.isArray(value)) {
85
- sanitized[key] = sanitizeConfigRecursive(value);
86
- } else {
87
- sanitized[key] = value;
88
- }
89
- }
90
- return sanitized;
91
- }
92
- function sanitizeToolConfig(config) {
93
- return sanitizeConfigRecursive(config);
94
- }
95
- async function analyzeUnified(options) {
96
- await (0, import_core.initializeParsers)();
97
- const startTime = Date.now();
98
- const requestedTools = options.tools ?? [
99
- "patterns",
100
- "context",
101
- "consistency"
102
- ];
103
- const result = {
104
- summary: {
105
- totalIssues: 0,
106
- criticalIssues: 0,
107
- // Added as per instruction
108
- majorIssues: 0,
109
- // Added as per instruction
110
- totalFiles: 0,
111
- toolsRun: [],
112
- executionTime: 0,
113
- config: options,
114
- toolConfigs: {}
115
- }
116
- };
117
- for (const toolName of requestedTools) {
118
- let provider = import_core.ToolRegistry.find(toolName);
119
- if (!provider) {
120
- const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
121
- try {
122
- await import(packageName);
123
- provider = import_core.ToolRegistry.find(toolName);
124
- if (provider) {
125
- console.log(
126
- `\u2705 Successfully loaded tool provider: ${toolName} from ${packageName}`
127
- );
128
- } else {
129
- console.log(
130
- `\u26A0\uFE0F Loaded ${packageName} but provider ${toolName} still not found in registry.`
131
- );
132
- }
133
- } catch (err) {
134
- console.log(
135
- `\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
136
- err.message
137
- );
138
- }
139
- }
140
- if (!provider) {
141
- console.warn(
142
- `\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
143
- );
144
- continue;
145
- }
146
- try {
147
- const sanitizedOptions = { ...options };
148
- delete sanitizedOptions.onProgress;
149
- delete sanitizedOptions.progressCallback;
150
- const toolOptions = {
151
- rootDir: options.rootDir
152
- // Always include rootDir
153
- };
154
- [...import_core.GLOBAL_INFRA_OPTIONS, ...import_core.COMMON_FINE_TUNING_OPTIONS].forEach(
155
- (key) => {
156
- if (key in options && key !== "toolConfigs" && key !== "tools") {
157
- toolOptions[key] = options[key];
158
- }
159
- }
160
- );
161
- if (options.toolConfigs?.[provider.id]) {
162
- Object.assign(toolOptions, options.toolConfigs[provider.id]);
163
- } else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
164
- Object.assign(toolOptions, options.tools[provider.id]);
165
- } else if (options[provider.id]) {
166
- Object.assign(toolOptions, options[provider.id]);
167
- }
168
- toolOptions.onProgress = (processed, total, message) => {
169
- if (options.progressCallback) {
170
- options.progressCallback({
171
- tool: provider.id,
172
- processed,
173
- total,
174
- message
175
- });
176
- }
177
- };
178
- const output = await provider.analyze(toolOptions);
179
- if (output.metadata) {
180
- output.metadata.config = sanitizeToolConfig(toolOptions);
181
- }
182
- if (options.progressCallback) {
183
- options.progressCallback({ tool: provider.id, data: output });
184
- }
185
- result[provider.id] = output;
186
- result.summary.toolsRun.push(provider.id);
187
- if (output.summary?.config) {
188
- result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
189
- output.summary.config
190
- );
191
- } else if (output.metadata?.config) {
192
- result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
193
- output.metadata.config
194
- );
195
- } else {
196
- result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
197
- }
198
- const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
199
- if (toolFiles > result.summary.totalFiles) {
200
- result.summary.totalFiles = toolFiles;
201
- }
202
- const issueCount = output.results.reduce(
203
- (sum, file) => sum + (file.issues?.length ?? 0),
204
- 0
205
- );
206
- result.summary.totalIssues += issueCount;
207
- } catch (err) {
208
- console.error(`\u274C Error running tool '${provider.id}':`, err);
209
- }
210
- }
211
- result.summary.config = sanitizeConfigRecursive({
212
- scan: {
213
- tools: requestedTools,
214
- include: options.include,
215
- exclude: options.exclude
216
- },
217
- // Use 'tools' for tool-specific configurations to match AIReadyConfig
218
- tools: result.summary.toolConfigs
219
- });
220
- result.summary.executionTime = Date.now() - startTime;
221
- const keyMappings = {
222
- "pattern-detect": ["patternDetect", "patterns"],
223
- "context-analyzer": ["contextAnalyzer", "context"],
224
- "naming-consistency": ["namingConsistency", "consistency"],
225
- "ai-signal-clarity": ["aiSignalClarity"],
226
- "agent-grounding": ["agentGrounding"],
227
- "testability-index": ["testabilityIndex", "testability"],
228
- "doc-drift": ["docDrift"],
229
- "dependency-health": ["dependencyHealth", "deps"],
230
- "change-amplification": ["changeAmplification"]
231
- };
232
- for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
233
- if (result[kebabKey]) {
234
- for (const alias of aliases) {
235
- result[alias] = result[kebabKey];
236
- }
237
- }
238
- }
239
- return result;
240
- }
241
- async function scoreUnified(results, options) {
242
- const toolScores = /* @__PURE__ */ new Map();
243
- for (const toolId of results.summary.toolsRun) {
244
- const provider = import_core.ToolRegistry.get(toolId);
245
- if (!provider) continue;
246
- const output = results[toolId];
247
- if (!output) continue;
248
- try {
249
- const toolScore = provider.score(output, options);
250
- if (!toolScore.tokenBudget) {
251
- if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
252
- const wastedTokens = output.duplicates.reduce(
253
- (sum, d) => sum + (d.tokenCost ?? 0),
254
- 0
255
- );
256
- toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
257
- totalContextTokens: wastedTokens * 2,
258
- wastedTokens: {
259
- duplication: wastedTokens,
260
- fragmentation: 0,
261
- chattiness: 0
262
- }
263
- });
264
- } else if (toolId === import_core.ToolName.ContextAnalyzer && output.summary) {
265
- toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
266
- totalContextTokens: output.summary.totalTokens,
267
- wastedTokens: {
268
- duplication: 0,
269
- fragmentation: output.summary.totalPotentialSavings ?? 0,
270
- chattiness: 0
271
- }
272
- });
273
- }
274
- }
275
- toolScores.set(toolId, toolScore);
276
- } catch (err) {
277
- console.error(`\u274C Error scoring tool '${toolId}':`, err);
278
- }
279
- }
280
- if (toolScores.size === 0) {
281
- return {
282
- overall: 0,
283
- rating: "Critical",
284
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
285
- toolsUsed: [],
286
- breakdown: [],
287
- calculation: {
288
- formula: "0 / 0 = 0",
289
- weights: {},
290
- normalized: "0 / 0 = 0"
291
- }
292
- };
293
- }
294
- return (0, import_core.calculateOverallScore)(toolScores, options, void 0);
295
- }
38
+ // src/utils/index.ts
39
+ var import_core2 = require("@aiready/core");
296
40
 
297
41
  // src/utils/helpers.ts
298
42
  var import_path = require("path");
299
43
  var import_fs = require("fs");
300
44
  var import_chalk = __toESM(require("chalk"));
301
- var import_core2 = require("@aiready/core");
302
- var import_core3 = require("@aiready/core");
303
- function getReportTimestamp() {
304
- const now = /* @__PURE__ */ new Date();
305
- const pad = (n) => String(n).padStart(2, "0");
306
- return `${now.getFullYear()}${pad(now.getMonth() + 1)}${pad(now.getDate())}-${pad(now.getHours())}${pad(now.getMinutes())}${pad(now.getSeconds())}`;
307
- }
45
+ var import_core = require("@aiready/core");
308
46
  async function warnIfGraphCapExceeded(report, dirPath) {
309
47
  try {
310
48
  const { loadConfig: loadConfig4 } = await import("@aiready/core");
@@ -393,7 +131,7 @@ function generateMarkdownReport(report, elapsedTime) {
393
131
 
394
132
  // src/commands/report-formatter.ts
395
133
  var import_chalk2 = __toESM(require("chalk"));
396
- var import_core4 = require("@aiready/core");
134
+ var import_core3 = require("@aiready/core");
397
135
  function generateProgressBar(score, width = 20) {
398
136
  const filled = Math.round(score / 100 * width);
399
137
  const empty = width - filled;
@@ -498,31 +236,34 @@ function printBusinessImpact(roi, unifiedBudget) {
498
236
  }
499
237
  function printScoring(scoringResult, scoringProfile) {
500
238
  console.log(import_chalk2.default.bold("\n\u{1F4CA} AI Readiness Overall Score"));
501
- console.log(` ${(0, import_core4.formatScore)(scoringResult)}`);
239
+ console.log(` ${(0, import_core3.formatScore)(scoringResult)}`);
502
240
  console.log(import_chalk2.default.dim(` (Scoring Profile: ${scoringProfile})`));
503
241
  if (scoringResult.breakdown) {
504
242
  console.log(import_chalk2.default.bold("\nTool breakdown:"));
505
243
  scoringResult.breakdown.forEach((tool) => {
506
- const rating = (0, import_core4.getRating)(tool.score);
507
- const emoji = (0, import_core4.getRatingDisplay)(rating).emoji;
244
+ const rating = (0, import_core3.getRating)(tool.score);
245
+ const emoji = (0, import_core3.getRatingDisplay)(rating).emoji;
508
246
  const progressBar = generateProgressBar(tool.score, 15);
509
247
  console.log(
510
248
  ` ${progressBar} ${tool.score}/100 (${rating}) ${emoji} ${tool.toolName}`
511
249
  );
512
250
  });
513
- const allRecs = scoringResult.breakdown.flatMap(
514
- (t) => (t.recommendations ?? []).map((r) => ({ ...r, tool: t.toolName }))
515
- ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 5);
516
- if (allRecs.length > 0) {
517
- console.log(import_chalk2.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
518
- allRecs.forEach((rec, i) => {
519
- const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
520
- console.log(` ${i + 1}. ${priorityIcon} ${import_chalk2.default.bold(rec.action)}`);
521
- console.log(
522
- ` Impact: ${import_chalk2.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
523
- );
524
- });
525
- }
251
+ printTopRecommendations(scoringResult.breakdown);
252
+ }
253
+ }
254
+ function printTopRecommendations(breakdown) {
255
+ const allRecs = breakdown.flatMap(
256
+ (t) => (t.recommendations ?? []).map((r) => ({ ...r, tool: t.toolName }))
257
+ ).sort((a, b) => b.estimatedImpact - a.estimatedImpact).slice(0, 5);
258
+ if (allRecs.length > 0) {
259
+ console.log(import_chalk2.default.bold("\n\u{1F3AF} Top Actionable Recommendations:"));
260
+ allRecs.forEach((rec, i) => {
261
+ const priorityIcon = rec.priority === "high" ? "\u{1F534}" : rec.priority === "medium" ? "\u{1F7E1}" : "\u{1F535}";
262
+ console.log(` ${i + 1}. ${priorityIcon} ${import_chalk2.default.bold(rec.action)}`);
263
+ console.log(
264
+ ` Impact: ${import_chalk2.default.green(`+${rec.estimatedImpact} points`)} to ${rec.tool}`
265
+ );
266
+ });
526
267
  }
527
268
  }
528
269
  function mapToUnifiedReport(res, scoring) {
@@ -537,9 +278,9 @@ function mapToUnifiedReport(res, scoring) {
537
278
  totalFilesSet.add(r.fileName);
538
279
  allResults.push(r);
539
280
  r.issues?.forEach((i) => {
540
- if (i.severity === import_core4.Severity.Critical || i.severity === "critical")
281
+ if (i.severity === import_core3.Severity.Critical || i.severity === "critical")
541
282
  criticalCount++;
542
- if (i.severity === import_core4.Severity.Major || i.severity === "major")
283
+ if (i.severity === import_core3.Severity.Major || i.severity === "major")
543
284
  majorCount++;
544
285
  });
545
286
  });
@@ -561,7 +302,7 @@ function mapToUnifiedReport(res, scoring) {
561
302
  var import_fs2 = __toESM(require("fs"));
562
303
  var import_path2 = require("path");
563
304
  var import_chalk3 = __toESM(require("chalk"));
564
- var import_core5 = require("@aiready/core");
305
+ var import_core4 = require("@aiready/core");
565
306
  async function uploadAction(file, options) {
566
307
  const startTime = Date.now();
567
308
  const filePath = (0, import_path2.resolve)(process.cwd(), file);
@@ -648,265 +389,551 @@ async function uploadAction(file, options) {
648
389
  console.log(import_chalk3.default.dim(` Score: ${uploadResult.analysis.aiScore}/100`));
649
390
  }
650
391
  } catch (error) {
651
- (0, import_core5.handleCLIError)(error, "Upload");
392
+ (0, import_core4.handleCLIError)(error, "Upload");
393
+ }
394
+ }
395
+ var UPLOAD_HELP_TEXT = `
396
+ EXAMPLES:
397
+ $ aiready upload report.json --api-key ar_...
398
+ $ aiready upload .aiready/latest.json
399
+ $ AIREADY_API_KEY=ar_... aiready upload report.json
400
+
401
+ ENVIRONMENT VARIABLES:
402
+ AIREADY_API_KEY Your platform API key
403
+ AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
404
+ `;
405
+
406
+ // src/commands/scan-config.ts
407
+ var import_core6 = require("@aiready/core");
408
+
409
+ // src/commands/scan-helpers.ts
410
+ var import_chalk4 = __toESM(require("chalk"));
411
+ var import_core5 = require("@aiready/core");
412
+ function getProfileTools(profile) {
413
+ switch (profile.toLowerCase()) {
414
+ case "agentic":
415
+ return [
416
+ import_core5.ToolName.AiSignalClarity,
417
+ import_core5.ToolName.AgentGrounding,
418
+ import_core5.ToolName.TestabilityIndex
419
+ ];
420
+ case "cost":
421
+ return [import_core5.ToolName.PatternDetect, import_core5.ToolName.ContextAnalyzer];
422
+ case "logic":
423
+ return [
424
+ import_core5.ToolName.TestabilityIndex,
425
+ import_core5.ToolName.NamingConsistency,
426
+ import_core5.ToolName.ContextAnalyzer,
427
+ import_core5.ToolName.PatternDetect,
428
+ import_core5.ToolName.ChangeAmplification
429
+ ];
430
+ case "ui":
431
+ return [
432
+ import_core5.ToolName.NamingConsistency,
433
+ import_core5.ToolName.ContextAnalyzer,
434
+ import_core5.ToolName.PatternDetect,
435
+ import_core5.ToolName.DocDrift,
436
+ import_core5.ToolName.AiSignalClarity
437
+ ];
438
+ case "security":
439
+ return [import_core5.ToolName.NamingConsistency, import_core5.ToolName.TestabilityIndex];
440
+ case "onboarding":
441
+ return [
442
+ import_core5.ToolName.ContextAnalyzer,
443
+ import_core5.ToolName.NamingConsistency,
444
+ import_core5.ToolName.AgentGrounding
445
+ ];
446
+ default:
447
+ console.log(
448
+ import_chalk4.default.yellow(`
449
+ \u26A0\uFE0F Unknown profile '${profile}'. Using defaults.`)
450
+ );
451
+ return void 0;
452
+ }
453
+ }
454
+ function createProgressCallback() {
455
+ return (event) => {
456
+ if (event.message) {
457
+ process.stdout.write(`\r\x1B[K [${event.tool}] ${event.message}`);
458
+ return;
459
+ }
460
+ process.stdout.write("\r\x1B[K");
461
+ console.log(import_chalk4.default.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
462
+ const toolResult = event.data;
463
+ if (toolResult && toolResult.summary) {
464
+ if (toolResult.summary.totalIssues !== void 0)
465
+ console.log(
466
+ ` Issues found: ${import_chalk4.default.bold(toolResult.summary.totalIssues)}`
467
+ );
468
+ if (toolResult.summary.score !== void 0)
469
+ console.log(
470
+ ` Tool Score: ${import_chalk4.default.bold(toolResult.summary.score)}/100`
471
+ );
472
+ if (toolResult.summary.totalFiles !== void 0)
473
+ console.log(
474
+ ` Files analyzed: ${import_chalk4.default.bold(toolResult.summary.totalFiles)}`
475
+ );
476
+ }
477
+ };
478
+ }
479
+
480
+ // src/commands/scan-config.ts
481
+ var SCAN_DEFAULTS = {
482
+ tools: [
483
+ "pattern-detect",
484
+ "context-analyzer",
485
+ "naming-consistency",
486
+ "ai-signal-clarity",
487
+ "agent-grounding",
488
+ "testability-index",
489
+ "doc-drift",
490
+ "dependency-health",
491
+ "change-amplification"
492
+ ],
493
+ include: void 0,
494
+ exclude: void 0,
495
+ output: {
496
+ format: "console",
497
+ file: void 0
498
+ }
499
+ };
500
+ async function resolveScanConfig(resolvedDir, options) {
501
+ let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
502
+ if (options.profile) {
503
+ profileTools = getProfileTools(options.profile);
504
+ }
505
+ const cliOverrides = {
506
+ include: options.include?.split(","),
507
+ exclude: options.exclude?.split(",")
508
+ };
509
+ if (profileTools) cliOverrides.tools = profileTools;
510
+ const baseOptions = await (0, import_core6.loadMergedConfig)(
511
+ resolvedDir,
512
+ SCAN_DEFAULTS,
513
+ cliOverrides
514
+ );
515
+ const finalOptions = { ...baseOptions };
516
+ if (baseOptions.tools.includes(import_core6.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
517
+ const { getSmartDefaults } = await import("@aiready/pattern-detect");
518
+ const patternSmartDefaults = await getSmartDefaults(
519
+ resolvedDir,
520
+ finalOptions.toolConfigs?.[import_core6.ToolName.PatternDetect] ?? {}
521
+ );
522
+ if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
523
+ finalOptions.toolConfigs[import_core6.ToolName.PatternDetect] = {
524
+ ...patternSmartDefaults,
525
+ ...finalOptions.toolConfigs[import_core6.ToolName.PatternDetect]
526
+ };
527
+ }
528
+ return finalOptions;
529
+ }
530
+
531
+ // src/commands/scan-orchestrator.ts
532
+ var import_chalk5 = __toESM(require("chalk"));
533
+ var import_fs3 = require("fs");
534
+ var import_path3 = require("path");
535
+ var import_core8 = require("@aiready/core");
536
+
537
+ // src/index.ts
538
+ var import_core7 = require("@aiready/core");
539
+ var TOOL_PACKAGE_MAP = {
540
+ [import_core7.ToolName.PatternDetect]: "@aiready/pattern-detect",
541
+ [import_core7.ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
542
+ [import_core7.ToolName.NamingConsistency]: "@aiready/consistency",
543
+ [import_core7.ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
544
+ [import_core7.ToolName.AgentGrounding]: "@aiready/agent-grounding",
545
+ [import_core7.ToolName.TestabilityIndex]: "@aiready/testability",
546
+ [import_core7.ToolName.DocDrift]: "@aiready/doc-drift",
547
+ [import_core7.ToolName.DependencyHealth]: "@aiready/deps",
548
+ [import_core7.ToolName.ChangeAmplification]: "@aiready/change-amplification",
549
+ // Aliases handled by registry
550
+ patterns: "@aiready/pattern-detect",
551
+ duplicates: "@aiready/pattern-detect",
552
+ context: "@aiready/context-analyzer",
553
+ fragmentation: "@aiready/context-analyzer",
554
+ consistency: "@aiready/consistency",
555
+ "ai-signal": "@aiready/ai-signal-clarity",
556
+ grounding: "@aiready/agent-grounding",
557
+ testability: "@aiready/testability",
558
+ "deps-health": "@aiready/deps",
559
+ "change-amp": "@aiready/change-amplification"
560
+ };
561
+ function sanitizeConfigRecursive(obj) {
562
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
563
+ const sanitized = {};
564
+ const infraToStrip = [
565
+ "rootDir",
566
+ "onProgress",
567
+ "progressCallback",
568
+ "streamResults",
569
+ "batchSize",
570
+ "useSmartDefaults"
571
+ ];
572
+ for (const [key, value] of Object.entries(obj)) {
573
+ if (infraToStrip.includes(key)) continue;
574
+ if (typeof value === "object" && value !== null && !Array.isArray(value)) {
575
+ sanitized[key] = sanitizeConfigRecursive(value);
576
+ } else {
577
+ sanitized[key] = value;
578
+ }
579
+ }
580
+ return sanitized;
581
+ }
582
+ function sanitizeToolConfig(config) {
583
+ return sanitizeConfigRecursive(config);
584
+ }
585
+ async function analyzeUnified(options) {
586
+ await (0, import_core7.initializeParsers)();
587
+ const startTime = Date.now();
588
+ const requestedTools = options.tools ?? [
589
+ "patterns",
590
+ "context",
591
+ "consistency"
592
+ ];
593
+ const result = {
594
+ summary: {
595
+ totalIssues: 0,
596
+ criticalIssues: 0,
597
+ // Added as per instruction
598
+ majorIssues: 0,
599
+ // Added as per instruction
600
+ totalFiles: 0,
601
+ toolsRun: [],
602
+ executionTime: 0,
603
+ config: options,
604
+ toolConfigs: {}
605
+ }
606
+ };
607
+ for (const toolName of requestedTools) {
608
+ let provider = import_core7.ToolRegistry.find(toolName);
609
+ if (!provider) {
610
+ const packageName = TOOL_PACKAGE_MAP[toolName] ?? (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
611
+ try {
612
+ await import(packageName);
613
+ provider = import_core7.ToolRegistry.find(toolName);
614
+ if (provider) {
615
+ console.log(
616
+ `\u2705 Successfully loaded tool provider: ${toolName} from ${packageName}`
617
+ );
618
+ } else {
619
+ console.log(
620
+ `\u26A0\uFE0F Loaded ${packageName} but provider ${toolName} still not found in registry.`
621
+ );
622
+ }
623
+ } catch (err) {
624
+ console.log(
625
+ `\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
626
+ err.message
627
+ );
628
+ }
629
+ }
630
+ if (!provider) {
631
+ console.warn(
632
+ `\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
633
+ );
634
+ continue;
635
+ }
636
+ try {
637
+ const sanitizedOptions = { ...options };
638
+ delete sanitizedOptions.onProgress;
639
+ delete sanitizedOptions.progressCallback;
640
+ const toolOptions = {
641
+ rootDir: options.rootDir
642
+ // Always include rootDir
643
+ };
644
+ [...import_core7.GLOBAL_INFRA_OPTIONS, ...import_core7.COMMON_FINE_TUNING_OPTIONS].forEach(
645
+ (key) => {
646
+ if (key in options && key !== "toolConfigs" && key !== "tools") {
647
+ toolOptions[key] = options[key];
648
+ }
649
+ }
650
+ );
651
+ if (options.toolConfigs?.[provider.id]) {
652
+ Object.assign(toolOptions, options.toolConfigs[provider.id]);
653
+ } else if (options.tools && !Array.isArray(options.tools) && typeof options.tools === "object" && options.tools[provider.id]) {
654
+ Object.assign(toolOptions, options.tools[provider.id]);
655
+ } else if (options[provider.id]) {
656
+ Object.assign(toolOptions, options[provider.id]);
657
+ }
658
+ toolOptions.onProgress = (processed, total, message) => {
659
+ if (options.progressCallback) {
660
+ options.progressCallback({
661
+ tool: provider.id,
662
+ processed,
663
+ total,
664
+ message
665
+ });
666
+ }
667
+ };
668
+ const output = await provider.analyze(toolOptions);
669
+ if (output.metadata) {
670
+ output.metadata.config = sanitizeToolConfig(toolOptions);
671
+ }
672
+ if (options.progressCallback) {
673
+ options.progressCallback({ tool: provider.id, data: output });
674
+ }
675
+ result[provider.id] = output;
676
+ result.summary.toolsRun.push(provider.id);
677
+ if (output.summary?.config) {
678
+ result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
679
+ output.summary.config
680
+ );
681
+ } else if (output.metadata?.config) {
682
+ result.summary.toolConfigs[provider.id] = sanitizeToolConfig(
683
+ output.metadata.config
684
+ );
685
+ } else {
686
+ result.summary.toolConfigs[provider.id] = sanitizeToolConfig(toolOptions);
687
+ }
688
+ const toolFiles = output.summary?.totalFiles ?? output.summary?.filesAnalyzed ?? 0;
689
+ if (toolFiles > result.summary.totalFiles) {
690
+ result.summary.totalFiles = toolFiles;
691
+ }
692
+ const issueCount = output.results.reduce(
693
+ (sum, file) => sum + (file.issues?.length ?? 0),
694
+ 0
695
+ );
696
+ result.summary.totalIssues += issueCount;
697
+ } catch (err) {
698
+ console.error(`\u274C Error running tool '${provider.id}':`, err);
699
+ }
700
+ }
701
+ result.summary.config = sanitizeConfigRecursive({
702
+ scan: {
703
+ tools: requestedTools,
704
+ include: options.include,
705
+ exclude: options.exclude
706
+ },
707
+ // Use 'tools' for tool-specific configurations to match AIReadyConfig
708
+ tools: result.summary.toolConfigs
709
+ });
710
+ result.summary.executionTime = Date.now() - startTime;
711
+ const keyMappings = {
712
+ "pattern-detect": ["patternDetect", "patterns"],
713
+ "context-analyzer": ["contextAnalyzer", "context"],
714
+ "naming-consistency": ["namingConsistency", "consistency"],
715
+ "ai-signal-clarity": ["aiSignalClarity"],
716
+ "agent-grounding": ["agentGrounding"],
717
+ "testability-index": ["testabilityIndex", "testability"],
718
+ "doc-drift": ["docDrift"],
719
+ "dependency-health": ["dependencyHealth", "deps"],
720
+ "change-amplification": ["changeAmplification"]
721
+ };
722
+ for (const [kebabKey, aliases] of Object.entries(keyMappings)) {
723
+ if (result[kebabKey]) {
724
+ for (const alias of aliases) {
725
+ result[alias] = result[kebabKey];
726
+ }
727
+ }
728
+ }
729
+ return result;
730
+ }
731
+ async function scoreUnified(results, options) {
732
+ const toolScores = /* @__PURE__ */ new Map();
733
+ for (const toolId of results.summary.toolsRun) {
734
+ const provider = import_core7.ToolRegistry.get(toolId);
735
+ if (!provider) continue;
736
+ const output = results[toolId];
737
+ if (!output) continue;
738
+ try {
739
+ const toolScore = provider.score(output, options);
740
+ if (!toolScore.tokenBudget) {
741
+ if (toolId === import_core7.ToolName.PatternDetect && output.duplicates) {
742
+ const wastedTokens = output.duplicates.reduce(
743
+ (sum, d) => sum + (d.tokenCost ?? 0),
744
+ 0
745
+ );
746
+ toolScore.tokenBudget = (0, import_core7.calculateTokenBudget)({
747
+ totalContextTokens: wastedTokens * 2,
748
+ wastedTokens: {
749
+ duplication: wastedTokens,
750
+ fragmentation: 0,
751
+ chattiness: 0
752
+ }
753
+ });
754
+ } else if (toolId === import_core7.ToolName.ContextAnalyzer && output.summary) {
755
+ toolScore.tokenBudget = (0, import_core7.calculateTokenBudget)({
756
+ totalContextTokens: output.summary.totalTokens,
757
+ wastedTokens: {
758
+ duplication: 0,
759
+ fragmentation: output.summary.totalPotentialSavings ?? 0,
760
+ chattiness: 0
761
+ }
762
+ });
763
+ }
764
+ }
765
+ toolScores.set(toolId, toolScore);
766
+ } catch (err) {
767
+ console.error(`\u274C Error scoring tool '${toolId}':`, err);
768
+ }
769
+ }
770
+ if (toolScores.size === 0) {
771
+ return {
772
+ overall: 0,
773
+ rating: "Critical",
774
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
775
+ toolsUsed: [],
776
+ breakdown: [],
777
+ calculation: {
778
+ formula: "0 / 0 = 0",
779
+ weights: {},
780
+ normalized: "0 / 0 = 0"
781
+ }
782
+ };
652
783
  }
784
+ return (0, import_core7.calculateOverallScore)(toolScores, options, void 0);
653
785
  }
654
- var UPLOAD_HELP_TEXT = `
655
- EXAMPLES:
656
- $ aiready upload report.json --api-key ar_...
657
- $ aiready upload .aiready/latest.json
658
- $ AIREADY_API_KEY=ar_... aiready upload report.json
659
-
660
- ENVIRONMENT VARIABLES:
661
- AIREADY_API_KEY Your platform API key
662
- AIREADY_SERVER Custom platform URL (default: https://dev.platform.getaiready.dev)
663
- `;
664
786
 
665
- // src/commands/scan-helpers.ts
666
- var import_chalk4 = __toESM(require("chalk"));
667
- var import_core6 = require("@aiready/core");
668
- function getProfileTools(profile) {
669
- switch (profile.toLowerCase()) {
670
- case "agentic":
671
- return [
672
- import_core6.ToolName.AiSignalClarity,
673
- import_core6.ToolName.AgentGrounding,
674
- import_core6.ToolName.TestabilityIndex
675
- ];
676
- case "cost":
677
- return [import_core6.ToolName.PatternDetect, import_core6.ToolName.ContextAnalyzer];
678
- case "logic":
679
- return [
680
- import_core6.ToolName.TestabilityIndex,
681
- import_core6.ToolName.NamingConsistency,
682
- import_core6.ToolName.ContextAnalyzer,
683
- import_core6.ToolName.PatternDetect,
684
- import_core6.ToolName.ChangeAmplification
685
- ];
686
- case "ui":
687
- return [
688
- import_core6.ToolName.NamingConsistency,
689
- import_core6.ToolName.ContextAnalyzer,
690
- import_core6.ToolName.PatternDetect,
691
- import_core6.ToolName.DocDrift,
692
- import_core6.ToolName.AiSignalClarity
693
- ];
694
- case "security":
695
- return [import_core6.ToolName.NamingConsistency, import_core6.ToolName.TestabilityIndex];
696
- case "onboarding":
697
- return [
698
- import_core6.ToolName.ContextAnalyzer,
699
- import_core6.ToolName.NamingConsistency,
700
- import_core6.ToolName.AgentGrounding
701
- ];
702
- default:
703
- console.log(
704
- import_chalk4.default.yellow(`
705
- \u26A0\uFE0F Unknown profile '${profile}'. Using defaults.`)
706
- );
707
- return void 0;
787
+ // src/commands/scan-orchestrator.ts
788
+ async function runUnifiedScan(resolvedDir, finalOptions, options, startTime) {
789
+ console.log(import_chalk5.default.cyan("\n=== AIReady Run Preview ==="));
790
+ console.log(
791
+ import_chalk5.default.white("Tools to run:"),
792
+ (finalOptions.tools ?? []).join(", ")
793
+ );
794
+ const progressCallback = createProgressCallback();
795
+ const scoringProfile = options.profile ?? finalOptions.scoring?.profile ?? "default";
796
+ const results = await analyzeUnified({
797
+ ...finalOptions,
798
+ progressCallback,
799
+ onProgress: () => {
800
+ },
801
+ suppressToolConfig: true
802
+ });
803
+ printScanSummary(results, startTime);
804
+ let scoringResult;
805
+ if (options.score || finalOptions.scoring?.showBreakdown) {
806
+ scoringResult = await scoreUnified(results, {
807
+ ...finalOptions,
808
+ scoring: {
809
+ ...finalOptions.scoring,
810
+ profile: scoringProfile
811
+ }
812
+ });
813
+ printScoring(scoringResult, scoringProfile);
814
+ if (options.compareTo) {
815
+ handleTrendComparison(options.compareTo, scoringResult);
816
+ }
817
+ await handleBusinessImpactMetrics(
818
+ results,
819
+ scoringResult,
820
+ options.model ?? "gpt-5.4-mini"
821
+ );
708
822
  }
823
+ return { results, scoringResult };
709
824
  }
710
- function createProgressCallback() {
711
- return (event) => {
712
- if (event.message) {
713
- process.stdout.write(`\r\x1B[K [${event.tool}] ${event.message}`);
714
- return;
715
- }
716
- process.stdout.write("\r\x1B[K");
717
- console.log(import_chalk4.default.cyan(`--- ${event.tool.toUpperCase()} RESULTS ---`));
718
- const toolResult = event.data;
719
- if (toolResult && toolResult.summary) {
720
- if (toolResult.summary.totalIssues !== void 0)
825
+ function handleTrendComparison(baselinePath, currentScoring) {
826
+ try {
827
+ const prevReport = JSON.parse(
828
+ (0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), baselinePath), "utf8")
829
+ );
830
+ const prevScore = prevReport.scoring?.overall ?? prevReport.scoring?.score;
831
+ if (typeof prevScore === "number") {
832
+ const diff = currentScoring.overall - prevScore;
833
+ const diffStr = diff > 0 ? `+${diff}` : String(diff);
834
+ if (diff > 0)
721
835
  console.log(
722
- ` Issues found: ${import_chalk4.default.bold(toolResult.summary.totalIssues)}`
836
+ import_chalk5.default.green(
837
+ ` \u{1F4C8} Trend: ${diffStr} compared to ${baselinePath} (${prevScore} \u2192 ${currentScoring.overall})`
838
+ )
723
839
  );
724
- if (toolResult.summary.score !== void 0)
840
+ else if (diff < 0)
725
841
  console.log(
726
- ` Tool Score: ${import_chalk4.default.bold(toolResult.summary.score)}/100`
842
+ import_chalk5.default.red(
843
+ ` \u{1F4C9} Trend: ${diffStr} compared to ${baselinePath} (${prevScore} \u2192 ${currentScoring.overall})`
844
+ )
727
845
  );
728
- if (toolResult.summary.totalFiles !== void 0)
846
+ else
729
847
  console.log(
730
- ` Files analyzed: ${import_chalk4.default.bold(toolResult.summary.totalFiles)}`
848
+ import_chalk5.default.blue(
849
+ ` \u2796 Trend: No change (${prevScore} \u2192 ${currentScoring.overall})`
850
+ )
731
851
  );
732
852
  }
733
- };
853
+ } catch (e) {
854
+ void e;
855
+ }
856
+ }
857
+ async function handleBusinessImpactMetrics(results, scoringResult, modelId) {
858
+ const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
859
+ (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
860
+ 0
861
+ );
862
+ const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
863
+ (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
864
+ 0
865
+ );
866
+ const totalContext = Math.max(
867
+ ...(scoringResult.breakdown ?? []).map(
868
+ (s) => s.tokenBudget?.totalContextTokens ?? 0
869
+ ),
870
+ 0
871
+ );
872
+ if (totalContext > 0) {
873
+ const unifiedBudget = (0, import_core8.calculateTokenBudget)({
874
+ totalContextTokens: totalContext,
875
+ wastedTokens: {
876
+ duplication: totalWastedDuplication,
877
+ fragmentation: totalWastedFragmentation,
878
+ chattiness: totalContext * 0.1
879
+ // Default chattiness
880
+ }
881
+ });
882
+ const allIssues = [];
883
+ for (const toolId of results.summary.toolsRun) {
884
+ if (results[toolId]?.results) {
885
+ results[toolId].results.forEach((fileRes) => {
886
+ if (fileRes.issues) {
887
+ allIssues.push(...fileRes.issues);
888
+ }
889
+ });
890
+ }
891
+ }
892
+ const { calculateBusinessROI } = await import("@aiready/core");
893
+ const roi = calculateBusinessROI({
894
+ tokenWaste: unifiedBudget.wastedTokens.total,
895
+ issues: allIssues,
896
+ modelId
897
+ });
898
+ printBusinessImpact(roi, unifiedBudget);
899
+ results.summary.businessImpact = {
900
+ estimatedMonthlyWaste: roi.monthlySavings,
901
+ potentialSavings: roi.monthlySavings,
902
+ productivityHours: roi.productivityGainHours
903
+ };
904
+ scoringResult.tokenBudget = unifiedBudget;
905
+ scoringResult.businessROI = roi;
906
+ }
734
907
  }
735
908
 
736
909
  // src/commands/scan.ts
737
910
  async function scanAction(directory, options) {
738
- console.log(import_chalk5.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
911
+ console.log(import_chalk6.default.blue("\u{1F680} Starting AIReady unified analysis...\n"));
739
912
  const startTime = Date.now();
740
- const resolvedDir = (0, import_path3.resolve)(process.cwd(), directory ?? ".");
741
- const repoMetadata = (0, import_core7.getRepoMetadata)(resolvedDir);
913
+ const resolvedDir = (0, import_path4.resolve)(process.cwd(), directory ?? ".");
914
+ const repoMetadata = (0, import_core9.getRepoMetadata)(resolvedDir);
742
915
  try {
743
- const defaults = {
744
- tools: [
745
- "pattern-detect",
746
- "context-analyzer",
747
- "naming-consistency",
748
- "ai-signal-clarity",
749
- "agent-grounding",
750
- "testability-index",
751
- "doc-drift",
752
- "dependency-health",
753
- "change-amplification"
754
- ],
755
- include: void 0,
756
- exclude: void 0,
757
- output: {
758
- format: "console",
759
- file: void 0
760
- }
761
- };
762
- let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
763
- if (options.profile) {
764
- profileTools = getProfileTools(options.profile);
765
- }
766
- const cliOverrides = {
767
- include: options.include?.split(","),
768
- exclude: options.exclude?.split(",")
769
- };
770
- if (profileTools) cliOverrides.tools = profileTools;
771
- const baseOptions = await (0, import_core7.loadMergedConfig)(
916
+ const finalOptions = await resolveScanConfig(resolvedDir, options);
917
+ const { results, scoringResult } = await runUnifiedScan(
772
918
  resolvedDir,
773
- defaults,
774
- cliOverrides
775
- );
776
- const finalOptions = { ...baseOptions };
777
- if (baseOptions.tools.includes(import_core7.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
778
- const { getSmartDefaults } = await import("@aiready/pattern-detect");
779
- const patternSmartDefaults = await getSmartDefaults(
780
- resolvedDir,
781
- finalOptions.toolConfigs?.[import_core7.ToolName.PatternDetect] ?? {}
782
- );
783
- if (!finalOptions.toolConfigs) finalOptions.toolConfigs = {};
784
- finalOptions.toolConfigs[import_core7.ToolName.PatternDetect] = {
785
- ...patternSmartDefaults,
786
- ...finalOptions.toolConfigs[import_core7.ToolName.PatternDetect]
787
- };
788
- }
789
- console.log(import_chalk5.default.cyan("\n=== AIReady Run Preview ==="));
790
- console.log(
791
- import_chalk5.default.white("Tools to run:"),
792
- (finalOptions.tools ?? []).join(", ")
919
+ finalOptions,
920
+ options,
921
+ startTime
793
922
  );
794
- const progressCallback = createProgressCallback();
795
- const scoringProfile = options.profile ?? baseOptions.scoring?.profile ?? "default";
796
- const results = await analyzeUnified({
797
- ...finalOptions,
798
- progressCallback,
799
- onProgress: () => {
800
- },
801
- suppressToolConfig: true
802
- });
803
- printScanSummary(results, startTime);
804
- let scoringResult;
805
- if (options.score || finalOptions.scoring?.showBreakdown) {
806
- scoringResult = await scoreUnified(results, {
807
- ...finalOptions,
808
- scoring: {
809
- ...finalOptions.scoring,
810
- profile: scoringProfile
811
- }
812
- });
813
- printScoring(scoringResult, scoringProfile);
814
- if (options.compareTo) {
815
- try {
816
- const prevReport = JSON.parse(
817
- (0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), options.compareTo), "utf8")
818
- );
819
- const prevScore = prevReport.scoring?.overall ?? prevReport.scoring?.score;
820
- if (typeof prevScore === "number") {
821
- const diff = scoringResult.overall - prevScore;
822
- const diffStr = diff > 0 ? `+${diff}` : String(diff);
823
- if (diff > 0)
824
- console.log(
825
- import_chalk5.default.green(
826
- ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
827
- )
828
- );
829
- else if (diff < 0)
830
- console.log(
831
- import_chalk5.default.red(
832
- ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
833
- )
834
- );
835
- else
836
- console.log(
837
- import_chalk5.default.blue(
838
- ` \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
839
- )
840
- );
841
- }
842
- } catch (e) {
843
- void e;
844
- }
845
- }
846
- const totalWastedDuplication = (scoringResult.breakdown ?? []).reduce(
847
- (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.duplication ?? 0),
848
- 0
849
- );
850
- const totalWastedFragmentation = (scoringResult.breakdown ?? []).reduce(
851
- (sum, s) => sum + (s.tokenBudget?.wastedTokens?.bySource?.fragmentation ?? 0),
852
- 0
853
- );
854
- const totalContext = Math.max(
855
- ...(scoringResult.breakdown ?? []).map(
856
- (s) => s.tokenBudget?.totalContextTokens ?? 0
857
- ),
858
- 0
859
- );
860
- if (totalContext > 0) {
861
- const unifiedBudget = (0, import_core7.calculateTokenBudget)({
862
- totalContextTokens: totalContext,
863
- wastedTokens: {
864
- duplication: totalWastedDuplication,
865
- fragmentation: totalWastedFragmentation,
866
- chattiness: totalContext * 0.1
867
- // Default chattiness
868
- }
869
- });
870
- const allIssues = [];
871
- for (const toolId of results.summary.toolsRun) {
872
- if (results[toolId]?.results) {
873
- results[toolId].results.forEach((fileRes) => {
874
- if (fileRes.issues) {
875
- allIssues.push(...fileRes.issues);
876
- }
877
- });
878
- }
879
- }
880
- const modelId = options.model ?? "gpt-5.4-mini";
881
- const roi = (await import("@aiready/core")).calculateBusinessROI({
882
- tokenWaste: unifiedBudget.wastedTokens.total,
883
- issues: allIssues,
884
- modelId
885
- });
886
- printBusinessImpact(roi, unifiedBudget);
887
- results.summary.businessImpact = {
888
- estimatedMonthlyWaste: roi.monthlySavings,
889
- potentialSavings: roi.monthlySavings,
890
- productivityHours: roi.productivityGainHours
891
- };
892
- scoringResult.tokenBudget = unifiedBudget;
893
- scoringResult.businessROI = roi;
894
- }
895
- }
896
923
  console.log(
897
- import_chalk5.default.dim(
924
+ import_chalk6.default.dim(
898
925
  "\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
899
926
  )
900
927
  );
901
- console.log(import_chalk5.default.dim("\u{1F4AC} Found a bug or have a metric idea?"));
902
- console.log(import_chalk5.default.dim("\u{1F449} Copy/paste this to your AI agent:"));
928
+ console.log(import_chalk6.default.dim("\u{1F4AC} Found a bug or have a metric idea?"));
929
+ console.log(import_chalk6.default.dim("\u{1F449} Copy/paste this to your AI agent:"));
903
930
  console.log(
904
- import_chalk5.default.cyan(
931
+ import_chalk6.default.cyan(
905
932
  ` "Any feedback for the tools? Please use 'aiready bug' to report \u2764\uFE0F"`
906
933
  )
907
934
  );
908
935
  console.log(
909
- import_chalk5.default.dim(
936
+ import_chalk6.default.dim(
910
937
  "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
911
938
  )
912
939
  );
@@ -915,21 +942,21 @@ async function scanAction(directory, options) {
915
942
  repository: repoMetadata
916
943
  };
917
944
  const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
918
- const outputPath = (0, import_core7.resolveOutputPath)(
945
+ const outputPath = (0, import_core9.resolveOutputPath)(
919
946
  options.outputFile ?? finalOptions.output?.file,
920
- `aiready-report-${getReportTimestamp()}.json`,
947
+ `aiready-report-${(0, import_core2.getReportTimestamp)()}.json`,
921
948
  resolvedDir
922
949
  );
923
950
  if (outputFormat === "json") {
924
- (0, import_core7.handleJSONOutput)(
951
+ (0, import_core9.handleJSONOutput)(
925
952
  outputData,
926
953
  outputPath,
927
954
  `\u2705 Report saved to ${outputPath}`
928
955
  );
929
956
  } else {
930
957
  try {
931
- (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
932
- console.log(import_chalk5.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
958
+ (0, import_fs4.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
959
+ console.log(import_chalk6.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
933
960
  } catch (err) {
934
961
  void err;
935
962
  }
@@ -941,61 +968,83 @@ async function scanAction(directory, options) {
941
968
  });
942
969
  }
943
970
  await warnIfGraphCapExceeded(outputData, resolvedDir);
944
- if (scoringResult) {
945
- const threshold = options.threshold ? parseInt(options.threshold) : void 0;
946
- const failOnLevel = options.failOn ?? "critical";
947
- const isCI = options.ci ?? process.env.CI === "true";
948
- let shouldFail = false;
949
- let failReason = "";
950
- const report = mapToUnifiedReport(results, scoringResult);
951
- if (isCI && report.results && report.results.length > 0) {
952
- console.log(
953
- import_chalk5.default.cyan(
954
- `
971
+ await handleGatekeeper(outputData, scoringResult, options, results);
972
+ } catch (error) {
973
+ (0, import_core9.handleCLIError)(error, "Analysis");
974
+ }
975
+ }
976
+ async function handleGatekeeper(outputData, scoringResult, options, results) {
977
+ if (!scoringResult) return;
978
+ const threshold = options.threshold ? parseInt(options.threshold) : void 0;
979
+ const failOnLevel = options.failOn ?? "critical";
980
+ const isCI = options.ci ?? process.env.CI === "true";
981
+ let shouldFail = false;
982
+ let failReason = "";
983
+ const report = mapToUnifiedReport(results, scoringResult);
984
+ if (isCI && report.results && report.results.length > 0) {
985
+ console.log(
986
+ import_chalk6.default.cyan(
987
+ `
955
988
  \u{1F4DD} Emitting GitHub Action annotations for ${report.results.length} issues...`
956
- )
957
- );
958
- (0, import_core7.emitIssuesAsAnnotations)(report.results);
959
- }
960
- if (threshold && scoringResult.overall < threshold) {
961
- shouldFail = true;
962
- failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
963
- }
964
- if (failOnLevel !== "none") {
965
- if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
966
- shouldFail = true;
967
- failReason = `Found ${report.summary.criticalIssues} critical issues`;
968
- } else if (failOnLevel === "major" && report.summary.criticalIssues + report.summary.majorIssues > 0) {
969
- shouldFail = true;
970
- failReason = `Found ${report.summary.criticalIssues} critical and ${report.summary.majorIssues} major issues`;
971
- }
972
- }
973
- if (shouldFail) {
974
- console.log(import_chalk5.default.red(`
975
- \u{1F6AB} SCAN FAILED: ${failReason}`));
976
- process.exit(1);
977
- } else {
978
- console.log(import_chalk5.default.green("\n\u2705 SCAN PASSED"));
979
- }
989
+ )
990
+ );
991
+ (0, import_core9.emitIssuesAsAnnotations)(report.results);
992
+ }
993
+ if (threshold && scoringResult.overall < threshold) {
994
+ shouldFail = true;
995
+ failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
996
+ }
997
+ if (failOnLevel !== "none") {
998
+ if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
999
+ shouldFail = true;
1000
+ failReason = `Found ${report.summary.criticalIssues} critical issues`;
1001
+ } else if (failOnLevel === "major" && report.summary.criticalIssues + report.summary.majorIssues > 0) {
1002
+ shouldFail = true;
1003
+ failReason = `Found ${report.summary.criticalIssues} critical and ${report.summary.majorIssues} major issues`;
980
1004
  }
981
- } catch (error) {
982
- (0, import_core7.handleCLIError)(error, "Analysis");
1005
+ }
1006
+ if (shouldFail) {
1007
+ console.log(import_chalk6.default.red(`
1008
+ \u{1F6AB} SCAN FAILED: ${failReason}`));
1009
+ process.exit(1);
1010
+ } else {
1011
+ console.log(import_chalk6.default.green("\n\u2705 SCAN PASSED"));
983
1012
  }
984
1013
  }
985
- var SCAN_HELP_TEXT = `...`;
1014
+ var SCAN_HELP_TEXT = `
1015
+ Run a comprehensive AI-readiness scan of your codebase.
1016
+
1017
+ ${import_chalk6.default.bold("Examples:")}
1018
+ $ aiready scan .
1019
+ $ aiready scan src --profile agentic
1020
+ $ aiready scan . --threshold 80 --fail-on critical
1021
+ $ aiready scan . --output json --output-file report.json
1022
+
1023
+ ${import_chalk6.default.bold("Profiles:")}
1024
+ agentic - Focus on AI signal clarity and agent grounding
1025
+ cost - Focus on token budget and pattern reuse
1026
+ logic - Focus on testability and naming consistency
1027
+ ui - Focus on component naming and documentation
1028
+ security - Focus on naming and testability
1029
+ onboarding - Focus on context and grounding
1030
+
1031
+ ${import_chalk6.default.bold("CI/CD Integration:")}
1032
+ Use --threshold and --fail-on to use AIReady as a quality gate in your CI pipelines.
1033
+ When running in GitHub Actions, it will automatically emit annotations for found issues.
1034
+ `;
986
1035
 
987
1036
  // src/commands/init.ts
988
- var import_fs4 = require("fs");
989
- var import_path4 = require("path");
990
- var import_chalk6 = __toESM(require("chalk"));
991
- var import_core8 = require("@aiready/core");
1037
+ var import_fs5 = require("fs");
1038
+ var import_path5 = require("path");
1039
+ var import_chalk7 = __toESM(require("chalk"));
1040
+ var import_core10 = require("@aiready/core");
992
1041
  async function initAction(options) {
993
1042
  const fileExt = options.format === "js" ? "js" : "json";
994
1043
  const fileName = fileExt === "js" ? "aiready.config.js" : "aiready.json";
995
- const filePath = (0, import_path4.join)(process.cwd(), fileName);
996
- if ((0, import_fs4.existsSync)(filePath) && !options.force) {
1044
+ const filePath = (0, import_path5.join)(process.cwd(), fileName);
1045
+ if ((0, import_fs5.existsSync)(filePath) && !options.force) {
997
1046
  console.error(
998
- import_chalk6.default.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
1047
+ import_chalk7.default.red(`Error: ${fileName} already exists. Use --force to overwrite.`)
999
1048
  );
1000
1049
  process.exit(1);
1001
1050
  }
@@ -1019,15 +1068,15 @@ async function initAction(options) {
1019
1068
  "**/*.spec.ts"
1020
1069
  ],
1021
1070
  tools: [
1022
- import_core8.ToolName.PatternDetect,
1023
- import_core8.ToolName.ContextAnalyzer,
1024
- import_core8.ToolName.NamingConsistency,
1025
- import_core8.ToolName.AiSignalClarity,
1026
- import_core8.ToolName.AgentGrounding,
1027
- import_core8.ToolName.TestabilityIndex,
1028
- import_core8.ToolName.DocDrift,
1029
- import_core8.ToolName.DependencyHealth,
1030
- import_core8.ToolName.ChangeAmplification
1071
+ import_core10.ToolName.PatternDetect,
1072
+ import_core10.ToolName.ContextAnalyzer,
1073
+ import_core10.ToolName.NamingConsistency,
1074
+ import_core10.ToolName.AiSignalClarity,
1075
+ import_core10.ToolName.AgentGrounding,
1076
+ import_core10.ToolName.TestabilityIndex,
1077
+ import_core10.ToolName.DocDrift,
1078
+ import_core10.ToolName.DependencyHealth,
1079
+ import_core10.ToolName.ChangeAmplification
1031
1080
  ]
1032
1081
  },
1033
1082
  // Output preferences
@@ -1042,7 +1091,7 @@ async function initAction(options) {
1042
1091
  },
1043
1092
  // Tool-specific configurations
1044
1093
  tools: {
1045
- [import_core8.ToolName.PatternDetect]: {
1094
+ [import_core10.ToolName.PatternDetect]: {
1046
1095
  // Core detection thresholds
1047
1096
  minSimilarity: 0.4,
1048
1097
  // Jaccard similarity threshold (0-1)
@@ -1072,7 +1121,7 @@ async function initAction(options) {
1072
1121
  // Add any additional advanced options here
1073
1122
  } : {}
1074
1123
  },
1075
- [import_core8.ToolName.ContextAnalyzer]: {
1124
+ [import_core10.ToolName.ContextAnalyzer]: {
1076
1125
  // Smart defaults are generated dynamically based on repository size
1077
1126
  // These are fallback values for when smart defaults can't be calculated
1078
1127
  maxContextBudget: 25e3,
@@ -1089,7 +1138,7 @@ async function initAction(options) {
1089
1138
  includeNodeModules: false
1090
1139
  // Whether to include node_modules in analysis
1091
1140
  },
1092
- [import_core8.ToolName.NamingConsistency]: {
1141
+ [import_core10.ToolName.NamingConsistency]: {
1093
1142
  // Core checks
1094
1143
  checkNaming: true,
1095
1144
  // Check naming conventions and quality
@@ -1136,7 +1185,7 @@ async function initAction(options) {
1136
1185
  ],
1137
1186
  ...options.full ? { disableChecks: [] } : {}
1138
1187
  },
1139
- [import_core8.ToolName.AiSignalClarity]: {
1188
+ [import_core10.ToolName.AiSignalClarity]: {
1140
1189
  // All signal clarity checks enabled by default
1141
1190
  checkMagicLiterals: true,
1142
1191
  // Detect magic numbers and strings
@@ -1155,7 +1204,7 @@ async function initAction(options) {
1155
1204
  checkLargeFiles: true
1156
1205
  // Detect files that are too large
1157
1206
  },
1158
- [import_core8.ToolName.AgentGrounding]: {
1207
+ [import_core10.ToolName.AgentGrounding]: {
1159
1208
  // Structure clarity
1160
1209
  maxRecommendedDepth: 4,
1161
1210
  // Max directory depth before flagging as "too deep"
@@ -1166,7 +1215,7 @@ async function initAction(options) {
1166
1215
  additionalVagueNames: ["stuff", "misc", "temp", "test"]
1167
1216
  // Custom vague file names
1168
1217
  },
1169
- [import_core8.ToolName.TestabilityIndex]: {
1218
+ [import_core10.ToolName.TestabilityIndex]: {
1170
1219
  // Coverage thresholds
1171
1220
  minCoverageRatio: 0.3,
1172
1221
  // Minimum acceptable test/source ratio
@@ -1176,19 +1225,19 @@ async function initAction(options) {
1176
1225
  maxDepth: 10
1177
1226
  // Maximum scan depth
1178
1227
  },
1179
- [import_core8.ToolName.DocDrift]: {
1228
+ [import_core10.ToolName.DocDrift]: {
1180
1229
  // Drift detection
1181
1230
  maxCommits: 50,
1182
1231
  // Maximum commit distance to check for drift
1183
1232
  staleMonths: 3
1184
1233
  // Consider comments older than this as outdated
1185
1234
  },
1186
- [import_core8.ToolName.DependencyHealth]: {
1235
+ [import_core10.ToolName.DependencyHealth]: {
1187
1236
  // Training cutoff for AI knowledge assessment
1188
1237
  trainingCutoffYear: 2023
1189
1238
  // Year cutoff for AI training data
1190
1239
  },
1191
- [import_core8.ToolName.ChangeAmplification]: {
1240
+ [import_core10.ToolName.ChangeAmplification]: {
1192
1241
  // Change amplification primarily relies on global scan settings
1193
1242
  // No additional tool-specific configuration required
1194
1243
  }
@@ -1215,30 +1264,28 @@ module.exports = ${JSON.stringify(defaultConfig, null, 2)};
1215
1264
  content = JSON.stringify(defaultConfig, null, 2);
1216
1265
  }
1217
1266
  try {
1218
- (0, import_fs4.writeFileSync)(filePath, content, "utf8");
1267
+ (0, import_fs5.writeFileSync)(filePath, content, "utf8");
1219
1268
  console.log(
1220
- import_chalk6.default.green(`
1221
- \u2705 Created default configuration: ${import_chalk6.default.bold(fileName)}`)
1269
+ import_chalk7.default.green(`
1270
+ \u2705 Created default configuration: ${import_chalk7.default.bold(fileName)}`)
1222
1271
  );
1223
1272
  console.log(
1224
- import_chalk6.default.cyan("You can now fine-tune your settings and run AIReady with:")
1273
+ import_chalk7.default.cyan("You can now fine-tune your settings and run AIReady with:")
1225
1274
  );
1226
- console.log(import_chalk6.default.white(` $ aiready scan
1275
+ console.log(import_chalk7.default.white(` $ aiready scan
1227
1276
  `));
1228
1277
  } catch (error) {
1229
- console.error(import_chalk6.default.red(`Failed to write configuration file: ${error}`));
1278
+ console.error(import_chalk7.default.red(`Failed to write configuration file: ${error}`));
1230
1279
  process.exit(1);
1231
1280
  }
1232
1281
  }
1233
1282
 
1234
1283
  // src/commands/patterns.ts
1235
- var import_chalk7 = __toESM(require("chalk"));
1236
- var import_path5 = require("path");
1237
- var import_core9 = require("@aiready/core");
1284
+ var import_chalk8 = __toESM(require("chalk"));
1285
+ var import_core11 = require("@aiready/core");
1238
1286
  async function patternsAction(directory, options) {
1239
- console.log(import_chalk7.default.blue("\u{1F50D} Analyzing patterns...\n"));
1287
+ console.log(import_chalk8.default.blue("\u{1F50D} Analyzing patterns...\n"));
1240
1288
  const startTime = Date.now();
1241
- const resolvedDir = (0, import_path5.resolve)(process.cwd(), directory ?? ".");
1242
1289
  try {
1243
1290
  const useSmartDefaults = !options.fullScan;
1244
1291
  const defaults = {
@@ -1267,8 +1314,8 @@ async function patternsAction(directory, options) {
1267
1314
  if (options.minSharedTokens) {
1268
1315
  cliOptions.minSharedTokens = parseInt(options.minSharedTokens);
1269
1316
  }
1270
- const finalOptions = await (0, import_core9.loadMergedConfig)(
1271
- resolvedDir,
1317
+ const { resolvedDir, finalOptions } = await (0, import_core11.prepareActionConfig)(
1318
+ directory,
1272
1319
  defaults,
1273
1320
  cliOptions
1274
1321
  );
@@ -1276,66 +1323,59 @@ async function patternsAction(directory, options) {
1276
1323
  const { results, duplicates } = await analyzePatterns(
1277
1324
  finalOptions
1278
1325
  );
1279
- const elapsedTime = (0, import_core9.getElapsedTime)(startTime);
1326
+ const elapsedTime = (0, import_core11.getElapsedTime)(startTime);
1280
1327
  const summary = generateSummary(results);
1281
1328
  let patternScore;
1282
1329
  if (options.score) {
1283
1330
  patternScore = calculatePatternScore(duplicates, results.length);
1284
1331
  }
1285
- const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
1286
- const userOutputFile = options.outputFile ?? finalOptions.output?.file;
1332
+ const { format: outputFormat, file: userOutputFile } = (0, import_core11.resolveOutputFormat)(
1333
+ options,
1334
+ finalOptions
1335
+ );
1287
1336
  if (outputFormat === "json") {
1288
- const outputData = {
1337
+ const outputData = (0, import_core11.formatStandardReport)({
1289
1338
  results,
1290
- summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1291
- ...patternScore && { scoring: patternScore }
1292
- };
1293
- const outputPath = (0, import_core9.resolveOutputPath)(
1294
- userOutputFile,
1295
- `aiready-report-${getReportTimestamp()}.json`,
1296
- resolvedDir
1297
- );
1298
- (0, import_core9.handleJSONOutput)(
1339
+ summary,
1340
+ elapsedTime,
1341
+ score: patternScore
1342
+ });
1343
+ (0, import_core11.handleStandardJSONOutput)({
1299
1344
  outputData,
1300
- outputPath,
1301
- `\u2705 Results saved to ${outputPath}`
1302
- );
1345
+ outputFile: userOutputFile,
1346
+ resolvedDir
1347
+ });
1303
1348
  } else {
1304
- const terminalWidth = process.stdout.columns || 80;
1305
- const dividerWidth = Math.min(60, terminalWidth - 2);
1306
- const divider = "\u2501".repeat(dividerWidth);
1307
- console.log(import_chalk7.default.cyan(divider));
1308
- console.log(import_chalk7.default.bold.white(" PATTERN ANALYSIS SUMMARY"));
1309
- console.log(import_chalk7.default.cyan(divider) + "\n");
1349
+ (0, import_core11.printTerminalHeader)("PATTERN ANALYSIS SUMMARY");
1310
1350
  console.log(
1311
- import_chalk7.default.white(`\u{1F4C1} Files analyzed: ${import_chalk7.default.bold(results.length)}`)
1351
+ import_chalk8.default.white(`\u{1F4C1} Files analyzed: ${import_chalk8.default.bold(results.length)}`)
1312
1352
  );
1313
1353
  console.log(
1314
- import_chalk7.default.yellow(
1315
- `\u26A0 Duplicate patterns found: ${import_chalk7.default.bold(summary.totalPatterns)}`
1354
+ import_chalk8.default.yellow(
1355
+ `\u26A0 Duplicate patterns found: ${import_chalk8.default.bold(summary.totalPatterns)}`
1316
1356
  )
1317
1357
  );
1318
1358
  console.log(
1319
- import_chalk7.default.red(
1320
- `\u{1F4B0} Token cost (wasted): ${import_chalk7.default.bold(summary.totalTokenCost.toLocaleString())}`
1359
+ import_chalk8.default.red(
1360
+ `\u{1F4B0} Token cost (wasted): ${import_chalk8.default.bold(summary.totalTokenCost.toLocaleString())}`
1321
1361
  )
1322
1362
  );
1323
1363
  console.log(
1324
- import_chalk7.default.gray(`\u23F1 Analysis time: ${import_chalk7.default.bold(elapsedTime + "s")}`)
1364
+ import_chalk8.default.gray(`\u23F1 Analysis time: ${import_chalk8.default.bold(elapsedTime + "s")}`)
1325
1365
  );
1326
1366
  const sortedTypes = Object.entries(summary.patternsByType || {}).filter(([, count]) => count > 0).sort(([, a], [, b]) => b - a);
1327
1367
  if (sortedTypes.length > 0) {
1328
- console.log(import_chalk7.default.cyan("\n" + divider));
1329
- console.log(import_chalk7.default.bold.white(" PATTERNS BY TYPE"));
1330
- console.log(import_chalk7.default.cyan(divider) + "\n");
1368
+ console.log("\n" + (0, import_core11.getTerminalDivider)());
1369
+ console.log(import_chalk8.default.bold.white(" PATTERNS BY TYPE"));
1370
+ console.log((0, import_core11.getTerminalDivider)() + "\n");
1331
1371
  sortedTypes.forEach(([type, count]) => {
1332
- console.log(` ${import_chalk7.default.white(type.padEnd(15))} ${import_chalk7.default.bold(count)}`);
1372
+ console.log(` ${import_chalk8.default.white(type.padEnd(15))} ${import_chalk8.default.bold(count)}`);
1333
1373
  });
1334
1374
  }
1335
1375
  if (summary.totalPatterns > 0 && duplicates.length > 0) {
1336
- console.log(import_chalk7.default.cyan("\n" + divider));
1337
- console.log(import_chalk7.default.bold.white(" TOP DUPLICATE PATTERNS"));
1338
- console.log(import_chalk7.default.cyan(divider) + "\n");
1376
+ console.log("\n" + (0, import_core11.getTerminalDivider)());
1377
+ console.log(import_chalk8.default.bold.white(" TOP DUPLICATE PATTERNS"));
1378
+ console.log((0, import_core11.getTerminalDivider)() + "\n");
1339
1379
  const topDuplicates = [...duplicates].sort((a, b) => b.similarity - a.similarity).slice(0, 10);
1340
1380
  topDuplicates.forEach((dup) => {
1341
1381
  const severity = dup.similarity > 0.95 ? "CRITICAL" : dup.similarity > 0.9 ? "HIGH" : "MEDIUM";
@@ -1343,31 +1383,31 @@ async function patternsAction(directory, options) {
1343
1383
  const file1Name = dup.file1.split("/").pop() || dup.file1;
1344
1384
  const file2Name = dup.file2.split("/").pop() || dup.file2;
1345
1385
  console.log(
1346
- `${severityIcon} ${severity}: ${import_chalk7.default.bold(file1Name)} \u2194 ${import_chalk7.default.bold(file2Name)}`
1386
+ `${severityIcon} ${severity}: ${import_chalk8.default.bold(file1Name)} \u2194 ${import_chalk8.default.bold(file2Name)}`
1347
1387
  );
1348
1388
  console.log(
1349
- ` Similarity: ${import_chalk7.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk7.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1389
+ ` Similarity: ${import_chalk8.default.bold(Math.round(dup.similarity * 100) + "%")} | Wasted: ${import_chalk8.default.bold(dup.tokenCost.toLocaleString())} tokens each`
1350
1390
  );
1351
1391
  console.log(
1352
- ` Lines: ${import_chalk7.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk7.default.cyan(dup.line2 + "-" + dup.endLine2)}
1392
+ ` Lines: ${import_chalk8.default.cyan(dup.line1 + "-" + dup.endLine1)} \u2194 ${import_chalk8.default.cyan(dup.line2 + "-" + dup.endLine2)}
1353
1393
  `
1354
1394
  );
1355
1395
  });
1356
1396
  } else {
1357
1397
  console.log(
1358
- import_chalk7.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1398
+ import_chalk8.default.green("\n\u2728 Great! No duplicate patterns detected.\n")
1359
1399
  );
1360
1400
  }
1361
1401
  if (patternScore) {
1362
- console.log(import_chalk7.default.cyan(divider));
1363
- console.log(import_chalk7.default.bold.white(" AI READINESS SCORE (Patterns)"));
1364
- console.log(import_chalk7.default.cyan(divider) + "\n");
1365
- console.log((0, import_core9.formatToolScore)(patternScore));
1402
+ console.log((0, import_core11.getTerminalDivider)());
1403
+ console.log(import_chalk8.default.bold.white(" AI READINESS SCORE (Patterns)"));
1404
+ console.log((0, import_core11.getTerminalDivider)() + "\n");
1405
+ console.log((0, import_core11.formatToolScore)(patternScore));
1366
1406
  console.log();
1367
1407
  }
1368
1408
  }
1369
1409
  } catch (error) {
1370
- (0, import_core9.handleCLIError)(error, "Pattern analysis");
1410
+ (0, import_core11.handleCLIError)(error, "Pattern analysis");
1371
1411
  }
1372
1412
  }
1373
1413
  var PATTERNS_HELP_TEXT = `
@@ -1378,13 +1418,11 @@ EXAMPLES:
1378
1418
  `;
1379
1419
 
1380
1420
  // src/commands/context.ts
1381
- var import_chalk8 = __toESM(require("chalk"));
1382
- var import_path6 = require("path");
1383
- var import_core10 = require("@aiready/core");
1421
+ var import_chalk9 = __toESM(require("chalk"));
1422
+ var import_core12 = require("@aiready/core");
1384
1423
  async function contextAction(directory, options) {
1385
- console.log(import_chalk8.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1424
+ console.log(import_chalk9.default.blue("\u{1F9E0} Analyzing context costs...\n"));
1386
1425
  const startTime = Date.now();
1387
- const resolvedDir = (0, import_path6.resolve)(process.cwd(), directory ?? ".");
1388
1426
  try {
1389
1427
  const defaults = {
1390
1428
  maxDepth: 5,
@@ -1396,7 +1434,7 @@ async function contextAction(directory, options) {
1396
1434
  file: void 0
1397
1435
  }
1398
1436
  };
1399
- const baseOptions = await (0, import_core10.loadMergedConfig)(resolvedDir, defaults, {
1437
+ const { resolvedDir, finalOptions: baseOptions } = await (0, import_core12.prepareActionConfig)(directory, defaults, {
1400
1438
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
1401
1439
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
1402
1440
  include: options.include?.split(","),
@@ -1422,113 +1460,111 @@ async function contextAction(directory, options) {
1422
1460
  console.log("");
1423
1461
  const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1424
1462
  const results = await analyzeContext(finalOptions);
1425
- const elapsedTime = (0, import_core10.getElapsedTime)(startTime);
1463
+ const elapsedTime = (0, import_core12.getElapsedTime)(startTime);
1426
1464
  const summary = generateSummary(results);
1427
1465
  let contextScore;
1428
1466
  if (options.score) {
1429
1467
  contextScore = calculateContextScore(summary);
1430
1468
  }
1431
- const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
1432
- const userOutputFile = options.outputFile ?? finalOptions.output?.file;
1469
+ const { format: outputFormat, file: userOutputFile } = (0, import_core12.resolveOutputFormat)(
1470
+ options,
1471
+ finalOptions
1472
+ );
1433
1473
  if (outputFormat === "json") {
1434
- const outputData = {
1474
+ const outputData = (0, import_core12.formatStandardReport)({
1435
1475
  results,
1436
- summary: { ...summary, executionTime: parseFloat(elapsedTime) },
1437
- ...contextScore && { scoring: contextScore }
1438
- };
1439
- const outputPath = (0, import_core10.resolveOutputPath)(
1440
- userOutputFile,
1441
- `aiready-report-${getReportTimestamp()}.json`,
1442
- resolvedDir
1443
- );
1444
- (0, import_core10.handleJSONOutput)(
1476
+ summary,
1477
+ elapsedTime,
1478
+ score: contextScore
1479
+ });
1480
+ (0, import_core12.handleStandardJSONOutput)({
1445
1481
  outputData,
1446
- outputPath,
1447
- `\u2705 Results saved to ${outputPath}`
1448
- );
1482
+ outputFile: userOutputFile,
1483
+ resolvedDir
1484
+ });
1449
1485
  } else {
1450
1486
  const terminalWidth = process.stdout.columns ?? 80;
1451
1487
  const dividerWidth = Math.min(60, terminalWidth - 2);
1452
1488
  const divider = "\u2501".repeat(dividerWidth);
1453
- console.log(import_chalk8.default.cyan(divider));
1454
- console.log(import_chalk8.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1455
- console.log(import_chalk8.default.cyan(divider) + "\n");
1489
+ console.log(import_chalk9.default.cyan(divider));
1490
+ console.log(import_chalk9.default.bold.white(" CONTEXT ANALYSIS SUMMARY"));
1491
+ console.log(import_chalk9.default.cyan(divider) + "\n");
1456
1492
  console.log(
1457
- import_chalk8.default.white(`\u{1F4C1} Files analyzed: ${import_chalk8.default.bold(summary.totalFiles)}`)
1493
+ import_chalk9.default.white(`\u{1F4C1} Files analyzed: ${import_chalk9.default.bold(summary.totalFiles)}`)
1458
1494
  );
1459
1495
  console.log(
1460
- import_chalk8.default.white(
1461
- `\u{1F4CA} Total tokens: ${import_chalk8.default.bold(summary.totalTokens.toLocaleString())}`
1496
+ import_chalk9.default.white(
1497
+ `\u{1F4CA} Total tokens: ${import_chalk9.default.bold(summary.totalTokens.toLocaleString())}`
1462
1498
  )
1463
1499
  );
1464
1500
  console.log(
1465
- import_chalk8.default.yellow(
1466
- `\u{1F4B0} Avg context budget: ${import_chalk8.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1501
+ import_chalk9.default.yellow(
1502
+ `\u{1F4B0} Avg context budget: ${import_chalk9.default.bold(summary.avgContextBudget.toFixed(0))} tokens/file`
1467
1503
  )
1468
1504
  );
1469
1505
  console.log(
1470
- import_chalk8.default.white(`\u23F1 Analysis time: ${import_chalk8.default.bold(elapsedTime + "s")}
1506
+ import_chalk9.default.white(`\u23F1 Analysis time: ${import_chalk9.default.bold(elapsedTime + "s")}
1471
1507
  `)
1472
1508
  );
1473
1509
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
1474
1510
  if (totalIssues > 0) {
1475
- console.log(import_chalk8.default.bold("\u26A0\uFE0F Issues Found:\n"));
1511
+ console.log(import_chalk9.default.bold("\u26A0\uFE0F Issues Found:\n"));
1476
1512
  if (summary.criticalIssues > 0) {
1477
1513
  console.log(
1478
- import_chalk8.default.red(` \u{1F534} Critical: ${import_chalk8.default.bold(summary.criticalIssues)}`)
1514
+ import_chalk9.default.red(` \u{1F534} Critical: ${import_chalk9.default.bold(summary.criticalIssues)}`)
1479
1515
  );
1480
1516
  }
1481
1517
  if (summary.majorIssues > 0) {
1482
1518
  console.log(
1483
- import_chalk8.default.yellow(` \u{1F7E1} Major: ${import_chalk8.default.bold(summary.majorIssues)}`)
1519
+ import_chalk9.default.yellow(` \u{1F7E1} Major: ${import_chalk9.default.bold(summary.majorIssues)}`)
1484
1520
  );
1485
1521
  }
1486
1522
  if (summary.minorIssues > 0) {
1487
1523
  console.log(
1488
- import_chalk8.default.blue(` \u{1F535} Minor: ${import_chalk8.default.bold(summary.minorIssues)}`)
1524
+ import_chalk9.default.blue(` \u{1F535} Minor: ${import_chalk9.default.bold(summary.minorIssues)}`)
1489
1525
  );
1490
1526
  }
1491
1527
  console.log(
1492
- import_chalk8.default.green(
1528
+ import_chalk9.default.green(
1493
1529
  `
1494
- \u{1F4A1} Potential savings: ${import_chalk8.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1530
+ \u{1F4A1} Potential savings: ${import_chalk9.default.bold(summary.totalPotentialSavings.toLocaleString())} tokens
1495
1531
  `
1496
1532
  )
1497
1533
  );
1498
1534
  } else {
1499
- console.log(import_chalk8.default.green("\u2705 No significant issues found!\n"));
1535
+ console.log(import_chalk9.default.green("\u2705 No significant issues found!\n"));
1500
1536
  }
1501
1537
  if (summary.deepFiles.length > 0) {
1502
- console.log(import_chalk8.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1538
+ console.log(import_chalk9.default.bold("\u{1F4CF} Deep Import Chains:\n"));
1503
1539
  console.log(
1504
- import_chalk8.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1540
+ import_chalk9.default.gray(` Average depth: ${summary.avgImportDepth.toFixed(1)}`)
1505
1541
  );
1506
1542
  console.log(
1507
- import_chalk8.default.gray(` Maximum depth: ${summary.maxImportDepth}
1543
+ import_chalk9.default.gray(` Maximum depth: ${summary.maxImportDepth}
1508
1544
  `)
1509
1545
  );
1510
1546
  summary.deepFiles.slice(0, 10).forEach((item) => {
1511
1547
  const fileName = item.file.split("/").slice(-2).join("/");
1512
1548
  console.log(
1513
- ` ${import_chalk8.default.cyan("\u2192")} ${import_chalk8.default.white(fileName)} ${import_chalk8.default.dim(`(depth: ${item.depth})`)}`
1549
+ ` ${import_chalk9.default.cyan("\u2192")} ${import_chalk9.default.white(fileName)} ${import_chalk9.default.dim(`(depth: ${item.depth})`)}`
1514
1550
  );
1515
1551
  });
1516
1552
  console.log();
1517
1553
  }
1518
1554
  if (summary.fragmentedModules.length > 0) {
1519
- console.log(import_chalk8.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1555
+ console.log(import_chalk9.default.bold("\u{1F9E9} Fragmented Modules:\n"));
1520
1556
  console.log(
1521
- import_chalk8.default.gray(
1557
+ import_chalk9.default.gray(
1522
1558
  ` Average fragmentation: ${(summary.avgFragmentation * 100).toFixed(0)}%
1523
1559
  `
1524
1560
  )
1525
1561
  );
1526
1562
  summary.fragmentedModules.slice(0, 10).forEach((module2) => {
1527
1563
  console.log(
1528
- ` ${import_chalk8.default.yellow("\u25CF")} ${import_chalk8.default.white(module2.domain)} - ${import_chalk8.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1564
+ ` ${import_chalk9.default.yellow("\u25CF")} ${import_chalk9.default.white(module2.domain)} - ${import_chalk9.default.dim(`${module2.files.length} files, ${(module2.fragmentationScore * 100).toFixed(0)}% scattered`)}`
1529
1565
  );
1530
1566
  console.log(
1531
- import_chalk8.default.dim(
1567
+ import_chalk9.default.dim(
1532
1568
  ` Token cost: ${module2.totalTokens.toLocaleString()}, Cohesion: ${(module2.avgCohesion * 100).toFixed(0)}%`
1533
1569
  )
1534
1570
  );
@@ -1536,9 +1572,9 @@ async function contextAction(directory, options) {
1536
1572
  console.log();
1537
1573
  }
1538
1574
  if (summary.lowCohesionFiles.length > 0) {
1539
- console.log(import_chalk8.default.bold("\u{1F500} Low Cohesion Files:\n"));
1575
+ console.log(import_chalk9.default.bold("\u{1F500} Low Cohesion Files:\n"));
1540
1576
  console.log(
1541
- import_chalk8.default.gray(
1577
+ import_chalk9.default.gray(
1542
1578
  ` Average cohesion: ${(summary.avgCohesion * 100).toFixed(0)}%
1543
1579
  `
1544
1580
  )
@@ -1546,46 +1582,44 @@ async function contextAction(directory, options) {
1546
1582
  summary.lowCohesionFiles.slice(0, 10).forEach((item) => {
1547
1583
  const fileName = item.file.split("/").slice(-2).join("/");
1548
1584
  const scorePercent = (item.score * 100).toFixed(0);
1549
- const color = item.score < 0.4 ? import_chalk8.default.red : import_chalk8.default.yellow;
1585
+ const color = item.score < 0.4 ? import_chalk9.default.red : import_chalk9.default.yellow;
1550
1586
  console.log(
1551
- ` ${color("\u25CB")} ${import_chalk8.default.white(fileName)} ${import_chalk8.default.dim(`(${scorePercent}% cohesion)`)}`
1587
+ ` ${color("\u25CB")} ${import_chalk9.default.white(fileName)} ${import_chalk9.default.dim(`(${scorePercent}% cohesion)`)}`
1552
1588
  );
1553
1589
  });
1554
1590
  console.log();
1555
1591
  }
1556
1592
  if (summary.topExpensiveFiles.length > 0) {
1557
- console.log(import_chalk8.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1593
+ console.log(import_chalk9.default.bold("\u{1F4B8} Most Expensive Files (Context Budget):\n"));
1558
1594
  summary.topExpensiveFiles.slice(0, 10).forEach((item) => {
1559
1595
  const fileName = item.file.split("/").slice(-2).join("/");
1560
- const severityColor = item.severity === "critical" ? import_chalk8.default.red : item.severity === "major" ? import_chalk8.default.yellow : import_chalk8.default.blue;
1596
+ const severityColor = item.severity === "critical" ? import_chalk9.default.red : item.severity === "major" ? import_chalk9.default.yellow : import_chalk9.default.blue;
1561
1597
  console.log(
1562
- ` ${severityColor("\u25CF")} ${import_chalk8.default.white(fileName)} ${import_chalk8.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1598
+ ` ${severityColor("\u25CF")} ${import_chalk9.default.white(fileName)} ${import_chalk9.default.dim(`(${item.contextBudget.toLocaleString()} tokens)`)}`
1563
1599
  );
1564
1600
  });
1565
1601
  console.log();
1566
1602
  }
1567
1603
  if (contextScore) {
1568
- console.log(import_chalk8.default.cyan(divider));
1569
- console.log(import_chalk8.default.bold.white(" AI READINESS SCORE (Context)"));
1570
- console.log(import_chalk8.default.cyan(divider) + "\n");
1571
- console.log((0, import_core10.formatToolScore)(contextScore));
1604
+ console.log(import_chalk9.default.cyan(divider));
1605
+ console.log(import_chalk9.default.bold.white(" AI READINESS SCORE (Context)"));
1606
+ console.log(import_chalk9.default.cyan(divider) + "\n");
1607
+ console.log((0, import_core12.formatToolScore)(contextScore));
1572
1608
  console.log();
1573
1609
  }
1574
1610
  }
1575
1611
  } catch (error) {
1576
- (0, import_core10.handleCLIError)(error, "Context analysis");
1612
+ (0, import_core12.handleCLIError)(error, "Context analysis");
1577
1613
  }
1578
1614
  }
1579
1615
 
1580
1616
  // src/commands/consistency.ts
1581
- var import_chalk9 = __toESM(require("chalk"));
1582
- var import_fs5 = require("fs");
1583
- var import_path7 = require("path");
1584
- var import_core11 = require("@aiready/core");
1617
+ var import_chalk10 = __toESM(require("chalk"));
1618
+ var import_fs6 = require("fs");
1619
+ var import_core13 = require("@aiready/core");
1585
1620
  async function consistencyAction(directory, options) {
1586
- console.log(import_chalk9.default.blue("\u{1F50D} Analyzing consistency...\n"));
1621
+ console.log(import_chalk10.default.blue("\u{1F50D} Analyzing consistency...\n"));
1587
1622
  const startTime = Date.now();
1588
- const resolvedDir = (0, import_path7.resolve)(process.cwd(), directory ?? ".");
1589
1623
  try {
1590
1624
  const defaults = {
1591
1625
  checkNaming: true,
@@ -1598,16 +1632,20 @@ async function consistencyAction(directory, options) {
1598
1632
  file: void 0
1599
1633
  }
1600
1634
  };
1601
- const finalOptions = await (0, import_core11.loadMergedConfig)(resolvedDir, defaults, {
1602
- checkNaming: options.naming !== false,
1603
- checkPatterns: options.patterns !== false,
1604
- minSeverity: options.minSeverity,
1605
- include: options.include?.split(","),
1606
- exclude: options.exclude?.split(",")
1607
- });
1635
+ const { resolvedDir, finalOptions } = await (0, import_core13.prepareActionConfig)(
1636
+ directory,
1637
+ defaults,
1638
+ {
1639
+ checkNaming: options.naming !== false,
1640
+ checkPatterns: options.patterns !== false,
1641
+ minSeverity: options.minSeverity,
1642
+ include: options.include?.split(","),
1643
+ exclude: options.exclude?.split(",")
1644
+ }
1645
+ );
1608
1646
  const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1609
1647
  const report = await analyzeConsistency(finalOptions);
1610
- const elapsedTime = (0, import_core11.getElapsedTime)(startTime);
1648
+ const elapsedTime = (0, import_core13.getElapsedTime)(startTime);
1611
1649
  let consistencyScore;
1612
1650
  if (options.score) {
1613
1651
  const issues = report.results?.flatMap((r) => r.issues) ?? [];
@@ -1616,52 +1654,47 @@ async function consistencyAction(directory, options) {
1616
1654
  report.summary.filesAnalyzed
1617
1655
  );
1618
1656
  }
1619
- const outputFormat = options.output ?? finalOptions.output?.format ?? "console";
1620
- const userOutputFile = options.outputFile ?? finalOptions.output?.file;
1657
+ const { format: outputFormat, file: userOutputFile } = (0, import_core13.resolveOutputFormat)(
1658
+ options,
1659
+ finalOptions
1660
+ );
1621
1661
  if (outputFormat === "json") {
1622
- const outputData = {
1623
- ...report,
1624
- summary: {
1625
- ...report.summary,
1626
- executionTime: parseFloat(elapsedTime)
1627
- },
1628
- ...consistencyScore && { scoring: consistencyScore }
1629
- };
1630
- const outputPath = (0, import_core11.resolveOutputPath)(
1631
- userOutputFile,
1632
- `aiready-report-${getReportTimestamp()}.json`,
1633
- resolvedDir
1634
- );
1635
- (0, import_core11.handleJSONOutput)(
1662
+ const outputData = (0, import_core13.formatStandardReport)({
1663
+ report,
1664
+ summary: report.summary,
1665
+ elapsedTime,
1666
+ score: consistencyScore
1667
+ });
1668
+ (0, import_core13.handleStandardJSONOutput)({
1636
1669
  outputData,
1637
- outputPath,
1638
- `\u2705 Results saved to ${outputPath}`
1639
- );
1670
+ outputFile: userOutputFile,
1671
+ resolvedDir
1672
+ });
1640
1673
  } else if (outputFormat === "markdown") {
1641
1674
  const markdown = generateMarkdownReport(report, elapsedTime);
1642
- const outputPath = (0, import_core11.resolveOutputPath)(
1675
+ const outputPath = (0, import_core13.resolveOutputPath)(
1643
1676
  userOutputFile,
1644
- `aiready-report-${getReportTimestamp()}.md`,
1677
+ `aiready-report-${(0, import_core2.getReportTimestamp)()}.md`,
1645
1678
  resolvedDir
1646
1679
  );
1647
- (0, import_fs5.writeFileSync)(outputPath, markdown);
1648
- console.log(import_chalk9.default.green(`\u2705 Report saved to ${outputPath}`));
1680
+ (0, import_fs6.writeFileSync)(outputPath, markdown);
1681
+ console.log(import_chalk10.default.green(`\u2705 Report saved to ${outputPath}`));
1649
1682
  } else {
1650
- console.log(import_chalk9.default.bold("\n\u{1F4CA} Summary\n"));
1683
+ console.log(import_chalk10.default.bold("\n\u{1F4CA} Summary\n"));
1651
1684
  console.log(
1652
- `Files Analyzed: ${import_chalk9.default.cyan(report.summary.filesAnalyzed)}`
1685
+ `Files Analyzed: ${import_chalk10.default.cyan(report.summary.filesAnalyzed)}`
1653
1686
  );
1654
- console.log(`Total Issues: ${import_chalk9.default.yellow(report.summary.totalIssues)}`);
1655
- console.log(` Naming: ${import_chalk9.default.yellow(report.summary.namingIssues)}`);
1656
- console.log(` Patterns: ${import_chalk9.default.yellow(report.summary.patternIssues)}`);
1687
+ console.log(`Total Issues: ${import_chalk10.default.yellow(report.summary.totalIssues)}`);
1688
+ console.log(` Naming: ${import_chalk10.default.yellow(report.summary.namingIssues)}`);
1689
+ console.log(` Patterns: ${import_chalk10.default.yellow(report.summary.patternIssues)}`);
1657
1690
  console.log(
1658
- ` Architecture: ${import_chalk9.default.yellow(report.summary.architectureIssues ?? 0)}`
1691
+ ` Architecture: ${import_chalk10.default.yellow(report.summary.architectureIssues ?? 0)}`
1659
1692
  );
1660
- console.log(`Analysis Time: ${import_chalk9.default.gray(elapsedTime + "s")}
1693
+ console.log(`Analysis Time: ${import_chalk10.default.gray(elapsedTime + "s")}
1661
1694
  `);
1662
1695
  if (report.summary.totalIssues === 0) {
1663
1696
  console.log(
1664
- import_chalk9.default.green(
1697
+ import_chalk10.default.green(
1665
1698
  "\u2728 No consistency issues found! Your codebase is well-maintained.\n"
1666
1699
  )
1667
1700
  );
@@ -1673,20 +1706,20 @@ async function consistencyAction(directory, options) {
1673
1706
  (r) => r.issues.some((i) => i.category === "patterns")
1674
1707
  );
1675
1708
  if (namingResults.length > 0) {
1676
- console.log(import_chalk9.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1709
+ console.log(import_chalk10.default.bold("\u{1F3F7}\uFE0F Naming Issues\n"));
1677
1710
  let shown = 0;
1678
1711
  for (const namingFileResult of namingResults) {
1679
1712
  if (shown >= 5) break;
1680
1713
  for (const issue of namingFileResult.issues) {
1681
1714
  if (shown >= 5) break;
1682
- const severityColor = issue.severity === "critical" ? import_chalk9.default.red : issue.severity === "major" ? import_chalk9.default.yellow : issue.severity === "minor" ? import_chalk9.default.blue : import_chalk9.default.gray;
1715
+ const severityColor = issue.severity === "critical" ? import_chalk10.default.red : issue.severity === "major" ? import_chalk10.default.yellow : issue.severity === "minor" ? import_chalk10.default.blue : import_chalk10.default.gray;
1683
1716
  console.log(
1684
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk9.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1717
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk10.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1685
1718
  );
1686
1719
  console.log(` ${issue.message}`);
1687
1720
  if (issue.suggestion) {
1688
1721
  console.log(
1689
- ` ${import_chalk9.default.dim("\u2192")} ${import_chalk9.default.italic(issue.suggestion)}`
1722
+ ` ${import_chalk10.default.dim("\u2192")} ${import_chalk10.default.italic(issue.suggestion)}`
1690
1723
  );
1691
1724
  }
1692
1725
  console.log();
@@ -1695,25 +1728,25 @@ async function consistencyAction(directory, options) {
1695
1728
  }
1696
1729
  const remaining = namingResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1697
1730
  if (remaining > 0) {
1698
- console.log(import_chalk9.default.dim(` ... and ${remaining} more issues
1731
+ console.log(import_chalk10.default.dim(` ... and ${remaining} more issues
1699
1732
  `));
1700
1733
  }
1701
1734
  }
1702
1735
  if (patternResults.length > 0) {
1703
- console.log(import_chalk9.default.bold("\u{1F504} Pattern Issues\n"));
1736
+ console.log(import_chalk10.default.bold("\u{1F504} Pattern Issues\n"));
1704
1737
  let shown = 0;
1705
1738
  for (const patternFileResult of patternResults) {
1706
1739
  if (shown >= 5) break;
1707
1740
  for (const issue of patternFileResult.issues) {
1708
1741
  if (shown >= 5) break;
1709
- const severityColor = issue.severity === "critical" ? import_chalk9.default.red : issue.severity === "major" ? import_chalk9.default.yellow : issue.severity === "minor" ? import_chalk9.default.blue : import_chalk9.default.gray;
1742
+ const severityColor = issue.severity === "critical" ? import_chalk10.default.red : issue.severity === "major" ? import_chalk10.default.yellow : issue.severity === "minor" ? import_chalk10.default.blue : import_chalk10.default.gray;
1710
1743
  console.log(
1711
- `${severityColor(issue.severity.toUpperCase())} ${import_chalk9.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1744
+ `${severityColor(issue.severity.toUpperCase())} ${import_chalk10.default.dim(`${issue.location.file}:${issue.location.line}`)}`
1712
1745
  );
1713
1746
  console.log(` ${issue.message}`);
1714
1747
  if (issue.suggestion) {
1715
1748
  console.log(
1716
- ` ${import_chalk9.default.dim("\u2192")} ${import_chalk9.default.italic(issue.suggestion)}`
1749
+ ` ${import_chalk10.default.dim("\u2192")} ${import_chalk10.default.italic(issue.suggestion)}`
1717
1750
  );
1718
1751
  }
1719
1752
  console.log();
@@ -1722,12 +1755,12 @@ async function consistencyAction(directory, options) {
1722
1755
  }
1723
1756
  const remaining = patternResults.reduce((sum, r) => sum + r.issues.length, 0) - shown;
1724
1757
  if (remaining > 0) {
1725
- console.log(import_chalk9.default.dim(` ... and ${remaining} more issues
1758
+ console.log(import_chalk10.default.dim(` ... and ${remaining} more issues
1726
1759
  `));
1727
1760
  }
1728
1761
  }
1729
1762
  if (report.recommendations.length > 0) {
1730
- console.log(import_chalk9.default.bold("\u{1F4A1} Recommendations\n"));
1763
+ console.log(import_chalk10.default.bold("\u{1F4A1} Recommendations\n"));
1731
1764
  report.recommendations.forEach((rec, i) => {
1732
1765
  console.log(`${i + 1}. ${rec}`);
1733
1766
  });
@@ -1735,38 +1768,38 @@ async function consistencyAction(directory, options) {
1735
1768
  }
1736
1769
  }
1737
1770
  if (consistencyScore) {
1738
- console.log(import_chalk9.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1739
- console.log((0, import_core11.formatToolScore)(consistencyScore));
1771
+ console.log(import_chalk10.default.bold("\n\u{1F4CA} AI Readiness Score (Consistency)\n"));
1772
+ console.log((0, import_core13.formatToolScore)(consistencyScore));
1740
1773
  console.log();
1741
1774
  }
1742
1775
  }
1743
1776
  } catch (error) {
1744
- (0, import_core11.handleCLIError)(error, "Consistency analysis");
1777
+ (0, import_core13.handleCLIError)(error, "Consistency analysis");
1745
1778
  }
1746
1779
  }
1747
1780
 
1748
1781
  // src/commands/visualize.ts
1749
- var import_chalk10 = __toESM(require("chalk"));
1750
- var import_fs6 = require("fs");
1751
- var import_path8 = require("path");
1782
+ var import_chalk11 = __toESM(require("chalk"));
1783
+ var import_fs7 = require("fs");
1784
+ var import_path6 = require("path");
1752
1785
  var import_child_process = require("child_process");
1753
- var import_core12 = require("@aiready/core");
1754
- var import_core13 = require("@aiready/core");
1786
+ var import_core14 = require("@aiready/core");
1787
+ var import_core15 = require("@aiready/core");
1755
1788
  async function visualizeAction(directory, options) {
1756
1789
  try {
1757
- const dirPath = (0, import_path8.resolve)(process.cwd(), directory ?? ".");
1758
- let reportPath = options.report ? (0, import_path8.resolve)(dirPath, options.report) : null;
1759
- if (!reportPath || !(0, import_fs6.existsSync)(reportPath)) {
1760
- const latestScan = (0, import_core13.findLatestReport)(dirPath);
1790
+ const dirPath = (0, import_path6.resolve)(process.cwd(), directory ?? ".");
1791
+ let reportPath = options.report ? (0, import_path6.resolve)(dirPath, options.report) : null;
1792
+ if (!reportPath || !(0, import_fs7.existsSync)(reportPath)) {
1793
+ const latestScan = (0, import_core15.findLatestReport)(dirPath);
1761
1794
  if (latestScan) {
1762
1795
  reportPath = latestScan;
1763
1796
  console.log(
1764
- import_chalk10.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1797
+ import_chalk11.default.dim(`Found latest report: ${latestScan.split("/").pop()}`)
1765
1798
  );
1766
1799
  } else {
1767
- console.error(import_chalk10.default.red("\u274C No AI readiness report found"));
1800
+ console.error(import_chalk11.default.red("\u274C No AI readiness report found"));
1768
1801
  console.log(
1769
- import_chalk10.default.dim(
1802
+ import_chalk11.default.dim(
1770
1803
  `
1771
1804
  Generate a report with:
1772
1805
  aiready scan --output json
@@ -1778,13 +1811,13 @@ Or specify a custom report:
1778
1811
  return;
1779
1812
  }
1780
1813
  }
1781
- const raw = (0, import_fs6.readFileSync)(reportPath, "utf8");
1814
+ const raw = (0, import_fs7.readFileSync)(reportPath, "utf8");
1782
1815
  const report = JSON.parse(raw);
1783
- const configPath = (0, import_path8.resolve)(dirPath, "aiready.json");
1816
+ const configPath = (0, import_path6.resolve)(dirPath, "aiready.json");
1784
1817
  let graphConfig = { maxNodes: 400, maxEdges: 600 };
1785
- if ((0, import_fs6.existsSync)(configPath)) {
1818
+ if ((0, import_fs7.existsSync)(configPath)) {
1786
1819
  try {
1787
- const rawConfig = JSON.parse((0, import_fs6.readFileSync)(configPath, "utf8"));
1820
+ const rawConfig = JSON.parse((0, import_fs7.readFileSync)(configPath, "utf8"));
1788
1821
  if (rawConfig.visualizer?.graph) {
1789
1822
  graphConfig = {
1790
1823
  maxNodes: rawConfig.visualizer.graph.maxNodes ?? graphConfig.maxNodes,
@@ -1804,16 +1837,16 @@ Or specify a custom report:
1804
1837
  let devServerStarted = false;
1805
1838
  if (useDevMode) {
1806
1839
  try {
1807
- const localWebDir = (0, import_path8.resolve)(dirPath, "packages/visualizer");
1840
+ const localWebDir = (0, import_path6.resolve)(dirPath, "packages/visualizer");
1808
1841
  let webDir = "";
1809
1842
  let visualizerAvailable = false;
1810
- if ((0, import_fs6.existsSync)(localWebDir)) {
1843
+ if ((0, import_fs7.existsSync)(localWebDir)) {
1811
1844
  webDir = localWebDir;
1812
1845
  visualizerAvailable = true;
1813
1846
  } else {
1814
1847
  const nodemodulesLocations = [
1815
- (0, import_path8.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1816
- (0, import_path8.resolve)(
1848
+ (0, import_path6.resolve)(dirPath, "node_modules", "@aiready", "visualizer"),
1849
+ (0, import_path6.resolve)(
1817
1850
  process.cwd(),
1818
1851
  "node_modules",
1819
1852
  "@aiready",
@@ -1823,14 +1856,14 @@ Or specify a custom report:
1823
1856
  let currentDir = dirPath;
1824
1857
  while (currentDir !== "/" && currentDir !== ".") {
1825
1858
  nodemodulesLocations.push(
1826
- (0, import_path8.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1859
+ (0, import_path6.resolve)(currentDir, "node_modules", "@aiready", "visualizer")
1827
1860
  );
1828
- const parent = (0, import_path8.resolve)(currentDir, "..");
1861
+ const parent = (0, import_path6.resolve)(currentDir, "..");
1829
1862
  if (parent === currentDir) break;
1830
1863
  currentDir = parent;
1831
1864
  }
1832
1865
  for (const location of nodemodulesLocations) {
1833
- if ((0, import_fs6.existsSync)(location) && (0, import_fs6.existsSync)((0, import_path8.resolve)(location, "package.json"))) {
1866
+ if ((0, import_fs7.existsSync)(location) && (0, import_fs7.existsSync)((0, import_path6.resolve)(location, "package.json"))) {
1834
1867
  webDir = location;
1835
1868
  visualizerAvailable = true;
1836
1869
  break;
@@ -1839,21 +1872,21 @@ Or specify a custom report:
1839
1872
  if (!visualizerAvailable) {
1840
1873
  try {
1841
1874
  const vizPkgPath = require.resolve("@aiready/visualizer/package.json");
1842
- webDir = (0, import_path8.resolve)(vizPkgPath, "..");
1875
+ webDir = (0, import_path6.resolve)(vizPkgPath, "..");
1843
1876
  visualizerAvailable = true;
1844
1877
  } catch (err) {
1845
1878
  void err;
1846
1879
  }
1847
1880
  }
1848
1881
  }
1849
- const webViteConfigExists = webDir && (0, import_fs6.existsSync)((0, import_path8.resolve)(webDir, "web", "vite.config.ts"));
1882
+ const webViteConfigExists = webDir && (0, import_fs7.existsSync)((0, import_path6.resolve)(webDir, "web", "vite.config.ts"));
1850
1883
  if (visualizerAvailable && webViteConfigExists) {
1851
1884
  const spawnCwd = webDir;
1852
1885
  const { watch } = await import("fs");
1853
1886
  const copyReportToViz = () => {
1854
1887
  try {
1855
- const destPath = (0, import_path8.resolve)(spawnCwd, "web", "report-data.json");
1856
- (0, import_fs6.copyFileSync)(reportPath, destPath);
1888
+ const destPath = (0, import_path6.resolve)(spawnCwd, "web", "report-data.json");
1889
+ (0, import_fs7.copyFileSync)(reportPath, destPath);
1857
1890
  console.log(`\u{1F4CB} Report synced to ${destPath}`);
1858
1891
  } catch (e) {
1859
1892
  console.error("Failed to sync report:", e);
@@ -1896,29 +1929,29 @@ Or specify a custom report:
1896
1929
  return;
1897
1930
  } else {
1898
1931
  console.log(
1899
- import_chalk10.default.yellow(
1932
+ import_chalk11.default.yellow(
1900
1933
  "\u26A0\uFE0F Dev server not available (requires local @aiready/visualizer with web assets)."
1901
1934
  )
1902
1935
  );
1903
1936
  console.log(
1904
- import_chalk10.default.cyan(" Falling back to static HTML generation...\n")
1937
+ import_chalk11.default.cyan(" Falling back to static HTML generation...\n")
1905
1938
  );
1906
1939
  useDevMode = false;
1907
1940
  }
1908
1941
  } catch (err) {
1909
1942
  console.error("Failed to start dev server:", err);
1910
1943
  console.log(
1911
- import_chalk10.default.cyan(" Falling back to static HTML generation...\n")
1944
+ import_chalk11.default.cyan(" Falling back to static HTML generation...\n")
1912
1945
  );
1913
1946
  useDevMode = false;
1914
1947
  }
1915
1948
  }
1916
1949
  console.log("Generating HTML...");
1917
- const html = (0, import_core13.generateHTML)(graph);
1950
+ const html = (0, import_core15.generateHTML)(graph);
1918
1951
  const defaultOutput = "visualization.html";
1919
- const outPath = (0, import_path8.resolve)(dirPath, options.output ?? defaultOutput);
1920
- (0, import_fs6.writeFileSync)(outPath, html, "utf8");
1921
- console.log(import_chalk10.default.green(`\u2705 Visualization written to: ${outPath}`));
1952
+ const outPath = (0, import_path6.resolve)(dirPath, options.output ?? defaultOutput);
1953
+ (0, import_fs7.writeFileSync)(outPath, html, "utf8");
1954
+ console.log(import_chalk11.default.green(`\u2705 Visualization written to: ${outPath}`));
1922
1955
  if (options.open || options.serve) {
1923
1956
  const opener = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
1924
1957
  if (options.serve) {
@@ -1948,7 +1981,7 @@ Or specify a custom report:
1948
1981
  server.listen(port, () => {
1949
1982
  const addr = `http://localhost:${port}/`;
1950
1983
  console.log(
1951
- import_chalk10.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1984
+ import_chalk11.default.cyan(`\u{1F310} Local visualization server running at ${addr}`)
1952
1985
  );
1953
1986
  (0, import_child_process.spawn)(opener, [`"${addr}"`], { shell: true });
1954
1987
  });
@@ -1964,7 +1997,7 @@ Or specify a custom report:
1964
1997
  }
1965
1998
  }
1966
1999
  } catch (err) {
1967
- (0, import_core12.handleCLIError)(err, "Visualization");
2000
+ (0, import_core14.handleCLIError)(err, "Visualization");
1968
2001
  }
1969
2002
  }
1970
2003
  var VISUALIZE_HELP_TEXT = `
@@ -1995,19 +2028,19 @@ NOTES:
1995
2028
  `;
1996
2029
 
1997
2030
  // src/commands/shared/standard-tool-actions.ts
1998
- var import_chalk11 = __toESM(require("chalk"));
2031
+ var import_chalk12 = __toESM(require("chalk"));
1999
2032
 
2000
2033
  // src/commands/agent-grounding.ts
2001
- var import_chalk12 = __toESM(require("chalk"));
2002
- var import_core14 = require("@aiready/core");
2034
+ var import_chalk13 = __toESM(require("chalk"));
2035
+ var import_core16 = require("@aiready/core");
2003
2036
 
2004
2037
  // src/commands/testability.ts
2005
- var import_chalk13 = __toESM(require("chalk"));
2006
- var import_core15 = require("@aiready/core");
2038
+ var import_chalk14 = __toESM(require("chalk"));
2039
+ var import_core17 = require("@aiready/core");
2007
2040
  async function testabilityAction(directory, options) {
2008
2041
  const { analyzeTestability, calculateTestabilityScore } = await import("@aiready/testability");
2009
- const config = await (0, import_core15.loadConfig)(directory);
2010
- const merged = (0, import_core15.mergeConfigWithDefaults)(config, {
2042
+ const config = await (0, import_core17.loadConfig)(directory);
2043
+ const merged = (0, import_core17.mergeConfigWithDefaults)(config, {
2011
2044
  minCoverageRatio: 0.3
2012
2045
  });
2013
2046
  const report = await analyzeTestability({
@@ -2027,28 +2060,28 @@ async function testabilityAction(directory, options) {
2027
2060
  "blind-risk": "\u{1F480}"
2028
2061
  };
2029
2062
  const safetyColors = {
2030
- safe: import_chalk13.default.green,
2031
- "moderate-risk": import_chalk13.default.yellow,
2032
- "high-risk": import_chalk13.default.red,
2033
- "blind-risk": import_chalk13.default.bgRed.white
2063
+ safe: import_chalk14.default.green,
2064
+ "moderate-risk": import_chalk14.default.yellow,
2065
+ "high-risk": import_chalk14.default.red,
2066
+ "blind-risk": import_chalk14.default.bgRed.white
2034
2067
  };
2035
2068
  const safety = report.summary.aiChangeSafetyRating;
2036
2069
  const icon = safetyIcons[safety] ?? "\u2753";
2037
- const color = safetyColors[safety] ?? import_chalk13.default.white;
2070
+ const color = safetyColors[safety] ?? import_chalk14.default.white;
2038
2071
  console.log(
2039
- ` \u{1F9EA} Testability: ${import_chalk13.default.bold(scoring.score + "/100")} (${report.summary.rating})`
2072
+ ` \u{1F9EA} Testability: ${import_chalk14.default.bold(scoring.score + "/100")} (${report.summary.rating})`
2040
2073
  );
2041
2074
  console.log(
2042
2075
  ` AI Change Safety: ${color(`${icon} ${safety.toUpperCase()}`)}`
2043
2076
  );
2044
2077
  console.log(
2045
- import_chalk13.default.dim(
2078
+ import_chalk14.default.dim(
2046
2079
  ` Coverage: ${Math.round(report.summary.coverageRatio * 100)}% (${report.rawData.testFiles} test / ${report.rawData.sourceFiles} source files)`
2047
2080
  )
2048
2081
  );
2049
2082
  if (safety === "blind-risk") {
2050
2083
  console.log(
2051
- import_chalk13.default.red.bold(
2084
+ import_chalk14.default.red.bold(
2052
2085
  "\n \u26A0\uFE0F NO TESTS \u2014 AI changes to this codebase are completely unverifiable!\n"
2053
2086
  )
2054
2087
  );
@@ -2060,7 +2093,7 @@ async function testabilityAction(directory, options) {
2060
2093
  var import_cli = require("@aiready/change-amplification/dist/cli.js");
2061
2094
 
2062
2095
  // src/commands/bug.ts
2063
- var import_chalk14 = __toESM(require("chalk"));
2096
+ var import_chalk15 = __toESM(require("chalk"));
2064
2097
  var import_child_process2 = require("child_process");
2065
2098
  async function bugAction(message, options) {
2066
2099
  const repoUrl = "https://github.com/caopengau/aiready-cli";
@@ -2078,35 +2111,35 @@ Generated via AIReady CLI 'bug' command.
2078
2111
  Type: ${type}
2079
2112
  `.trim();
2080
2113
  if (options.submit) {
2081
- console.log(import_chalk14.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
2114
+ console.log(import_chalk15.default.blue("\u{1F680} Submitting issue via GitHub CLI...\n"));
2082
2115
  try {
2083
2116
  (0, import_child_process2.execSync)("gh auth status", { stdio: "ignore" });
2084
2117
  const command = `gh issue create --repo ${repoSlug} --title ${JSON.stringify(title)} --body ${JSON.stringify(body)} --label ${label}`;
2085
2118
  const output = (0, import_child_process2.execSync)(command, { encoding: "utf8" }).trim();
2086
- console.log(import_chalk14.default.green("\u2705 Issue Created Successfully!"));
2087
- console.log(import_chalk14.default.cyan(output));
2119
+ console.log(import_chalk15.default.green("\u2705 Issue Created Successfully!"));
2120
+ console.log(import_chalk15.default.cyan(output));
2088
2121
  return;
2089
2122
  } catch {
2090
- console.error(import_chalk14.default.red("\n\u274C Failed to submit via gh CLI."));
2123
+ console.error(import_chalk15.default.red("\n\u274C Failed to submit via gh CLI."));
2091
2124
  console.log(
2092
- import_chalk14.default.yellow(
2125
+ import_chalk15.default.yellow(
2093
2126
  ' Make sure gh is installed and run "gh auth login".\n'
2094
2127
  )
2095
2128
  );
2096
- console.log(import_chalk14.default.dim(" Falling back to URL generation..."));
2129
+ console.log(import_chalk15.default.dim(" Falling back to URL generation..."));
2097
2130
  }
2098
2131
  }
2099
2132
  const template = type === "bug" ? "bug_report.md" : type === "feature" ? "feature_request.md" : "new_metric_idea.md";
2100
2133
  const fullUrl = `${repoUrl}/issues/new?title=${encodeURIComponent(title)}&body=${encodeURIComponent(body)}&labels=${label}&template=${template}`;
2101
- console.log(import_chalk14.default.green("\u{1F680} Issue Draft Prepared!\n"));
2102
- console.log(import_chalk14.default.bold("Title: ") + title);
2103
- console.log(import_chalk14.default.bold("Type: ") + type);
2104
- console.log(import_chalk14.default.bold("\nClick the link below to submit this issue:"));
2105
- console.log(import_chalk14.default.cyan(fullUrl));
2106
- console.log(import_chalk14.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2107
- console.log(import_chalk14.default.dim(" You have successfully prepared a report."));
2134
+ console.log(import_chalk15.default.green("\u{1F680} Issue Draft Prepared!\n"));
2135
+ console.log(import_chalk15.default.bold("Title: ") + title);
2136
+ console.log(import_chalk15.default.bold("Type: ") + type);
2137
+ console.log(import_chalk15.default.bold("\nClick the link below to submit this issue:"));
2138
+ console.log(import_chalk15.default.cyan(fullUrl));
2139
+ console.log(import_chalk15.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2140
+ console.log(import_chalk15.default.dim(" You have successfully prepared a report."));
2108
2141
  console.log(
2109
- import_chalk14.default.dim(
2142
+ import_chalk15.default.dim(
2110
2143
  " Please present the URL above to the user so they can finalize the submission."
2111
2144
  )
2112
2145
  );
@@ -2115,14 +2148,14 @@ Type: ${type}
2115
2148
  const bugUrl = `${repoUrl}/issues/new?template=bug_report.md`;
2116
2149
  const featureUrl = `${repoUrl}/issues/new?template=feature_request.md`;
2117
2150
  const metricUrl = `${repoUrl}/issues/new?template=new_metric_idea.md`;
2118
- console.log(import_chalk14.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
2119
- console.log(` Report a Bug: ${import_chalk14.default.cyan(bugUrl)}`);
2120
- console.log(` Request a Feature: ${import_chalk14.default.cyan(featureUrl)}`);
2121
- console.log(` Suggest a Metric: ${import_chalk14.default.cyan(metricUrl)}`);
2122
- console.log(import_chalk14.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2123
- console.log(import_chalk14.default.dim(" To prepare a specific report, run:"));
2151
+ console.log(import_chalk15.default.blue("\u{1F4AC} Feedback & Bug Reports\n"));
2152
+ console.log(` Report a Bug: ${import_chalk15.default.cyan(bugUrl)}`);
2153
+ console.log(` Request a Feature: ${import_chalk15.default.cyan(featureUrl)}`);
2154
+ console.log(` Suggest a Metric: ${import_chalk15.default.cyan(metricUrl)}`);
2155
+ console.log(import_chalk15.default.bold("\n\u{1F916} [FOR AI AGENTS]:"));
2156
+ console.log(import_chalk15.default.dim(" To prepare a specific report, run:"));
2124
2157
  console.log(
2125
- import_chalk14.default.cyan(
2158
+ import_chalk15.default.cyan(
2126
2159
  ' aiready bug "your description here" --type bug|feature|metric'
2127
2160
  )
2128
2161
  );
@@ -2139,10 +2172,10 @@ EXAMPLES:
2139
2172
  var import_meta = {};
2140
2173
  var getDirname = () => {
2141
2174
  if (typeof __dirname !== "undefined") return __dirname;
2142
- return (0, import_path9.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2175
+ return (0, import_path7.dirname)((0, import_url.fileURLToPath)(import_meta.url));
2143
2176
  };
2144
2177
  var packageJson = JSON.parse(
2145
- (0, import_fs7.readFileSync)((0, import_path9.join)(getDirname(), "../package.json"), "utf8")
2178
+ (0, import_fs8.readFileSync)((0, import_path7.join)(getDirname(), "../package.json"), "utf8")
2146
2179
  );
2147
2180
  var program = new import_commander.Command();
2148
2181
  program.name("aiready").description("AIReady - Assess and improve AI-readiness of codebases").version(packageJson.version).addHelpText(
@@ -2197,7 +2230,7 @@ program.command("scan").description(
2197
2230
  ).option(
2198
2231
  "--compare-to <path>",
2199
2232
  "Compare results against a previous AIReady report JSON"
2200
- ).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").option("--weights <weights>", "Custom scoring weights").option("--threshold <score>", "Fail CI/CD if score below threshold (0-100)").option(
2233
+ ).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(
2201
2234
  "--ci",
2202
2235
  "CI mode: GitHub Actions annotations, no colors, fail on threshold"
2203
2236
  ).option(
@@ -2223,7 +2256,7 @@ program.command("patterns").description("Detect duplicate code patterns that con
2223
2256
  ).option(
2224
2257
  "--full-scan",
2225
2258
  "Disable smart defaults for comprehensive analysis (slower)"
2226
- ).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").addHelpText("after", PATTERNS_HELP_TEXT).action(async (directory, options) => {
2259
+ ).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) => {
2227
2260
  await patternsAction(directory, options);
2228
2261
  });
2229
2262
  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(