@aiready/cli 0.10.6 → 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,357 +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
- 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 });
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
+ }
224
91
  }
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
+ if (!provider) {
93
+ console.warn(
94
+ `\u26A0\uFE0F Warning: Tool provider for '${toolName}' not found. Skipping.`
95
+ );
96
+ continue;
242
97
  }
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
98
  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),
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),
264
107
  0
265
108
  );
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;
278
- }
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
- 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
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
+ }
292
115
  }
293
- });
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]
116
+ }
117
+ const camelCaseId = provider.id.replace(
118
+ /-([a-z])/g,
119
+ (g) => g[1].toUpperCase()
316
120
  );
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);
121
+ if (camelCaseId !== provider.id && !result[camelCaseId]) {
122
+ result[camelCaseId] = output;
123
+ }
327
124
  } catch (err) {
328
- void err;
125
+ console.error(`\u274C Error running tool '${provider.id}':`, err);
329
126
  }
330
127
  }
331
- if (results[import_core.ToolName.TestabilityIndex]) {
332
- const { calculateTestabilityScore } = await import("@aiready/testability");
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;
333
138
  try {
334
- const tbScore = calculateTestabilityScore(
335
- results[import_core.ToolName.TestabilityIndex]
336
- );
337
- toolScores.set(import_core.ToolName.TestabilityIndex, tbScore);
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
+ });
163
+ }
164
+ }
165
+ toolScores.set(toolId, toolScore);
338
166
  } catch (err) {
339
- void err;
167
+ console.error(`\u274C Error scoring tool '${toolId}':`, err);
340
168
  }
341
169
  }
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
170
  if (toolScores.size === 0) {
391
171
  return {
392
172
  overall: 0,
@@ -521,12 +301,6 @@ function generateMarkdownReport(report, elapsedTime) {
521
301
  }
522
302
  return markdown;
523
303
  }
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
304
 
531
305
  // src/commands/upload.ts
532
306
  var import_fs2 = __toESM(require("fs"));
@@ -640,14 +414,14 @@ async function scanAction(directory, options) {
640
414
  try {
641
415
  const defaults = {
642
416
  tools: [
643
- "patterns",
644
- "context",
645
- "consistency",
417
+ "pattern-detect",
418
+ "context-analyzer",
419
+ "naming-consistency",
646
420
  "ai-signal-clarity",
647
421
  "agent-grounding",
648
- "testability",
422
+ "testability-index",
649
423
  "doc-drift",
650
- "deps-health",
424
+ "dependency-health",
651
425
  "change-amplification"
652
426
  ],
653
427
  include: void 0,
@@ -657,35 +431,37 @@ async function scanAction(directory, options) {
657
431
  file: void 0
658
432
  }
659
433
  };
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;
434
+ let profileTools = options.tools ? options.tools.split(",").map((t) => t.trim()) : void 0;
666
435
  if (options.profile) {
667
436
  switch (options.profile.toLowerCase()) {
668
437
  case "agentic":
669
438
  profileTools = [
670
- "ai-signal-clarity",
671
- "agent-grounding",
672
- "testability"
439
+ import_core3.ToolName.AiSignalClarity,
440
+ import_core3.ToolName.AgentGrounding,
441
+ import_core3.ToolName.TestabilityIndex
673
442
  ];
674
443
  break;
675
444
  case "cost":
676
- profileTools = ["patterns", "context"];
445
+ profileTools = [import_core3.ToolName.PatternDetect, import_core3.ToolName.ContextAnalyzer];
677
446
  break;
678
447
  case "security":
679
- profileTools = ["consistency", "testability"];
448
+ profileTools = [
449
+ import_core3.ToolName.NamingConsistency,
450
+ import_core3.ToolName.TestabilityIndex
451
+ ];
680
452
  break;
681
453
  case "onboarding":
682
- profileTools = ["context", "consistency", "agent-grounding"];
454
+ profileTools = [
455
+ import_core3.ToolName.ContextAnalyzer,
456
+ import_core3.ToolName.NamingConsistency,
457
+ import_core3.ToolName.AgentGrounding
458
+ ];
683
459
  break;
684
460
  default:
685
461
  console.log(
686
462
  import_chalk3.default.yellow(
687
463
  `
688
- \u26A0\uFE0F Unknown profile '${options.profile}'. Using specified tools or defaults.`
464
+ \u26A0\uFE0F Unknown profile '${options.profile}'. Using defaults.`
689
465
  )
690
466
  );
691
467
  }
@@ -694,16 +470,14 @@ async function scanAction(directory, options) {
694
470
  include: options.include?.split(","),
695
471
  exclude: options.exclude?.split(",")
696
472
  };
697
- if (profileTools) {
698
- cliOverrides.tools = profileTools;
699
- }
473
+ if (profileTools) cliOverrides.tools = profileTools;
700
474
  const baseOptions = await (0, import_core3.loadMergedConfig)(
701
475
  resolvedDir,
702
476
  defaults,
703
477
  cliOverrides
704
478
  );
705
479
  let finalOptions = { ...baseOptions };
706
- if (baseOptions.tools.includes("patterns")) {
480
+ if (baseOptions.tools.includes(import_core3.ToolName.PatternDetect) || baseOptions.tools.includes("patterns")) {
707
481
  const { getSmartDefaults } = await import("@aiready/pattern-detect");
708
482
  const patternSmartDefaults = await getSmartDefaults(
709
483
  resolvedDir,
@@ -718,256 +492,21 @@ async function scanAction(directory, options) {
718
492
  console.log(import_chalk3.default.cyan("\n=== AIReady Run Preview ==="));
719
493
  console.log(
720
494
  import_chalk3.default.white("Tools to run:"),
721
- (finalOptions.tools || ["patterns", "context", "consistency"]).join(", ")
495
+ (finalOptions.tools || []).join(", ")
722
496
  );
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
497
  const progressCallback = (event) => {
832
498
  console.log(import_chalk3.default.cyan(`
833
499
  --- ${event.tool.toUpperCase()} RESULTS ---`));
834
- try {
835
- if (event.tool === "patterns") {
836
- const pr = event.data;
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)
837
507
  console.log(
838
- ` Duplicate patterns: ${import_chalk3.default.bold(String(pr.duplicates?.length || 0))}`
508
+ ` Files analyzed: ${import_chalk3.default.bold(res.summary.totalFiles)}`
839
509
  );
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;
960
- console.log(
961
- ` Coupling issues: ${import_chalk3.default.bold(String(dr.issues?.length || 0))}`
962
- );
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
510
  }
972
511
  };
973
512
  const results = await analyzeUnified({
@@ -977,44 +516,14 @@ async function scanAction(directory, options) {
977
516
  process.stdout.write(
978
517
  `\r\x1B[K [${processed}/${total}] ${message}...`
979
518
  );
980
- if (processed === total) {
981
- process.stdout.write("\n");
982
- }
519
+ if (processed === total) process.stdout.write("\n");
983
520
  },
984
521
  suppressToolConfig: true
985
522
  });
986
523
  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
524
  console.log(
993
525
  ` Total issues (all tools): ${import_chalk3.default.bold(String(results.summary.totalIssues || 0))}`
994
526
  );
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
527
  let scoringResult;
1019
528
  if (options.score || finalOptions.scoring?.showBreakdown) {
1020
529
  scoringResult = await scoreUnified(results, finalOptions);
@@ -1022,55 +531,34 @@ async function scanAction(directory, options) {
1022
531
  console.log(` ${(0, import_core3.formatScore)(scoringResult)}`);
1023
532
  if (options.compareTo) {
1024
533
  try {
1025
- const prevReportStr = (0, import_fs3.readFileSync)(
1026
- (0, import_path3.resolve)(process.cwd(), options.compareTo),
1027
- "utf8"
534
+ const prevReport = JSON.parse(
535
+ (0, import_fs3.readFileSync)((0, import_path3.resolve)(process.cwd(), options.compareTo), "utf8")
1028
536
  );
1029
- const prevReport = JSON.parse(prevReportStr);
1030
- const prevScore = prevReport.scoring?.score || prevReport.scoring?.overallScore;
537
+ const prevScore = prevReport.scoring?.overall || prevReport.scoring?.score;
1031
538
  if (typeof prevScore === "number") {
1032
539
  const diff = scoringResult.overall - prevScore;
1033
540
  const diffStr = diff > 0 ? `+${diff}` : String(diff);
1034
- console.log();
1035
- if (diff > 0) {
541
+ if (diff > 0)
1036
542
  console.log(
1037
543
  import_chalk3.default.green(
1038
544
  ` \u{1F4C8} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
1039
545
  )
1040
546
  );
1041
- } else if (diff < 0) {
547
+ else if (diff < 0)
1042
548
  console.log(
1043
549
  import_chalk3.default.red(
1044
550
  ` \u{1F4C9} Trend: ${diffStr} compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
1045
551
  )
1046
552
  );
1047
- } else {
553
+ else
1048
554
  console.log(
1049
555
  import_chalk3.default.blue(
1050
- ` \u2796 Trend: No change compared to ${options.compareTo} (${prevScore} \u2192 ${scoringResult.overall})`
556
+ ` \u2796 Trend: No change (${prevScore} \u2192 ${scoringResult.overall})`
1051
557
  )
1052
558
  );
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
559
  }
1066
560
  } catch (e) {
1067
561
  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
562
  }
1075
563
  }
1076
564
  const totalWastedDuplication = (scoringResult.breakdown || []).reduce(
@@ -1084,7 +572,8 @@ async function scanAction(directory, options) {
1084
572
  const totalContext = Math.max(
1085
573
  ...(scoringResult.breakdown || []).map(
1086
574
  (s) => s.tokenBudget?.totalContextTokens || 0
1087
- )
575
+ ),
576
+ 0
1088
577
  );
1089
578
  if (totalContext > 0) {
1090
579
  const unifiedBudget = (0, import_core3.calculateTokenBudget)({
@@ -1095,35 +584,17 @@ async function scanAction(directory, options) {
1095
584
  chattiness: 0
1096
585
  }
1097
586
  });
1098
- const targetModel = options.model || "claude-4.6";
1099
- const modelPreset = (0, import_core3.getModelPreset)(targetModel);
587
+ const modelPreset = (0, import_core3.getModelPreset)(options.model || "claude-4.6");
1100
588
  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
- );
589
+ console.log(import_chalk3.default.bold("\n\u{1F4CA} AI Token Budget Analysis"));
1118
590
  console.log(
1119
- ` \u2022 Fragmentation: ${unifiedBudget.wastedTokens.bySource.fragmentation.toLocaleString()} tokens`
591
+ ` Efficiency: ${(unifiedBudget.efficiencyRatio * 100).toFixed(0)}%`
1120
592
  );
1121
593
  console.log(
1122
- ` Potential Savings: ${import_chalk3.default.green(unifiedBudget.potentialRetrievableTokens.toLocaleString())} tokens retrievable`
594
+ ` Wasted Tokens: ${import_chalk3.default.red(unifiedBudget.wastedTokens.total.toLocaleString())}`
1123
595
  );
1124
596
  console.log(
1125
- `
1126
- 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)}`
1127
598
  );
1128
599
  scoringResult.tokenBudget = unifiedBudget;
1129
600
  scoringResult.costEstimate = {
@@ -1131,85 +602,31 @@ async function scanAction(directory, options) {
1131
602
  ...costEstimate
1132
603
  };
1133
604
  }
1134
- if (scoringResult.breakdown && scoringResult.breakdown.length > 0) {
605
+ if (scoringResult.breakdown) {
1135
606
  console.log(import_chalk3.default.bold("\nTool breakdown:"));
1136
607
  scoringResult.breakdown.forEach((tool) => {
1137
608
  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
- );
609
+ console.log(` - ${tool.toolName}: ${tool.score}/100 (${rating})`);
1142
610
  });
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
611
  }
1152
612
  }
1153
613
  const mapToUnifiedReport = (res, scoring) => {
1154
614
  const allResults = [];
1155
- let totalFilesSet = /* @__PURE__ */ new Set();
615
+ const totalFilesSet = /* @__PURE__ */ new Set();
1156
616
  let criticalCount = 0;
1157
617
  let majorCount = 0;
1158
- const collect = (spokeRes, defaultType = import_core3.IssueType.AiSignalClarity) => {
618
+ res.summary.toolsRun.forEach((toolId) => {
619
+ const spokeRes = res[toolId];
1159
620
  if (!spokeRes || !spokeRes.results) return;
1160
621
  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);
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
+ });
1202
628
  });
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);
629
+ });
1213
630
  return {
1214
631
  ...res,
1215
632
  results: allResults,
@@ -1222,199 +639,70 @@ async function scanAction(directory, options) {
1222
639
  scoring
1223
640
  };
1224
641
  };
642
+ const outputData = {
643
+ ...mapToUnifiedReport(results, scoringResult),
644
+ repository: repoMetadata
645
+ };
1225
646
  const outputFormat = options.output || finalOptions.output?.format || "console";
1226
- 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
+ );
1227
652
  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
653
  (0, import_core3.handleJSONOutput)(
1240
654
  outputData,
1241
655
  outputPath,
1242
656
  `\u2705 Report saved to ${outputPath}`
1243
657
  );
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
658
  } 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
659
  try {
1265
660
  (0, import_fs3.writeFileSync)(outputPath, JSON.stringify(outputData, null, 2));
1266
661
  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
662
  } catch (err) {
1276
663
  void err;
1277
664
  }
1278
665
  }
1279
- 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";
1280
674
  if (isCI && scoringResult) {
1281
675
  const threshold = options.threshold ? parseInt(options.threshold) : void 0;
1282
676
  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
677
  let shouldFail = false;
1314
678
  let failReason = "";
1315
679
  if (threshold && scoringResult.overall < threshold) {
1316
680
  shouldFail = true;
1317
- failReason = `AI Readiness Score ${scoringResult.overall} is below threshold ${threshold}`;
681
+ failReason = `Score ${scoringResult.overall} < threshold ${threshold}`;
1318
682
  }
683
+ const report = mapToUnifiedReport(results, scoringResult);
1319
684
  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) {
685
+ if (failOnLevel === "critical" && report.summary.criticalIssues > 0) {
1347
686
  shouldFail = true;
1348
- failReason = `Found ${criticalCount} critical issues`;
1349
- } 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) {
1350
689
  shouldFail = true;
1351
- failReason = `Found ${criticalCount} critical and ${majorCount} major issues`;
690
+ failReason = `Found ${report.summary.criticalIssues} critical and ${report.summary.majorIssues} major issues`;
1352
691
  }
1353
692
  }
1354
693
  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
- );
694
+ console.log(import_chalk3.default.red(`
695
+ \u{1F6AB} PR BLOCKED: ${failReason}`));
1367
696
  process.exit(1);
1368
697
  } 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
- );
698
+ console.log(import_chalk3.default.green("\n\u2705 PR PASSED"));
1382
699
  }
1383
700
  }
1384
701
  } catch (error) {
1385
702
  (0, import_core3.handleCLIError)(error, "Analysis");
1386
703
  }
1387
704
  }
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
- `;
705
+ var scanHelpText = `...`;
1418
706
 
1419
707
  // src/commands/patterns.ts
1420
708
  var import_chalk4 = __toESM(require("chalk"));
@@ -1457,8 +745,8 @@ async function patternsAction(directory, options) {
1457
745
  defaults,
1458
746
  cliOptions
1459
747
  );
1460
- const { analyzePatterns: analyzePatterns2, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
1461
- const { results, duplicates } = await analyzePatterns2(finalOptions);
748
+ const { analyzePatterns, generateSummary, calculatePatternScore } = await import("@aiready/pattern-detect");
749
+ const { results, duplicates } = await analyzePatterns(finalOptions);
1462
750
  const elapsedTime = (0, import_core4.getElapsedTime)(startTime);
1463
751
  const summary = generateSummary(results);
1464
752
  let patternScore;
@@ -1603,8 +891,8 @@ async function contextAction(directory, options) {
1603
891
  );
1604
892
  console.log(` Analysis focus: ${finalOptions.focus}`);
1605
893
  console.log("");
1606
- const { analyzeContext: analyzeContext2, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
1607
- const results = await analyzeContext2(finalOptions);
894
+ const { analyzeContext, generateSummary, calculateContextScore } = await import("@aiready/context-analyzer");
895
+ const results = await analyzeContext(finalOptions);
1608
896
  const elapsedTime = (0, import_core5.getElapsedTime)(startTime);
1609
897
  const summary = generateSummary(results);
1610
898
  let contextScore;
@@ -1788,8 +1076,8 @@ async function consistencyAction(directory, options) {
1788
1076
  include: options.include?.split(","),
1789
1077
  exclude: options.exclude?.split(",")
1790
1078
  });
1791
- const { analyzeConsistency: analyzeConsistency2, calculateConsistencyScore } = await import("@aiready/consistency");
1792
- const report = await analyzeConsistency2(finalOptions);
1079
+ const { analyzeConsistency, calculateConsistencyScore } = await import("@aiready/consistency");
1080
+ const report = await analyzeConsistency(finalOptions);
1793
1081
  const elapsedTime = (0, import_core6.getElapsedTime)(startTime);
1794
1082
  let consistencyScore;
1795
1083
  if (options.score) {