@aiready/context-analyzer 0.21.26 → 0.21.27
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 +32 -25
- package/.turbo/turbo-test.log +51 -87
- package/coverage/clover.xml +392 -1878
- package/coverage/coverage-final.json +15 -19
- package/coverage/index.html +48 -63
- package/coverage/src/analyzers/index.html +21 -21
- package/coverage/src/analyzers/python-context.ts.html +96 -96
- package/coverage/src/ast-utils.ts.html +34 -109
- package/coverage/src/classifier.ts.html +104 -104
- package/coverage/src/classify/classification-patterns.ts.html +1 -1
- package/coverage/src/classify/file-classifiers.ts.html +1 -1
- package/coverage/src/classify/index.html +1 -1
- package/coverage/src/cluster-detector.ts.html +72 -72
- package/coverage/src/defaults.ts.html +1 -1
- package/coverage/src/graph-builder.ts.html +131 -131
- package/coverage/src/index.html +101 -116
- package/coverage/src/index.ts.html +2 -2
- package/coverage/src/issue-analyzer.ts.html +32 -83
- package/coverage/src/mapper.ts.html +20 -2
- package/coverage/src/metrics.ts.html +127 -130
- package/coverage/src/orchestrator.ts.html +13 -13
- package/coverage/src/provider.ts.html +19 -19
- package/coverage/src/remediation.ts.html +59 -59
- package/coverage/src/report/console-report.ts.html +2 -2
- package/coverage/src/report/html-report.ts.html +60 -84
- package/coverage/src/report/index.html +7 -7
- package/coverage/src/report/interactive-setup.ts.html +1 -1
- package/coverage/src/scoring.ts.html +62 -62
- package/coverage/src/semantic/co-usage.ts.html +1 -1
- package/coverage/src/semantic/consolidation.ts.html +1 -1
- package/coverage/src/semantic/domain-inference.ts.html +1 -1
- package/coverage/src/semantic/index.html +1 -1
- package/coverage/src/semantic/type-graph.ts.html +1 -1
- package/coverage/src/summary.ts.html +67 -67
- package/coverage/src/types.ts.html +1 -1
- package/coverage/src/utils/dependency-graph-utils.ts.html +41 -41
- package/coverage/src/utils/index.html +21 -21
- package/coverage/src/utils/string-utils.ts.html +1 -1
- package/dist/chunk-22ZO4EKZ.mjs +1297 -0
- package/dist/chunk-4U4LDWGF.mjs +360 -0
- package/dist/chunk-BA7QGUHN.mjs +1722 -0
- package/dist/chunk-BCEZGRXI.mjs +1297 -0
- package/dist/chunk-BQCISA2F.mjs +91 -0
- package/dist/chunk-EMYD7NS6.mjs +137 -0
- package/dist/chunk-EWFR366Y.mjs +1740 -0
- package/dist/chunk-FO6YT6RG.mjs +1751 -0
- package/dist/chunk-J3SZQZNU.mjs +221 -0
- package/dist/chunk-OZE3FVZT.mjs +1089 -0
- package/dist/chunk-WHB7QI7N.mjs +91 -0
- package/dist/cli-action-CXIHOVAC.mjs +95 -0
- package/dist/cli-action-SA7SCYNV.mjs +95 -0
- package/dist/cli-action-YAJOJCXJ.mjs +95 -0
- package/dist/cli.js +688 -566
- package/dist/cli.mjs +4 -88
- package/dist/index.js +889 -773
- package/dist/index.mjs +21 -14
- package/dist/orchestrator-3L3NAZYP.mjs +10 -0
- package/dist/orchestrator-MONOZHVW.mjs +10 -0
- package/dist/orchestrator-ZR7JSKWI.mjs +10 -0
- package/dist/summary-7PZVW72O.mjs +7 -0
- package/dist/summary-LKUCJAIS.mjs +7 -0
- package/package.json +2 -2
- package/src/__tests__/analyzer.test.ts +1 -1
- package/src/__tests__/enhanced-cohesion.test.ts +4 -1
- package/src/__tests__/orchestrator.test.ts +19 -4
- package/src/__tests__/python-context.test.ts +6 -0
- package/src/__tests__/report/html-report.test.ts +8 -2
- package/src/ast-utils.ts +1 -26
- package/src/cli-definition.ts +4 -2
- package/src/issue-analyzer.ts +4 -19
- package/src/metrics.ts +1 -2
- package/src/provider.ts +4 -4
- package/src/report/html-report.ts +43 -59
- package/coverage/dist/chunk-64U3PNO3.mjs.html +0 -367
- package/coverage/dist/chunk-J3MUOWHC.mjs.html +0 -5326
- package/coverage/dist/index.html +0 -146
- package/coverage/dist/index.mjs.html +0 -1396
- package/coverage/src/analyzer.ts.html +0 -88
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
displayConsoleReport,
|
|
3
|
+
generateHTMLReport,
|
|
4
|
+
runInteractiveSetup
|
|
5
|
+
} from "./chunk-J3SZQZNU.mjs";
|
|
1
6
|
import {
|
|
2
7
|
BARREL_EXPORT_MIN_EXPORTS,
|
|
3
8
|
BARREL_EXPORT_TOKEN_LIMIT,
|
|
@@ -17,22 +22,14 @@ import {
|
|
|
17
22
|
buildTypeGraph,
|
|
18
23
|
calculateCohesion,
|
|
19
24
|
calculateContextBudget,
|
|
20
|
-
calculateDirectoryDistance,
|
|
21
25
|
calculateDomainConfidence,
|
|
22
|
-
calculateEnhancedCohesion,
|
|
23
|
-
calculateFragmentation,
|
|
24
26
|
calculateImportDepth,
|
|
25
|
-
calculatePathEntropy,
|
|
26
|
-
calculateStructuralCohesionFromCoUsage,
|
|
27
27
|
classifyFile,
|
|
28
28
|
detectCircularDependencies,
|
|
29
29
|
detectModuleClusters,
|
|
30
|
-
displayConsoleReport,
|
|
31
30
|
extractDomainKeywordsFromPaths,
|
|
32
31
|
extractExports,
|
|
33
32
|
findSemanticClusters,
|
|
34
|
-
generateHTMLReport,
|
|
35
|
-
generateSummary,
|
|
36
33
|
getClassificationRecommendations,
|
|
37
34
|
getCoUsageData,
|
|
38
35
|
getGeneralRecommendations,
|
|
@@ -50,10 +47,19 @@ import {
|
|
|
50
47
|
isServiceFile,
|
|
51
48
|
isSessionFile,
|
|
52
49
|
isTypeDefinition,
|
|
53
|
-
isUtilityModule
|
|
54
|
-
|
|
55
|
-
} from "./chunk-VLV6MXPL.mjs";
|
|
50
|
+
isUtilityModule
|
|
51
|
+
} from "./chunk-BCEZGRXI.mjs";
|
|
56
52
|
import "./chunk-64U3PNO3.mjs";
|
|
53
|
+
import {
|
|
54
|
+
generateSummary
|
|
55
|
+
} from "./chunk-BQCISA2F.mjs";
|
|
56
|
+
import {
|
|
57
|
+
calculateDirectoryDistance,
|
|
58
|
+
calculateEnhancedCohesion,
|
|
59
|
+
calculateFragmentation,
|
|
60
|
+
calculatePathEntropy,
|
|
61
|
+
calculateStructuralCohesionFromCoUsage
|
|
62
|
+
} from "./chunk-EMYD7NS6.mjs";
|
|
57
63
|
|
|
58
64
|
// src/index.ts
|
|
59
65
|
import { ToolRegistry } from "@aiready/core";
|
|
@@ -259,8 +265,10 @@ var ContextAnalyzerProvider = {
|
|
|
259
265
|
id: ToolName2.ContextAnalyzer,
|
|
260
266
|
alias: ["context", "fragmentation", "budget"],
|
|
261
267
|
async analyze(options) {
|
|
262
|
-
const
|
|
263
|
-
const
|
|
268
|
+
const { analyzeContext: analyzeContext2 } = await import("./orchestrator-3L3NAZYP.mjs");
|
|
269
|
+
const { generateSummary: generateSummary2 } = await import("./summary-7PZVW72O.mjs");
|
|
270
|
+
const results = await analyzeContext2(options);
|
|
271
|
+
const summary = generateSummary2(results, options);
|
|
264
272
|
const normalizedResults = results.map(
|
|
265
273
|
(r) => ({
|
|
266
274
|
fileName: r.file,
|
|
@@ -274,7 +282,6 @@ var ContextAnalyzerProvider = {
|
|
|
274
282
|
metrics: {
|
|
275
283
|
tokenCost: r.tokenCost,
|
|
276
284
|
complexityScore: r.importDepth
|
|
277
|
-
// Map other context-specific metrics if needed
|
|
278
285
|
}
|
|
279
286
|
})
|
|
280
287
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/context-analyzer",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.27",
|
|
4
4
|
"description": "AI context window cost analysis - detect fragmented code, deep import chains, and expensive context budgets",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"commander": "^14.0.0",
|
|
50
50
|
"chalk": "^5.3.0",
|
|
51
51
|
"prompts": "^2.4.2",
|
|
52
|
-
"@aiready/core": "0.23.
|
|
52
|
+
"@aiready/core": "0.23.24"
|
|
53
53
|
},
|
|
54
54
|
"devDependencies": {
|
|
55
55
|
"@types/node": "^24.0.0",
|
|
@@ -207,7 +207,7 @@ describe('calculateCohesion', () => {
|
|
|
207
207
|
// Mock file - should return 1 despite mixed domains
|
|
208
208
|
const cohesionMockFile = calculateCohesion(
|
|
209
209
|
exports,
|
|
210
|
-
'src/
|
|
210
|
+
'src/__tests__/mocks.ts'
|
|
211
211
|
);
|
|
212
212
|
expect(cohesionMockFile).toBe(1);
|
|
213
213
|
|
|
@@ -132,7 +132,10 @@ describe('Enhanced Cohesion Calculation', () => {
|
|
|
132
132
|
},
|
|
133
133
|
];
|
|
134
134
|
|
|
135
|
-
const cohesion = calculateCohesion(
|
|
135
|
+
const cohesion = calculateCohesion(
|
|
136
|
+
exports,
|
|
137
|
+
'src/__tests__/test-helpers.ts'
|
|
138
|
+
);
|
|
136
139
|
expect(cohesion).toBe(1);
|
|
137
140
|
});
|
|
138
141
|
});
|
|
@@ -12,6 +12,20 @@ vi.mock('@aiready/core', async () => {
|
|
|
12
12
|
};
|
|
13
13
|
});
|
|
14
14
|
|
|
15
|
+
// Mock fs to prevent ENOENT errors when python-context tries to read files
|
|
16
|
+
vi.mock('fs', () => ({
|
|
17
|
+
default: {
|
|
18
|
+
promises: {
|
|
19
|
+
readFile: vi.fn().mockResolvedValue('# Python file\nprint("hello")'),
|
|
20
|
+
},
|
|
21
|
+
existsSync: vi.fn().mockReturnValue(true),
|
|
22
|
+
},
|
|
23
|
+
promises: {
|
|
24
|
+
readFile: vi.fn().mockResolvedValue('# Python file\nprint("hello")'),
|
|
25
|
+
},
|
|
26
|
+
existsSync: vi.fn().mockReturnValue(true),
|
|
27
|
+
}));
|
|
28
|
+
|
|
15
29
|
describe('analyzeContext', () => {
|
|
16
30
|
beforeEach(() => {
|
|
17
31
|
vi.clearAllMocks();
|
|
@@ -60,7 +74,7 @@ describe('analyzeContext', () => {
|
|
|
60
74
|
expect(results).toEqual([]);
|
|
61
75
|
});
|
|
62
76
|
|
|
63
|
-
it('should
|
|
77
|
+
it('should process both TypeScript and Python files', async () => {
|
|
64
78
|
const mockFiles = ['src/file1.ts', 'src/file2.py'];
|
|
65
79
|
vi.mocked(core.scanFiles).mockResolvedValue(mockFiles);
|
|
66
80
|
vi.mocked(core.readFileContent).mockResolvedValue('export const a = 1;');
|
|
@@ -69,9 +83,10 @@ describe('analyzeContext', () => {
|
|
|
69
83
|
rootDir: '.',
|
|
70
84
|
});
|
|
71
85
|
|
|
72
|
-
//
|
|
73
|
-
expect(results.length).toBe(
|
|
74
|
-
expect(results
|
|
86
|
+
// Orchestrator processes both TypeScript and Python files
|
|
87
|
+
expect(results.length).toBe(2);
|
|
88
|
+
expect(results.some((r) => r.file === 'src/file1.ts')).toBe(true);
|
|
89
|
+
expect(results.some((r) => r.file === 'src/file2.py')).toBe(true);
|
|
75
90
|
});
|
|
76
91
|
|
|
77
92
|
it('should use default options when not provided', async () => {
|
|
@@ -22,6 +22,13 @@ vi.mock('@aiready/core', () => ({
|
|
|
22
22
|
`<div class="issue-summary">Issues: Critical:${critical}, Major:${major}, Minor:${minor}. Savings: ${savings}</div>`,
|
|
23
23
|
wrapInCard: (content: string, title?: string) =>
|
|
24
24
|
`<div class="card"><h2>${title}</h2>${content}</div>`,
|
|
25
|
+
generateStandardHtmlReport: (config: any, stats: any[], sections: any[]) => {
|
|
26
|
+
const sectionHtml = sections
|
|
27
|
+
.map((s: any) => `<h2>${s.title}</h2>${s.content}`)
|
|
28
|
+
.join('');
|
|
29
|
+
const footerHtml = `<footer>${config.packageName} - ${config.packageUrl}</footer>`;
|
|
30
|
+
return `<!DOCTYPE html><html>${config.title}<body>${stats.map((s: any) => s.label).join(', ')}${sectionHtml}${footerHtml}</body></html>`;
|
|
31
|
+
},
|
|
25
32
|
}));
|
|
26
33
|
|
|
27
34
|
describe('generateHTMLReport', () => {
|
|
@@ -81,8 +88,7 @@ describe('generateHTMLReport', () => {
|
|
|
81
88
|
|
|
82
89
|
const html = generateHTMLReport(summary, results);
|
|
83
90
|
|
|
84
|
-
expect(html).toContain('
|
|
85
|
-
expect(html).toContain('head');
|
|
91
|
+
expect(html).toContain('Context Analysis Report');
|
|
86
92
|
expect(html).toContain('body');
|
|
87
93
|
});
|
|
88
94
|
|
package/src/ast-utils.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { parseFileExports } from '@aiready/core';
|
|
1
|
+
import { parseFileExports, isTestFile } from '@aiready/core';
|
|
2
2
|
import type { ExportInfo } from './types';
|
|
3
3
|
import { inferDomain, extractExports } from './semantic/domain-inference';
|
|
4
4
|
|
|
@@ -46,31 +46,6 @@ export async function extractExportsWithAST(
|
|
|
46
46
|
}
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
-
/**
|
|
50
|
-
* Check if a file is a test, mock, or fixture file.
|
|
51
|
-
*
|
|
52
|
-
* @param filePath - The path to the file to check.
|
|
53
|
-
* @returns True if the file matches test/mock patterns.
|
|
54
|
-
*/
|
|
55
|
-
export function isTestFile(filePath: string): boolean {
|
|
56
|
-
const lower = filePath.toLowerCase();
|
|
57
|
-
return (
|
|
58
|
-
lower.includes('.test.') ||
|
|
59
|
-
lower.includes('.spec.') ||
|
|
60
|
-
lower.includes('/__tests__/') ||
|
|
61
|
-
lower.includes('/tests/') ||
|
|
62
|
-
lower.includes('/test/') ||
|
|
63
|
-
lower.includes('test-') ||
|
|
64
|
-
lower.includes('-test') ||
|
|
65
|
-
lower.includes('/__mocks__/') ||
|
|
66
|
-
lower.includes('/mocks/') ||
|
|
67
|
-
lower.includes('/fixtures/') ||
|
|
68
|
-
lower.includes('.mock.') ||
|
|
69
|
-
lower.includes('.fixture.') ||
|
|
70
|
-
lower.includes('/test-utils/')
|
|
71
|
-
);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
49
|
/**
|
|
75
50
|
* Heuristic to check if all exports share a common entity noun
|
|
76
51
|
*/
|
package/src/cli-definition.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
|
-
import { contextActionHandler } from './cli-action';
|
|
3
2
|
|
|
4
3
|
/**
|
|
5
4
|
* Define the context analysis command structure.
|
|
@@ -57,5 +56,8 @@ export function defineContextCommand(program: Command): void {
|
|
|
57
56
|
'--interactive',
|
|
58
57
|
'Run interactive setup to suggest excludes and focus areas'
|
|
59
58
|
)
|
|
60
|
-
.action(
|
|
59
|
+
.action(async (directory, options) => {
|
|
60
|
+
const { contextActionHandler } = await import('./cli-action');
|
|
61
|
+
await contextActionHandler(directory, options);
|
|
62
|
+
});
|
|
61
63
|
}
|
package/src/issue-analyzer.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { Severity } from '@aiready/core';
|
|
1
|
+
import { Severity, isBuildArtifact } from '@aiready/core';
|
|
2
|
+
|
|
3
|
+
// Re-export for testing
|
|
4
|
+
export { isBuildArtifact };
|
|
2
5
|
|
|
3
6
|
/**
|
|
4
7
|
* Internal issue analysis logic
|
|
@@ -136,21 +139,3 @@ export function analyzeIssues(params: {
|
|
|
136
139
|
potentialSavings: Math.floor(potentialSavings),
|
|
137
140
|
};
|
|
138
141
|
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Determines if a file path belongs to a build artifact or dependency folder.
|
|
142
|
-
* Helps exclude generated files from analysis to prevent false positives.
|
|
143
|
-
*
|
|
144
|
-
* @param filePath - The path to check
|
|
145
|
-
* @returns True if the file is a build artifact, false otherwise
|
|
146
|
-
*/
|
|
147
|
-
export function isBuildArtifact(filePath: string): boolean {
|
|
148
|
-
const lower = filePath.toLowerCase();
|
|
149
|
-
return (
|
|
150
|
-
lower.includes('/node_modules/') ||
|
|
151
|
-
lower.includes('/dist/') ||
|
|
152
|
-
lower.includes('/build/') ||
|
|
153
|
-
lower.includes('/out/') ||
|
|
154
|
-
lower.includes('/.next/')
|
|
155
|
-
);
|
|
156
|
-
}
|
package/src/metrics.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { calculateImportSimilarity } from '@aiready/core';
|
|
1
|
+
import { calculateImportSimilarity, isTestFile } from '@aiready/core';
|
|
2
2
|
import type { ExportInfo } from './types';
|
|
3
|
-
import { isTestFile } from './ast-utils';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Calculates a cohesion score (0-1) for a module based on its exports,
|
package/src/provider.ts
CHANGED
|
@@ -9,10 +9,8 @@ import {
|
|
|
9
9
|
IssueType,
|
|
10
10
|
SpokeOutputSchema,
|
|
11
11
|
} from '@aiready/core';
|
|
12
|
-
import { analyzeContext } from './orchestrator';
|
|
13
|
-
import { generateSummary } from './summary';
|
|
14
12
|
import { calculateContextScore } from './scoring';
|
|
15
|
-
import { ContextAnalyzerOptions, ContextAnalysisResult } from './types';
|
|
13
|
+
import type { ContextAnalyzerOptions, ContextAnalysisResult } from './types';
|
|
16
14
|
|
|
17
15
|
/**
|
|
18
16
|
* Context Analyzer Tool Provider
|
|
@@ -22,6 +20,9 @@ export const ContextAnalyzerProvider: ToolProvider = {
|
|
|
22
20
|
alias: ['context', 'fragmentation', 'budget'],
|
|
23
21
|
|
|
24
22
|
async analyze(options: ScanOptions): Promise<SpokeOutput> {
|
|
23
|
+
const { analyzeContext } = await import('./orchestrator');
|
|
24
|
+
const { generateSummary } = await import('./summary');
|
|
25
|
+
|
|
25
26
|
const results = await analyzeContext(options as ContextAnalyzerOptions);
|
|
26
27
|
const summary = generateSummary(results, options);
|
|
27
28
|
|
|
@@ -39,7 +40,6 @@ export const ContextAnalyzerProvider: ToolProvider = {
|
|
|
39
40
|
metrics: {
|
|
40
41
|
tokenCost: r.tokenCost,
|
|
41
42
|
complexityScore: r.importDepth,
|
|
42
|
-
// Map other context-specific metrics if needed
|
|
43
43
|
},
|
|
44
44
|
})
|
|
45
45
|
);
|
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { analyzeContext } from '../orchestrator';
|
|
2
2
|
import { generateSummary } from '../summary';
|
|
3
3
|
import {
|
|
4
|
-
generateReportHead,
|
|
5
|
-
generateReportHero,
|
|
6
|
-
generateStatCards,
|
|
7
4
|
generateIssueSummary,
|
|
8
5
|
generateTable,
|
|
9
|
-
|
|
10
|
-
wrapInCard,
|
|
6
|
+
generateStandardHtmlReport,
|
|
11
7
|
} from '@aiready/core';
|
|
12
8
|
|
|
13
9
|
/**
|
|
@@ -19,13 +15,9 @@ export function generateHTMLReport(
|
|
|
19
15
|
): string {
|
|
20
16
|
const totalIssues =
|
|
21
17
|
summary.criticalIssues + summary.majorIssues + summary.minorIssues;
|
|
22
|
-
|
|
23
|
-
// 'results' may be used in templates later; reference to avoid lint warnings
|
|
24
18
|
void results;
|
|
25
19
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
const stats = generateStatCards([
|
|
20
|
+
const stats = [
|
|
29
21
|
{ value: summary.totalFiles, label: 'Files Analyzed' },
|
|
30
22
|
{ value: summary.totalTokens.toLocaleString(), label: 'Total Tokens' },
|
|
31
23
|
{ value: summary.avgContextBudget.toFixed(0), label: 'Avg Context Budget' },
|
|
@@ -34,67 +26,59 @@ export function generateHTMLReport(
|
|
|
34
26
|
label: 'Total Issues',
|
|
35
27
|
color: totalIssues > 0 ? '#f39c12' : undefined,
|
|
36
28
|
},
|
|
37
|
-
]
|
|
38
|
-
|
|
39
|
-
const hero = generateReportHero(
|
|
40
|
-
'🔍 AIReady Context Analysis Report',
|
|
41
|
-
`Generated on ${new Date().toLocaleString()}`
|
|
42
|
-
);
|
|
43
|
-
|
|
44
|
-
let body = `${hero}
|
|
45
|
-
${stats}`;
|
|
29
|
+
];
|
|
46
30
|
|
|
31
|
+
const sections: any[] = [];
|
|
47
32
|
if (totalIssues > 0) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
33
|
+
sections.push({
|
|
34
|
+
title: '⚠️ Issues Summary',
|
|
35
|
+
content: generateIssueSummary(
|
|
36
|
+
summary.criticalIssues,
|
|
37
|
+
summary.majorIssues,
|
|
38
|
+
summary.minorIssues,
|
|
39
|
+
summary.totalPotentialSavings
|
|
40
|
+
),
|
|
41
|
+
});
|
|
54
42
|
}
|
|
55
43
|
|
|
56
44
|
if (summary.fragmentedModules.length > 0) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`${(m.fragmentationScore * 100).toFixed(0)}%`,
|
|
61
|
-
m.totalTokens.toLocaleString(),
|
|
62
|
-
]);
|
|
63
|
-
body += wrapInCard(
|
|
64
|
-
generateTable({
|
|
45
|
+
sections.push({
|
|
46
|
+
title: '🧩 Fragmented Modules',
|
|
47
|
+
content: generateTable({
|
|
65
48
|
headers: ['Domain', 'Files', 'Fragmentation', 'Token Cost'],
|
|
66
|
-
rows:
|
|
49
|
+
rows: summary.fragmentedModules.map((m) => [
|
|
50
|
+
m.domain,
|
|
51
|
+
String(m.files.length),
|
|
52
|
+
`${(m.fragmentationScore * 100).toFixed(0)}%`,
|
|
53
|
+
m.totalTokens.toLocaleString(),
|
|
54
|
+
]),
|
|
67
55
|
}),
|
|
68
|
-
|
|
69
|
-
);
|
|
56
|
+
});
|
|
70
57
|
}
|
|
71
58
|
|
|
72
59
|
if (summary.topExpensiveFiles.length > 0) {
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
`<span class="issue-${f.severity}">${f.severity.toUpperCase()}</span>`,
|
|
77
|
-
]);
|
|
78
|
-
body += wrapInCard(
|
|
79
|
-
generateTable({
|
|
60
|
+
sections.push({
|
|
61
|
+
title: '💸 Most Expensive Files',
|
|
62
|
+
content: generateTable({
|
|
80
63
|
headers: ['File', 'Context Budget', 'Severity'],
|
|
81
|
-
rows:
|
|
64
|
+
rows: summary.topExpensiveFiles.map((f) => [
|
|
65
|
+
f.file,
|
|
66
|
+
`${f.contextBudget.toLocaleString()} tokens`,
|
|
67
|
+
`<span class="issue-${f.severity}">${f.severity.toUpperCase()}</span>`,
|
|
68
|
+
]),
|
|
82
69
|
}),
|
|
83
|
-
|
|
84
|
-
);
|
|
70
|
+
});
|
|
85
71
|
}
|
|
86
72
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
</body>
|
|
99
|
-
</html>`;
|
|
73
|
+
return generateStandardHtmlReport(
|
|
74
|
+
{
|
|
75
|
+
title: 'Context Analysis Report',
|
|
76
|
+
packageName: 'context-analyzer',
|
|
77
|
+
packageUrl: 'https://github.com/caopengau/aiready-context-analyzer',
|
|
78
|
+
bugUrl: 'https://github.com/caopengau/aiready-context-analyzer/issues',
|
|
79
|
+
emoji: '🧠',
|
|
80
|
+
},
|
|
81
|
+
stats,
|
|
82
|
+
sections
|
|
83
|
+
);
|
|
100
84
|
}
|