@aiready/context-analyzer 0.9.22 → 0.9.25

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/dist/cli.js CHANGED
@@ -890,6 +890,155 @@ 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, file } = node;
895
+ if (isBarrelExport(node)) {
896
+ return "barrel-export";
897
+ }
898
+ if (isTypeDefinitionFile(node)) {
899
+ return "type-definition";
900
+ }
901
+ if (isConfigOrSchemaFile(node)) {
902
+ return "cohesive-module";
903
+ }
904
+ const uniqueDomains = domains.filter((d) => d !== "unknown");
905
+ const hasSingleDomain = uniqueDomains.length <= 1;
906
+ const hasReasonableCohesion = cohesionScore >= 0.5;
907
+ if (hasSingleDomain) {
908
+ return "cohesive-module";
909
+ }
910
+ if (isUtilityFile(node)) {
911
+ return "cohesive-module";
912
+ }
913
+ const hasMultipleDomains = uniqueDomains.length > 1;
914
+ const hasLowCohesion = cohesionScore < 0.4;
915
+ if (hasMultipleDomains && hasLowCohesion) {
916
+ return "mixed-concerns";
917
+ }
918
+ if (cohesionScore >= 0.5) {
919
+ return "cohesive-module";
920
+ }
921
+ return "unknown";
922
+ }
923
+ function isBarrelExport(node) {
924
+ const { file, exports: exports2, imports, linesOfCode } = node;
925
+ const fileName = file.split("/").pop()?.toLowerCase();
926
+ const isIndexFile = fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx";
927
+ const hasReExports = exports2.length > 0 && imports.length > 0;
928
+ const highExportToLinesRatio = exports2.length > 3 && linesOfCode < exports2.length * 5;
929
+ const sparseCode = linesOfCode > 0 && linesOfCode < 50 && exports2.length >= 2;
930
+ if (isIndexFile && hasReExports) {
931
+ return true;
932
+ }
933
+ if (highExportToLinesRatio && imports.length >= exports2.length * 0.5) {
934
+ return true;
935
+ }
936
+ if (sparseCode && imports.length > 0) {
937
+ return true;
938
+ }
939
+ return false;
940
+ }
941
+ function isTypeDefinitionFile(node) {
942
+ const { file, exports: exports2 } = node;
943
+ const fileName = file.split("/").pop()?.toLowerCase();
944
+ const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
945
+ const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
946
+ const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
947
+ const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
948
+ return isTypesFile || mostlyTypes;
949
+ }
950
+ function isConfigOrSchemaFile(node) {
951
+ const { file, exports: exports2 } = node;
952
+ const fileName = file.split("/").pop()?.toLowerCase();
953
+ const configPatterns = [
954
+ "config",
955
+ "schema",
956
+ "settings",
957
+ "options",
958
+ "constants",
959
+ "env",
960
+ "environment",
961
+ ".config.",
962
+ "-config.",
963
+ "_config."
964
+ ];
965
+ const isConfigName = configPatterns.some(
966
+ (pattern) => fileName?.includes(pattern) || fileName?.startsWith(pattern) || fileName?.endsWith(`${pattern}.ts`)
967
+ );
968
+ const isConfigPath = file.toLowerCase().includes("/config/") || file.toLowerCase().includes("/schemas/") || file.toLowerCase().includes("/settings/");
969
+ const hasSchemaExports = exports2.some(
970
+ (e) => e.name.toLowerCase().includes("table") || e.name.toLowerCase().includes("schema") || e.name.toLowerCase().includes("config") || e.name.toLowerCase().includes("setting")
971
+ );
972
+ return isConfigName || isConfigPath || hasSchemaExports;
973
+ }
974
+ function isUtilityFile(node) {
975
+ const { file, exports: exports2 } = node;
976
+ const fileName = file.split("/").pop()?.toLowerCase();
977
+ const utilityPatterns = [
978
+ "util",
979
+ "utility",
980
+ "utilities",
981
+ "helper",
982
+ "helpers",
983
+ "common",
984
+ "shared",
985
+ "lib",
986
+ "toolbox",
987
+ "toolkit",
988
+ ".util.",
989
+ "-util.",
990
+ "_util."
991
+ ];
992
+ const isUtilityName = utilityPatterns.some(
993
+ (pattern) => fileName?.includes(pattern)
994
+ );
995
+ const isUtilityPath = file.toLowerCase().includes("/utils/") || file.toLowerCase().includes("/helpers/") || file.toLowerCase().includes("/lib/") || file.toLowerCase().includes("/common/");
996
+ const hasManySmallExports = exports2.length >= 3 && exports2.every(
997
+ (e) => e.type === "function" || e.type === "const"
998
+ );
999
+ return isUtilityName || isUtilityPath || hasManySmallExports;
1000
+ }
1001
+ function adjustFragmentationForClassification(baseFragmentation, classification) {
1002
+ switch (classification) {
1003
+ case "barrel-export":
1004
+ return 0;
1005
+ case "type-definition":
1006
+ return 0;
1007
+ case "cohesive-module":
1008
+ return baseFragmentation * 0.3;
1009
+ case "mixed-concerns":
1010
+ return baseFragmentation;
1011
+ default:
1012
+ return baseFragmentation * 0.7;
1013
+ }
1014
+ }
1015
+ function getClassificationRecommendations(classification, file, issues) {
1016
+ switch (classification) {
1017
+ case "barrel-export":
1018
+ return [
1019
+ "Barrel export file detected - multiple domains are expected here",
1020
+ "Consider if this barrel export improves or hinders discoverability"
1021
+ ];
1022
+ case "type-definition":
1023
+ return [
1024
+ "Type definition file - centralized types improve consistency",
1025
+ "Consider splitting if file becomes too large (>500 lines)"
1026
+ ];
1027
+ case "cohesive-module":
1028
+ return [
1029
+ "Module has good cohesion despite its size",
1030
+ "Consider documenting the module boundaries for AI assistants"
1031
+ ];
1032
+ case "mixed-concerns":
1033
+ return [
1034
+ "Consider splitting this file by domain",
1035
+ "Identify independent responsibilities and extract them",
1036
+ "Review import dependencies to understand coupling"
1037
+ ];
1038
+ default:
1039
+ return issues;
1040
+ }
1041
+ }
893
1042
 
894
1043
  // src/index.ts
895
1044
  async function analyzeContext(options) {
@@ -952,6 +1101,8 @@ async function analyzeContext(options) {
952
1101
  contextBudget: metric.contextBudget,
953
1102
  fragmentationScore: 0,
954
1103
  relatedFiles: [],
1104
+ fileClassification: "unknown",
1105
+ // Python files not yet classified
955
1106
  severity,
956
1107
  issues,
957
1108
  recommendations,
@@ -999,6 +1150,33 @@ async function analyzeContext(options) {
999
1150
  const domains = [
1000
1151
  ...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
1001
1152
  ];
1153
+ const fileClassification = classifyFile(node, cohesionScore, domains);
1154
+ const adjustedFragmentationScore = adjustFragmentationForClassification(
1155
+ fragmentationScore,
1156
+ fileClassification
1157
+ );
1158
+ const classificationRecommendations = getClassificationRecommendations(
1159
+ fileClassification,
1160
+ file,
1161
+ issues
1162
+ );
1163
+ const {
1164
+ severity: adjustedSeverity,
1165
+ issues: adjustedIssues,
1166
+ recommendations: finalRecommendations,
1167
+ potentialSavings: adjustedSavings
1168
+ } = analyzeIssues({
1169
+ file,
1170
+ importDepth,
1171
+ contextBudget,
1172
+ cohesionScore,
1173
+ fragmentationScore: adjustedFragmentationScore,
1174
+ maxDepth,
1175
+ maxContextBudget,
1176
+ minCohesion,
1177
+ maxFragmentation,
1178
+ circularDeps
1179
+ });
1002
1180
  results.push({
1003
1181
  file,
1004
1182
  tokenCost: node.tokenCost,
@@ -1011,12 +1189,13 @@ async function analyzeContext(options) {
1011
1189
  domains,
1012
1190
  exportCount: node.exports.length,
1013
1191
  contextBudget,
1014
- fragmentationScore,
1192
+ fragmentationScore: adjustedFragmentationScore,
1015
1193
  relatedFiles,
1016
- severity,
1017
- issues,
1018
- recommendations,
1019
- potentialSavings
1194
+ fileClassification,
1195
+ severity: adjustedSeverity,
1196
+ issues: adjustedIssues,
1197
+ recommendations: [...finalRecommendations, ...classificationRecommendations.slice(0, 1)],
1198
+ potentialSavings: adjustedSavings
1020
1199
  });
1021
1200
  }
1022
1201
  const allResults = [...results, ...pythonResults];
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  analyzeContext,
4
4
  generateSummary
5
- } from "./chunk-VTALAPQZ.mjs";
5
+ } from "./chunk-HOUDVRG2.mjs";
6
6
  import "./chunk-Y6FXYEAI.mjs";
7
7
 
8
8
  // src/cli.ts
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,155 @@ 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, file } = node;
970
+ if (isBarrelExport(node)) {
971
+ return "barrel-export";
972
+ }
973
+ if (isTypeDefinitionFile(node)) {
974
+ return "type-definition";
975
+ }
976
+ if (isConfigOrSchemaFile(node)) {
977
+ return "cohesive-module";
978
+ }
979
+ const uniqueDomains = domains.filter((d) => d !== "unknown");
980
+ const hasSingleDomain = uniqueDomains.length <= 1;
981
+ const hasReasonableCohesion = cohesionScore >= 0.5;
982
+ if (hasSingleDomain) {
983
+ return "cohesive-module";
984
+ }
985
+ if (isUtilityFile(node)) {
986
+ return "cohesive-module";
987
+ }
988
+ const hasMultipleDomains = uniqueDomains.length > 1;
989
+ const hasLowCohesion = cohesionScore < 0.4;
990
+ if (hasMultipleDomains && hasLowCohesion) {
991
+ return "mixed-concerns";
992
+ }
993
+ if (cohesionScore >= 0.5) {
994
+ return "cohesive-module";
995
+ }
996
+ return "unknown";
997
+ }
998
+ function isBarrelExport(node) {
999
+ const { file, exports: exports2, imports, linesOfCode } = node;
1000
+ const fileName = file.split("/").pop()?.toLowerCase();
1001
+ const isIndexFile = fileName === "index.ts" || fileName === "index.js" || fileName === "index.tsx" || fileName === "index.jsx";
1002
+ const hasReExports = exports2.length > 0 && imports.length > 0;
1003
+ const highExportToLinesRatio = exports2.length > 3 && linesOfCode < exports2.length * 5;
1004
+ const sparseCode = linesOfCode > 0 && linesOfCode < 50 && exports2.length >= 2;
1005
+ if (isIndexFile && hasReExports) {
1006
+ return true;
1007
+ }
1008
+ if (highExportToLinesRatio && imports.length >= exports2.length * 0.5) {
1009
+ return true;
1010
+ }
1011
+ if (sparseCode && imports.length > 0) {
1012
+ return true;
1013
+ }
1014
+ return false;
1015
+ }
1016
+ function isTypeDefinitionFile(node) {
1017
+ const { file, exports: exports2 } = node;
1018
+ const fileName = file.split("/").pop()?.toLowerCase();
1019
+ const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
1020
+ const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
1021
+ const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
1022
+ const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
1023
+ return isTypesFile || mostlyTypes;
1024
+ }
1025
+ function isConfigOrSchemaFile(node) {
1026
+ const { file, exports: exports2 } = node;
1027
+ const fileName = file.split("/").pop()?.toLowerCase();
1028
+ const configPatterns = [
1029
+ "config",
1030
+ "schema",
1031
+ "settings",
1032
+ "options",
1033
+ "constants",
1034
+ "env",
1035
+ "environment",
1036
+ ".config.",
1037
+ "-config.",
1038
+ "_config."
1039
+ ];
1040
+ const isConfigName = configPatterns.some(
1041
+ (pattern) => fileName?.includes(pattern) || fileName?.startsWith(pattern) || fileName?.endsWith(`${pattern}.ts`)
1042
+ );
1043
+ const isConfigPath = file.toLowerCase().includes("/config/") || file.toLowerCase().includes("/schemas/") || file.toLowerCase().includes("/settings/");
1044
+ const hasSchemaExports = exports2.some(
1045
+ (e) => e.name.toLowerCase().includes("table") || e.name.toLowerCase().includes("schema") || e.name.toLowerCase().includes("config") || e.name.toLowerCase().includes("setting")
1046
+ );
1047
+ return isConfigName || isConfigPath || hasSchemaExports;
1048
+ }
1049
+ function isUtilityFile(node) {
1050
+ const { file, exports: exports2 } = node;
1051
+ const fileName = file.split("/").pop()?.toLowerCase();
1052
+ const utilityPatterns = [
1053
+ "util",
1054
+ "utility",
1055
+ "utilities",
1056
+ "helper",
1057
+ "helpers",
1058
+ "common",
1059
+ "shared",
1060
+ "lib",
1061
+ "toolbox",
1062
+ "toolkit",
1063
+ ".util.",
1064
+ "-util.",
1065
+ "_util."
1066
+ ];
1067
+ const isUtilityName = utilityPatterns.some(
1068
+ (pattern) => fileName?.includes(pattern)
1069
+ );
1070
+ const isUtilityPath = file.toLowerCase().includes("/utils/") || file.toLowerCase().includes("/helpers/") || file.toLowerCase().includes("/lib/") || file.toLowerCase().includes("/common/");
1071
+ const hasManySmallExports = exports2.length >= 3 && exports2.every(
1072
+ (e) => e.type === "function" || e.type === "const"
1073
+ );
1074
+ return isUtilityName || isUtilityPath || hasManySmallExports;
1075
+ }
1076
+ function adjustFragmentationForClassification(baseFragmentation, classification) {
1077
+ switch (classification) {
1078
+ case "barrel-export":
1079
+ return 0;
1080
+ case "type-definition":
1081
+ return 0;
1082
+ case "cohesive-module":
1083
+ return baseFragmentation * 0.3;
1084
+ case "mixed-concerns":
1085
+ return baseFragmentation;
1086
+ default:
1087
+ return baseFragmentation * 0.7;
1088
+ }
1089
+ }
1090
+ function getClassificationRecommendations(classification, file, issues) {
1091
+ switch (classification) {
1092
+ case "barrel-export":
1093
+ return [
1094
+ "Barrel export file detected - multiple domains are expected here",
1095
+ "Consider if this barrel export improves or hinders discoverability"
1096
+ ];
1097
+ case "type-definition":
1098
+ return [
1099
+ "Type definition file - centralized types improve consistency",
1100
+ "Consider splitting if file becomes too large (>500 lines)"
1101
+ ];
1102
+ case "cohesive-module":
1103
+ return [
1104
+ "Module has good cohesion despite its size",
1105
+ "Consider documenting the module boundaries for AI assistants"
1106
+ ];
1107
+ case "mixed-concerns":
1108
+ return [
1109
+ "Consider splitting this file by domain",
1110
+ "Identify independent responsibilities and extract them",
1111
+ "Review import dependencies to understand coupling"
1112
+ ];
1113
+ default:
1114
+ return issues;
1115
+ }
1116
+ }
966
1117
 
967
1118
  // src/scoring.ts
968
1119
  function calculateContextScore(summary) {
@@ -1176,6 +1327,8 @@ async function analyzeContext(options) {
1176
1327
  contextBudget: metric.contextBudget,
1177
1328
  fragmentationScore: 0,
1178
1329
  relatedFiles: [],
1330
+ fileClassification: "unknown",
1331
+ // Python files not yet classified
1179
1332
  severity,
1180
1333
  issues,
1181
1334
  recommendations,
@@ -1223,6 +1376,33 @@ async function analyzeContext(options) {
1223
1376
  const domains = [
1224
1377
  ...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
1225
1378
  ];
1379
+ const fileClassification = classifyFile(node, cohesionScore, domains);
1380
+ const adjustedFragmentationScore = adjustFragmentationForClassification(
1381
+ fragmentationScore,
1382
+ fileClassification
1383
+ );
1384
+ const classificationRecommendations = getClassificationRecommendations(
1385
+ fileClassification,
1386
+ file,
1387
+ issues
1388
+ );
1389
+ const {
1390
+ severity: adjustedSeverity,
1391
+ issues: adjustedIssues,
1392
+ recommendations: finalRecommendations,
1393
+ potentialSavings: adjustedSavings
1394
+ } = analyzeIssues({
1395
+ file,
1396
+ importDepth,
1397
+ contextBudget,
1398
+ cohesionScore,
1399
+ fragmentationScore: adjustedFragmentationScore,
1400
+ maxDepth,
1401
+ maxContextBudget,
1402
+ minCohesion,
1403
+ maxFragmentation,
1404
+ circularDeps
1405
+ });
1226
1406
  results.push({
1227
1407
  file,
1228
1408
  tokenCost: node.tokenCost,
@@ -1235,12 +1415,13 @@ async function analyzeContext(options) {
1235
1415
  domains,
1236
1416
  exportCount: node.exports.length,
1237
1417
  contextBudget,
1238
- fragmentationScore,
1418
+ fragmentationScore: adjustedFragmentationScore,
1239
1419
  relatedFiles,
1240
- severity,
1241
- issues,
1242
- recommendations,
1243
- potentialSavings
1420
+ fileClassification,
1421
+ severity: adjustedSeverity,
1422
+ issues: adjustedIssues,
1423
+ recommendations: [...finalRecommendations, ...classificationRecommendations.slice(0, 1)],
1424
+ potentialSavings: adjustedSavings
1244
1425
  });
1245
1426
  }
1246
1427
  const allResults = [...results, ...pythonResults];
@@ -1470,11 +1651,13 @@ function downgradeSeverity(s) {
1470
1651
  }
1471
1652
  // Annotate the CommonJS export names for ESM import in node:
1472
1653
  0 && (module.exports = {
1654
+ adjustFragmentationForClassification,
1473
1655
  analyzeContext,
1474
1656
  buildCoUsageMatrix,
1475
1657
  buildTypeGraph,
1476
1658
  calculateContextScore,
1477
1659
  calculateDomainConfidence,
1660
+ classifyFile,
1478
1661
  findConsolidationCandidates,
1479
1662
  findSemanticClusters,
1480
1663
  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-VTALAPQZ.mjs";
15
+ } from "./chunk-HOUDVRG2.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.22",
3
+ "version": "0.9.25",
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",