@aiready/context-analyzer 0.9.23 → 0.9.26

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
@@ -891,24 +891,50 @@ function calculateDomainCohesion(exports2) {
891
891
  return maxEntropy > 0 ? 1 - entropy / maxEntropy : 1;
892
892
  }
893
893
  function classifyFile(node, cohesionScore, domains) {
894
- const { exports: exports2, imports, linesOfCode } = node;
894
+ const { exports: exports2, imports, linesOfCode, file } = node;
895
895
  if (isBarrelExport(node)) {
896
896
  return "barrel-export";
897
897
  }
898
898
  if (isTypeDefinitionFile(node)) {
899
899
  return "type-definition";
900
900
  }
901
+ if (isConfigOrSchemaFile(node)) {
902
+ return "cohesive-module";
903
+ }
904
+ if (isLambdaHandler(node)) {
905
+ return "lambda-handler";
906
+ }
907
+ if (isEmailTemplate(node)) {
908
+ return "email-template";
909
+ }
910
+ if (isParserFile(node)) {
911
+ return "parser-file";
912
+ }
913
+ if (isServiceFile(node)) {
914
+ return "service-file";
915
+ }
916
+ if (isSessionFile(node)) {
917
+ return "cohesive-module";
918
+ }
919
+ if (isNextJsPage(node)) {
920
+ return "nextjs-page";
921
+ }
922
+ if (isUtilityFile(node)) {
923
+ return "utility-module";
924
+ }
901
925
  const uniqueDomains = domains.filter((d) => d !== "unknown");
902
926
  const hasSingleDomain = uniqueDomains.length <= 1;
903
- const hasHighCohesion = cohesionScore >= 0.7;
904
- if (hasSingleDomain && hasHighCohesion) {
927
+ if (hasSingleDomain) {
905
928
  return "cohesive-module";
906
929
  }
907
930
  const hasMultipleDomains = uniqueDomains.length > 1;
908
- const hasLowCohesion = cohesionScore < 0.5;
909
- if (hasMultipleDomains || hasLowCohesion) {
931
+ const hasLowCohesion = cohesionScore < 0.4;
932
+ if (hasMultipleDomains && hasLowCohesion) {
910
933
  return "mixed-concerns";
911
934
  }
935
+ if (cohesionScore >= 0.5) {
936
+ return "cohesive-module";
937
+ }
912
938
  return "unknown";
913
939
  }
914
940
  function isBarrelExport(node) {
@@ -933,10 +959,300 @@ function isTypeDefinitionFile(node) {
933
959
  const { file, exports: exports2 } = node;
934
960
  const fileName = file.split("/").pop()?.toLowerCase();
935
961
  const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
962
+ const lowerPath = file.toLowerCase();
963
+ const isTypesPath = lowerPath.includes("/types/") || lowerPath.includes("/typings/") || lowerPath.includes("/@types/") || lowerPath.startsWith("types/") || lowerPath.startsWith("typings/");
936
964
  const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
937
965
  const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
938
966
  const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
939
- return isTypesFile || mostlyTypes;
967
+ const pureTypeFile = exports2.length > 0 && typeExports.length === exports2.length;
968
+ const emptyOrReExportInTypesDir = isTypesPath && exports2.length === 0;
969
+ return isTypesFile || isTypesPath || mostlyTypes || pureTypeFile || emptyOrReExportInTypesDir;
970
+ }
971
+ function isConfigOrSchemaFile(node) {
972
+ const { file, exports: exports2 } = node;
973
+ const fileName = file.split("/").pop()?.toLowerCase();
974
+ const configPatterns = [
975
+ "config",
976
+ "schema",
977
+ "settings",
978
+ "options",
979
+ "constants",
980
+ "env",
981
+ "environment",
982
+ ".config.",
983
+ "-config.",
984
+ "_config."
985
+ ];
986
+ const isConfigName = configPatterns.some(
987
+ (pattern) => fileName?.includes(pattern) || fileName?.startsWith(pattern) || fileName?.endsWith(`${pattern}.ts`)
988
+ );
989
+ const isConfigPath = file.toLowerCase().includes("/config/") || file.toLowerCase().includes("/schemas/") || file.toLowerCase().includes("/settings/");
990
+ const hasSchemaExports = exports2.some(
991
+ (e) => e.name.toLowerCase().includes("table") || e.name.toLowerCase().includes("schema") || e.name.toLowerCase().includes("config") || e.name.toLowerCase().includes("setting")
992
+ );
993
+ return isConfigName || isConfigPath || hasSchemaExports;
994
+ }
995
+ function isUtilityFile(node) {
996
+ const { file, exports: exports2 } = node;
997
+ const fileName = file.split("/").pop()?.toLowerCase();
998
+ const utilityPatterns = [
999
+ "util",
1000
+ "utility",
1001
+ "utilities",
1002
+ "helper",
1003
+ "helpers",
1004
+ "common",
1005
+ "shared",
1006
+ "toolbox",
1007
+ "toolkit",
1008
+ ".util.",
1009
+ "-util.",
1010
+ "_util.",
1011
+ "-utils.",
1012
+ ".utils."
1013
+ ];
1014
+ const isUtilityName = utilityPatterns.some(
1015
+ (pattern) => fileName?.includes(pattern)
1016
+ );
1017
+ const isUtilityPath = file.toLowerCase().includes("/utils/") || file.toLowerCase().includes("/helpers/") || file.toLowerCase().includes("/common/") || file.toLowerCase().endsWith("-utils.ts") || file.toLowerCase().endsWith("-util.ts") || file.toLowerCase().endsWith("-helper.ts") || file.toLowerCase().endsWith("-helpers.ts");
1018
+ const hasManySmallExportsInUtilityContext = exports2.length >= 3 && exports2.every((e) => e.type === "function" || e.type === "const") && (isUtilityName || isUtilityPath);
1019
+ return isUtilityName || isUtilityPath || hasManySmallExportsInUtilityContext;
1020
+ }
1021
+ function isLambdaHandler(node) {
1022
+ const { file, exports: exports2 } = node;
1023
+ const fileName = file.split("/").pop()?.toLowerCase();
1024
+ const handlerPatterns = [
1025
+ "handler",
1026
+ ".handler.",
1027
+ "-handler.",
1028
+ "lambda",
1029
+ ".lambda.",
1030
+ "-lambda."
1031
+ ];
1032
+ const isHandlerName = handlerPatterns.some(
1033
+ (pattern) => fileName?.includes(pattern)
1034
+ );
1035
+ const isHandlerPath = file.toLowerCase().includes("/handlers/") || file.toLowerCase().includes("/lambdas/") || file.toLowerCase().includes("/functions/");
1036
+ const hasHandlerExport = exports2.some(
1037
+ (e) => e.name.toLowerCase() === "handler" || e.name.toLowerCase() === "main" || e.name.toLowerCase() === "lambdahandler" || e.name.toLowerCase().endsWith("handler")
1038
+ );
1039
+ const hasSingleEntryInHandlerContext = exports2.length === 1 && (exports2[0].type === "function" || exports2[0].name === "default") && (isHandlerPath || isHandlerName);
1040
+ return isHandlerName || isHandlerPath || hasHandlerExport || hasSingleEntryInHandlerContext;
1041
+ }
1042
+ function isServiceFile(node) {
1043
+ const { file, exports: exports2 } = node;
1044
+ const fileName = file.split("/").pop()?.toLowerCase();
1045
+ const servicePatterns = [
1046
+ "service",
1047
+ ".service.",
1048
+ "-service.",
1049
+ "_service."
1050
+ ];
1051
+ const isServiceName = servicePatterns.some(
1052
+ (pattern) => fileName?.includes(pattern)
1053
+ );
1054
+ const isServicePath = file.toLowerCase().includes("/services/");
1055
+ const hasServiceNamedExport = exports2.some(
1056
+ (e) => e.name.toLowerCase().includes("service") || e.name.toLowerCase().endsWith("service")
1057
+ );
1058
+ const hasClassExport = exports2.some((e) => e.type === "class");
1059
+ return isServiceName || isServicePath || hasServiceNamedExport && hasClassExport;
1060
+ }
1061
+ function isEmailTemplate(node) {
1062
+ const { file, exports: exports2 } = node;
1063
+ const fileName = file.split("/").pop()?.toLowerCase();
1064
+ const emailTemplatePatterns = [
1065
+ "-email-",
1066
+ ".email.",
1067
+ "_email_",
1068
+ "-template",
1069
+ ".template.",
1070
+ "_template",
1071
+ "-mail.",
1072
+ ".mail."
1073
+ ];
1074
+ const isEmailTemplateName = emailTemplatePatterns.some(
1075
+ (pattern) => fileName?.includes(pattern)
1076
+ );
1077
+ const isSpecificTemplateName = fileName?.includes("receipt") || fileName?.includes("invoice-email") || fileName?.includes("welcome-email") || fileName?.includes("notification-email") || fileName?.includes("writer") && fileName.includes("receipt");
1078
+ const isEmailPath = file.toLowerCase().includes("/emails/") || file.toLowerCase().includes("/mail/") || file.toLowerCase().includes("/notifications/");
1079
+ const hasTemplateFunction = exports2.some(
1080
+ (e) => e.type === "function" && (e.name.toLowerCase().startsWith("render") || e.name.toLowerCase().startsWith("generate") || e.name.toLowerCase().includes("template") && e.name.toLowerCase().includes("email"))
1081
+ );
1082
+ const hasEmailExport = exports2.some(
1083
+ (e) => e.name.toLowerCase().includes("template") && e.type === "function" || e.name.toLowerCase().includes("render") && e.type === "function" || e.name.toLowerCase().includes("email") && e.type !== "class"
1084
+ );
1085
+ return isEmailPath || isEmailTemplateName || isSpecificTemplateName || hasTemplateFunction && hasEmailExport;
1086
+ }
1087
+ function isParserFile(node) {
1088
+ const { file, exports: exports2 } = node;
1089
+ const fileName = file.split("/").pop()?.toLowerCase();
1090
+ const parserPatterns = [
1091
+ "parser",
1092
+ ".parser.",
1093
+ "-parser.",
1094
+ "_parser.",
1095
+ "transform",
1096
+ ".transform.",
1097
+ "-transform.",
1098
+ "converter",
1099
+ ".converter.",
1100
+ "-converter.",
1101
+ "mapper",
1102
+ ".mapper.",
1103
+ "-mapper.",
1104
+ "serializer",
1105
+ ".serializer.",
1106
+ "deterministic"
1107
+ // For base-parser-deterministic.ts pattern
1108
+ ];
1109
+ const isParserName = parserPatterns.some(
1110
+ (pattern) => fileName?.includes(pattern)
1111
+ );
1112
+ const isParserPath = file.toLowerCase().includes("/parsers/") || file.toLowerCase().includes("/transformers/") || file.toLowerCase().includes("/converters/") || file.toLowerCase().includes("/mappers/");
1113
+ const hasParserExport = exports2.some(
1114
+ (e) => e.name.toLowerCase().includes("parse") || e.name.toLowerCase().includes("transform") || e.name.toLowerCase().includes("convert") || e.name.toLowerCase().includes("map") || e.name.toLowerCase().includes("serialize") || e.name.toLowerCase().includes("deserialize")
1115
+ );
1116
+ const hasParseFunction = exports2.some(
1117
+ (e) => e.type === "function" && (e.name.toLowerCase().startsWith("parse") || e.name.toLowerCase().startsWith("transform") || e.name.toLowerCase().startsWith("convert") || e.name.toLowerCase().startsWith("map") || e.name.toLowerCase().startsWith("extract"))
1118
+ );
1119
+ return isParserName || isParserPath || hasParserExport || hasParseFunction;
1120
+ }
1121
+ function isSessionFile(node) {
1122
+ const { file, exports: exports2 } = node;
1123
+ const fileName = file.split("/").pop()?.toLowerCase();
1124
+ const sessionPatterns = [
1125
+ "session",
1126
+ ".session.",
1127
+ "-session.",
1128
+ "state",
1129
+ ".state.",
1130
+ "-state.",
1131
+ "context",
1132
+ ".context.",
1133
+ "-context.",
1134
+ "store",
1135
+ ".store.",
1136
+ "-store."
1137
+ ];
1138
+ const isSessionName = sessionPatterns.some(
1139
+ (pattern) => fileName?.includes(pattern)
1140
+ );
1141
+ const isSessionPath = file.toLowerCase().includes("/sessions/") || file.toLowerCase().includes("/state/") || file.toLowerCase().includes("/context/") || file.toLowerCase().includes("/store/");
1142
+ const hasSessionExport = exports2.some(
1143
+ (e) => e.name.toLowerCase().includes("session") || e.name.toLowerCase().includes("state") || e.name.toLowerCase().includes("context") || e.name.toLowerCase().includes("manager") || e.name.toLowerCase().includes("store")
1144
+ );
1145
+ return isSessionName || isSessionPath || hasSessionExport;
1146
+ }
1147
+ function isNextJsPage(node) {
1148
+ const { file, exports: exports2 } = node;
1149
+ const lowerPath = file.toLowerCase();
1150
+ const fileName = file.split("/").pop()?.toLowerCase();
1151
+ const isInAppDir = lowerPath.includes("/app/") || lowerPath.startsWith("app/");
1152
+ const isPageFile = fileName === "page.tsx" || fileName === "page.ts";
1153
+ if (!isInAppDir || !isPageFile) {
1154
+ return false;
1155
+ }
1156
+ const exportNames = exports2.map((e) => e.name.toLowerCase());
1157
+ const hasDefaultExport = exports2.some((e) => e.type === "default");
1158
+ const nextJsExports = ["metadata", "generatemetadata", "faqjsonld", "jsonld", "icon", "viewport", "dynamic"];
1159
+ const hasNextJsExports = exportNames.some(
1160
+ (name) => nextJsExports.includes(name) || name.includes("jsonld")
1161
+ );
1162
+ return hasDefaultExport || hasNextJsExports;
1163
+ }
1164
+ function adjustCohesionForClassification(baseCohesion, classification, node) {
1165
+ switch (classification) {
1166
+ case "barrel-export":
1167
+ return 1;
1168
+ case "type-definition":
1169
+ return 1;
1170
+ case "utility-module": {
1171
+ if (node) {
1172
+ const exportNames = node.exports.map((e) => e.name.toLowerCase());
1173
+ const hasRelatedNames = hasRelatedExportNames(exportNames);
1174
+ if (hasRelatedNames) {
1175
+ return Math.min(1, baseCohesion + 0.45);
1176
+ }
1177
+ }
1178
+ return Math.min(1, baseCohesion + 0.35);
1179
+ }
1180
+ case "service-file": {
1181
+ if (node?.exports.some((e) => e.type === "class")) {
1182
+ return Math.min(1, baseCohesion + 0.4);
1183
+ }
1184
+ return Math.min(1, baseCohesion + 0.3);
1185
+ }
1186
+ case "lambda-handler": {
1187
+ if (node) {
1188
+ const hasSingleEntry = node.exports.length === 1 || node.exports.some((e) => e.name.toLowerCase() === "handler");
1189
+ if (hasSingleEntry) {
1190
+ return Math.min(1, baseCohesion + 0.45);
1191
+ }
1192
+ }
1193
+ return Math.min(1, baseCohesion + 0.35);
1194
+ }
1195
+ case "email-template": {
1196
+ if (node) {
1197
+ const hasTemplateFunc = node.exports.some(
1198
+ (e) => e.name.toLowerCase().includes("render") || e.name.toLowerCase().includes("generate") || e.name.toLowerCase().includes("template")
1199
+ );
1200
+ if (hasTemplateFunc) {
1201
+ return Math.min(1, baseCohesion + 0.4);
1202
+ }
1203
+ }
1204
+ return Math.min(1, baseCohesion + 0.3);
1205
+ }
1206
+ case "parser-file": {
1207
+ if (node) {
1208
+ const hasParseFunc = node.exports.some(
1209
+ (e) => e.name.toLowerCase().startsWith("parse") || e.name.toLowerCase().startsWith("transform") || e.name.toLowerCase().startsWith("convert")
1210
+ );
1211
+ if (hasParseFunc) {
1212
+ return Math.min(1, baseCohesion + 0.4);
1213
+ }
1214
+ }
1215
+ return Math.min(1, baseCohesion + 0.3);
1216
+ }
1217
+ case "nextjs-page":
1218
+ return 1;
1219
+ case "cohesive-module":
1220
+ return Math.max(baseCohesion, 0.7);
1221
+ case "mixed-concerns":
1222
+ return baseCohesion;
1223
+ default:
1224
+ return Math.min(1, baseCohesion + 0.1);
1225
+ }
1226
+ }
1227
+ function hasRelatedExportNames(exportNames) {
1228
+ if (exportNames.length < 2) return true;
1229
+ const stems = /* @__PURE__ */ new Set();
1230
+ const domains = /* @__PURE__ */ new Set();
1231
+ for (const name of exportNames) {
1232
+ const verbs = ["get", "set", "create", "update", "delete", "fetch", "save", "load", "parse", "format", "validate", "convert", "transform", "build", "generate", "render", "send", "receive"];
1233
+ for (const verb of verbs) {
1234
+ if (name.startsWith(verb) && name.length > verb.length) {
1235
+ stems.add(name.slice(verb.length).toLowerCase());
1236
+ }
1237
+ }
1238
+ const domainPatterns = ["user", "order", "product", "session", "email", "file", "db", "s3", "dynamo", "api", "config"];
1239
+ for (const domain of domainPatterns) {
1240
+ if (name.includes(domain)) {
1241
+ domains.add(domain);
1242
+ }
1243
+ }
1244
+ }
1245
+ if (stems.size === 1 && exportNames.length >= 2) return true;
1246
+ if (domains.size === 1 && exportNames.length >= 2) return true;
1247
+ const prefixes = exportNames.map((name) => {
1248
+ const match = name.match(/^([a-z]+)/);
1249
+ return match ? match[1] : "";
1250
+ }).filter((p) => p.length >= 3);
1251
+ if (prefixes.length >= 2) {
1252
+ const uniquePrefixes = new Set(prefixes);
1253
+ if (uniquePrefixes.size === 1) return true;
1254
+ }
1255
+ return false;
940
1256
  }
941
1257
  function adjustFragmentationForClassification(baseFragmentation, classification) {
942
1258
  switch (classification) {
@@ -944,6 +1260,13 @@ function adjustFragmentationForClassification(baseFragmentation, classification)
944
1260
  return 0;
945
1261
  case "type-definition":
946
1262
  return 0;
1263
+ case "utility-module":
1264
+ case "service-file":
1265
+ case "lambda-handler":
1266
+ case "email-template":
1267
+ case "parser-file":
1268
+ case "nextjs-page":
1269
+ return baseFragmentation * 0.2;
947
1270
  case "cohesive-module":
948
1271
  return baseFragmentation * 0.3;
949
1272
  case "mixed-concerns":
@@ -969,6 +1292,36 @@ function getClassificationRecommendations(classification, file, issues) {
969
1292
  "Module has good cohesion despite its size",
970
1293
  "Consider documenting the module boundaries for AI assistants"
971
1294
  ];
1295
+ case "utility-module":
1296
+ return [
1297
+ "Utility module detected - multiple domains are acceptable here",
1298
+ "Consider grouping related utilities by prefix or domain for better discoverability"
1299
+ ];
1300
+ case "service-file":
1301
+ return [
1302
+ "Service file detected - orchestration of multiple dependencies is expected",
1303
+ "Consider documenting service boundaries and dependencies"
1304
+ ];
1305
+ case "lambda-handler":
1306
+ return [
1307
+ "Lambda handler detected - coordination of services is expected",
1308
+ "Ensure handler has clear single responsibility"
1309
+ ];
1310
+ case "email-template":
1311
+ return [
1312
+ "Email template detected - references multiple domains for rendering",
1313
+ "Template structure is cohesive by design"
1314
+ ];
1315
+ case "parser-file":
1316
+ return [
1317
+ "Parser/transformer file detected - handles multiple data sources",
1318
+ "Consider documenting input/output schemas"
1319
+ ];
1320
+ case "nextjs-page":
1321
+ return [
1322
+ "Next.js App Router page detected - metadata/JSON-LD/component pattern is cohesive",
1323
+ "Multiple exports (metadata, faqJsonLd, default) serve single page purpose"
1324
+ ];
972
1325
  case "mixed-concerns":
973
1326
  return [
974
1327
  "Consider splitting this file by domain",
@@ -1091,6 +1444,11 @@ async function analyzeContext(options) {
1091
1444
  ...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
1092
1445
  ];
1093
1446
  const fileClassification = classifyFile(node, cohesionScore, domains);
1447
+ const adjustedCohesionScore = adjustCohesionForClassification(
1448
+ cohesionScore,
1449
+ fileClassification,
1450
+ node
1451
+ );
1094
1452
  const adjustedFragmentationScore = adjustFragmentationForClassification(
1095
1453
  fragmentationScore,
1096
1454
  fileClassification
@@ -1109,7 +1467,8 @@ async function analyzeContext(options) {
1109
1467
  file,
1110
1468
  importDepth,
1111
1469
  contextBudget,
1112
- cohesionScore,
1470
+ cohesionScore: adjustedCohesionScore,
1471
+ // Use adjusted cohesion
1113
1472
  fragmentationScore: adjustedFragmentationScore,
1114
1473
  maxDepth,
1115
1474
  maxContextBudget,
@@ -1125,7 +1484,8 @@ async function analyzeContext(options) {
1125
1484
  dependencyCount: dependencyList.length,
1126
1485
  dependencyList,
1127
1486
  circularDeps: circularDeps.filter((cycle) => cycle.includes(file)),
1128
- cohesionScore,
1487
+ cohesionScore: adjustedCohesionScore,
1488
+ // Report adjusted cohesion
1129
1489
  domains,
1130
1490
  exportCount: node.exports.length,
1131
1491
  contextBudget,
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  analyzeContext,
4
4
  generateSummary
5
- } from "./chunk-MBE4AQP5.mjs";
5
+ } from "./chunk-PJD4VCIH.mjs";
6
6
  import "./chunk-Y6FXYEAI.mjs";
7
7
 
8
8
  // src/cli.ts
package/dist/index.d.mts CHANGED
@@ -32,7 +32,7 @@ interface ContextAnalysisResult {
32
32
  * Classification of file type for analysis context
33
33
  * Helps distinguish real issues from false positives
34
34
  */
35
- type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'mixed-concerns' | 'unknown';
35
+ type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'utility-module' | 'service-file' | 'lambda-handler' | 'email-template' | 'parser-file' | 'nextjs-page' | 'mixed-concerns' | 'unknown';
36
36
  interface ModuleCluster {
37
37
  domain: string;
38
38
  files: string[];
@@ -130,6 +130,11 @@ interface TypeDependency {
130
130
  * - barrel-export: Re-exports from other modules (index.ts files)
131
131
  * - type-definition: Primarily type/interface definitions
132
132
  * - cohesive-module: Single domain, high cohesion (acceptable large files)
133
+ * - utility-module: Utility/helper files with cohesive purpose despite multi-domain
134
+ * - service-file: Service files orchestrating multiple dependencies
135
+ * - lambda-handler: Lambda/API handlers with single business purpose
136
+ * - email-template: Email templates/layouts with structural cohesion
137
+ * - parser-file: Parser/transformer files with single transformation purpose
133
138
  * - mixed-concerns: Multiple domains, potential refactoring candidate
134
139
  * - unknown: Unable to classify
135
140
  */
@@ -141,6 +146,7 @@ declare function classifyFile(node: DependencyNode, cohesionScore: number, domai
141
146
  * - Ignoring fragmentation for barrel exports (they're meant to aggregate)
142
147
  * - Ignoring fragmentation for type definitions (centralized types are good)
143
148
  * - Reducing fragmentation for cohesive modules (large but focused is OK)
149
+ * - Reducing fragmentation for utility/service/handler/template files
144
150
  */
145
151
  declare function adjustFragmentationForClassification(baseFragmentation: number, classification: FileClassification): number;
146
152
 
package/dist/index.d.ts CHANGED
@@ -32,7 +32,7 @@ interface ContextAnalysisResult {
32
32
  * Classification of file type for analysis context
33
33
  * Helps distinguish real issues from false positives
34
34
  */
35
- type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'mixed-concerns' | 'unknown';
35
+ type FileClassification = 'barrel-export' | 'type-definition' | 'cohesive-module' | 'utility-module' | 'service-file' | 'lambda-handler' | 'email-template' | 'parser-file' | 'nextjs-page' | 'mixed-concerns' | 'unknown';
36
36
  interface ModuleCluster {
37
37
  domain: string;
38
38
  files: string[];
@@ -130,6 +130,11 @@ interface TypeDependency {
130
130
  * - barrel-export: Re-exports from other modules (index.ts files)
131
131
  * - type-definition: Primarily type/interface definitions
132
132
  * - cohesive-module: Single domain, high cohesion (acceptable large files)
133
+ * - utility-module: Utility/helper files with cohesive purpose despite multi-domain
134
+ * - service-file: Service files orchestrating multiple dependencies
135
+ * - lambda-handler: Lambda/API handlers with single business purpose
136
+ * - email-template: Email templates/layouts with structural cohesion
137
+ * - parser-file: Parser/transformer files with single transformation purpose
133
138
  * - mixed-concerns: Multiple domains, potential refactoring candidate
134
139
  * - unknown: Unable to classify
135
140
  */
@@ -141,6 +146,7 @@ declare function classifyFile(node: DependencyNode, cohesionScore: number, domai
141
146
  * - Ignoring fragmentation for barrel exports (they're meant to aggregate)
142
147
  * - Ignoring fragmentation for type definitions (centralized types are good)
143
148
  * - Reducing fragmentation for cohesive modules (large but focused is OK)
149
+ * - Reducing fragmentation for utility/service/handler/template files
144
150
  */
145
151
  declare function adjustFragmentationForClassification(baseFragmentation: number, classification: FileClassification): number;
146
152