@aiready/cli 0.10.4 → 0.12.0

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
@@ -36,339 +36,137 @@ var import_path3 = require("path");
36
36
  var import_core3 = require("@aiready/core");
37
37
 
38
38
  // src/index.ts
39
- var import_pattern_detect = require("@aiready/pattern-detect");
40
- var import_context_analyzer = require("@aiready/context-analyzer");
41
- var import_consistency = require("@aiready/consistency");
42
39
  var import_core = require("@aiready/core");
43
- var severityOrder = {
44
- critical: 4,
45
- major: 3,
46
- minor: 2,
47
- info: 1
40
+ var TOOL_PACKAGE_MAP = {
41
+ [import_core.ToolName.PatternDetect]: "@aiready/pattern-detect",
42
+ [import_core.ToolName.ContextAnalyzer]: "@aiready/context-analyzer",
43
+ [import_core.ToolName.NamingConsistency]: "@aiready/consistency",
44
+ [import_core.ToolName.AiSignalClarity]: "@aiready/ai-signal-clarity",
45
+ [import_core.ToolName.AgentGrounding]: "@aiready/agent-grounding",
46
+ [import_core.ToolName.TestabilityIndex]: "@aiready/testability",
47
+ [import_core.ToolName.DocDrift]: "@aiready/doc-drift",
48
+ [import_core.ToolName.DependencyHealth]: "@aiready/deps",
49
+ [import_core.ToolName.ChangeAmplification]: "@aiready/change-amplification",
50
+ // Aliases handled by registry
51
+ patterns: "@aiready/pattern-detect",
52
+ context: "@aiready/context-analyzer",
53
+ consistency: "@aiready/consistency"
48
54
  };
49
- function sortBySeverity(results) {
50
- return results.map((file) => {
51
- const sortedIssues = [...file.issues].sort((a, b) => {
52
- const severityDiff = (severityOrder[b.severity] || 0) - (severityOrder[a.severity] || 0);
53
- if (severityDiff !== 0) return severityDiff;
54
- return (a.location?.line || 0) - (b.location?.line || 0);
55
- });
56
- return { ...file, issues: sortedIssues };
57
- }).sort((a, b) => {
58
- const aMaxSeverity = Math.max(
59
- ...a.issues.map((i) => severityOrder[i.severity] || 0),
60
- 0
61
- );
62
- const bMaxSeverity = Math.max(
63
- ...b.issues.map((i) => severityOrder[i.severity] || 0),
64
- 0
65
- );
66
- if (aMaxSeverity !== bMaxSeverity) {
67
- return bMaxSeverity - aMaxSeverity;
68
- }
69
- if (a.issues.length !== b.issues.length) {
70
- return b.issues.length - a.issues.length;
71
- }
72
- return a.fileName.localeCompare(b.fileName);
73
- });
74
- }
75
55
  async function analyzeUnified(options) {
76
56
  const startTime = Date.now();
77
- const tools = options.tools || ["patterns", "context", "consistency"];
57
+ const requestedTools = options.tools || [
58
+ "patterns",
59
+ "context",
60
+ "consistency"
61
+ ];
78
62
  const result = {
79
63
  summary: {
80
64
  totalIssues: 0,
81
- toolsRun: tools,
65
+ toolsRun: [],
82
66
  executionTime: 0
83
67
  }
84
68
  };
85
- if (tools.includes("patterns")) {
86
- const patternResult = await (0, import_pattern_detect.analyzePatterns)(options);
87
- if (options.progressCallback) {
88
- options.progressCallback({ tool: "patterns", data: patternResult });
89
- }
90
- result.patternDetect = {
91
- results: sortBySeverity(patternResult.results),
92
- summary: patternResult.summary || {},
93
- duplicates: patternResult.duplicates || []
94
- };
95
- result.summary.totalIssues += patternResult.results.reduce(
96
- (sum, file) => sum + file.issues.length,
97
- 0
98
- );
99
- }
100
- if (tools.includes("context")) {
101
- const contextResults = await (0, import_context_analyzer.analyzeContext)(options);
102
- if (options.progressCallback) {
103
- options.progressCallback({ tool: "context", data: contextResults });
104
- }
105
- const sorted = contextResults.sort((a, b) => {
106
- const severityDiff = (severityOrder[b.severity] || 0) - (severityOrder[a.severity] || 0);
107
- if (severityDiff !== 0) return severityDiff;
108
- if (a.tokenCost !== b.tokenCost) return b.tokenCost - a.tokenCost;
109
- return b.fragmentationScore - a.fragmentationScore;
110
- });
111
- const { generateSummary: genContextSummary } = await import("@aiready/context-analyzer");
112
- result.contextAnalyzer = {
113
- results: sorted,
114
- summary: genContextSummary(sorted)
115
- };
116
- result.summary.totalIssues += sorted.length;
117
- }
118
- if (tools.includes("consistency")) {
119
- const consistencyOptions = {
120
- rootDir: options.rootDir,
121
- include: options.include,
122
- exclude: options.exclude,
123
- ...options.consistency || {}
124
- };
125
- const report = await (0, import_consistency.analyzeConsistency)(consistencyOptions);
126
- if (options.progressCallback) {
127
- options.progressCallback({ tool: "consistency", data: report });
128
- }
129
- result.consistency = {
130
- results: report.results ? sortBySeverity(report.results) : [],
131
- summary: report.summary
132
- };
133
- result.summary.totalIssues += report.summary.totalIssues;
134
- }
135
- if (tools.includes("doc-drift")) {
136
- const { analyzeDocDrift } = await import("@aiready/doc-drift");
137
- const report = await analyzeDocDrift({
138
- rootDir: options.rootDir,
139
- include: options.include,
140
- exclude: options.exclude,
141
- onProgress: options.onProgress
142
- });
143
- if (options.progressCallback) {
144
- options.progressCallback({ tool: "doc-drift", data: report });
145
- }
146
- result.docDrift = {
147
- results: report.results || report.issues || [],
148
- summary: report.summary || {}
149
- };
150
- const issueCount = report.issues?.length || (report.results ? report.results.length : 0);
151
- result.summary.totalIssues += issueCount;
152
- }
153
- if (tools.includes("deps-health")) {
154
- const { analyzeDeps } = await import("@aiready/deps");
155
- const report = await analyzeDeps({
156
- rootDir: options.rootDir,
157
- include: options.include,
158
- exclude: options.exclude,
159
- onProgress: options.onProgress
160
- });
161
- if (options.progressCallback) {
162
- options.progressCallback({ tool: "deps-health", data: report });
163
- }
164
- result.dependencyHealth = {
165
- results: report.results || report.issues || [],
166
- summary: report.summary || {}
167
- };
168
- const issueCount = report.issues?.length || (report.results ? report.results.length : 0);
169
- result.summary.totalIssues += issueCount;
170
- }
171
- if (tools.includes("ai-signal-clarity")) {
172
- const { analyzeAiSignalClarity } = await import("@aiready/ai-signal-clarity");
173
- const report = await analyzeAiSignalClarity({
174
- rootDir: options.rootDir,
175
- include: options.include,
176
- exclude: options.exclude,
177
- onProgress: options.onProgress
178
- });
179
- if (options.progressCallback) {
180
- options.progressCallback({ tool: "ai-signal-clarity", data: report });
181
- }
182
- result.aiSignalClarity = {
183
- ...report,
184
- results: report.results || report.issues || [],
185
- summary: report.summary || {}
186
- };
187
- result.summary.totalIssues += (report.results || report.issues)?.reduce(
188
- (sum, r) => sum + (r.issues?.length || 1),
189
- 0
190
- ) || 0;
191
- }
192
- if (tools.includes("agent-grounding")) {
193
- const { analyzeAgentGrounding } = await import("@aiready/agent-grounding");
194
- const report = await analyzeAgentGrounding({
195
- rootDir: options.rootDir,
196
- include: options.include,
197
- exclude: options.exclude,
198
- onProgress: options.onProgress
199
- });
200
- if (options.progressCallback) {
201
- options.progressCallback({ tool: "agent-grounding", data: report });
202
- }
203
- result.agentGrounding = {
204
- ...report,
205
- results: report.results || report.issues || [],
206
- summary: report.summary || {}
207
- };
208
- result.summary.totalIssues += (report.issues || report.results || []).length;
209
- }
210
- if (tools.includes("testability")) {
211
- const { analyzeTestability } = await import("@aiready/testability");
212
- const report = await analyzeTestability({
213
- rootDir: options.rootDir,
214
- include: options.include,
215
- exclude: options.exclude,
216
- onProgress: options.onProgress
217
- });
218
- if (options.progressCallback) {
219
- options.progressCallback({ tool: "testability", data: report });
69
+ for (const toolName of requestedTools) {
70
+ let provider = import_core.ToolRegistry.find(toolName);
71
+ if (!provider) {
72
+ const packageName = TOOL_PACKAGE_MAP[toolName] || (toolName.startsWith("@aiready/") ? toolName : `@aiready/${toolName}`);
73
+ try {
74
+ await import(packageName);
75
+ provider = import_core.ToolRegistry.find(toolName);
76
+ if (provider) {
77
+ console.log(
78
+ `\u2705 Successfully loaded tool provider: ${toolName} from ${packageName}`
79
+ );
80
+ } else {
81
+ console.log(
82
+ `\u26A0\uFE0F Loaded ${packageName} but provider ${toolName} still not found in registry.`
83
+ );
84
+ }
85
+ } catch (err) {
86
+ console.log(
87
+ `\u274C Failed to dynamically load tool ${toolName} (${packageName}):`,
88
+ err.message
89
+ );
90
+ }
220
91
  }
221
- result.testability = {
222
- ...report,
223
- results: report.results || report.issues || [],
224
- summary: report.summary || {}
225
- };
226
- result.summary.totalIssues += (report.issues || report.results || []).length;
227
- }
228
- if (tools.includes("change-amplification")) {
229
- const { analyzeChangeAmplification } = await import("@aiready/change-amplification");
230
- const report = await analyzeChangeAmplification({
231
- rootDir: options.rootDir,
232
- include: options.include,
233
- exclude: options.exclude,
234
- onProgress: options.onProgress
235
- });
236
- if (options.progressCallback) {
237
- options.progressCallback({ tool: "change-amplification", data: report });
92
+ if (!provider) {
93
+ console.warn(
94
+ `\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
95
+ );
96
+ continue;
238
97
  }
239
- result.changeAmplification = {
240
- results: report.results || [],
241
- summary: report.summary || {}
242
- };
243
- result.summary.totalIssues += report.summary?.totalIssues || 0;
244
- }
245
- result.summary.executionTime = Date.now() - startTime;
246
- return result;
247
- }
248
- async function scoreUnified(results, options) {
249
- const toolScores = /* @__PURE__ */ new Map();
250
- if (results.patternDetect) {
251
- const { calculatePatternScore } = await import("@aiready/pattern-detect");
252
98
  try {
253
- const patternScore = calculatePatternScore(
254
- results.patternDetect.duplicates,
255
- results.patternDetect.results?.length || 0
256
- );
257
- const wastedTokens = results.patternDetect.duplicates.reduce(
258
- (sum, d) => sum + (d.tokenCost || 0),
99
+ const output = await provider.analyze(options);
100
+ if (options.progressCallback) {
101
+ options.progressCallback({ tool: provider.id, data: output });
102
+ }
103
+ result[provider.id] = output;
104
+ result.summary.toolsRun.push(provider.id);
105
+ const issueCount = output.results.reduce(
106
+ (sum, file) => sum + (file.issues?.length || 0),
259
107
  0
260
108
  );
261
- patternScore.tokenBudget = (0, import_core.calculateTokenBudget)({
262
- totalContextTokens: wastedTokens * 2,
263
- // Estimated context
264
- wastedTokens: {
265
- duplication: wastedTokens,
266
- fragmentation: 0,
267
- chattiness: 0
109
+ result.summary.totalIssues += issueCount;
110
+ if (provider.alias && Array.isArray(provider.alias)) {
111
+ for (const alias of provider.alias) {
112
+ if (!result[alias]) {
113
+ result[alias] = output;
114
+ }
268
115
  }
269
- });
270
- toolScores.set("pattern-detect", patternScore);
116
+ }
117
+ const camelCaseId = provider.id.replace(
118
+ /-([a-z])/g,
119
+ (g) => g[1].toUpperCase()
120
+ );
121
+ if (camelCaseId !== provider.id && !result[camelCaseId]) {
122
+ result[camelCaseId] = output;
123
+ }
271
124
  } catch (err) {
272
- void err;
125
+ console.error(`\u274C Error running tool '${provider.id}':`, err);
273
126
  }
274
127
  }
275
- if (results.contextAnalyzer) {
276
- const { calculateContextScore } = await import("@aiready/context-analyzer");
128
+ result.summary.executionTime = Date.now() - startTime;
129
+ return result;
130
+ }
131
+ async function scoreUnified(results, options) {
132
+ const toolScores = /* @__PURE__ */ new Map();
133
+ for (const toolId of results.summary.toolsRun) {
134
+ const provider = import_core.ToolRegistry.get(toolId);
135
+ if (!provider) continue;
136
+ const output = results[toolId];
137
+ if (!output) continue;
277
138
  try {
278
- const ctxSummary = results.contextAnalyzer.summary;
279
- const contextScore = calculateContextScore(ctxSummary);
280
- contextScore.tokenBudget = (0, import_core.calculateTokenBudget)({
281
- totalContextTokens: ctxSummary.totalTokens,
282
- wastedTokens: {
283
- duplication: 0,
284
- fragmentation: ctxSummary.totalPotentialSavings || 0,
285
- chattiness: 0
139
+ const toolScore = provider.score(output, options);
140
+ if (!toolScore.tokenBudget) {
141
+ if (toolId === import_core.ToolName.PatternDetect && output.duplicates) {
142
+ const wastedTokens = output.duplicates.reduce(
143
+ (sum, d) => sum + (d.tokenCost || 0),
144
+ 0
145
+ );
146
+ toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
147
+ totalContextTokens: wastedTokens * 2,
148
+ wastedTokens: {
149
+ duplication: wastedTokens,
150
+ fragmentation: 0,
151
+ chattiness: 0
152
+ }
153
+ });
154
+ } else if (toolId === import_core.ToolName.ContextAnalyzer && output.summary) {
155
+ toolScore.tokenBudget = (0, import_core.calculateTokenBudget)({
156
+ totalContextTokens: output.summary.totalTokens,
157
+ wastedTokens: {
158
+ duplication: 0,
159
+ fragmentation: output.summary.totalPotentialSavings || 0,
160
+ chattiness: 0
161
+ }
162
+ });
286
163
  }
287
- });
288
- toolScores.set("context-analyzer", contextScore);
289
- } catch (err) {
290
- void err;
291
- }
292
- }
293
- if (results.consistency) {
294
- const { calculateConsistencyScore } = await import("@aiready/consistency");
295
- try {
296
- const issues = results.consistency.results?.flatMap((r) => r.issues) || [];
297
- const totalFiles = results.consistency.summary?.filesAnalyzed || 0;
298
- const consistencyScore = calculateConsistencyScore(issues, totalFiles);
299
- toolScores.set("consistency", consistencyScore);
300
- } catch (err) {
301
- void err;
302
- }
303
- }
304
- if (results.aiSignalClarity) {
305
- const { calculateAiSignalClarityScore } = await import("@aiready/ai-signal-clarity");
306
- try {
307
- const hrScore = calculateAiSignalClarityScore(results.aiSignalClarity);
308
- toolScores.set("ai-signal-clarity", hrScore);
309
- } catch (err) {
310
- void err;
311
- }
312
- }
313
- if (results.agentGrounding) {
314
- const { calculateGroundingScore } = await import("@aiready/agent-grounding");
315
- try {
316
- const agScore = calculateGroundingScore(results.agentGrounding);
317
- toolScores.set("agent-grounding", agScore);
318
- } catch (err) {
319
- void err;
320
- }
321
- }
322
- if (results.testability) {
323
- const { calculateTestabilityScore } = await import("@aiready/testability");
324
- try {
325
- const tbScore = calculateTestabilityScore(results.testability);
326
- toolScores.set("testability", tbScore);
164
+ }
165
+ toolScores.set(toolId, toolScore);
327
166
  } catch (err) {
328
- void err;
167
+ console.error(`\u274C Error scoring tool '${toolId}':`, err);
329
168
  }
330
169
  }
331
- if (results.docDrift) {
332
- toolScores.set("doc-drift", {
333
- toolName: "doc-drift",
334
- score: results.docDrift.summary.score || results.docDrift.summary.totalScore || 0,
335
- rawMetrics: results.docDrift.summary,
336
- factors: [],
337
- recommendations: (results.docDrift.summary.recommendations || []).map(
338
- (action) => ({
339
- action,
340
- estimatedImpact: 5,
341
- priority: "medium"
342
- })
343
- )
344
- });
345
- }
346
- if (results.dependencyHealth) {
347
- toolScores.set("dependency-health", {
348
- toolName: "dependency-health",
349
- score: results.dependencyHealth.summary.score || 0,
350
- rawMetrics: results.dependencyHealth.summary,
351
- factors: [],
352
- recommendations: (results.dependencyHealth.summary.recommendations || []).map((action) => ({
353
- action,
354
- estimatedImpact: 5,
355
- priority: "medium"
356
- }))
357
- });
358
- }
359
- if (results.changeAmplification) {
360
- toolScores.set("change-amplification", {
361
- toolName: "change-amplification",
362
- score: results.changeAmplification.summary.score || 0,
363
- rawMetrics: results.changeAmplification.summary,
364
- factors: [],
365
- recommendations: (results.changeAmplification.summary.recommendations || []).map((action) => ({
366
- action,
367
- estimatedImpact: 5,
368
- priority: "medium"
369
- }))
370
- });
371
- }
372
170
  if (toolScores.size === 0) {
373
171
  return {
374
172
  overall: 0,
@@ -503,12 +301,6 @@ function generateMarkdownReport(report, elapsedTime) {
503
301
  }
504
302
  return markdown;
505
303
  }
506
- function truncateArray(arr, cap = 8) {
507
- if (!Array.isArray(arr)) return "";
508
- const shown = arr.slice(0, cap).map((v) => String(v));
509
- const more = arr.length - shown.length;
510
- return shown.join(", ") + (more > 0 ? `, ... (+${more} more)` : "");
511
- }
512
304
 
513
305
  // src/commands/upload.ts
514
306
  var import_fs2 = __toESM(require("fs"));
@@ -622,14 +414,14 @@ async function scanAction(directory, options) {
622
414
  try {
623
415
  const defaults = {
624
416
  tools: [
625
- "patterns",
626
- "context",
627
- "consistency",
417
+ "pattern-detect",
418
+ "context-analyzer",
419
+ "naming-consistency",
628
420
  "ai-signal-clarity",
629
421
  "agent-grounding",
630
- "testability",
422
+ "testability-index",
631
423
  "doc-drift",
632
- "deps-health",
424
+ "dependency-health",
633
425
  "change-amplification"
634
426
  ],
635
427
  include: void 0,
@@ -639,35 +431,37 @@ async function scanAction(directory, options) {
639
431
  file: void 0
640
432
  }
641
433
  };
642
- let profileTools = options.tools ? options.tools.split(",").map((t) => {
643
- const tool = t.trim();
644
- if (tool === "hallucination" || tool === "hallucination-risk")
645
- return "aiSignalClarity";
646
- return tool;
647
- }) : void 0;
434
+ let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
648
435
  if (options.profile) {
649
436
  switch (options.profile.toLowerCase()) {
650
437
  case "agentic":
651
438
  profileTools = [
652
- "ai-signal-clarity",
653
- "agent-grounding",
654
- "testability"
439
+ import_core3.ToolName.AiSignalClarity,
440
+ import_core3.ToolName.AgentGrounding,
441
+ import_core3.ToolName.TestabilityIndex
655
442
  ];
656
443
  break;
657
444
  case "cost":
658
- profileTools = ["patterns", "context"];
445
+ profileTools = [import_core3.ToolName.PatternDetect, import_core3.ToolName.ContextAnalyzer];
659
446
  break;
660
447
  case "security":
661
- profileTools = ["consistency", "testability"];
448
+ profileTools = [
449
+ import_core3.ToolName.NamingConsistency,
450
+ import_core3.ToolName.TestabilityIndex
451
+ ];
662
452
  break;
663
453
  case "onboarding":
664
- profileTools = ["context", "consistency", "agent-grounding"];
454
+ profileTools = [
455
+ import_core3.ToolName.ContextAnalyzer,
456
+ import_core3.ToolName.NamingConsistency,
457
+ import_core3.ToolName.AgentGrounding
458
+ ];
665
459
  break;
666
460
  default:
667
461
  console.log(
668
462
  import_chalk3.default.yellow(
669
463
  `
670
- \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`
464
+ \u26A0\uFE0F Unknown profile '${options.profile}'. Using defaults.`
671
465
  )
672
466
  );
673
467
  }
@@ -676,16 +470,14 @@ async function scanAction(directory, options) {
676
470
  include: options.include?.split(","),
677
471
  exclude: options.exclude?.split(",")
678
472
  };
679
- if (profileTools) {
680
- cliOverrides.tools = profileTools;
681
- }
473
+ if (profileTools) cliOverrides.tools = profileTools;
682
474
  const baseOptions = await (0, import_core3.loadMergedConfig)(
683
475
  resolvedDir,
684
476
  defaults,
685
477
  cliOverrides
686
478
  );
687
479
  let finalOptions = { ...baseOptions };
688
- if (baseOptions.tools.includes("patterns")) {
480
+ if (baseOptions.tools.includes(import_core3.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
689
481
  const { getSmartDefaults } = await import("@aiready/pattern-detect");
690
482
  const patternSmartDefaults = await getSmartDefaults(
691
483
  resolvedDir,
@@ -700,256 +492,21 @@ async function scanAction(directory, options) {
700
492
  console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
701
493
  console.log(
702
494
  import_chalk3.default.white("Tools to run:"),
703
- (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
495
+ (finalOptions.tools || []).join(", ")
704
496
  );
705
- console.log(import_chalk3.default.white("Will use settings from config and defaults."));
706
- console.log(import_chalk3.default.white("\nGeneral settings:"));
707
- if (finalOptions.rootDir)
708
- console.log(` rootDir: ${import_chalk3.default.bold(String(finalOptions.rootDir))}`);
709
- if (finalOptions.include)
710
- console.log(
711
- ` include: ${import_chalk3.default.bold(truncateArray(finalOptions.include, 6))}`
712
- );
713
- if (finalOptions.exclude)
714
- console.log(
715
- ` exclude: ${import_chalk3.default.bold(truncateArray(finalOptions.exclude, 6))}`
716
- );
717
- if (finalOptions["pattern-detect"] || finalOptions.minSimilarity) {
718
- const patternDetectConfig = finalOptions["pattern-detect"] || {
719
- minSimilarity: finalOptions.minSimilarity,
720
- minLines: finalOptions.minLines,
721
- approx: finalOptions.approx,
722
- minSharedTokens: finalOptions.minSharedTokens,
723
- maxCandidatesPerBlock: finalOptions.maxCandidatesPerBlock,
724
- batchSize: finalOptions.batchSize,
725
- streamResults: finalOptions.streamResults,
726
- severity: finalOptions.severity,
727
- includeTests: finalOptions.includeTests
728
- };
729
- console.log(import_chalk3.default.white("\nPattern-detect settings:"));
730
- console.log(
731
- ` minSimilarity: ${import_chalk3.default.bold(patternDetectConfig.minSimilarity ?? "default")}`
732
- );
733
- console.log(
734
- ` minLines: ${import_chalk3.default.bold(patternDetectConfig.minLines ?? "default")}`
735
- );
736
- if (patternDetectConfig.approx !== void 0)
737
- console.log(
738
- ` approx: ${import_chalk3.default.bold(String(patternDetectConfig.approx))}`
739
- );
740
- if (patternDetectConfig.minSharedTokens !== void 0)
741
- console.log(
742
- ` minSharedTokens: ${import_chalk3.default.bold(String(patternDetectConfig.minSharedTokens))}`
743
- );
744
- if (patternDetectConfig.maxCandidatesPerBlock !== void 0)
745
- console.log(
746
- ` maxCandidatesPerBlock: ${import_chalk3.default.bold(String(patternDetectConfig.maxCandidatesPerBlock))}`
747
- );
748
- if (patternDetectConfig.batchSize !== void 0)
749
- console.log(
750
- ` batchSize: ${import_chalk3.default.bold(String(patternDetectConfig.batchSize))}`
751
- );
752
- if (patternDetectConfig.streamResults !== void 0)
753
- console.log(
754
- ` streamResults: ${import_chalk3.default.bold(String(patternDetectConfig.streamResults))}`
755
- );
756
- if (patternDetectConfig.severity !== void 0)
757
- console.log(
758
- ` severity: ${import_chalk3.default.bold(String(patternDetectConfig.severity))}`
759
- );
760
- if (patternDetectConfig.includeTests !== void 0)
761
- console.log(
762
- ` includeTests: ${import_chalk3.default.bold(String(patternDetectConfig.includeTests))}`
763
- );
764
- }
765
- if (finalOptions["context-analyzer"] || finalOptions.maxDepth) {
766
- const ca = finalOptions["context-analyzer"] || {
767
- maxDepth: finalOptions.maxDepth,
768
- maxContextBudget: finalOptions.maxContextBudget,
769
- minCohesion: finalOptions.minCohesion,
770
- maxFragmentation: finalOptions.maxFragmentation,
771
- includeNodeModules: finalOptions.includeNodeModules
772
- };
773
- console.log(import_chalk3.default.white("\nContext-analyzer settings:"));
774
- console.log(` maxDepth: ${import_chalk3.default.bold(ca.maxDepth ?? "default")}`);
775
- console.log(
776
- ` maxContextBudget: ${import_chalk3.default.bold(ca.maxContextBudget ?? "default")}`
777
- );
778
- if (ca.minCohesion !== void 0)
779
- console.log(` minCohesion: ${import_chalk3.default.bold(String(ca.minCohesion))}`);
780
- if (ca.maxFragmentation !== void 0)
781
- console.log(
782
- ` maxFragmentation: ${import_chalk3.default.bold(String(ca.maxFragmentation))}`
783
- );
784
- if (ca.includeNodeModules !== void 0)
785
- console.log(
786
- ` includeNodeModules: ${import_chalk3.default.bold(String(ca.includeNodeModules))}`
787
- );
788
- }
789
- if (finalOptions.consistency) {
790
- const c = finalOptions.consistency;
791
- console.log(import_chalk3.default.white("\nConsistency settings:"));
792
- console.log(
793
- ` checkNaming: ${import_chalk3.default.bold(String(c.checkNaming ?? true))}`
794
- );
795
- console.log(
796
- ` checkPatterns: ${import_chalk3.default.bold(String(c.checkPatterns ?? true))}`
797
- );
798
- console.log(
799
- ` checkArchitecture: ${import_chalk3.default.bold(String(c.checkArchitecture ?? false))}`
800
- );
801
- if (c.minSeverity)
802
- console.log(` minSeverity: ${import_chalk3.default.bold(c.minSeverity)}`);
803
- if (c.acceptedAbbreviations)
804
- console.log(
805
- ` acceptedAbbreviations: ${import_chalk3.default.bold(truncateArray(c.acceptedAbbreviations, 8))}`
806
- );
807
- if (c.shortWords)
808
- console.log(
809
- ` shortWords: ${import_chalk3.default.bold(truncateArray(c.shortWords, 8))}`
810
- );
811
- }
812
- console.log(import_chalk3.default.white("\nStarting analysis..."));
813
497
  const progressCallback = (event) => {
814
498
  console.log(import_chalk3.default.cyan(`
815
499
  --- ${event.tool.toUpperCase()} RESULTS ---`));
816
- try {
817
- if (event.tool === "patterns") {
818
- const pr = event.data;
819
- console.log(
820
- ` Duplicate patterns: ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))}`
821
- );
500
+ const res = event.data;
501
+ if (res.summary) {
502
+ if (res.summary.totalIssues !== void 0)
503
+ console.log(` Issues found: ${import_chalk3.default.bold(res.summary.totalIssues)}`);
504
+ if (res.summary.score !== void 0)
505
+ console.log(` Tool Score: ${import_chalk3.default.bold(res.summary.score)}/100`);
506
+ if (res.summary.totalFiles !== void 0)
822
507
  console.log(
823
- ` Files with pattern issues: ${import_chalk3.default.bold(String(pr.results?.length || 0))}`
508
+ ` Files analyzed: ${import_chalk3.default.bold(res.summary.totalFiles)}`
824
509
  );
825
- if (pr.duplicates && pr.duplicates.length > 0) {
826
- pr.duplicates.slice(0, 5).forEach((d, i) => {
827
- console.log(
828
- ` ${i + 1}. ${d.file1.split("/").pop()} \u2194 ${d.file2.split("/").pop()} (sim=${(d.similarity * 100).toFixed(1)}%)`
829
- );
830
- });
831
- }
832
- if (pr.results && pr.results.length > 0) {
833
- console.log(` Top files with pattern issues:`);
834
- const sortedByIssues = [...pr.results].sort(
835
- (a, b) => (b.issues?.length || 0) - (a.issues?.length || 0)
836
- );
837
- sortedByIssues.slice(0, 5).forEach((r, i) => {
838
- console.log(
839
- ` ${i + 1}. ${r.fileName.split("/").pop()} - ${r.issues.length} issue(s)`
840
- );
841
- });
842
- }
843
- if (pr.groups && pr.groups.length >= 0) {
844
- console.log(
845
- ` \u2705 Grouped ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))} duplicates into ${import_chalk3.default.bold(String(pr.groups.length))} file pairs`
846
- );
847
- }
848
- if (pr.clusters && pr.clusters.length >= 0) {
849
- console.log(
850
- ` \u2705 Created ${import_chalk3.default.bold(String(pr.clusters.length))} refactor clusters`
851
- );
852
- pr.clusters.slice(0, 3).forEach((cl, idx) => {
853
- const files = (cl.files || []).map((f) => f.path.split("/").pop()).join(", ");
854
- console.log(
855
- ` ${idx + 1}. ${files} (${cl.tokenCost || "n/a"} tokens)`
856
- );
857
- });
858
- }
859
- } else if (event.tool === "context") {
860
- const cr = event.data;
861
- console.log(
862
- ` Context issues found: ${import_chalk3.default.bold(String(cr.length || 0))}`
863
- );
864
- cr.slice(0, 5).forEach((c, i) => {
865
- const msg = c.message ? ` - ${c.message}` : "";
866
- console.log(
867
- ` ${i + 1}. ${c.file} (${c.severity || "n/a"})${msg}`
868
- );
869
- });
870
- } else if (event.tool === "consistency") {
871
- const rep = event.data;
872
- console.log(
873
- ` Consistency totalIssues: ${import_chalk3.default.bold(String(rep.summary?.totalIssues || 0))}`
874
- );
875
- if (rep.results && rep.results.length > 0) {
876
- const fileMap = /* @__PURE__ */ new Map();
877
- rep.results.forEach((r) => {
878
- (r.issues || []).forEach((issue) => {
879
- const file = issue.location?.file || r.file || "unknown";
880
- if (!fileMap.has(file)) fileMap.set(file, []);
881
- fileMap.get(file).push(issue);
882
- });
883
- });
884
- const files = Array.from(fileMap.entries()).sort(
885
- (a, b) => b[1].length - a[1].length
886
- );
887
- const topFiles = files.slice(0, 10);
888
- topFiles.forEach(([file, issues], idx) => {
889
- const counts = issues.reduce(
890
- (acc, it) => {
891
- const s = (it.severity || import_core3.Severity.Info).toLowerCase();
892
- acc[s] = (acc[s] || 0) + 1;
893
- return acc;
894
- },
895
- {}
896
- );
897
- const sample = issues.find(
898
- (it) => it.severity === import_core3.Severity.Critical || it.severity === import_core3.Severity.Major
899
- ) || issues[0];
900
- const sampleMsg = sample ? ` \u2014 ${sample.message}` : "";
901
- console.log(
902
- ` ${idx + 1}. ${file} \u2014 ${issues.length} issue(s) (critical:${counts[import_core3.Severity.Critical] || 0} major:${counts[import_core3.Severity.Major] || 0} minor:${counts[import_core3.Severity.Minor] || 0} info:${counts[import_core3.Severity.Info] || 0})${sampleMsg}`
903
- );
904
- });
905
- const remaining = files.length - topFiles.length;
906
- if (remaining > 0) {
907
- console.log(
908
- import_chalk3.default.dim(
909
- ` ... and ${remaining} more files with issues (use --output json for full details)`
910
- )
911
- );
912
- }
913
- }
914
- } else if (event.tool === "doc-drift") {
915
- const dr = event.data;
916
- console.log(
917
- ` Issues found: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
918
- );
919
- if (dr.rawData) {
920
- console.log(
921
- ` Signature Mismatches: ${import_chalk3.default.bold(dr.rawData.outdatedComments || 0)}`
922
- );
923
- console.log(
924
- ` Undocumented Complexity: ${import_chalk3.default.bold(dr.rawData.undocumentedComplexity || 0)}`
925
- );
926
- }
927
- } else if (event.tool === "deps-health") {
928
- const dr = event.data;
929
- console.log(
930
- ` Packages Analyzed: ${import_chalk3.default.bold(String(dr.summary?.packagesAnalyzed || 0))}`
931
- );
932
- if (dr.rawData) {
933
- console.log(
934
- ` Deprecated Packages: ${import_chalk3.default.bold(dr.rawData.deprecatedPackages || 0)}`
935
- );
936
- console.log(
937
- ` AI Cutoff Skew Score: ${import_chalk3.default.bold(dr.rawData.trainingCutoffSkew?.toFixed(1) || 0)}`
938
- );
939
- }
940
- } else if (event.tool === "change-amplification" || event.tool === "changeAmplification") {
941
- const dr = event.data;
942
- console.log(
943
- ` Coupling issues: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
944
- );
945
- if (dr.summary) {
946
- console.log(
947
- ` Complexity Score: ${import_chalk3.default.bold(dr.summary.score || 0)}/100`
948
- );
949
- }
950
- }
951
- } catch (err) {
952
- void err;
953
510
  }
954
511
  };
955
512
  const results = await analyzeUnified({
@@ -959,44 +516,14 @@ async function scanAction(directory, options) {
959
516
  process.stdout.write(
960
517
  `\r\x1B[K [${processed}/${total}] ${message}...`
961
518
  );
962
- if (processed === total) {
963
- process.stdout.write("\n");
964
- }
519
+ if (processed === total) process.stdout.write("\n");
965
520
  },
966
521
  suppressToolConfig: true
967
522
  });
968
523
  console.log(import_chalk3.default.cyan("\n=== AIReady Run Summary ==="));
969
- console.log(
970
- import_chalk3.default.white("Tools run:"),
971
- (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
972
- );
973
- console.log(import_chalk3.default.cyan("\nResults summary:"));
974
524
  console.log(
975
525
  ` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
976
526
  );
977
- if (results.patternDetect) {
978
- console.log(
979
- ` Duplicate patterns found: ${import_chalk3.default.bold(String(results.patternDetect.duplicates?.length || 0))}`
980
- );
981
- console.log(
982
- ` Pattern files with issues: ${import_chalk3.default.bold(String(results.patternDetect.results.length || 0))}`
983
- );
984
- }
985
- if (results.contextAnalyzer)
986
- console.log(
987
- ` Context issues: ${import_chalk3.default.bold(String(results.contextAnalyzer.results.length || 0))}`
988
- );
989
- if (results.consistency)
990
- console.log(
991
- ` Consistency issues: ${import_chalk3.default.bold(String(results.consistency.summary?.totalIssues || 0))}`
992
- );
993
- if (results.changeAmplification)
994
- console.log(
995
- ` Change amplification: ${import_chalk3.default.bold(String(results.changeAmplification.summary?.score || 0))}/100`
996
- );
997
- console.log(import_chalk3.default.cyan("===========================\n"));
998
- const elapsedTime = (0, import_core3.getElapsedTime)(startTime);
999
- void elapsedTime;
1000
527
  let scoringResult;
1001
528
  if (options.score || finalOptions.scoring?.showBreakdown) {
1002
529
  scoringResult = await scoreUnified(results, finalOptions);
@@ -1004,55 +531,34 @@ async function scanAction(directory, options) {
1004
531
  console.log(` ${(0, import_core3.formatScore)(scoringResult)}`);
1005
532
  if (options.compareTo) {
1006
533
  try {
1007
- const prevReportStr = (0, import_fs3.readFileSync)(
1008
- (0, import_path3.resolve)(process.cwd(), options.compareTo),
1009
- "utf8"
534
+ const prevReport = JSON.parse(
535
+ (0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), options.compareTo), "utf8")
1010
536
  );
1011
- const prevReport = JSON.parse(prevReportStr);
1012
- const prevScore = prevReport.scoring?.score || prevReport.scoring?.overallScore;
537
+ const prevScore = prevReport.scoring?.overall || prevReport.scoring?.score;
1013
538
  if (typeof prevScore === "number") {
1014
539
  const diff = scoringResult.overall - prevScore;
1015
540
  const diffStr = diff > 0 ? `+${diff}` : String(diff);
1016
- console.log();
1017
- if (diff > 0) {
541
+ if (diff > 0)
1018
542
  console.log(
1019
543
  import_chalk3.default.green(
1020
544
  ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
1021
545
  )
1022
546
  );
1023
- } else if (diff < 0) {
547
+ else if (diff < 0)
1024
548
  console.log(
1025
549
  import_chalk3.default.red(
1026
550
  ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
1027
551
  )
1028
552
  );
1029
- } else {
553
+ else
1030
554
  console.log(
1031
555
  import_chalk3.default.blue(
1032
- ` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
556
+ ` \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
1033
557
  )
1034
558
  );
1035
- }
1036
- scoringResult.trend = {
1037
- previousScore: prevScore,
1038
- difference: diff
1039
- };
1040
- } else {
1041
- console.log(
1042
- import_chalk3.default.yellow(
1043
- `
1044
- \u26A0\uFE0F Previous report at ${options.compareTo} does not contain an overall score.`
1045
- )
1046
- );
1047
559
  }
1048
560
  } catch (e) {
1049
561
  void e;
1050
- console.log(
1051
- import_chalk3.default.yellow(
1052
- `
1053
- \u26A0\uFE0F Could not read or parse previous report at ${options.compareTo}.`
1054
- )
1055
- );
1056
562
  }
1057
563
  }
1058
564
  const totalWastedDuplication = (scoringResult.breakdown || []).reduce(
@@ -1066,7 +572,8 @@ async function scanAction(directory, options) {
1066
572
  const totalContext = Math.max(
1067
573
  ...(scoringResult.breakdown || []).map(
1068
574
  (s) => s.tokenBudget?.totalContextTokens || 0
1069
- )
575
+ ),
576
+ 0
1070
577
  );
1071
578
  if (totalContext > 0) {
1072
579
  const unifiedBudget = (0, import_core3.calculateTokenBudget)({
@@ -1077,35 +584,17 @@ async function scanAction(directory, options) {
1077
584
  chattiness: 0
1078
585
  }
1079
586
  });
1080
- const targetModel = options.model || "claude-4.6";
1081
- const modelPreset = (0, import_core3.getModelPreset)(targetModel);
587
+ const modelPreset = (0, import_core3.getModelPreset)(options.model || "claude-4.6");
1082
588
  const costEstimate = (0, import_core3.estimateCostFromBudget)(unifiedBudget, modelPreset);
1083
- const barWidth = 20;
1084
- const filled = Math.round(unifiedBudget.efficiencyRatio * barWidth);
1085
- const bar = import_chalk3.default.green("\u2588".repeat(filled)) + import_chalk3.default.dim("\u2591".repeat(barWidth - filled));
1086
- console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis (v0.13)"));
1087
- console.log(
1088
- ` Efficiency: [${bar}] ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`
1089
- );
1090
- console.log(
1091
- ` Total Context: ${import_chalk3.default.bold(unifiedBudget.totalContextTokens.toLocaleString())} tokens`
1092
- );
589
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis"));
1093
590
  console.log(
1094
- ` Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())} (${(unifiedBudget.wastedTokens.total / unifiedBudget.totalContextTokens * 100).toFixed(1)}%)`
591
+ ` Efficiency: ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`
1095
592
  );
1096
- console.log(` Waste Breakdown:`);
1097
593
  console.log(
1098
- ` \u2022 Duplication: ${unifiedBudget.wastedTokens.bySource.duplication.toLocaleString()} tokens`
594
+ ` Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())}`
1099
595
  );
1100
596
  console.log(
1101
- ` \u2022 Fragmentation: ${unifiedBudget.wastedTokens.bySource.fragmentation.toLocaleString()} tokens`
1102
- );
1103
- console.log(
1104
- ` Potential Savings: ${import_chalk3.default.green(unifiedBudget.potentialRetrievableTokens.toLocaleString())} tokens retrievable`
1105
- );
1106
- console.log(
1107
- `
1108
- Est. Monthly Cost (${modelPreset.name}): ${import_chalk3.default.bold("$" + costEstimate.total)} [range: $${costEstimate.range[0]}-$${costEstimate.range[1]}]`
597
+ ` Est. Monthly Cost (${modelPreset.name}): ${import_chalk3.default.bold("$" + costEstimate.total)}`
1109
598
  );
1110
599
  scoringResult.tokenBudget = unifiedBudget;
1111
600
  scoringResult.costEstimate = {
@@ -1113,85 +602,31 @@ async function scanAction(directory, options) {
1113
602
  ...costEstimate
1114
603
  };
1115
604
  }
1116
- if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
605
+ if (scoringResult.breakdown) {
1117
606
  console.log(import_chalk3.default.bold("\nTool breakdown:"));
1118
607
  scoringResult.breakdown.forEach((tool) => {
1119
608
  const rating = (0, import_core3.getRating)(tool.score);
1120
- const rd = (0, import_core3.getRatingDisplay)(rating);
1121
- console.log(
1122
- ` - ${tool.toolName}: ${tool.score}/100 (${rating}) ${rd.emoji}`
1123
- );
609
+ console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
1124
610
  });
1125
- console.log();
1126
- if (finalOptions.scoring?.showBreakdown) {
1127
- console.log(import_chalk3.default.bold("Detailed tool breakdown:"));
1128
- scoringResult.breakdown.forEach((tool) => {
1129
- console.log((0, import_core3.formatToolScore)(tool));
1130
- });
1131
- console.log();
1132
- }
1133
611
  }
1134
612
  }
1135
613
  const mapToUnifiedReport = (res, scoring) => {
1136
614
  const allResults = [];
1137
- let totalFilesSet = /* @__PURE__ */ new Set();
615
+ const totalFilesSet = /* @__PURE__ */ new Set();
1138
616
  let criticalCount = 0;
1139
617
  let majorCount = 0;
1140
- const collect = (spokeRes, defaultType = import_core3.IssueType.AiSignalClarity) => {
618
+ res.summary.toolsRun.forEach((toolId) => {
619
+ const spokeRes = res[toolId];
1141
620
  if (!spokeRes || !spokeRes.results) return;
1142
621
  spokeRes.results.forEach((r) => {
1143
- const fileName = r.fileName || r.file || "unknown";
1144
- totalFilesSet.add(fileName);
1145
- const normalizedResult = {
1146
- fileName,
1147
- issues: [],
1148
- metrics: r.metrics || { tokenCost: r.tokenCost || 0 }
1149
- };
1150
- if (r.issues && Array.isArray(r.issues)) {
1151
- r.issues.forEach((i) => {
1152
- const normalizedIssue = typeof i === "string" ? {
1153
- type: defaultType,
1154
- severity: r.severity || import_core3.Severity.Info,
1155
- message: i,
1156
- location: { file: fileName, line: 1 }
1157
- } : {
1158
- type: i.type || defaultType,
1159
- severity: i.severity || r.severity || import_core3.Severity.Info,
1160
- message: i.message || String(i),
1161
- location: i.location || { file: fileName, line: 1 },
1162
- suggestion: i.suggestion
1163
- };
1164
- if (normalizedIssue.severity === import_core3.Severity.Critical || normalizedIssue.severity === "critical")
1165
- criticalCount++;
1166
- if (normalizedIssue.severity === import_core3.Severity.Major || normalizedIssue.severity === "major")
1167
- majorCount++;
1168
- normalizedResult.issues.push(normalizedIssue);
1169
- });
1170
- } else if (r.severity) {
1171
- const normalizedIssue = {
1172
- type: defaultType,
1173
- severity: r.severity,
1174
- message: r.message || "General issue",
1175
- location: { file: fileName, line: 1 }
1176
- };
1177
- if (normalizedIssue.severity === import_core3.Severity.Critical || normalizedIssue.severity === "critical")
1178
- criticalCount++;
1179
- if (normalizedIssue.severity === import_core3.Severity.Major || normalizedIssue.severity === "major")
1180
- majorCount++;
1181
- normalizedResult.issues.push(normalizedIssue);
1182
- }
1183
- allResults.push(normalizedResult);
622
+ totalFilesSet.add(r.fileName);
623
+ allResults.push(r);
624
+ r.issues?.forEach((i) => {
625
+ if (i.severity === import_core3.Severity.Critical) criticalCount++;
626
+ if (i.severity === import_core3.Severity.Major) majorCount++;
627
+ });
1184
628
  });
1185
- };
1186
- collect(res.patternDetect, import_core3.IssueType.DuplicatePattern);
1187
- collect(res.contextAnalyzer, import_core3.IssueType.ContextFragmentation);
1188
- collect(res.consistency, import_core3.IssueType.NamingInconsistency);
1189
- collect(res.docDrift, import_core3.IssueType.DocDrift);
1190
- collect(res.dependencyHealth, import_core3.IssueType.DependencyHealth);
1191
- collect(res.aiSignalClarity, import_core3.IssueType.AiSignalClarity);
1192
- collect(res.agentGrounding, import_core3.IssueType.AgentNavigationFailure);
1193
- collect(res.testability, import_core3.IssueType.LowTestability);
1194
- collect(res.changeAmplification, import_core3.IssueType.ChangeAmplification);
629
+ });
1195
630
  return {
1196
631
  ...res,
1197
632
  results: allResults,
@@ -1204,199 +639,70 @@ async function scanAction(directory, options) {
1204
639
  scoring
1205
640
  };
1206
641
  };
642
+ const outputData = {
643
+ ...mapToUnifiedReport(results, scoringResult),
644
+ repository: repoMetadata
645
+ };
1207
646
  const outputFormat = options.output || finalOptions.output?.format || "console";
1208
- const userOutputFile = options.outputFile || finalOptions.output?.file;
647
+ const outputPath = (0, import_core3.resolveOutputPath)(
648
+ options.outputFile || finalOptions.output?.file,
649
+ `aiready-report-${getReportTimestamp()}.json`,
650
+ resolvedDir
651
+ );
1209
652
  if (outputFormat === "json") {
1210
- const timestamp = getReportTimestamp();
1211
- const defaultFilename = `aiready-report-${timestamp}.json`;
1212
- const outputPath = (0, import_core3.resolveOutputPath)(
1213
- userOutputFile,
1214
- defaultFilename,
1215
- resolvedDir
1216
- );
1217
- const outputData = {
1218
- ...mapToUnifiedReport(results, scoringResult),
1219
- repository: repoMetadata
1220
- };
1221
653
  (0, import_core3.handleJSONOutput)(
1222
654
  outputData,
1223
655
  outputPath,
1224
656
  `\u2705 Report saved to ${outputPath}`
1225
657
  );
1226
- if (options.upload) {
1227
- console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1228
- await uploadAction(outputPath, {
1229
- apiKey: options.apiKey,
1230
- server: options.server
1231
- });
1232
- }
1233
- await warnIfGraphCapExceeded(outputData, resolvedDir);
1234
658
  } else {
1235
- const timestamp = getReportTimestamp();
1236
- const defaultFilename = `aiready-report-${timestamp}.json`;
1237
- const outputPath = (0, import_core3.resolveOutputPath)(
1238
- userOutputFile,
1239
- defaultFilename,
1240
- resolvedDir
1241
- );
1242
- const outputData = {
1243
- ...mapToUnifiedReport(results, scoringResult),
1244
- repository: repoMetadata
1245
- };
1246
659
  try {
1247
660
  (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
1248
661
  console.log(import_chalk3.default.dim(`\u2705 Report auto-persisted to ${outputPath}`));
1249
- if (options.upload) {
1250
- console.log(import_chalk3.default.blue("\n\u{1F4E4} Automatic upload triggered..."));
1251
- await uploadAction(outputPath, {
1252
- apiKey: options.apiKey,
1253
- server: options.server
1254
- });
1255
- }
1256
- await warnIfGraphCapExceeded(outputData, resolvedDir);
1257
662
  } catch (err) {
1258
663
  void err;
1259
664
  }
1260
665
  }
1261
- const isCI = options.ci || process.env.CI === "true" || process.env.GITHUB_ACTIONS === "true";
666
+ if (options.upload) {
667
+ await uploadAction(outputPath, {
668
+ apiKey: options.apiKey,
669
+ server: options.server
670
+ });
671
+ }
672
+ await warnIfGraphCapExceeded(outputData, resolvedDir);
673
+ const isCI = options.ci || process.env.CI === "true";
1262
674
  if (isCI && scoringResult) {
1263
675
  const threshold = options.threshold ? parseInt(options.threshold) : void 0;
1264
676
  const failOnLevel = options.failOn || "critical";
1265
- if (process.env.GITHUB_ACTIONS === "true") {
1266
- console.log(`
1267
- ::group::AI Readiness Score`);
1268
- console.log(`score=${scoringResult.overall}`);
1269
- if (scoringResult.breakdown) {
1270
- scoringResult.breakdown.forEach((tool) => {
1271
- console.log(`${tool.toolName}=${tool.score}`);
1272
- });
1273
- }
1274
- console.log("::endgroup::");
1275
- if (threshold && scoringResult.overall < threshold) {
1276
- console.log(
1277
- `::error::AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`
1278
- );
1279
- } else if (threshold) {
1280
- console.log(
1281
- `::notice::AI Readiness Score: ${scoringResult.overall}/100 (threshold: ${threshold})`
1282
- );
1283
- }
1284
- if (results.patternDetect) {
1285
- const criticalPatterns = results.patternDetect.results.flatMap(
1286
- (p) => p.issues.filter((i) => i.severity === import_core3.Severity.Critical)
1287
- );
1288
- criticalPatterns.slice(0, 10).forEach((issue) => {
1289
- console.log(
1290
- `::warning file=${issue.location?.file || "unknown"},line=${issue.location?.line || 1}::${issue.message}`
1291
- );
1292
- });
1293
- }
1294
- }
1295
677
  let shouldFail = false;
1296
678
  let failReason = "";
1297
679
  if (threshold && scoringResult.overall < threshold) {
1298
680
  shouldFail = true;
1299
- failReason = `AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`;
681
+ failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
1300
682
  }
683
+ const report = mapToUnifiedReport(results, scoringResult);
1301
684
  if (failOnLevel !== "none") {
1302
- const severityLevels = { critical: 4, major: 3, minor: 2, any: 1 };
1303
- const minSeverity = severityLevels[failOnLevel] || 4;
1304
- let criticalCount = 0;
1305
- let majorCount = 0;
1306
- if (results.patternDetect) {
1307
- results.patternDetect.results.forEach((p) => {
1308
- p.issues.forEach((i) => {
1309
- if (i.severity === import_core3.Severity.Critical) criticalCount++;
1310
- if (i.severity === import_core3.Severity.Major) majorCount++;
1311
- });
1312
- });
1313
- }
1314
- if (results.contextAnalyzer) {
1315
- results.contextAnalyzer.results.forEach((c) => {
1316
- if (c.severity === import_core3.Severity.Critical) criticalCount++;
1317
- if (c.severity === import_core3.Severity.Major) majorCount++;
1318
- });
1319
- }
1320
- if (results.consistency) {
1321
- results.consistency.results.forEach((r) => {
1322
- r.issues?.forEach((i) => {
1323
- if (i.severity === import_core3.Severity.Critical) criticalCount++;
1324
- if (i.severity === import_core3.Severity.Major) majorCount++;
1325
- });
1326
- });
1327
- }
1328
- if (minSeverity >= 4 && criticalCount > 0) {
685
+ if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
1329
686
  shouldFail = true;
1330
- failReason = `Found ${criticalCount} critical issues`;
1331
- } else if (minSeverity >= 3 && criticalCount + majorCount > 0) {
687
+ failReason = `Found ${report.summary.criticalIssues} critical issues`;
688
+ } else if (failOnLevel === "major" && report.summary.criticalIssues + report.summary.majorIssues > 0) {
1332
689
  shouldFail = true;
1333
- failReason = `Found ${criticalCount} critical and ${majorCount} major issues`;
690
+ failReason = `Found ${report.summary.criticalIssues} critical and ${report.summary.majorIssues} major issues`;
1334
691
  }
1335
692
  }
1336
693
  if (shouldFail) {
1337
- console.log(import_chalk3.default.red("\n\u{1F6AB} PR BLOCKED: AI Readiness Check Failed"));
1338
- console.log(import_chalk3.default.red(` Reason: ${failReason}`));
1339
- console.log(import_chalk3.default.dim("\n Remediation steps:"));
1340
- console.log(
1341
- import_chalk3.default.dim(" 1. Run `aiready scan` locally to see detailed issues")
1342
- );
1343
- console.log(import_chalk3.default.dim(" 2. Fix the critical issues before merging"));
1344
- console.log(
1345
- import_chalk3.default.dim(
1346
- " 3. Consider upgrading to Team plan for historical tracking: https://getaiready.dev/pricing"
1347
- )
1348
- );
694
+ console.log(import_chalk3.default.red(`
695
+ \u{1F6AB} PR BLOCKED: ${failReason}`));
1349
696
  process.exit(1);
1350
697
  } else {
1351
- console.log(import_chalk3.default.green("\n\u2705 PR PASSED: AI Readiness Check"));
1352
- if (threshold) {
1353
- console.log(
1354
- import_chalk3.default.green(
1355
- ` Score: ${scoringResult.overall}/100 (threshold: ${threshold})`
1356
- )
1357
- );
1358
- }
1359
- console.log(
1360
- import_chalk3.default.dim(
1361
- "\n \u{1F4A1} Track historical trends: https://getaiready.dev \u2014 Team plan $99/mo"
1362
- )
1363
- );
698
+ console.log(import_chalk3.default.green("\n\u2705 PR PASSED"));
1364
699
  }
1365
700
  }
1366
701
  } catch (error) {
1367
702
  (0, import_core3.handleCLIError)(error, "Analysis");
1368
703
  }
1369
704
  }
1370
- var scanHelpText = `
1371
- EXAMPLES:
1372
- $ aiready scan # Analyze all tools
1373
- $ aiready scan --tools patterns,context # Skip consistency
1374
- $ aiready scan --profile agentic # Optimize for AI agent execution
1375
- $ aiready scan --profile security # Optimize for secure coding (testability)
1376
- $ aiready scan --compare-to prev-report.json # Compare trends against previous run
1377
- $ aiready scan --score --threshold 75 # CI/CD with threshold
1378
- $ aiready scan --ci --threshold 70 # GitHub Actions gatekeeper
1379
- $ aiready scan --ci --fail-on major # Fail on major+ issues
1380
- $ aiready scan --output json --output-file report.json
1381
- $ aiready scan --upload --api-key ar_... # Automatic platform upload
1382
- $ aiready scan --upload --server custom-url.com # Upload to custom platform
1383
-
1384
- PROFILES:
1385
- agentic: aiSignalClarity, grounding, testability
1386
- cost: patterns, context
1387
- security: consistency, testability
1388
- onboarding: context, consistency, grounding
1389
-
1390
- CI/CD INTEGRATION (Gatekeeper Mode):
1391
- Use --ci for GitHub Actions integration:
1392
- - Outputs GitHub Actions annotations for PR checks
1393
- - Fails with exit code 1 if threshold not met
1394
- - Shows clear "blocked" message with remediation steps
1395
-
1396
- Example GitHub Actions workflow:
1397
- - name: AI Readiness Check
1398
- run: aiready scan --ci --threshold 70
1399
- `;
705
+ var scanHelpText = `...`;
1400
706
 
1401
707
  // src/commands/patterns.ts
1402
708
  var import_chalk4 = __toESM(require("chalk"));
@@ -1439,8 +745,8 @@ async function patternsAction(directory, options) {
1439
745
  defaults,
1440
746
  cliOptions
1441
747
  );
1442
- const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
1443
- const { results, duplicates } = await analyzePatterns2(finalOptions);
748
+ const { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
749
+ const { results, duplicates } = await analyzePatterns(finalOptions);
1444
750
  const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1445
751
  const summary = generateSummary(results);
1446
752
  let patternScore;
@@ -1585,8 +891,8 @@ async function contextAction(directory, options) {
1585
891
  );
1586
892
  console.log(` Analysis focus: ${finalOptions.focus}`);
1587
893
  console.log("");
1588
- const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1589
- const results = await analyzeContext2(finalOptions);
894
+ const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
895
+ const results = await analyzeContext(finalOptions);
1590
896
  const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
1591
897
  const summary = generateSummary(results);
1592
898
  let contextScore;
@@ -1770,8 +1076,8 @@ async function consistencyAction(directory, options) {
1770
1076
  include: options.include?.split(","),
1771
1077
  exclude: options.exclude?.split(",")
1772
1078
  });
1773
- const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
1774
- const report = await analyzeConsistency2(finalOptions);
1079
+ const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1080
+ const report = await analyzeConsistency(finalOptions);
1775
1081
  const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
1776
1082
  let consistencyScore;
1777
1083
  if (options.score) {