@aiready/change-amplification 0.14.8 → 0.14.11

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.
@@ -1,24 +1,23 @@
1
-
2
- 
3
- > @aiready/change-amplification@0.14.8 build /Users/pengcao/projects/aiready/packages/change-amplification
4
- > tsup src/index.ts src/cli.ts --format cjs,esm --dts
5
-
6
- CLI Building entry: src/cli.ts, src/index.ts
7
- CLI Using tsconfig: tsconfig.json
8
- CLI tsup v8.5.1
9
- CLI Target: es2020
10
- CJS Build start
11
- ESM Build start
12
- ESM dist/cli.mjs 2.41 KB
13
- ESM dist/index.mjs 1.53 KB
14
- ESM dist/chunk-SPXGOPNW.mjs 4.83 KB
15
- ESM ⚡️ Build success in 65ms
16
- CJS dist/cli.js 8.51 KB
17
- CJS dist/index.js 7.74 KB
18
- CJS ⚡️ Build success in 66ms
19
- DTS Build start
20
- DTS ⚡️ Build success in 1855ms
21
- DTS dist/cli.d.ts 266.00 B
22
- DTS dist/index.d.ts 1.15 KB
23
- DTS dist/cli.d.mts 266.00 B
24
- DTS dist/index.d.mts 1.15 KB
1
+
2
+ > @aiready/change-amplification@0.14.9 build /Users/pengcao/projects/aiready/packages/change-amplification
3
+ > tsup src/index.ts src/cli.ts --format cjs,esm --dts
4
+
5
+ CLI Building entry: src/cli.ts, src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.1
8
+ CLI Target: es2020
9
+ CJS Build start
10
+ ESM Build start
11
+ ESM dist/cli.mjs 2.41 KB
12
+ ESM dist/chunk-SPXGOPNW.mjs 4.83 KB
13
+ ESM dist/index.mjs 900.00 B
14
+ ESM ⚡️ Build success in 53ms
15
+ CJS dist/cli.js 8.51 KB
16
+ CJS dist/index.js 7.02 KB
17
+ CJS ⚡️ Build success in 55ms
18
+ DTS Build start
19
+ DTS ⚡️ Build success in 2926ms
20
+ DTS dist/cli.d.ts 266.00 B
21
+ DTS dist/index.d.ts 937.00 B
22
+ DTS dist/cli.d.mts 266.00 B
23
+ DTS dist/index.d.mts 937.00 B
@@ -1,6 +1,6 @@
1
1
 
2
2
  
3
- > @aiready/change-amplification@0.14.8 format-check /Users/pengcao/projects/aiready/packages/change-amplification
3
+ > @aiready/change-amplification@0.14.9 format-check /Users/pengcao/projects/aiready/packages/change-amplification
4
4
  > prettier --check . --ignore-path ../../.prettierignore
5
5
 
6
6
  Checking formatting...
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > @aiready/change-amplification@0.14.8 lint /Users/pengcao/projects/aiready/packages/change-amplification
3
+ > @aiready/change-amplification@0.14.9 lint /Users/pengcao/projects/aiready/packages/change-amplification
4
4
  > eslint src --ext .ts
5
5
 
@@ -1,24 +1,24 @@
1
1
 
2
2
  
3
- > @aiready/change-amplification@0.14.7 test /Users/pengcao/projects/aiready/packages/change-amplification
3
+ > @aiready/change-amplification@0.14.8 test /Users/pengcao/projects/aiready/packages/change-amplification
4
4
  > vitest run
5
5
 
6
6
  [?25l
7
7
   RUN  v4.0.18 /Users/pengcao/projects/aiready/packages/change-amplification
8
8
 
9
- ✓ src/__tests__/dummy.test.ts (1 test) 12ms
10
- ✓ src/__tests__/cli.test.ts (2 tests) 10ms
11
- ✓ src/__tests__/scoring.test.ts (2 tests) 9ms
9
+ ✓ src/__tests__/dummy.test.ts (1 test) 4ms
10
+ ✓ src/__tests__/cli.test.ts (2 tests) 2ms
12
11
  stdout | src/__tests__/analyzer.test.ts > analyzeChangeAmplification reproduction > should see how it gets to 0
13
12
  Resulting score for highly coupled: 27
14
13
  Rating: explosive
15
14
 
15
+ ✓ src/__tests__/scoring.test.ts (2 tests) 2ms
16
16
  ✓ src/__tests__/analyzer.test.ts (2 tests) 3ms
17
- ✓ src/__tests__/provider.test.ts (2 tests) 7ms
17
+ ✓ src/__tests__/provider.test.ts (2 tests) 6ms
18
18
 
19
19
   Test Files  5 passed (5)
20
20
   Tests  9 passed (9)
21
-  Start at  00:08:32
22
-  Duration  3.04s (transform 3.50s, setup 0ms, import 11.31s, tests 41ms, environment 0ms)
21
+  Start at  00:14:10
22
+  Duration  1.40s (transform 1.04s, setup 0ms, import 3.63s, tests 18ms, environment 0ms)
23
23
 
24
24
  [?25h
@@ -1,5 +1,5 @@
1
1
 
2
2
  
3
- > @aiready/change-amplification@0.14.8 type-check /Users/pengcao/projects/aiready/packages/change-amplification
3
+ > @aiready/change-amplification@0.14.9 type-check /Users/pengcao/projects/aiready/packages/change-amplification
4
4
  > tsc --noEmit
5
5
 
package/dist/index.d.mts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as _aiready_core from '@aiready/core';
2
- import { Issue, IssueType, ScanOptions, SpokeOutput, AnalysisResult, ToolScoringOutput } from '@aiready/core';
2
+ import { Issue, IssueType, ScanOptions, SpokeOutput, AnalysisResult } from '@aiready/core';
3
3
 
4
4
  /**
5
5
  * Change Amplification Tool Provider
6
6
  */
7
- declare const ChangeAmplificationProvider: _aiready_core.ToolProvider;
7
+ declare const CHANGE_AMPLIFICATION_PROVIDER: _aiready_core.ToolProvider;
8
8
 
9
9
  type ChangeAmplificationOptions = ScanOptions;
10
10
  interface ChangeAmplificationIssue extends Issue {
@@ -19,9 +19,4 @@ interface ChangeAmplificationReport extends SpokeOutput {
19
19
 
20
20
  declare function analyzeChangeAmplification(options: ChangeAmplificationOptions): Promise<ChangeAmplificationReport>;
21
21
 
22
- /**
23
- * Convert change amplification report into a standardized ToolScoringOutput.
24
- */
25
- declare function calculateChangeAmplificationScore(report: ChangeAmplificationReport): ToolScoringOutput;
26
-
27
- export { type ChangeAmplificationIssue, type ChangeAmplificationOptions, ChangeAmplificationProvider, type ChangeAmplificationReport, type FileChangeAmplificationResult, analyzeChangeAmplification, calculateChangeAmplificationScore };
22
+ export { CHANGE_AMPLIFICATION_PROVIDER, type ChangeAmplificationIssue, type ChangeAmplificationOptions, type ChangeAmplificationReport, type FileChangeAmplificationResult, analyzeChangeAmplification };
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import * as _aiready_core from '@aiready/core';
2
- import { Issue, IssueType, ScanOptions, SpokeOutput, AnalysisResult, ToolScoringOutput } from '@aiready/core';
2
+ import { Issue, IssueType, ScanOptions, SpokeOutput, AnalysisResult } from '@aiready/core';
3
3
 
4
4
  /**
5
5
  * Change Amplification Tool Provider
6
6
  */
7
- declare const ChangeAmplificationProvider: _aiready_core.ToolProvider;
7
+ declare const CHANGE_AMPLIFICATION_PROVIDER: _aiready_core.ToolProvider;
8
8
 
9
9
  type ChangeAmplificationOptions = ScanOptions;
10
10
  interface ChangeAmplificationIssue extends Issue {
@@ -19,9 +19,4 @@ interface ChangeAmplificationReport extends SpokeOutput {
19
19
 
20
20
  declare function analyzeChangeAmplification(options: ChangeAmplificationOptions): Promise<ChangeAmplificationReport>;
21
21
 
22
- /**
23
- * Convert change amplification report into a standardized ToolScoringOutput.
24
- */
25
- declare function calculateChangeAmplificationScore(report: ChangeAmplificationReport): ToolScoringOutput;
26
-
27
- export { type ChangeAmplificationIssue, type ChangeAmplificationOptions, ChangeAmplificationProvider, type ChangeAmplificationReport, type FileChangeAmplificationResult, analyzeChangeAmplification, calculateChangeAmplificationScore };
22
+ export { CHANGE_AMPLIFICATION_PROVIDER, type ChangeAmplificationIssue, type ChangeAmplificationOptions, type ChangeAmplificationReport, type FileChangeAmplificationResult, analyzeChangeAmplification };
package/dist/index.js CHANGED
@@ -30,12 +30,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
- ChangeAmplificationProvider: () => ChangeAmplificationProvider,
34
- analyzeChangeAmplification: () => analyzeChangeAmplification,
35
- calculateChangeAmplificationScore: () => calculateChangeAmplificationScore
33
+ CHANGE_AMPLIFICATION_PROVIDER: () => CHANGE_AMPLIFICATION_PROVIDER,
34
+ analyzeChangeAmplification: () => analyzeChangeAmplification
36
35
  });
37
36
  module.exports = __toCommonJS(index_exports);
38
- var import_core4 = require("@aiready/core");
37
+ var import_core3 = require("@aiready/core");
39
38
 
40
39
  // src/provider.ts
41
40
  var import_core2 = require("@aiready/core");
@@ -170,7 +169,7 @@ async function analyzeChangeAmplification(options) {
170
169
  }
171
170
 
172
171
  // src/provider.ts
173
- var ChangeAmplificationProvider = (0, import_core2.createProvider)({
172
+ var CHANGE_AMPLIFICATION_PROVIDER = (0, import_core2.createProvider)({
174
173
  id: import_core2.ToolName.ChangeAmplification,
175
174
  alias: ["change-amp", "change-amplification", "coupling"],
176
175
  version: "0.9.5",
@@ -192,34 +191,10 @@ var ChangeAmplificationProvider = (0, import_core2.createProvider)({
192
191
  }
193
192
  });
194
193
 
195
- // src/scoring.ts
196
- var import_core3 = require("@aiready/core");
197
- function calculateChangeAmplificationScore(report) {
198
- const { summary } = report;
199
- return (0, import_core3.buildStandardToolScore)({
200
- toolName: import_core3.ToolName.ChangeAmplification,
201
- score: summary.score ?? 0,
202
- rawData: {
203
- totalFiles: summary.totalFiles,
204
- totalIssues: summary.totalIssues
205
- },
206
- dimensions: {
207
- graphStability: summary.score ?? 0
208
- },
209
- dimensionNames: {
210
- graphStability: "Graph Stability"
211
- },
212
- recommendations: summary.recommendations,
213
- recommendationImpact: 10,
214
- rating: summary.rating
215
- });
216
- }
217
-
218
194
  // src/index.ts
219
- import_core4.ToolRegistry.register(ChangeAmplificationProvider);
195
+ import_core3.ToolRegistry.register(CHANGE_AMPLIFICATION_PROVIDER);
220
196
  // Annotate the CommonJS export names for ESM import in node:
221
197
  0 && (module.exports = {
222
- ChangeAmplificationProvider,
223
- analyzeChangeAmplification,
224
- calculateChangeAmplificationScore
198
+ CHANGE_AMPLIFICATION_PROVIDER,
199
+ analyzeChangeAmplification
225
200
  });
package/dist/index.mjs CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  ToolName,
12
12
  buildSimpleProviderScore
13
13
  } from "@aiready/core";
14
- var ChangeAmplificationProvider = createProvider({
14
+ var CHANGE_AMPLIFICATION_PROVIDER = createProvider({
15
15
  id: ToolName.ChangeAmplification,
16
16
  alias: ["change-amp", "change-amplification", "coupling"],
17
17
  version: "0.9.5",
@@ -33,36 +33,9 @@ var ChangeAmplificationProvider = createProvider({
33
33
  }
34
34
  });
35
35
 
36
- // src/scoring.ts
37
- import {
38
- ToolName as ToolName2,
39
- buildStandardToolScore
40
- } from "@aiready/core";
41
- function calculateChangeAmplificationScore(report) {
42
- const { summary } = report;
43
- return buildStandardToolScore({
44
- toolName: ToolName2.ChangeAmplification,
45
- score: summary.score ?? 0,
46
- rawData: {
47
- totalFiles: summary.totalFiles,
48
- totalIssues: summary.totalIssues
49
- },
50
- dimensions: {
51
- graphStability: summary.score ?? 0
52
- },
53
- dimensionNames: {
54
- graphStability: "Graph Stability"
55
- },
56
- recommendations: summary.recommendations,
57
- recommendationImpact: 10,
58
- rating: summary.rating
59
- });
60
- }
61
-
62
36
  // src/index.ts
63
- ToolRegistry.register(ChangeAmplificationProvider);
37
+ ToolRegistry.register(CHANGE_AMPLIFICATION_PROVIDER);
64
38
  export {
65
- ChangeAmplificationProvider,
66
- analyzeChangeAmplification,
67
- calculateChangeAmplificationScore
39
+ CHANGE_AMPLIFICATION_PROVIDER,
40
+ analyzeChangeAmplification
68
41
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/change-amplification",
3
- "version": "0.14.8",
3
+ "version": "0.14.11",
4
4
  "description": "AI-Readiness: Change Amplification Detection",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -10,7 +10,7 @@
10
10
  "commander": "^14.0.0",
11
11
  "glob": "^13.0.0",
12
12
  "chalk": "^5.3.0",
13
- "@aiready/core": "0.24.8"
13
+ "@aiready/core": "0.24.12"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@types/node": "^24.0.0",
@@ -1,42 +1,12 @@
1
- import { describe, it, expect, vi } from 'vitest';
2
- import { ChangeAmplificationProvider } from '../provider';
3
- import * as analyzer from '../analyzer';
4
-
5
- vi.mock('../analyzer', () => ({
6
- analyzeChangeAmplification: vi.fn(),
7
- }));
1
+ import { describe, it, expect } from 'vitest';
2
+ import { CHANGE_AMPLIFICATION_PROVIDER } from '../provider';
8
3
 
9
4
  describe('Change Amplification Provider', () => {
10
- it('should analyze and return SpokeOutput', async () => {
11
- vi.mocked(analyzer.analyzeChangeAmplification).mockResolvedValue({
12
- summary: {
13
- totalFiles: 1,
14
- totalIssues: 0,
15
- criticalIssues: 0,
16
- majorIssues: 0,
17
- score: 90,
18
- rating: 'stable',
19
- recommendations: [],
20
- },
21
- results: [],
22
- });
23
-
24
- const output = await ChangeAmplificationProvider.analyze({ rootDir: '.' });
25
-
26
- expect(output.summary.totalFiles).toBe(1);
27
- expect(output.metadata!.toolName).toBe('change-amplification');
5
+ it('should have correct ID', () => {
6
+ expect(CHANGE_AMPLIFICATION_PROVIDER.id).toBe('change-amplification');
28
7
  });
29
8
 
30
- it('should score an output', () => {
31
- const mockOutput = {
32
- summary: { score: 85, recommendations: ['Decouple logic'] } as any,
33
- results: [],
34
- };
35
-
36
- const scoring = ChangeAmplificationProvider.score(mockOutput as any, {
37
- rootDir: '.',
38
- });
39
- expect(scoring.score).toBe(85);
40
- expect(scoring.recommendations[0].action).toBe('Decouple logic');
9
+ it('should have alias', () => {
10
+ expect(CHANGE_AMPLIFICATION_PROVIDER.alias).toContain('blast-radius');
41
11
  });
42
12
  });
package/src/index.ts CHANGED
@@ -1,15 +1,9 @@
1
1
  import { ToolRegistry } from '@aiready/core';
2
- import { ChangeAmplificationProvider } from './provider';
2
+ import { CHANGE_AMPLIFICATION_PROVIDER } from './provider';
3
3
 
4
4
  // Register with global registry
5
- ToolRegistry.register(ChangeAmplificationProvider);
5
+ ToolRegistry.register(CHANGE_AMPLIFICATION_PROVIDER);
6
6
 
7
- export { analyzeChangeAmplification } from './analyzer';
8
- export { calculateChangeAmplificationScore } from './scoring';
9
- export { ChangeAmplificationProvider };
10
- export type {
11
- ChangeAmplificationOptions,
12
- ChangeAmplificationReport,
13
- ChangeAmplificationIssue,
14
- FileChangeAmplificationResult,
15
- } from './types';
7
+ export * from './types';
8
+ export * from './analyzer';
9
+ export { CHANGE_AMPLIFICATION_PROVIDER };
package/src/provider.ts CHANGED
@@ -10,7 +10,7 @@ import { ChangeAmplificationOptions } from './types';
10
10
  /**
11
11
  * Change Amplification Tool Provider
12
12
  */
13
- export const ChangeAmplificationProvider = createProvider({
13
+ export const CHANGE_AMPLIFICATION_PROVIDER = createProvider({
14
14
  id: ToolName.ChangeAmplification,
15
15
  alias: ['change-amp', 'change-amplification', 'coupling'],
16
16
  version: '0.9.5',
@@ -1,112 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import * as fs from "fs";
10
- import * as path from "path";
11
- import {
12
- scanFiles,
13
- calculateChangeAmplification,
14
- getParser,
15
- Severity
16
- } from "@aiready/core";
17
- async function analyzeChangeAmplification(options) {
18
- const files = await scanFiles({
19
- ...options,
20
- include: options.include || ["**/*.{ts,tsx,js,jsx,py,go}"]
21
- });
22
- const dependencyGraph = /* @__PURE__ */ new Map();
23
- const reverseGraph = /* @__PURE__ */ new Map();
24
- for (const file of files) {
25
- dependencyGraph.set(file, []);
26
- reverseGraph.set(file, []);
27
- }
28
- let processed = 0;
29
- for (const file of files) {
30
- processed++;
31
- options.onProgress?.(
32
- processed,
33
- files.length,
34
- `change-amplification: analyzing files`
35
- );
36
- try {
37
- const parser = getParser(file);
38
- if (!parser) continue;
39
- const content = fs.readFileSync(file, "utf8");
40
- const parseResult = parser.parse(content, file);
41
- const dependencies = parseResult.imports.map((i) => i.source);
42
- for (const dep of dependencies) {
43
- const depDir = path.dirname(file);
44
- const resolvedPath = files.find((f) => {
45
- if (dep.startsWith(".")) {
46
- return f.startsWith(path.resolve(depDir, dep));
47
- } else {
48
- return f.includes(dep);
49
- }
50
- });
51
- if (resolvedPath) {
52
- dependencyGraph.get(file)?.push(resolvedPath);
53
- reverseGraph.get(resolvedPath)?.push(file);
54
- }
55
- }
56
- } catch (err) {
57
- void err;
58
- }
59
- }
60
- const fileMetrics = files.map((file) => {
61
- const fanOut = dependencyGraph.get(file)?.length || 0;
62
- const fanIn = reverseGraph.get(file)?.length || 0;
63
- return { file, fanOut, fanIn };
64
- });
65
- const riskResult = calculateChangeAmplification({ files: fileMetrics });
66
- const results = [];
67
- for (const hotspot of riskResult.hotspots) {
68
- const issues = [];
69
- if (hotspot.amplificationFactor > 20) {
70
- issues.push({
71
- type: "change-amplification",
72
- severity: hotspot.amplificationFactor > 40 ? Severity.Critical : Severity.Major,
73
- message: `High change amplification detected (Factor: ${hotspot.amplificationFactor}). Changes here cascade heavily.`,
74
- location: { file: hotspot.file, line: 1 },
75
- suggestion: `Reduce coupling. Fan-out is ${hotspot.fanOut}, Fan-in is ${hotspot.fanIn}.`
76
- });
77
- }
78
- if (hotspot.amplificationFactor > 5) {
79
- results.push({
80
- fileName: hotspot.file,
81
- issues,
82
- metrics: {
83
- aiSignalClarityScore: 100 - hotspot.amplificationFactor
84
- // Just a rough score
85
- }
86
- });
87
- }
88
- }
89
- return {
90
- summary: {
91
- totalFiles: files.length,
92
- totalIssues: results.reduce((sum, r) => sum + r.issues.length, 0),
93
- criticalIssues: results.reduce(
94
- (sum, r) => sum + r.issues.filter((i) => i.severity === Severity.Critical || i.severity === "critical").length,
95
- 0
96
- ),
97
- majorIssues: results.reduce(
98
- (sum, r) => sum + r.issues.filter((i) => i.severity === Severity.Major || i.severity === "major").length,
99
- 0
100
- ),
101
- score: riskResult.score,
102
- rating: riskResult.rating,
103
- recommendations: riskResult.recommendations
104
- },
105
- results
106
- };
107
- }
108
-
109
- export {
110
- __require,
111
- analyzeChangeAmplification
112
- };
@@ -1,111 +0,0 @@
1
- var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
- get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
- }) : x)(function(x) {
4
- if (typeof require !== "undefined") return require.apply(this, arguments);
5
- throw Error('Dynamic require of "' + x + '" is not supported');
6
- });
7
-
8
- // src/analyzer.ts
9
- import * as fs from "fs";
10
- import * as path from "path";
11
- import {
12
- scanFiles,
13
- calculateChangeAmplification,
14
- getParser
15
- } from "@aiready/core";
16
- async function analyzeChangeAmplification(options) {
17
- const files = await scanFiles({
18
- ...options,
19
- include: options.include || ["**/*.{ts,tsx,js,jsx,py,go}"]
20
- });
21
- const dependencyGraph = /* @__PURE__ */ new Map();
22
- const reverseGraph = /* @__PURE__ */ new Map();
23
- for (const file of files) {
24
- dependencyGraph.set(file, []);
25
- reverseGraph.set(file, []);
26
- }
27
- let processed = 0;
28
- for (const file of files) {
29
- processed++;
30
- options.onProgress?.(
31
- processed,
32
- files.length,
33
- `change-amplification: analyzing files`
34
- );
35
- try {
36
- const parser = getParser(file);
37
- if (!parser) continue;
38
- const content = fs.readFileSync(file, "utf8");
39
- const parseResult = parser.parse(content, file);
40
- const dependencies = parseResult.imports.map((i) => i.source);
41
- for (const dep of dependencies) {
42
- const depDir = path.dirname(file);
43
- const resolvedPath = files.find((f) => {
44
- if (dep.startsWith(".")) {
45
- return f.startsWith(path.resolve(depDir, dep));
46
- } else {
47
- return f.includes(dep);
48
- }
49
- });
50
- if (resolvedPath) {
51
- dependencyGraph.get(file)?.push(resolvedPath);
52
- reverseGraph.get(resolvedPath)?.push(file);
53
- }
54
- }
55
- } catch (err) {
56
- void err;
57
- }
58
- }
59
- const fileMetrics = files.map((file) => {
60
- const fanOut = dependencyGraph.get(file)?.length || 0;
61
- const fanIn = reverseGraph.get(file)?.length || 0;
62
- return { file, fanOut, fanIn };
63
- });
64
- const riskResult = calculateChangeAmplification({ files: fileMetrics });
65
- const results = [];
66
- for (const hotspot of riskResult.hotspots) {
67
- const issues = [];
68
- if (hotspot.amplificationFactor > 20) {
69
- issues.push({
70
- type: "change-amplification",
71
- severity: hotspot.amplificationFactor > 40 ? "critical" : "major",
72
- message: `High change amplification detected (Factor: ${hotspot.amplificationFactor}). Changes here cascade heavily.`,
73
- location: { file: hotspot.file, line: 1 },
74
- suggestion: `Reduce coupling. Fan-out is ${hotspot.fanOut}, Fan-in is ${hotspot.fanIn}.`
75
- });
76
- }
77
- if (hotspot.amplificationFactor > 5) {
78
- results.push({
79
- fileName: hotspot.file,
80
- issues,
81
- metrics: {
82
- aiSignalClarityScore: 100 - hotspot.amplificationFactor
83
- // Just a rough score
84
- }
85
- });
86
- }
87
- }
88
- return {
89
- summary: {
90
- totalFiles: files.length,
91
- totalIssues: results.reduce((sum, r) => sum + r.issues.length, 0),
92
- criticalIssues: results.reduce(
93
- (sum, r) => sum + r.issues.filter((i) => i.severity === "critical").length,
94
- 0
95
- ),
96
- majorIssues: results.reduce(
97
- (sum, r) => sum + r.issues.filter((i) => i.severity === "major").length,
98
- 0
99
- ),
100
- score: riskResult.score,
101
- rating: riskResult.rating,
102
- recommendations: riskResult.recommendations
103
- },
104
- results
105
- };
106
- }
107
-
108
- export {
109
- __require,
110
- analyzeChangeAmplification
111
- };