@aiready/cli 0.14.22 → 0.14.23

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