@aiready/change-amplification 0.14.9 → 0.14.12
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/.turbo/turbo-build.log +23 -24
- package/dist/index.d.mts +3 -8
- package/dist/index.d.ts +3 -8
- package/dist/index.js +7 -32
- package/dist/index.mjs +4 -31
- package/package.json +2 -2
- package/src/__tests__/provider.test.ts +6 -36
- package/src/index.ts +5 -11
- package/src/provider.ts +1 -1
- package/dist/chunk-2EOPHC5S.mjs +0 -112
- package/dist/chunk-3CM4X7K3.mjs +0 -111
- package/dist/chunk-7GH73LRM.mjs +0 -128
- package/dist/chunk-A5ACPWWO.mjs +0 -114
- package/dist/chunk-DS7GBUP2.mjs +0 -100
- package/dist/chunk-GLHIV53G.mjs +0 -120
- package/dist/chunk-MARO4FT6.mjs +0 -112
- package/dist/chunk-OBBL7HKE.mjs +0 -146
- package/dist/chunk-SHJMNP6Q.mjs +0 -126
- package/dist/chunk-V5J3BP4N.mjs +0 -117
- package/dist/chunk-VW57ZQRN.mjs +0 -103
- package/dist/chunk-XCXQGNCX.mjs +0 -129
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,24 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
DTS Build
|
|
20
|
-
DTS
|
|
21
|
-
DTS dist/
|
|
22
|
-
DTS dist/
|
|
23
|
-
DTS dist/
|
|
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
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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(
|
|
37
|
+
ToolRegistry.register(CHANGE_AMPLIFICATION_PROVIDER);
|
|
64
38
|
export {
|
|
65
|
-
|
|
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.
|
|
3
|
+
"version": "0.14.12",
|
|
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.
|
|
13
|
+
"@aiready/core": "0.24.13"
|
|
14
14
|
},
|
|
15
15
|
"devDependencies": {
|
|
16
16
|
"@types/node": "^24.0.0",
|
|
@@ -1,42 +1,12 @@
|
|
|
1
|
-
import { describe, it, expect
|
|
2
|
-
import {
|
|
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
|
|
11
|
-
|
|
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
|
|
31
|
-
|
|
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 {
|
|
2
|
+
import { CHANGE_AMPLIFICATION_PROVIDER } from './provider';
|
|
3
3
|
|
|
4
4
|
// Register with global registry
|
|
5
|
-
ToolRegistry.register(
|
|
5
|
+
ToolRegistry.register(CHANGE_AMPLIFICATION_PROVIDER);
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
export
|
|
9
|
-
export {
|
|
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
|
|
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',
|
package/dist/chunk-2EOPHC5S.mjs
DELETED
|
@@ -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
|
-
};
|
package/dist/chunk-3CM4X7K3.mjs
DELETED
|
@@ -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
|
-
};
|
package/dist/chunk-7GH73LRM.mjs
DELETED
|
@@ -1,128 +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
|
-
IssueType
|
|
17
|
-
} from "@aiready/core";
|
|
18
|
-
async function analyzeChangeAmplification(options) {
|
|
19
|
-
const files = await scanFiles({
|
|
20
|
-
...options,
|
|
21
|
-
include: options.include || ["**/*.{ts,tsx,js,jsx,py,go}"]
|
|
22
|
-
});
|
|
23
|
-
const dependencyGraph = /* @__PURE__ */ new Map();
|
|
24
|
-
const reverseGraph = /* @__PURE__ */ new Map();
|
|
25
|
-
for (const file of files) {
|
|
26
|
-
dependencyGraph.set(file, []);
|
|
27
|
-
reverseGraph.set(file, []);
|
|
28
|
-
}
|
|
29
|
-
let processed = 0;
|
|
30
|
-
for (const file of files) {
|
|
31
|
-
processed++;
|
|
32
|
-
options.onProgress?.(
|
|
33
|
-
processed,
|
|
34
|
-
files.length,
|
|
35
|
-
`change-amplification: analyzing files`
|
|
36
|
-
);
|
|
37
|
-
try {
|
|
38
|
-
const parser = getParser(file);
|
|
39
|
-
if (!parser) continue;
|
|
40
|
-
const content = fs.readFileSync(file, "utf8");
|
|
41
|
-
const parseResult = parser.parse(content, file);
|
|
42
|
-
const dependencies = parseResult.imports.map((i) => i.source);
|
|
43
|
-
for (const dep of dependencies) {
|
|
44
|
-
const depDir = path.dirname(file);
|
|
45
|
-
const resolvedPath = files.find((f) => {
|
|
46
|
-
if (dep.startsWith(".")) {
|
|
47
|
-
return f.startsWith(path.resolve(depDir, dep));
|
|
48
|
-
} else {
|
|
49
|
-
return f.includes(dep);
|
|
50
|
-
}
|
|
51
|
-
});
|
|
52
|
-
if (resolvedPath) {
|
|
53
|
-
dependencyGraph.get(file)?.push(resolvedPath);
|
|
54
|
-
reverseGraph.get(resolvedPath)?.push(file);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
} catch (err) {
|
|
58
|
-
void err;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const fileMetrics = files.map((file) => {
|
|
62
|
-
const fanOut = dependencyGraph.get(file)?.length || 0;
|
|
63
|
-
const fanIn = reverseGraph.get(file)?.length || 0;
|
|
64
|
-
return { file, fanOut, fanIn };
|
|
65
|
-
});
|
|
66
|
-
const riskResult = calculateChangeAmplification({ files: fileMetrics });
|
|
67
|
-
const results = [];
|
|
68
|
-
const getLevel = (s) => {
|
|
69
|
-
const map = {
|
|
70
|
-
[Severity.Critical]: 4,
|
|
71
|
-
[Severity.Major]: 3,
|
|
72
|
-
[Severity.Minor]: 2,
|
|
73
|
-
[Severity.Info]: 1,
|
|
74
|
-
critical: 4,
|
|
75
|
-
major: 3,
|
|
76
|
-
minor: 2,
|
|
77
|
-
info: 1
|
|
78
|
-
};
|
|
79
|
-
if (map[s] !== void 0) return map[s];
|
|
80
|
-
const lower = String(s).toLowerCase();
|
|
81
|
-
return map[lower] ?? 0;
|
|
82
|
-
};
|
|
83
|
-
for (const hotspot of riskResult.hotspots) {
|
|
84
|
-
const issues = [];
|
|
85
|
-
if (hotspot.amplificationFactor > 20) {
|
|
86
|
-
issues.push({
|
|
87
|
-
type: IssueType.ChangeAmplification,
|
|
88
|
-
severity: hotspot.amplificationFactor > 40 ? Severity.Critical : Severity.Major,
|
|
89
|
-
message: `High change amplification detected (Factor: ${hotspot.amplificationFactor}). Changes here cascade heavily.`,
|
|
90
|
-
location: { file: hotspot.file, line: 1 },
|
|
91
|
-
suggestion: `Reduce coupling. Fan-out is ${hotspot.fanOut}, Fan-in is ${hotspot.fanIn}.`
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
if (hotspot.amplificationFactor > 5) {
|
|
95
|
-
results.push({
|
|
96
|
-
fileName: hotspot.file,
|
|
97
|
-
issues,
|
|
98
|
-
metrics: {
|
|
99
|
-
aiSignalClarityScore: 100 - hotspot.amplificationFactor
|
|
100
|
-
// Just a rough score
|
|
101
|
-
}
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return {
|
|
106
|
-
summary: {
|
|
107
|
-
totalFiles: files.length,
|
|
108
|
-
totalIssues: results.reduce((sum, r) => sum + r.issues.length, 0),
|
|
109
|
-
criticalIssues: results.reduce(
|
|
110
|
-
(sum, r) => sum + r.issues.filter((i) => getLevel(i.severity) === 4).length,
|
|
111
|
-
0
|
|
112
|
-
),
|
|
113
|
-
majorIssues: results.reduce(
|
|
114
|
-
(sum, r) => sum + r.issues.filter((i) => getLevel(i.severity) === 3).length,
|
|
115
|
-
0
|
|
116
|
-
),
|
|
117
|
-
score: riskResult.score,
|
|
118
|
-
rating: riskResult.rating,
|
|
119
|
-
recommendations: riskResult.recommendations
|
|
120
|
-
},
|
|
121
|
-
results
|
|
122
|
-
};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export {
|
|
126
|
-
__require,
|
|
127
|
-
analyzeChangeAmplification
|
|
128
|
-
};
|