@aiready/cli 0.10.6 → 0.12.1

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