@aiready/context-analyzer 0.9.25 → 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/.turbo/turbo-build.log +11 -11
- package/.turbo/turbo-test.log +21 -24
- package/dist/chunk-PJD4VCIH.mjs +1722 -0
- package/dist/cli.js +313 -13
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +7 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.js +313 -13
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/src/__tests__/file-classification.test.ts +560 -9
- package/src/analyzer.ts +567 -18
- package/src/index.ts +11 -3
- package/src/types.ts +6 -0
package/dist/index.js
CHANGED
|
@@ -976,13 +976,30 @@ function classifyFile(node, cohesionScore, domains) {
|
|
|
976
976
|
if (isConfigOrSchemaFile(node)) {
|
|
977
977
|
return "cohesive-module";
|
|
978
978
|
}
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
if (
|
|
979
|
+
if (isLambdaHandler(node)) {
|
|
980
|
+
return "lambda-handler";
|
|
981
|
+
}
|
|
982
|
+
if (isEmailTemplate(node)) {
|
|
983
|
+
return "email-template";
|
|
984
|
+
}
|
|
985
|
+
if (isParserFile(node)) {
|
|
986
|
+
return "parser-file";
|
|
987
|
+
}
|
|
988
|
+
if (isServiceFile(node)) {
|
|
989
|
+
return "service-file";
|
|
990
|
+
}
|
|
991
|
+
if (isSessionFile(node)) {
|
|
983
992
|
return "cohesive-module";
|
|
984
993
|
}
|
|
994
|
+
if (isNextJsPage(node)) {
|
|
995
|
+
return "nextjs-page";
|
|
996
|
+
}
|
|
985
997
|
if (isUtilityFile(node)) {
|
|
998
|
+
return "utility-module";
|
|
999
|
+
}
|
|
1000
|
+
const uniqueDomains = domains.filter((d) => d !== "unknown");
|
|
1001
|
+
const hasSingleDomain = uniqueDomains.length <= 1;
|
|
1002
|
+
if (hasSingleDomain) {
|
|
986
1003
|
return "cohesive-module";
|
|
987
1004
|
}
|
|
988
1005
|
const hasMultipleDomains = uniqueDomains.length > 1;
|
|
@@ -1017,10 +1034,14 @@ function isTypeDefinitionFile(node) {
|
|
|
1017
1034
|
const { file, exports: exports2 } = node;
|
|
1018
1035
|
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1019
1036
|
const isTypesFile = fileName?.includes("types") || fileName?.includes(".d.ts") || fileName === "types.ts" || fileName === "interfaces.ts";
|
|
1037
|
+
const lowerPath = file.toLowerCase();
|
|
1038
|
+
const isTypesPath = lowerPath.includes("/types/") || lowerPath.includes("/typings/") || lowerPath.includes("/@types/") || lowerPath.startsWith("types/") || lowerPath.startsWith("typings/");
|
|
1020
1039
|
const typeExports = exports2.filter((e) => e.type === "type" || e.type === "interface");
|
|
1021
1040
|
const runtimeExports = exports2.filter((e) => e.type === "function" || e.type === "class" || e.type === "const");
|
|
1022
1041
|
const mostlyTypes = exports2.length > 0 && typeExports.length > runtimeExports.length && typeExports.length / exports2.length > 0.7;
|
|
1023
|
-
|
|
1042
|
+
const pureTypeFile = exports2.length > 0 && typeExports.length === exports2.length;
|
|
1043
|
+
const emptyOrReExportInTypesDir = isTypesPath && exports2.length === 0;
|
|
1044
|
+
return isTypesFile || isTypesPath || mostlyTypes || pureTypeFile || emptyOrReExportInTypesDir;
|
|
1024
1045
|
}
|
|
1025
1046
|
function isConfigOrSchemaFile(node) {
|
|
1026
1047
|
const { file, exports: exports2 } = node;
|
|
@@ -1057,21 +1078,256 @@ function isUtilityFile(node) {
|
|
|
1057
1078
|
"helpers",
|
|
1058
1079
|
"common",
|
|
1059
1080
|
"shared",
|
|
1060
|
-
"lib",
|
|
1061
1081
|
"toolbox",
|
|
1062
1082
|
"toolkit",
|
|
1063
1083
|
".util.",
|
|
1064
1084
|
"-util.",
|
|
1065
|
-
"_util."
|
|
1085
|
+
"_util.",
|
|
1086
|
+
"-utils.",
|
|
1087
|
+
".utils."
|
|
1066
1088
|
];
|
|
1067
1089
|
const isUtilityName = utilityPatterns.some(
|
|
1068
1090
|
(pattern) => fileName?.includes(pattern)
|
|
1069
1091
|
);
|
|
1070
|
-
const isUtilityPath = file.toLowerCase().includes("/utils/") || file.toLowerCase().includes("/helpers/") || file.toLowerCase().includes("/
|
|
1071
|
-
const
|
|
1072
|
-
|
|
1092
|
+
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");
|
|
1093
|
+
const hasManySmallExportsInUtilityContext = exports2.length >= 3 && exports2.every((e) => e.type === "function" || e.type === "const") && (isUtilityName || isUtilityPath);
|
|
1094
|
+
return isUtilityName || isUtilityPath || hasManySmallExportsInUtilityContext;
|
|
1095
|
+
}
|
|
1096
|
+
function isLambdaHandler(node) {
|
|
1097
|
+
const { file, exports: exports2 } = node;
|
|
1098
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1099
|
+
const handlerPatterns = [
|
|
1100
|
+
"handler",
|
|
1101
|
+
".handler.",
|
|
1102
|
+
"-handler.",
|
|
1103
|
+
"lambda",
|
|
1104
|
+
".lambda.",
|
|
1105
|
+
"-lambda."
|
|
1106
|
+
];
|
|
1107
|
+
const isHandlerName = handlerPatterns.some(
|
|
1108
|
+
(pattern) => fileName?.includes(pattern)
|
|
1109
|
+
);
|
|
1110
|
+
const isHandlerPath = file.toLowerCase().includes("/handlers/") || file.toLowerCase().includes("/lambdas/") || file.toLowerCase().includes("/functions/");
|
|
1111
|
+
const hasHandlerExport = exports2.some(
|
|
1112
|
+
(e) => e.name.toLowerCase() === "handler" || e.name.toLowerCase() === "main" || e.name.toLowerCase() === "lambdahandler" || e.name.toLowerCase().endsWith("handler")
|
|
1113
|
+
);
|
|
1114
|
+
const hasSingleEntryInHandlerContext = exports2.length === 1 && (exports2[0].type === "function" || exports2[0].name === "default") && (isHandlerPath || isHandlerName);
|
|
1115
|
+
return isHandlerName || isHandlerPath || hasHandlerExport || hasSingleEntryInHandlerContext;
|
|
1116
|
+
}
|
|
1117
|
+
function isServiceFile(node) {
|
|
1118
|
+
const { file, exports: exports2 } = node;
|
|
1119
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1120
|
+
const servicePatterns = [
|
|
1121
|
+
"service",
|
|
1122
|
+
".service.",
|
|
1123
|
+
"-service.",
|
|
1124
|
+
"_service."
|
|
1125
|
+
];
|
|
1126
|
+
const isServiceName = servicePatterns.some(
|
|
1127
|
+
(pattern) => fileName?.includes(pattern)
|
|
1128
|
+
);
|
|
1129
|
+
const isServicePath = file.toLowerCase().includes("/services/");
|
|
1130
|
+
const hasServiceNamedExport = exports2.some(
|
|
1131
|
+
(e) => e.name.toLowerCase().includes("service") || e.name.toLowerCase().endsWith("service")
|
|
1132
|
+
);
|
|
1133
|
+
const hasClassExport = exports2.some((e) => e.type === "class");
|
|
1134
|
+
return isServiceName || isServicePath || hasServiceNamedExport && hasClassExport;
|
|
1135
|
+
}
|
|
1136
|
+
function isEmailTemplate(node) {
|
|
1137
|
+
const { file, exports: exports2 } = node;
|
|
1138
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1139
|
+
const emailTemplatePatterns = [
|
|
1140
|
+
"-email-",
|
|
1141
|
+
".email.",
|
|
1142
|
+
"_email_",
|
|
1143
|
+
"-template",
|
|
1144
|
+
".template.",
|
|
1145
|
+
"_template",
|
|
1146
|
+
"-mail.",
|
|
1147
|
+
".mail."
|
|
1148
|
+
];
|
|
1149
|
+
const isEmailTemplateName = emailTemplatePatterns.some(
|
|
1150
|
+
(pattern) => fileName?.includes(pattern)
|
|
1151
|
+
);
|
|
1152
|
+
const isSpecificTemplateName = fileName?.includes("receipt") || fileName?.includes("invoice-email") || fileName?.includes("welcome-email") || fileName?.includes("notification-email") || fileName?.includes("writer") && fileName.includes("receipt");
|
|
1153
|
+
const isEmailPath = file.toLowerCase().includes("/emails/") || file.toLowerCase().includes("/mail/") || file.toLowerCase().includes("/notifications/");
|
|
1154
|
+
const hasTemplateFunction = exports2.some(
|
|
1155
|
+
(e) => e.type === "function" && (e.name.toLowerCase().startsWith("render") || e.name.toLowerCase().startsWith("generate") || e.name.toLowerCase().includes("template") && e.name.toLowerCase().includes("email"))
|
|
1156
|
+
);
|
|
1157
|
+
const hasEmailExport = exports2.some(
|
|
1158
|
+
(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"
|
|
1159
|
+
);
|
|
1160
|
+
return isEmailPath || isEmailTemplateName || isSpecificTemplateName || hasTemplateFunction && hasEmailExport;
|
|
1161
|
+
}
|
|
1162
|
+
function isParserFile(node) {
|
|
1163
|
+
const { file, exports: exports2 } = node;
|
|
1164
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1165
|
+
const parserPatterns = [
|
|
1166
|
+
"parser",
|
|
1167
|
+
".parser.",
|
|
1168
|
+
"-parser.",
|
|
1169
|
+
"_parser.",
|
|
1170
|
+
"transform",
|
|
1171
|
+
".transform.",
|
|
1172
|
+
"-transform.",
|
|
1173
|
+
"converter",
|
|
1174
|
+
".converter.",
|
|
1175
|
+
"-converter.",
|
|
1176
|
+
"mapper",
|
|
1177
|
+
".mapper.",
|
|
1178
|
+
"-mapper.",
|
|
1179
|
+
"serializer",
|
|
1180
|
+
".serializer.",
|
|
1181
|
+
"deterministic"
|
|
1182
|
+
// For base-parser-deterministic.ts pattern
|
|
1183
|
+
];
|
|
1184
|
+
const isParserName = parserPatterns.some(
|
|
1185
|
+
(pattern) => fileName?.includes(pattern)
|
|
1186
|
+
);
|
|
1187
|
+
const isParserPath = file.toLowerCase().includes("/parsers/") || file.toLowerCase().includes("/transformers/") || file.toLowerCase().includes("/converters/") || file.toLowerCase().includes("/mappers/");
|
|
1188
|
+
const hasParserExport = exports2.some(
|
|
1189
|
+
(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")
|
|
1190
|
+
);
|
|
1191
|
+
const hasParseFunction = exports2.some(
|
|
1192
|
+
(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"))
|
|
1193
|
+
);
|
|
1194
|
+
return isParserName || isParserPath || hasParserExport || hasParseFunction;
|
|
1195
|
+
}
|
|
1196
|
+
function isSessionFile(node) {
|
|
1197
|
+
const { file, exports: exports2 } = node;
|
|
1198
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1199
|
+
const sessionPatterns = [
|
|
1200
|
+
"session",
|
|
1201
|
+
".session.",
|
|
1202
|
+
"-session.",
|
|
1203
|
+
"state",
|
|
1204
|
+
".state.",
|
|
1205
|
+
"-state.",
|
|
1206
|
+
"context",
|
|
1207
|
+
".context.",
|
|
1208
|
+
"-context.",
|
|
1209
|
+
"store",
|
|
1210
|
+
".store.",
|
|
1211
|
+
"-store."
|
|
1212
|
+
];
|
|
1213
|
+
const isSessionName = sessionPatterns.some(
|
|
1214
|
+
(pattern) => fileName?.includes(pattern)
|
|
1215
|
+
);
|
|
1216
|
+
const isSessionPath = file.toLowerCase().includes("/sessions/") || file.toLowerCase().includes("/state/") || file.toLowerCase().includes("/context/") || file.toLowerCase().includes("/store/");
|
|
1217
|
+
const hasSessionExport = exports2.some(
|
|
1218
|
+
(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")
|
|
1219
|
+
);
|
|
1220
|
+
return isSessionName || isSessionPath || hasSessionExport;
|
|
1221
|
+
}
|
|
1222
|
+
function isNextJsPage(node) {
|
|
1223
|
+
const { file, exports: exports2 } = node;
|
|
1224
|
+
const lowerPath = file.toLowerCase();
|
|
1225
|
+
const fileName = file.split("/").pop()?.toLowerCase();
|
|
1226
|
+
const isInAppDir = lowerPath.includes("/app/") || lowerPath.startsWith("app/");
|
|
1227
|
+
const isPageFile = fileName === "page.tsx" || fileName === "page.ts";
|
|
1228
|
+
if (!isInAppDir || !isPageFile) {
|
|
1229
|
+
return false;
|
|
1230
|
+
}
|
|
1231
|
+
const exportNames = exports2.map((e) => e.name.toLowerCase());
|
|
1232
|
+
const hasDefaultExport = exports2.some((e) => e.type === "default");
|
|
1233
|
+
const nextJsExports = ["metadata", "generatemetadata", "faqjsonld", "jsonld", "icon", "viewport", "dynamic"];
|
|
1234
|
+
const hasNextJsExports = exportNames.some(
|
|
1235
|
+
(name) => nextJsExports.includes(name) || name.includes("jsonld")
|
|
1073
1236
|
);
|
|
1074
|
-
return
|
|
1237
|
+
return hasDefaultExport || hasNextJsExports;
|
|
1238
|
+
}
|
|
1239
|
+
function adjustCohesionForClassification(baseCohesion, classification, node) {
|
|
1240
|
+
switch (classification) {
|
|
1241
|
+
case "barrel-export":
|
|
1242
|
+
return 1;
|
|
1243
|
+
case "type-definition":
|
|
1244
|
+
return 1;
|
|
1245
|
+
case "utility-module": {
|
|
1246
|
+
if (node) {
|
|
1247
|
+
const exportNames = node.exports.map((e) => e.name.toLowerCase());
|
|
1248
|
+
const hasRelatedNames = hasRelatedExportNames(exportNames);
|
|
1249
|
+
if (hasRelatedNames) {
|
|
1250
|
+
return Math.min(1, baseCohesion + 0.45);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
return Math.min(1, baseCohesion + 0.35);
|
|
1254
|
+
}
|
|
1255
|
+
case "service-file": {
|
|
1256
|
+
if (node?.exports.some((e) => e.type === "class")) {
|
|
1257
|
+
return Math.min(1, baseCohesion + 0.4);
|
|
1258
|
+
}
|
|
1259
|
+
return Math.min(1, baseCohesion + 0.3);
|
|
1260
|
+
}
|
|
1261
|
+
case "lambda-handler": {
|
|
1262
|
+
if (node) {
|
|
1263
|
+
const hasSingleEntry = node.exports.length === 1 || node.exports.some((e) => e.name.toLowerCase() === "handler");
|
|
1264
|
+
if (hasSingleEntry) {
|
|
1265
|
+
return Math.min(1, baseCohesion + 0.45);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
return Math.min(1, baseCohesion + 0.35);
|
|
1269
|
+
}
|
|
1270
|
+
case "email-template": {
|
|
1271
|
+
if (node) {
|
|
1272
|
+
const hasTemplateFunc = node.exports.some(
|
|
1273
|
+
(e) => e.name.toLowerCase().includes("render") || e.name.toLowerCase().includes("generate") || e.name.toLowerCase().includes("template")
|
|
1274
|
+
);
|
|
1275
|
+
if (hasTemplateFunc) {
|
|
1276
|
+
return Math.min(1, baseCohesion + 0.4);
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
return Math.min(1, baseCohesion + 0.3);
|
|
1280
|
+
}
|
|
1281
|
+
case "parser-file": {
|
|
1282
|
+
if (node) {
|
|
1283
|
+
const hasParseFunc = node.exports.some(
|
|
1284
|
+
(e) => e.name.toLowerCase().startsWith("parse") || e.name.toLowerCase().startsWith("transform") || e.name.toLowerCase().startsWith("convert")
|
|
1285
|
+
);
|
|
1286
|
+
if (hasParseFunc) {
|
|
1287
|
+
return Math.min(1, baseCohesion + 0.4);
|
|
1288
|
+
}
|
|
1289
|
+
}
|
|
1290
|
+
return Math.min(1, baseCohesion + 0.3);
|
|
1291
|
+
}
|
|
1292
|
+
case "nextjs-page":
|
|
1293
|
+
return 1;
|
|
1294
|
+
case "cohesive-module":
|
|
1295
|
+
return Math.max(baseCohesion, 0.7);
|
|
1296
|
+
case "mixed-concerns":
|
|
1297
|
+
return baseCohesion;
|
|
1298
|
+
default:
|
|
1299
|
+
return Math.min(1, baseCohesion + 0.1);
|
|
1300
|
+
}
|
|
1301
|
+
}
|
|
1302
|
+
function hasRelatedExportNames(exportNames) {
|
|
1303
|
+
if (exportNames.length < 2) return true;
|
|
1304
|
+
const stems = /* @__PURE__ */ new Set();
|
|
1305
|
+
const domains = /* @__PURE__ */ new Set();
|
|
1306
|
+
for (const name of exportNames) {
|
|
1307
|
+
const verbs = ["get", "set", "create", "update", "delete", "fetch", "save", "load", "parse", "format", "validate", "convert", "transform", "build", "generate", "render", "send", "receive"];
|
|
1308
|
+
for (const verb of verbs) {
|
|
1309
|
+
if (name.startsWith(verb) && name.length > verb.length) {
|
|
1310
|
+
stems.add(name.slice(verb.length).toLowerCase());
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
const domainPatterns = ["user", "order", "product", "session", "email", "file", "db", "s3", "dynamo", "api", "config"];
|
|
1314
|
+
for (const domain of domainPatterns) {
|
|
1315
|
+
if (name.includes(domain)) {
|
|
1316
|
+
domains.add(domain);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
}
|
|
1320
|
+
if (stems.size === 1 && exportNames.length >= 2) return true;
|
|
1321
|
+
if (domains.size === 1 && exportNames.length >= 2) return true;
|
|
1322
|
+
const prefixes = exportNames.map((name) => {
|
|
1323
|
+
const match = name.match(/^([a-z]+)/);
|
|
1324
|
+
return match ? match[1] : "";
|
|
1325
|
+
}).filter((p) => p.length >= 3);
|
|
1326
|
+
if (prefixes.length >= 2) {
|
|
1327
|
+
const uniquePrefixes = new Set(prefixes);
|
|
1328
|
+
if (uniquePrefixes.size === 1) return true;
|
|
1329
|
+
}
|
|
1330
|
+
return false;
|
|
1075
1331
|
}
|
|
1076
1332
|
function adjustFragmentationForClassification(baseFragmentation, classification) {
|
|
1077
1333
|
switch (classification) {
|
|
@@ -1079,6 +1335,13 @@ function adjustFragmentationForClassification(baseFragmentation, classification)
|
|
|
1079
1335
|
return 0;
|
|
1080
1336
|
case "type-definition":
|
|
1081
1337
|
return 0;
|
|
1338
|
+
case "utility-module":
|
|
1339
|
+
case "service-file":
|
|
1340
|
+
case "lambda-handler":
|
|
1341
|
+
case "email-template":
|
|
1342
|
+
case "parser-file":
|
|
1343
|
+
case "nextjs-page":
|
|
1344
|
+
return baseFragmentation * 0.2;
|
|
1082
1345
|
case "cohesive-module":
|
|
1083
1346
|
return baseFragmentation * 0.3;
|
|
1084
1347
|
case "mixed-concerns":
|
|
@@ -1104,6 +1367,36 @@ function getClassificationRecommendations(classification, file, issues) {
|
|
|
1104
1367
|
"Module has good cohesion despite its size",
|
|
1105
1368
|
"Consider documenting the module boundaries for AI assistants"
|
|
1106
1369
|
];
|
|
1370
|
+
case "utility-module":
|
|
1371
|
+
return [
|
|
1372
|
+
"Utility module detected - multiple domains are acceptable here",
|
|
1373
|
+
"Consider grouping related utilities by prefix or domain for better discoverability"
|
|
1374
|
+
];
|
|
1375
|
+
case "service-file":
|
|
1376
|
+
return [
|
|
1377
|
+
"Service file detected - orchestration of multiple dependencies is expected",
|
|
1378
|
+
"Consider documenting service boundaries and dependencies"
|
|
1379
|
+
];
|
|
1380
|
+
case "lambda-handler":
|
|
1381
|
+
return [
|
|
1382
|
+
"Lambda handler detected - coordination of services is expected",
|
|
1383
|
+
"Ensure handler has clear single responsibility"
|
|
1384
|
+
];
|
|
1385
|
+
case "email-template":
|
|
1386
|
+
return [
|
|
1387
|
+
"Email template detected - references multiple domains for rendering",
|
|
1388
|
+
"Template structure is cohesive by design"
|
|
1389
|
+
];
|
|
1390
|
+
case "parser-file":
|
|
1391
|
+
return [
|
|
1392
|
+
"Parser/transformer file detected - handles multiple data sources",
|
|
1393
|
+
"Consider documenting input/output schemas"
|
|
1394
|
+
];
|
|
1395
|
+
case "nextjs-page":
|
|
1396
|
+
return [
|
|
1397
|
+
"Next.js App Router page detected - metadata/JSON-LD/component pattern is cohesive",
|
|
1398
|
+
"Multiple exports (metadata, faqJsonLd, default) serve single page purpose"
|
|
1399
|
+
];
|
|
1107
1400
|
case "mixed-concerns":
|
|
1108
1401
|
return [
|
|
1109
1402
|
"Consider splitting this file by domain",
|
|
@@ -1377,6 +1670,11 @@ async function analyzeContext(options) {
|
|
|
1377
1670
|
...new Set(node.exports.map((e) => e.inferredDomain || "unknown"))
|
|
1378
1671
|
];
|
|
1379
1672
|
const fileClassification = classifyFile(node, cohesionScore, domains);
|
|
1673
|
+
const adjustedCohesionScore = adjustCohesionForClassification(
|
|
1674
|
+
cohesionScore,
|
|
1675
|
+
fileClassification,
|
|
1676
|
+
node
|
|
1677
|
+
);
|
|
1380
1678
|
const adjustedFragmentationScore = adjustFragmentationForClassification(
|
|
1381
1679
|
fragmentationScore,
|
|
1382
1680
|
fileClassification
|
|
@@ -1395,7 +1693,8 @@ async function analyzeContext(options) {
|
|
|
1395
1693
|
file,
|
|
1396
1694
|
importDepth,
|
|
1397
1695
|
contextBudget,
|
|
1398
|
-
cohesionScore,
|
|
1696
|
+
cohesionScore: adjustedCohesionScore,
|
|
1697
|
+
// Use adjusted cohesion
|
|
1399
1698
|
fragmentationScore: adjustedFragmentationScore,
|
|
1400
1699
|
maxDepth,
|
|
1401
1700
|
maxContextBudget,
|
|
@@ -1411,7 +1710,8 @@ async function analyzeContext(options) {
|
|
|
1411
1710
|
dependencyCount: dependencyList.length,
|
|
1412
1711
|
dependencyList,
|
|
1413
1712
|
circularDeps: circularDeps.filter((cycle) => cycle.includes(file)),
|
|
1414
|
-
cohesionScore,
|
|
1713
|
+
cohesionScore: adjustedCohesionScore,
|
|
1714
|
+
// Report adjusted cohesion
|
|
1415
1715
|
domains,
|
|
1416
1716
|
exportCount: node.exports.length,
|
|
1417
1717
|
contextBudget,
|
package/dist/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aiready/context-analyzer",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.26",
|
|
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",
|