@aiready/context-analyzer 0.9.22 → 0.9.23
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 +11 -11
- package/.turbo/turbo-test.log +24 -20
- package/README.md +51 -0
- package/dist/chunk-MBE4AQP5.mjs +1362 -0
- package/dist/cli.js +124 -5
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +29 -1
- package/dist/index.d.ts +29 -1
- package/dist/index.js +128 -5
- package/dist/index.mjs +5 -1
- package/package.json +1 -1
- package/src/__tests__/file-classification.test.ts +216 -0
- package/src/analyzer.ts +187 -0
- package/src/index.ts +52 -5
- package/src/types.ts +14 -0
package/dist/cli.js
CHANGED
|
@@ -890,6 +890,95 @@ function calculateDomainCohesion(exports2) {
|
|
|
890
890
|
const maxEntropy = Math.log2(total);
|
|
891
891
|
return maxEntropy > 0 ? 1 - entropy / maxEntropy : 1;
|
|
892
892
|
}
|
|
893
|
+
function classifyFile(node, cohesionScore, domains) {
|
|
894
|
+
const { exports: exports2, imports, linesOfCode } = node;
|
|
895
|
+
if (isBarrelExport(node)) {
|
|
896
|
+
return "barrel-export";
|
|
897
|
+
}
|
|
898
|
+
if (isTypeDefinitionFile(node)) {
|
|
899
|
+
return "type-definition";
|
|
900
|
+
}
|
|
901
|
+
const uniqueDomains = domains.filter((d) => d !== "unknown");
|
|
902
|
+
const hasSingleDomain = uniqueDomains.length <= 1;
|
|
903
|
+
const hasHighCohesion = cohesionScore >= 0.7;
|
|
904
|
+
if (hasSingleDomain && hasHighCohesion) {
|
|
905
|
+
return "cohesive-module";
|
|
906
|
+
}
|
|
907
|
+
const hasMultipleDomains = uniqueDomains.length > 1;
|
|
908
|
+
const hasLowCohesion = cohesionScore < 0.5;
|
|
909
|
+
if (hasMultipleDomains || hasLowCohesion) {
|
|
910
|
+
return "mixed-concerns";
|
|
911
|
+
}
|
|
912
|
+
return "unknown";
|
|
913
|
+
}
|
|
914
|
+
function isBarrelExport(node) {
|
|
915
|
+
const { file, exports: exports2, imports, linesOfCode } = node;
|
|
916
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
917
|
+
const isIndexFile = fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx";
|
|
918
|
+
const hasReExports = exports2.length > 0 && imports.length > 0;
|
|
919
|
+
const highExportToLinesRatio = exports2.length > 3 && linesOfCode < exports2.length * 5;
|
|
920
|
+
const sparseCode = linesOfCode > 0 && linesOfCode < 50 && exports2.length >= 2;
|
|
921
|
+
if (isIndexFile && hasReExports) {
|
|
922
|
+
return true;
|
|
923
|
+
}
|
|
924
|
+
if (highExportToLinesRatio && imports.length >= exports2.length * 0.5) {
|
|
925
|
+
return true;
|
|
926
|
+
}
|
|
927
|
+
if (sparseCode && imports.length > 0) {
|
|
928
|
+
return true;
|
|
929
|
+
}
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
function isTypeDefinitionFile(node) {
|
|
933
|
+
const { file, exports: exports2 } = node;
|
|
934
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
935
|
+
const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
|
|
936
|
+
const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
|
|
937
|
+
const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
|
|
938
|
+
const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
|
|
939
|
+
return isTypesFile || mostlyTypes;
|
|
940
|
+
}
|
|
941
|
+
function adjustFragmentationForClassification(baseFragmentation, classification) {
|
|
942
|
+
switch (classification) {
|
|
943
|
+
case "barrel-export":
|
|
944
|
+
return 0;
|
|
945
|
+
case "type-definition":
|
|
946
|
+
return 0;
|
|
947
|
+
case "cohesive-module":
|
|
948
|
+
return baseFragmentation * 0.3;
|
|
949
|
+
case "mixed-concerns":
|
|
950
|
+
return baseFragmentation;
|
|
951
|
+
default:
|
|
952
|
+
return baseFragmentation * 0.7;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
function getClassificationRecommendations(classification, file, issues) {
|
|
956
|
+
switch (classification) {
|
|
957
|
+
case "barrel-export":
|
|
958
|
+
return [
|
|
959
|
+
"Barrel export file detected - multiple domains are expected here",
|
|
960
|
+
"Consider if this barrel export improves or hinders discoverability"
|
|
961
|
+
];
|
|
962
|
+
case "type-definition":
|
|
963
|
+
return [
|
|
964
|
+
"Type definition file - centralized types improve consistency",
|
|
965
|
+
"Consider splitting if file becomes too large (>500 lines)"
|
|
966
|
+
];
|
|
967
|
+
case "cohesive-module":
|
|
968
|
+
return [
|
|
969
|
+
"Module has good cohesion despite its size",
|
|
970
|
+
"Consider documenting the module boundaries for AI assistants"
|
|
971
|
+
];
|
|
972
|
+
case "mixed-concerns":
|
|
973
|
+
return [
|
|
974
|
+
"Consider splitting this file by domain",
|
|
975
|
+
"Identify independent responsibilities and extract them",
|
|
976
|
+
"Review import dependencies to understand coupling"
|
|
977
|
+
];
|
|
978
|
+
default:
|
|
979
|
+
return issues;
|
|
980
|
+
}
|
|
981
|
+
}
|
|
893
982
|
|
|
894
983
|
// src/index.ts
|
|
895
984
|
async function analyzeContext(options) {
|
|
@@ -952,6 +1041,8 @@ async function analyzeContext(options) {
|
|
|
952
1041
|
contextBudget: metric.contextBudget,
|
|
953
1042
|
fragmentationScore: 0,
|
|
954
1043
|
relatedFiles: [],
|
|
1044
|
+
fileClassification: "unknown",
|
|
1045
|
+
// Python files not yet classified
|
|
955
1046
|
severity,
|
|
956
1047
|
issues,
|
|
957
1048
|
recommendations,
|
|
@@ -999,6 +1090,33 @@ async function analyzeContext(options) {
|
|
|
999
1090
|
const domains = [
|
|
1000
1091
|
...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
|
|
1001
1092
|
];
|
|
1093
|
+
const fileClassification = classifyFile(node, cohesionScore, domains);
|
|
1094
|
+
const adjustedFragmentationScore = adjustFragmentationForClassification(
|
|
1095
|
+
fragmentationScore,
|
|
1096
|
+
fileClassification
|
|
1097
|
+
);
|
|
1098
|
+
const classificationRecommendations = getClassificationRecommendations(
|
|
1099
|
+
fileClassification,
|
|
1100
|
+
file,
|
|
1101
|
+
issues
|
|
1102
|
+
);
|
|
1103
|
+
const {
|
|
1104
|
+
severity: adjustedSeverity,
|
|
1105
|
+
issues: adjustedIssues,
|
|
1106
|
+
recommendations: finalRecommendations,
|
|
1107
|
+
potentialSavings: adjustedSavings
|
|
1108
|
+
} = analyzeIssues({
|
|
1109
|
+
file,
|
|
1110
|
+
importDepth,
|
|
1111
|
+
contextBudget,
|
|
1112
|
+
cohesionScore,
|
|
1113
|
+
fragmentationScore: adjustedFragmentationScore,
|
|
1114
|
+
maxDepth,
|
|
1115
|
+
maxContextBudget,
|
|
1116
|
+
minCohesion,
|
|
1117
|
+
maxFragmentation,
|
|
1118
|
+
circularDeps
|
|
1119
|
+
});
|
|
1002
1120
|
results.push({
|
|
1003
1121
|
file,
|
|
1004
1122
|
tokenCost: node.tokenCost,
|
|
@@ -1011,12 +1129,13 @@ async function analyzeContext(options) {
|
|
|
1011
1129
|
domains,
|
|
1012
1130
|
exportCount: node.exports.length,
|
|
1013
1131
|
contextBudget,
|
|
1014
|
-
fragmentationScore,
|
|
1132
|
+
fragmentationScore: adjustedFragmentationScore,
|
|
1015
1133
|
relatedFiles,
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1134
|
+
fileClassification,
|
|
1135
|
+
severity: adjustedSeverity,
|
|
1136
|
+
issues: adjustedIssues,
|
|
1137
|
+
recommendations: [...finalRecommendations, ...classificationRecommendations.slice(0, 1)],
|
|
1138
|
+
potentialSavings: adjustedSavings
|
|
1020
1139
|
});
|
|
1021
1140
|
}
|
|
1022
1141
|
const allResults = [...results, ...pythonResults];
|
package/dist/cli.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -22,11 +22,17 @@ interface ContextAnalysisResult {
|
|
|
22
22
|
contextBudget: number;
|
|
23
23
|
fragmentationScore: number;
|
|
24
24
|
relatedFiles: string[];
|
|
25
|
+
fileClassification: FileClassification;
|
|
25
26
|
severity: 'critical' | 'major' | 'minor' | 'info';
|
|
26
27
|
issues: string[];
|
|
27
28
|
recommendations: string[];
|
|
28
29
|
potentialSavings: number;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Classification of file type for analysis context
|
|
33
|
+
* Helps distinguish real issues from false positives
|
|
34
|
+
*/
|
|
35
|
+
type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'mixed-concerns' | 'unknown';
|
|
30
36
|
interface ModuleCluster {
|
|
31
37
|
domain: string;
|
|
32
38
|
files: string[];
|
|
@@ -116,6 +122,28 @@ interface TypeDependency {
|
|
|
116
122
|
usedBy: string[];
|
|
117
123
|
}
|
|
118
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Classify a file based on its characteristics to help distinguish
|
|
127
|
+
* real issues from false positives.
|
|
128
|
+
*
|
|
129
|
+
* Classification types:
|
|
130
|
+
* - barrel-export: Re-exports from other modules (index.ts files)
|
|
131
|
+
* - type-definition: Primarily type/interface definitions
|
|
132
|
+
* - cohesive-module: Single domain, high cohesion (acceptable large files)
|
|
133
|
+
* - mixed-concerns: Multiple domains, potential refactoring candidate
|
|
134
|
+
* - unknown: Unable to classify
|
|
135
|
+
*/
|
|
136
|
+
declare function classifyFile(node: DependencyNode, cohesionScore: number, domains: string[]): FileClassification;
|
|
137
|
+
/**
|
|
138
|
+
* Adjust fragmentation score based on file classification
|
|
139
|
+
*
|
|
140
|
+
* This reduces false positives by:
|
|
141
|
+
* - Ignoring fragmentation for barrel exports (they're meant to aggregate)
|
|
142
|
+
* - Ignoring fragmentation for type definitions (centralized types are good)
|
|
143
|
+
* - Reducing fragmentation for cohesive modules (large but focused is OK)
|
|
144
|
+
*/
|
|
145
|
+
declare function adjustFragmentationForClassification(baseFragmentation: number, classification: FileClassification): number;
|
|
146
|
+
|
|
119
147
|
/**
|
|
120
148
|
* Calculate AI Readiness Score for context efficiency (0-100)
|
|
121
149
|
*
|
|
@@ -184,4 +212,4 @@ declare function analyzeContext(options: ContextAnalyzerOptions): Promise<Contex
|
|
|
184
212
|
*/
|
|
185
213
|
declare function generateSummary(results: ContextAnalysisResult[]): ContextSummary;
|
|
186
214
|
|
|
187
|
-
export { type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, type ContextSummary, type DomainAssignment, type DomainSignals, type ModuleCluster, type TypeDependency, analyzeContext, buildCoUsageMatrix, buildTypeGraph, calculateContextScore, calculateDomainConfidence, findConsolidationCandidates, findSemanticClusters, generateSummary, getCoUsageData, getSmartDefaults, inferDomainFromSemantics };
|
|
215
|
+
export { type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, type ContextSummary, type DomainAssignment, type DomainSignals, type FileClassification, type ModuleCluster, type TypeDependency, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildTypeGraph, calculateContextScore, calculateDomainConfidence, classifyFile, findConsolidationCandidates, findSemanticClusters, generateSummary, getCoUsageData, getSmartDefaults, inferDomainFromSemantics };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,11 +22,17 @@ interface ContextAnalysisResult {
|
|
|
22
22
|
contextBudget: number;
|
|
23
23
|
fragmentationScore: number;
|
|
24
24
|
relatedFiles: string[];
|
|
25
|
+
fileClassification: FileClassification;
|
|
25
26
|
severity: 'critical' | 'major' | 'minor' | 'info';
|
|
26
27
|
issues: string[];
|
|
27
28
|
recommendations: string[];
|
|
28
29
|
potentialSavings: number;
|
|
29
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Classification of file type for analysis context
|
|
33
|
+
* Helps distinguish real issues from false positives
|
|
34
|
+
*/
|
|
35
|
+
type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'mixed-concerns' | 'unknown';
|
|
30
36
|
interface ModuleCluster {
|
|
31
37
|
domain: string;
|
|
32
38
|
files: string[];
|
|
@@ -116,6 +122,28 @@ interface TypeDependency {
|
|
|
116
122
|
usedBy: string[];
|
|
117
123
|
}
|
|
118
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Classify a file based on its characteristics to help distinguish
|
|
127
|
+
* real issues from false positives.
|
|
128
|
+
*
|
|
129
|
+
* Classification types:
|
|
130
|
+
* - barrel-export: Re-exports from other modules (index.ts files)
|
|
131
|
+
* - type-definition: Primarily type/interface definitions
|
|
132
|
+
* - cohesive-module: Single domain, high cohesion (acceptable large files)
|
|
133
|
+
* - mixed-concerns: Multiple domains, potential refactoring candidate
|
|
134
|
+
* - unknown: Unable to classify
|
|
135
|
+
*/
|
|
136
|
+
declare function classifyFile(node: DependencyNode, cohesionScore: number, domains: string[]): FileClassification;
|
|
137
|
+
/**
|
|
138
|
+
* Adjust fragmentation score based on file classification
|
|
139
|
+
*
|
|
140
|
+
* This reduces false positives by:
|
|
141
|
+
* - Ignoring fragmentation for barrel exports (they're meant to aggregate)
|
|
142
|
+
* - Ignoring fragmentation for type definitions (centralized types are good)
|
|
143
|
+
* - Reducing fragmentation for cohesive modules (large but focused is OK)
|
|
144
|
+
*/
|
|
145
|
+
declare function adjustFragmentationForClassification(baseFragmentation: number, classification: FileClassification): number;
|
|
146
|
+
|
|
119
147
|
/**
|
|
120
148
|
* Calculate AI Readiness Score for context efficiency (0-100)
|
|
121
149
|
*
|
|
@@ -184,4 +212,4 @@ declare function analyzeContext(options: ContextAnalyzerOptions): Promise<Contex
|
|
|
184
212
|
*/
|
|
185
213
|
declare function generateSummary(results: ContextAnalysisResult[]): ContextSummary;
|
|
186
214
|
|
|
187
|
-
export { type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, type ContextSummary, type DomainAssignment, type DomainSignals, type ModuleCluster, type TypeDependency, analyzeContext, buildCoUsageMatrix, buildTypeGraph, calculateContextScore, calculateDomainConfidence, findConsolidationCandidates, findSemanticClusters, generateSummary, getCoUsageData, getSmartDefaults, inferDomainFromSemantics };
|
|
215
|
+
export { type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, type ContextSummary, type DomainAssignment, type DomainSignals, type FileClassification, type ModuleCluster, type TypeDependency, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildTypeGraph, calculateContextScore, calculateDomainConfidence, classifyFile, findConsolidationCandidates, findSemanticClusters, generateSummary, getCoUsageData, getSmartDefaults, inferDomainFromSemantics };
|
package/dist/index.js
CHANGED
|
@@ -229,11 +229,13 @@ var init_python_context = __esm({
|
|
|
229
229
|
// src/index.ts
|
|
230
230
|
var index_exports = {};
|
|
231
231
|
__export(index_exports, {
|
|
232
|
+
adjustFragmentationForClassification: () => adjustFragmentationForClassification,
|
|
232
233
|
analyzeContext: () => analyzeContext,
|
|
233
234
|
buildCoUsageMatrix: () => buildCoUsageMatrix,
|
|
234
235
|
buildTypeGraph: () => buildTypeGraph,
|
|
235
236
|
calculateContextScore: () => calculateContextScore,
|
|
236
237
|
calculateDomainConfidence: () => calculateDomainConfidence,
|
|
238
|
+
classifyFile: () => classifyFile,
|
|
237
239
|
findConsolidationCandidates: () => findConsolidationCandidates,
|
|
238
240
|
findSemanticClusters: () => findSemanticClusters,
|
|
239
241
|
generateSummary: () => generateSummary,
|
|
@@ -963,6 +965,95 @@ function calculateDomainCohesion(exports2) {
|
|
|
963
965
|
const maxEntropy = Math.log2(total);
|
|
964
966
|
return maxEntropy > 0 ? 1 - entropy / maxEntropy : 1;
|
|
965
967
|
}
|
|
968
|
+
function classifyFile(node, cohesionScore, domains) {
|
|
969
|
+
const { exports: exports2, imports, linesOfCode } = node;
|
|
970
|
+
if (isBarrelExport(node)) {
|
|
971
|
+
return "barrel-export";
|
|
972
|
+
}
|
|
973
|
+
if (isTypeDefinitionFile(node)) {
|
|
974
|
+
return "type-definition";
|
|
975
|
+
}
|
|
976
|
+
const uniqueDomains = domains.filter((d) => d !== "unknown");
|
|
977
|
+
const hasSingleDomain = uniqueDomains.length <= 1;
|
|
978
|
+
const hasHighCohesion = cohesionScore >= 0.7;
|
|
979
|
+
if (hasSingleDomain && hasHighCohesion) {
|
|
980
|
+
return "cohesive-module";
|
|
981
|
+
}
|
|
982
|
+
const hasMultipleDomains = uniqueDomains.length > 1;
|
|
983
|
+
const hasLowCohesion = cohesionScore < 0.5;
|
|
984
|
+
if (hasMultipleDomains || hasLowCohesion) {
|
|
985
|
+
return "mixed-concerns";
|
|
986
|
+
}
|
|
987
|
+
return "unknown";
|
|
988
|
+
}
|
|
989
|
+
function isBarrelExport(node) {
|
|
990
|
+
const { file, exports: exports2, imports, linesOfCode } = node;
|
|
991
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
992
|
+
const isIndexFile = fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx";
|
|
993
|
+
const hasReExports = exports2.length > 0 && imports.length > 0;
|
|
994
|
+
const highExportToLinesRatio = exports2.length > 3 && linesOfCode < exports2.length * 5;
|
|
995
|
+
const sparseCode = linesOfCode > 0 && linesOfCode < 50 && exports2.length >= 2;
|
|
996
|
+
if (isIndexFile && hasReExports) {
|
|
997
|
+
return true;
|
|
998
|
+
}
|
|
999
|
+
if (highExportToLinesRatio && imports.length >= exports2.length * 0.5) {
|
|
1000
|
+
return true;
|
|
1001
|
+
}
|
|
1002
|
+
if (sparseCode && imports.length > 0) {
|
|
1003
|
+
return true;
|
|
1004
|
+
}
|
|
1005
|
+
return false;
|
|
1006
|
+
}
|
|
1007
|
+
function isTypeDefinitionFile(node) {
|
|
1008
|
+
const { file, exports: exports2 } = node;
|
|
1009
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1010
|
+
const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
|
|
1011
|
+
const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
|
|
1012
|
+
const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
|
|
1013
|
+
const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
|
|
1014
|
+
return isTypesFile || mostlyTypes;
|
|
1015
|
+
}
|
|
1016
|
+
function adjustFragmentationForClassification(baseFragmentation, classification) {
|
|
1017
|
+
switch (classification) {
|
|
1018
|
+
case "barrel-export":
|
|
1019
|
+
return 0;
|
|
1020
|
+
case "type-definition":
|
|
1021
|
+
return 0;
|
|
1022
|
+
case "cohesive-module":
|
|
1023
|
+
return baseFragmentation * 0.3;
|
|
1024
|
+
case "mixed-concerns":
|
|
1025
|
+
return baseFragmentation;
|
|
1026
|
+
default:
|
|
1027
|
+
return baseFragmentation * 0.7;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
function getClassificationRecommendations(classification, file, issues) {
|
|
1031
|
+
switch (classification) {
|
|
1032
|
+
case "barrel-export":
|
|
1033
|
+
return [
|
|
1034
|
+
"Barrel export file detected - multiple domains are expected here",
|
|
1035
|
+
"Consider if this barrel export improves or hinders discoverability"
|
|
1036
|
+
];
|
|
1037
|
+
case "type-definition":
|
|
1038
|
+
return [
|
|
1039
|
+
"Type definition file - centralized types improve consistency",
|
|
1040
|
+
"Consider splitting if file becomes too large (>500 lines)"
|
|
1041
|
+
];
|
|
1042
|
+
case "cohesive-module":
|
|
1043
|
+
return [
|
|
1044
|
+
"Module has good cohesion despite its size",
|
|
1045
|
+
"Consider documenting the module boundaries for AI assistants"
|
|
1046
|
+
];
|
|
1047
|
+
case "mixed-concerns":
|
|
1048
|
+
return [
|
|
1049
|
+
"Consider splitting this file by domain",
|
|
1050
|
+
"Identify independent responsibilities and extract them",
|
|
1051
|
+
"Review import dependencies to understand coupling"
|
|
1052
|
+
];
|
|
1053
|
+
default:
|
|
1054
|
+
return issues;
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
966
1057
|
|
|
967
1058
|
// src/scoring.ts
|
|
968
1059
|
function calculateContextScore(summary) {
|
|
@@ -1176,6 +1267,8 @@ async function analyzeContext(options) {
|
|
|
1176
1267
|
contextBudget: metric.contextBudget,
|
|
1177
1268
|
fragmentationScore: 0,
|
|
1178
1269
|
relatedFiles: [],
|
|
1270
|
+
fileClassification: "unknown",
|
|
1271
|
+
// Python files not yet classified
|
|
1179
1272
|
severity,
|
|
1180
1273
|
issues,
|
|
1181
1274
|
recommendations,
|
|
@@ -1223,6 +1316,33 @@ async function analyzeContext(options) {
|
|
|
1223
1316
|
const domains = [
|
|
1224
1317
|
...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
|
|
1225
1318
|
];
|
|
1319
|
+
const fileClassification = classifyFile(node, cohesionScore, domains);
|
|
1320
|
+
const adjustedFragmentationScore = adjustFragmentationForClassification(
|
|
1321
|
+
fragmentationScore,
|
|
1322
|
+
fileClassification
|
|
1323
|
+
);
|
|
1324
|
+
const classificationRecommendations = getClassificationRecommendations(
|
|
1325
|
+
fileClassification,
|
|
1326
|
+
file,
|
|
1327
|
+
issues
|
|
1328
|
+
);
|
|
1329
|
+
const {
|
|
1330
|
+
severity: adjustedSeverity,
|
|
1331
|
+
issues: adjustedIssues,
|
|
1332
|
+
recommendations: finalRecommendations,
|
|
1333
|
+
potentialSavings: adjustedSavings
|
|
1334
|
+
} = analyzeIssues({
|
|
1335
|
+
file,
|
|
1336
|
+
importDepth,
|
|
1337
|
+
contextBudget,
|
|
1338
|
+
cohesionScore,
|
|
1339
|
+
fragmentationScore: adjustedFragmentationScore,
|
|
1340
|
+
maxDepth,
|
|
1341
|
+
maxContextBudget,
|
|
1342
|
+
minCohesion,
|
|
1343
|
+
maxFragmentation,
|
|
1344
|
+
circularDeps
|
|
1345
|
+
});
|
|
1226
1346
|
results.push({
|
|
1227
1347
|
file,
|
|
1228
1348
|
tokenCost: node.tokenCost,
|
|
@@ -1235,12 +1355,13 @@ async function analyzeContext(options) {
|
|
|
1235
1355
|
domains,
|
|
1236
1356
|
exportCount: node.exports.length,
|
|
1237
1357
|
contextBudget,
|
|
1238
|
-
fragmentationScore,
|
|
1358
|
+
fragmentationScore: adjustedFragmentationScore,
|
|
1239
1359
|
relatedFiles,
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1360
|
+
fileClassification,
|
|
1361
|
+
severity: adjustedSeverity,
|
|
1362
|
+
issues: adjustedIssues,
|
|
1363
|
+
recommendations: [...finalRecommendations, ...classificationRecommendations.slice(0, 1)],
|
|
1364
|
+
potentialSavings: adjustedSavings
|
|
1244
1365
|
});
|
|
1245
1366
|
}
|
|
1246
1367
|
const allResults = [...results, ...pythonResults];
|
|
@@ -1470,11 +1591,13 @@ function downgradeSeverity(s) {
|
|
|
1470
1591
|
}
|
|
1471
1592
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1472
1593
|
0 && (module.exports = {
|
|
1594
|
+
adjustFragmentationForClassification,
|
|
1473
1595
|
analyzeContext,
|
|
1474
1596
|
buildCoUsageMatrix,
|
|
1475
1597
|
buildTypeGraph,
|
|
1476
1598
|
calculateContextScore,
|
|
1477
1599
|
calculateDomainConfidence,
|
|
1600
|
+
classifyFile,
|
|
1478
1601
|
findConsolidationCandidates,
|
|
1479
1602
|
findSemanticClusters,
|
|
1480
1603
|
generateSummary,
|
package/dist/index.mjs
CHANGED
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
import {
|
|
2
|
+
adjustFragmentationForClassification,
|
|
2
3
|
analyzeContext,
|
|
3
4
|
buildCoUsageMatrix,
|
|
4
5
|
buildTypeGraph,
|
|
5
6
|
calculateContextScore,
|
|
6
7
|
calculateDomainConfidence,
|
|
8
|
+
classifyFile,
|
|
7
9
|
findConsolidationCandidates,
|
|
8
10
|
findSemanticClusters,
|
|
9
11
|
generateSummary,
|
|
10
12
|
getCoUsageData,
|
|
11
13
|
getSmartDefaults,
|
|
12
14
|
inferDomainFromSemantics
|
|
13
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-MBE4AQP5.mjs";
|
|
14
16
|
import "./chunk-Y6FXYEAI.mjs";
|
|
15
17
|
export {
|
|
18
|
+
adjustFragmentationForClassification,
|
|
16
19
|
analyzeContext,
|
|
17
20
|
buildCoUsageMatrix,
|
|
18
21
|
buildTypeGraph,
|
|
19
22
|
calculateContextScore,
|
|
20
23
|
calculateDomainConfidence,
|
|
24
|
+
classifyFile,
|
|
21
25
|
findConsolidationCandidates,
|
|
22
26
|
findSemanticClusters,
|
|
23
27
|
generateSummary,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/context-analyzer",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.23",
|
|
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",
|