@aiready/cli 0.10.4 โ†’ 0.10.6

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.
@@ -24,6 +24,7 @@ import {
24
24
  getRepoMetadata,
25
25
  Severity,
26
26
  IssueType,
27
+ ToolName,
27
28
  type ToolScoringOutput,
28
29
  } from '@aiready/core';
29
30
  import { analyzeUnified, scoreUnified, type ScoringResult } from '../index';
@@ -465,30 +466,29 @@ export async function scanAction(directory: string, options: ScanOptions) {
465
466
  (finalOptions.tools || ['patterns', 'context', 'consistency']).join(', ')
466
467
  );
467
468
 
468
- // Results summary
469
469
  console.log(chalk.cyan('\nResults summary:'));
470
470
  console.log(
471
471
  ` Total issues (all tools): ${chalk.bold(String(results.summary.totalIssues || 0))}`
472
472
  );
473
- if (results.patternDetect) {
473
+ if (results[ToolName.PatternDetect]) {
474
474
  console.log(
475
- ` Duplicate patterns found: ${chalk.bold(String(results.patternDetect.duplicates?.length || 0))}`
475
+ ` Duplicate patterns found: ${chalk.bold(String(results[ToolName.PatternDetect].duplicates?.length || 0))}`
476
476
  );
477
477
  console.log(
478
- ` Pattern files with issues: ${chalk.bold(String(results.patternDetect.results.length || 0))}`
478
+ ` Pattern files with issues: ${chalk.bold(String(results[ToolName.PatternDetect].results.length || 0))}`
479
479
  );
480
480
  }
481
- if (results.contextAnalyzer)
481
+ if (results[ToolName.ContextAnalyzer])
482
482
  console.log(
483
- ` Context issues: ${chalk.bold(String(results.contextAnalyzer.results.length || 0))}`
483
+ ` Context issues: ${chalk.bold(String(results[ToolName.ContextAnalyzer].results.length || 0))}`
484
484
  );
485
- if (results.consistency)
485
+ if (results[ToolName.NamingConsistency])
486
486
  console.log(
487
- ` Consistency issues: ${chalk.bold(String(results.consistency.summary?.totalIssues || 0))}`
487
+ ` Consistency issues: ${chalk.bold(String(results[ToolName.NamingConsistency].summary?.totalIssues || 0))}`
488
488
  );
489
- if (results.changeAmplification)
489
+ if (results[ToolName.ChangeAmplification])
490
490
  console.log(
491
- ` Change amplification: ${chalk.bold(String(results.changeAmplification.summary?.score || 0))}/100`
491
+ ` Change amplification: ${chalk.bold(String(results[ToolName.ChangeAmplification].summary?.score || 0))}/100`
492
492
  );
493
493
  console.log(chalk.cyan('===========================\n'));
494
494
 
@@ -741,15 +741,15 @@ export async function scanAction(directory: string, options: ScanOptions) {
741
741
  });
742
742
  };
743
743
 
744
- collect(res.patternDetect, IssueType.DuplicatePattern);
745
- collect(res.contextAnalyzer, IssueType.ContextFragmentation);
746
- collect(res.consistency, IssueType.NamingInconsistency);
747
- collect(res.docDrift, IssueType.DocDrift);
748
- collect(res.dependencyHealth, IssueType.DependencyHealth);
749
- collect(res.aiSignalClarity, IssueType.AiSignalClarity);
750
- collect(res.agentGrounding, IssueType.AgentNavigationFailure);
751
- collect(res.testability, IssueType.LowTestability);
752
- collect(res.changeAmplification, IssueType.ChangeAmplification);
744
+ collect(res[ToolName.PatternDetect], IssueType.DuplicatePattern);
745
+ collect(res[ToolName.ContextAnalyzer], IssueType.ContextFragmentation);
746
+ collect(res[ToolName.NamingConsistency], IssueType.NamingInconsistency);
747
+ collect(res[ToolName.DocDrift], IssueType.DocDrift);
748
+ collect(res[ToolName.DependencyHealth], IssueType.DependencyHealth);
749
+ collect(res[ToolName.AiSignalClarity], IssueType.AiSignalClarity);
750
+ collect(res[ToolName.AgentGrounding], IssueType.AgentNavigationFailure);
751
+ collect(res[ToolName.TestabilityIndex], IssueType.LowTestability);
752
+ collect(res[ToolName.ChangeAmplification], IssueType.ChangeAmplification);
753
753
 
754
754
  return {
755
755
  ...res,
@@ -864,11 +864,13 @@ export async function scanAction(directory: string, options: ScanOptions) {
864
864
  }
865
865
 
866
866
  // Output annotations for critical issues
867
- if (results.patternDetect) {
868
- const criticalPatterns = results.patternDetect.results.flatMap(
869
- (p: any) =>
870
- p.issues.filter((i: any) => i.severity === Severity.Critical)
867
+ if (results[ToolName.PatternDetect]) {
868
+ const criticalPatterns = results[
869
+ ToolName.PatternDetect
870
+ ].results.flatMap((p: any) =>
871
+ p.issues.filter((i: any) => i.severity === Severity.Critical)
871
872
  );
873
+
872
874
  criticalPatterns.slice(0, 10).forEach((issue: any) => {
873
875
  console.log(
874
876
  `::warning file=${issue.location?.file || 'unknown'},line=${issue.location?.line || 1}::${issue.message}`
@@ -896,22 +898,22 @@ export async function scanAction(directory: string, options: ScanOptions) {
896
898
  let criticalCount = 0;
897
899
  let majorCount = 0;
898
900
 
899
- if (results.patternDetect) {
900
- results.patternDetect.results.forEach((p: any) => {
901
+ if (results[ToolName.PatternDetect]) {
902
+ results[ToolName.PatternDetect].results.forEach((p: any) => {
901
903
  p.issues.forEach((i: any) => {
902
904
  if (i.severity === Severity.Critical) criticalCount++;
903
905
  if (i.severity === Severity.Major) majorCount++;
904
906
  });
905
907
  });
906
908
  }
907
- if (results.contextAnalyzer) {
908
- results.contextAnalyzer.results.forEach((c: any) => {
909
+ if (results[ToolName.ContextAnalyzer]) {
910
+ results[ToolName.ContextAnalyzer].results.forEach((c: any) => {
909
911
  if (c.severity === Severity.Critical) criticalCount++;
910
912
  if (c.severity === Severity.Major) majorCount++;
911
913
  });
912
914
  }
913
- if (results.consistency) {
914
- results.consistency.results.forEach((r: any) => {
915
+ if (results[ToolName.NamingConsistency]) {
916
+ results[ToolName.NamingConsistency].results.forEach((r: any) => {
915
917
  r.issues?.forEach((i: any) => {
916
918
  if (i.severity === Severity.Critical) criticalCount++;
917
919
  if (i.severity === Severity.Major) majorCount++;
package/src/index.ts CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  type ToolScoringOutput,
8
8
  type ScoringResult,
9
9
  calculateTokenBudget,
10
+ ToolName,
10
11
  } from '@aiready/core';
11
12
  export type { ToolScoringOutput, ScoringResult };
12
13
 
@@ -32,23 +33,29 @@ export interface UnifiedAnalysisOptions extends ScanOptions {
32
33
  }
33
34
 
34
35
  export interface UnifiedAnalysisResult {
35
- // Standardized keys matching tool names
36
- patternDetect?: SpokeOutput & { duplicates: any[] };
37
- contextAnalyzer?: SpokeOutput;
38
- consistency?: SpokeOutput;
39
- docDrift?: SpokeOutput;
40
- dependencyHealth?: SpokeOutput;
41
- aiSignalClarity?: any;
42
- agentGrounding?: any;
43
- testability?: any;
44
- changeAmplification?: SpokeOutput;
45
-
36
+ // Canonical keys matching ToolName enum members
37
+ [ToolName.PatternDetect]?: SpokeOutput & { duplicates: any[] };
38
+ [ToolName.ContextAnalyzer]?: SpokeOutput;
39
+ [ToolName.NamingConsistency]?: SpokeOutput;
40
+ [ToolName.DocDrift]?: SpokeOutput;
41
+ [ToolName.DependencyHealth]?: SpokeOutput;
42
+ [ToolName.AiSignalClarity]?: any;
43
+ [ToolName.AgentGrounding]?: any;
44
+ [ToolName.TestabilityIndex]?: any;
45
+ [ToolName.ChangeAmplification]?: SpokeOutput;
46
+
47
+ // Legacy/Internal metadata
46
48
  summary: {
47
49
  totalIssues: number;
48
50
  toolsRun: string[];
49
51
  executionTime: number;
50
52
  };
51
53
  scoring?: ScoringResult;
54
+ // Compatibility fallbacks (deprecated)
55
+ /** @deprecated use [ToolName.PatternDetect] */
56
+ patternDetect?: any;
57
+ /** @deprecated use [ToolName.ContextAnalyzer] */
58
+ contextAnalyzer?: any;
52
59
  }
53
60
 
54
61
  // Severity ordering (higher number = more severe)
@@ -114,11 +121,14 @@ export async function analyzeUnified(
114
121
  if (options.progressCallback) {
115
122
  options.progressCallback({ tool: 'patterns', data: patternResult });
116
123
  }
117
- result.patternDetect = {
124
+ const output = {
118
125
  results: sortBySeverity(patternResult.results),
119
126
  summary: patternResult.summary || {},
120
127
  duplicates: patternResult.duplicates || [],
121
128
  };
129
+ result[ToolName.PatternDetect] = output;
130
+ result.patternDetect = output; // Compatibility fallback
131
+
122
132
  result.summary.totalIssues += patternResult.results.reduce(
123
133
  (sum, file) => sum + file.issues.length,
124
134
  0
@@ -141,10 +151,13 @@ export async function analyzeUnified(
141
151
 
142
152
  const { generateSummary: genContextSummary } =
143
153
  await import('@aiready/context-analyzer');
144
- result.contextAnalyzer = {
154
+ const output = {
145
155
  results: sorted,
146
156
  summary: genContextSummary(sorted),
147
157
  };
158
+ result[ToolName.ContextAnalyzer] = output;
159
+ result.contextAnalyzer = output; // Compatibility fallback
160
+
148
161
  result.summary.totalIssues += sorted.length;
149
162
  }
150
163
 
@@ -160,7 +173,7 @@ export async function analyzeUnified(
160
173
  if (options.progressCallback) {
161
174
  options.progressCallback({ tool: 'consistency', data: report });
162
175
  }
163
- result.consistency = {
176
+ result[ToolName.NamingConsistency] = {
164
177
  results: report.results ? sortBySeverity(report.results) : [],
165
178
  summary: report.summary,
166
179
  };
@@ -179,7 +192,7 @@ export async function analyzeUnified(
179
192
  if (options.progressCallback) {
180
193
  options.progressCallback({ tool: 'doc-drift', data: report });
181
194
  }
182
- result.docDrift = {
195
+ result[ToolName.DocDrift] = {
183
196
  results: (report as any).results || (report as any).issues || [],
184
197
  summary: report.summary || {},
185
198
  };
@@ -201,7 +214,7 @@ export async function analyzeUnified(
201
214
  if (options.progressCallback) {
202
215
  options.progressCallback({ tool: 'deps-health', data: report });
203
216
  }
204
- result.dependencyHealth = {
217
+ result[ToolName.DependencyHealth] = {
205
218
  results: (report as any).results || (report as any).issues || [],
206
219
  summary: report.summary || {},
207
220
  };
@@ -224,7 +237,7 @@ export async function analyzeUnified(
224
237
  if (options.progressCallback) {
225
238
  options.progressCallback({ tool: 'ai-signal-clarity', data: report });
226
239
  }
227
- result.aiSignalClarity = {
240
+ result[ToolName.AiSignalClarity] = {
228
241
  ...report,
229
242
  results: report.results || report.issues || [],
230
243
  summary: report.summary || {},
@@ -248,7 +261,7 @@ export async function analyzeUnified(
248
261
  if (options.progressCallback) {
249
262
  options.progressCallback({ tool: 'agent-grounding', data: report });
250
263
  }
251
- result.agentGrounding = {
264
+ result[ToolName.AgentGrounding] = {
252
265
  ...(report as any),
253
266
  results: (report as any).results || (report as any).issues || [],
254
267
  summary: report.summary || {},
@@ -272,7 +285,7 @@ export async function analyzeUnified(
272
285
  if (options.progressCallback) {
273
286
  options.progressCallback({ tool: 'testability', data: report });
274
287
  }
275
- result.testability = {
288
+ result[ToolName.TestabilityIndex] = {
276
289
  ...(report as any),
277
290
  results: (report as any).results || (report as any).issues || [],
278
291
  summary: report.summary || {},
@@ -297,7 +310,7 @@ export async function analyzeUnified(
297
310
  if (options.progressCallback) {
298
311
  options.progressCallback({ tool: 'change-amplification', data: report });
299
312
  }
300
- result.changeAmplification = {
313
+ result[ToolName.ChangeAmplification] = {
301
314
  results: report.results || [],
302
315
  summary: report.summary || {},
303
316
  };
@@ -315,16 +328,17 @@ export async function scoreUnified(
315
328
  const toolScores: Map<string, ToolScoringOutput> = new Map();
316
329
 
317
330
  // Patterns score
318
- if (results.patternDetect) {
331
+ if (results[ToolName.PatternDetect]) {
332
+ const data = results[ToolName.PatternDetect];
319
333
  const { calculatePatternScore } = await import('@aiready/pattern-detect');
320
334
  try {
321
335
  const patternScore = calculatePatternScore(
322
- results.patternDetect.duplicates,
323
- results.patternDetect.results?.length || 0
336
+ data.duplicates,
337
+ data.results?.length || 0
324
338
  );
325
339
 
326
340
  // Calculate token budget for patterns (waste = duplication)
327
- const wastedTokens = results.patternDetect.duplicates.reduce(
341
+ const wastedTokens = data.duplicates.reduce(
328
342
  (sum: number, d: any) => sum + (d.tokenCost || 0),
329
343
  0
330
344
  );
@@ -337,17 +351,18 @@ export async function scoreUnified(
337
351
  },
338
352
  });
339
353
 
340
- toolScores.set('pattern-detect', patternScore);
354
+ toolScores.set(ToolName.PatternDetect, patternScore);
341
355
  } catch (err) {
342
356
  void err;
343
357
  }
344
358
  }
345
359
 
346
360
  // Context score
347
- if (results.contextAnalyzer) {
361
+ if (results[ToolName.ContextAnalyzer]) {
362
+ const data = results[ToolName.ContextAnalyzer];
348
363
  const { calculateContextScore } = await import('@aiready/context-analyzer');
349
364
  try {
350
- const ctxSummary = results.contextAnalyzer.summary;
365
+ const ctxSummary = data.summary;
351
366
  const contextScore = calculateContextScore(ctxSummary);
352
367
 
353
368
  // Calculate token budget for context (waste = fragmentation + depth overhead)
@@ -360,72 +375,74 @@ export async function scoreUnified(
360
375
  },
361
376
  });
362
377
 
363
- toolScores.set('context-analyzer', contextScore);
378
+ toolScores.set(ToolName.ContextAnalyzer, contextScore);
364
379
  } catch (err) {
365
380
  void err;
366
381
  }
367
382
  }
368
383
 
369
384
  // Consistency score
370
- if (results.consistency) {
385
+ if (results[ToolName.NamingConsistency]) {
386
+ const data = results[ToolName.NamingConsistency];
371
387
  const { calculateConsistencyScore } = await import('@aiready/consistency');
372
388
  try {
373
- const issues =
374
- results.consistency.results?.flatMap((r: any) => r.issues) || [];
375
- const totalFiles = results.consistency.summary?.filesAnalyzed || 0;
389
+ const issues = data.results?.flatMap((r: any) => r.issues) || [];
390
+ const totalFiles = data.summary?.filesAnalyzed || 0;
376
391
  const consistencyScore = calculateConsistencyScore(issues, totalFiles);
377
- toolScores.set('consistency', consistencyScore);
392
+ toolScores.set(ToolName.NamingConsistency, consistencyScore);
378
393
  } catch (err) {
379
394
  void err;
380
395
  }
381
396
  }
382
397
 
383
398
  // AI signal clarity score
384
- if (results.aiSignalClarity) {
399
+ if (results[ToolName.AiSignalClarity]) {
385
400
  const { calculateAiSignalClarityScore } =
386
401
  await import('@aiready/ai-signal-clarity');
387
402
  try {
388
- const hrScore = calculateAiSignalClarityScore(results.aiSignalClarity);
389
- toolScores.set('ai-signal-clarity', hrScore);
403
+ const hrScore = calculateAiSignalClarityScore(
404
+ results[ToolName.AiSignalClarity]
405
+ );
406
+ toolScores.set(ToolName.AiSignalClarity, hrScore);
390
407
  } catch (err) {
391
408
  void err;
392
409
  }
393
410
  }
394
411
 
395
412
  // Agent grounding score
396
- if (results.agentGrounding) {
413
+ if (results[ToolName.AgentGrounding]) {
397
414
  const { calculateGroundingScore } =
398
415
  await import('@aiready/agent-grounding');
399
416
  try {
400
- const agScore = calculateGroundingScore(results.agentGrounding);
401
- toolScores.set('agent-grounding', agScore);
417
+ const agScore = calculateGroundingScore(results[ToolName.AgentGrounding]);
418
+ toolScores.set(ToolName.AgentGrounding, agScore);
402
419
  } catch (err) {
403
420
  void err;
404
421
  }
405
422
  }
406
423
 
407
424
  // Testability score
408
- if (results.testability) {
425
+ if (results[ToolName.TestabilityIndex]) {
409
426
  const { calculateTestabilityScore } = await import('@aiready/testability');
410
427
  try {
411
- const tbScore = calculateTestabilityScore(results.testability);
412
- toolScores.set('testability', tbScore);
428
+ const tbScore = calculateTestabilityScore(
429
+ results[ToolName.TestabilityIndex]
430
+ );
431
+ toolScores.set(ToolName.TestabilityIndex, tbScore);
413
432
  } catch (err) {
414
433
  void err;
415
434
  }
416
435
  }
417
436
 
418
437
  // Documentation Drift score
419
- if (results.docDrift) {
420
- toolScores.set('doc-drift', {
421
- toolName: 'doc-drift',
422
- score:
423
- results.docDrift.summary.score ||
424
- results.docDrift.summary.totalScore ||
425
- 0,
426
- rawMetrics: results.docDrift.summary,
438
+ if (results[ToolName.DocDrift]) {
439
+ const data = results[ToolName.DocDrift];
440
+ toolScores.set(ToolName.DocDrift, {
441
+ toolName: ToolName.DocDrift,
442
+ score: data.summary.score || data.summary.totalScore || 0,
443
+ rawMetrics: data.summary,
427
444
  factors: [],
428
- recommendations: (results.docDrift.summary.recommendations || []).map(
445
+ recommendations: (data.summary.recommendations || []).map(
429
446
  (action: string) => ({
430
447
  action,
431
448
  estimatedImpact: 5,
@@ -436,36 +453,38 @@ export async function scoreUnified(
436
453
  }
437
454
 
438
455
  // Dependency Health score
439
- if (results.dependencyHealth) {
440
- toolScores.set('dependency-health', {
441
- toolName: 'dependency-health',
442
- score: results.dependencyHealth.summary.score || 0,
443
- rawMetrics: results.dependencyHealth.summary,
456
+ if (results[ToolName.DependencyHealth]) {
457
+ const data = results[ToolName.DependencyHealth];
458
+ toolScores.set(ToolName.DependencyHealth, {
459
+ toolName: ToolName.DependencyHealth,
460
+ score: data.summary.score || 0,
461
+ rawMetrics: data.summary,
444
462
  factors: [],
445
- recommendations: (
446
- results.dependencyHealth.summary.recommendations || []
447
- ).map((action: string) => ({
448
- action,
449
- estimatedImpact: 5,
450
- priority: 'medium',
451
- })),
463
+ recommendations: (data.summary.recommendations || []).map(
464
+ (action: string) => ({
465
+ action,
466
+ estimatedImpact: 5,
467
+ priority: 'medium',
468
+ })
469
+ ),
452
470
  });
453
471
  }
454
472
 
455
473
  // Change Amplification score
456
- if (results.changeAmplification) {
457
- toolScores.set('change-amplification', {
458
- toolName: 'change-amplification',
459
- score: results.changeAmplification.summary.score || 0,
460
- rawMetrics: results.changeAmplification.summary,
474
+ if (results[ToolName.ChangeAmplification]) {
475
+ const data = results[ToolName.ChangeAmplification];
476
+ toolScores.set(ToolName.ChangeAmplification, {
477
+ toolName: ToolName.ChangeAmplification,
478
+ score: data.summary.score || 0,
479
+ rawMetrics: data.summary,
461
480
  factors: [],
462
- recommendations: (
463
- results.changeAmplification.summary.recommendations || []
464
- ).map((action: string) => ({
465
- action,
466
- estimatedImpact: 5,
467
- priority: 'medium',
468
- })),
481
+ recommendations: (data.summary.recommendations || []).map(
482
+ (action: string) => ({
483
+ action,
484
+ estimatedImpact: 5,
485
+ priority: 'medium',
486
+ })
487
+ ),
469
488
  });
470
489
  }
471
490
 
@@ -496,40 +515,40 @@ export function generateUnifiedSummary(result: UnifiedAnalysisResult): string {
496
515
  output += ` Total issues found: ${summary.totalIssues}\n`;
497
516
  output += ` Execution time: ${(summary.executionTime / 1000).toFixed(2)}s\n\n`;
498
517
 
499
- if (result.patternDetect) {
500
- output += `๐Ÿ” Pattern Analysis: ${result.patternDetect.results.length} issues\n`;
518
+ if (result[ToolName.PatternDetect]) {
519
+ output += `๐Ÿ” Pattern Analysis: ${result[ToolName.PatternDetect].results.length} issues\n`;
501
520
  }
502
521
 
503
- if (result.contextAnalyzer) {
504
- output += `๐Ÿง  Context Analysis: ${result.contextAnalyzer.results.length} issues\n`;
522
+ if (result[ToolName.ContextAnalyzer]) {
523
+ output += `๐Ÿง  Context Analysis: ${result[ToolName.ContextAnalyzer].results.length} issues\n`;
505
524
  }
506
525
 
507
- if (result.consistency) {
508
- output += `๐Ÿท๏ธ Consistency Analysis: ${result.consistency.summary.totalIssues} issues\n`;
526
+ if (result[ToolName.NamingConsistency]) {
527
+ output += `๐Ÿท๏ธ Consistency Analysis: ${result[ToolName.NamingConsistency].summary.totalIssues} issues\n`;
509
528
  }
510
529
 
511
- if (result.docDrift) {
512
- output += `๐Ÿ“ Doc Drift Analysis: ${result.docDrift.results?.length || 0} issues\n`;
530
+ if (result[ToolName.DocDrift]) {
531
+ output += `๐Ÿ“ Doc Drift Analysis: ${result[ToolName.DocDrift].results?.length || 0} issues\n`;
513
532
  }
514
533
 
515
- if (result.dependencyHealth) {
516
- output += `๐Ÿ“ฆ Dependency Health: ${result.dependencyHealth.results?.length || 0} issues\n`;
534
+ if (result[ToolName.DependencyHealth]) {
535
+ output += `๐Ÿ“ฆ Dependency Health: ${result[ToolName.DependencyHealth].results?.length || 0} issues\n`;
517
536
  }
518
537
 
519
- if (result.aiSignalClarity) {
520
- output += `๐Ÿง  AI Signal Clarity: ${result.aiSignalClarity.summary?.totalSignals || 0} signals\n`;
538
+ if (result[ToolName.AiSignalClarity]) {
539
+ output += `๐Ÿง  AI Signal Clarity: ${result[ToolName.AiSignalClarity].summary?.totalSignals || 0} signals\n`;
521
540
  }
522
541
 
523
- if (result.agentGrounding) {
524
- output += `๐Ÿงญ Agent Grounding: ${result.agentGrounding.results?.length || 0} issues\n`;
542
+ if (result[ToolName.AgentGrounding]) {
543
+ output += `๐Ÿงญ Agent Grounding: ${result[ToolName.AgentGrounding].results?.length || 0} issues\n`;
525
544
  }
526
545
 
527
- if (result.testability) {
528
- output += `๐Ÿงช Testability Index: ${result.testability.results?.length || 0} issues\n`;
546
+ if (result[ToolName.TestabilityIndex]) {
547
+ output += `๐Ÿงช Testability Index: ${result[ToolName.TestabilityIndex].results?.length || 0} issues\n`;
529
548
  }
530
549
 
531
- if (result.changeAmplification) {
532
- output += `๐Ÿ’ฅ Change Amplification: ${result.changeAmplification.summary?.totalIssues || 0} cascading risks\n`;
550
+ if (result[ToolName.ChangeAmplification]) {
551
+ output += `๐Ÿ’ฅ Change Amplification: ${result[ToolName.ChangeAmplification].summary?.totalIssues || 0} cascading risks\n`;
533
552
  }
534
553
 
535
554
  return output;