@aiready/context-analyzer 0.21.26 → 0.21.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/.turbo/turbo-build.log +32 -25
  2. package/.turbo/turbo-test.log +51 -87
  3. package/coverage/clover.xml +392 -1878
  4. package/coverage/coverage-final.json +15 -19
  5. package/coverage/index.html +48 -63
  6. package/coverage/src/analyzers/index.html +21 -21
  7. package/coverage/src/analyzers/python-context.ts.html +96 -96
  8. package/coverage/src/ast-utils.ts.html +34 -109
  9. package/coverage/src/classifier.ts.html +104 -104
  10. package/coverage/src/classify/classification-patterns.ts.html +1 -1
  11. package/coverage/src/classify/file-classifiers.ts.html +1 -1
  12. package/coverage/src/classify/index.html +1 -1
  13. package/coverage/src/cluster-detector.ts.html +72 -72
  14. package/coverage/src/defaults.ts.html +1 -1
  15. package/coverage/src/graph-builder.ts.html +131 -131
  16. package/coverage/src/index.html +101 -116
  17. package/coverage/src/index.ts.html +2 -2
  18. package/coverage/src/issue-analyzer.ts.html +32 -83
  19. package/coverage/src/mapper.ts.html +20 -2
  20. package/coverage/src/metrics.ts.html +127 -130
  21. package/coverage/src/orchestrator.ts.html +13 -13
  22. package/coverage/src/provider.ts.html +19 -19
  23. package/coverage/src/remediation.ts.html +59 -59
  24. package/coverage/src/report/console-report.ts.html +2 -2
  25. package/coverage/src/report/html-report.ts.html +60 -84
  26. package/coverage/src/report/index.html +7 -7
  27. package/coverage/src/report/interactive-setup.ts.html +1 -1
  28. package/coverage/src/scoring.ts.html +62 -62
  29. package/coverage/src/semantic/co-usage.ts.html +1 -1
  30. package/coverage/src/semantic/consolidation.ts.html +1 -1
  31. package/coverage/src/semantic/domain-inference.ts.html +1 -1
  32. package/coverage/src/semantic/index.html +1 -1
  33. package/coverage/src/semantic/type-graph.ts.html +1 -1
  34. package/coverage/src/summary.ts.html +67 -67
  35. package/coverage/src/types.ts.html +1 -1
  36. package/coverage/src/utils/dependency-graph-utils.ts.html +41 -41
  37. package/coverage/src/utils/index.html +21 -21
  38. package/coverage/src/utils/string-utils.ts.html +1 -1
  39. package/dist/chunk-22ZO4EKZ.mjs +1297 -0
  40. package/dist/chunk-4U4LDWGF.mjs +360 -0
  41. package/dist/chunk-BA7QGUHN.mjs +1722 -0
  42. package/dist/chunk-BCEZGRXI.mjs +1297 -0
  43. package/dist/chunk-BQCISA2F.mjs +91 -0
  44. package/dist/chunk-EMYD7NS6.mjs +137 -0
  45. package/dist/chunk-EWFR366Y.mjs +1740 -0
  46. package/dist/chunk-FO6YT6RG.mjs +1751 -0
  47. package/dist/chunk-J3SZQZNU.mjs +221 -0
  48. package/dist/chunk-OZE3FVZT.mjs +1089 -0
  49. package/dist/chunk-WHB7QI7N.mjs +91 -0
  50. package/dist/cli-action-CXIHOVAC.mjs +95 -0
  51. package/dist/cli-action-SA7SCYNV.mjs +95 -0
  52. package/dist/cli-action-YAJOJCXJ.mjs +95 -0
  53. package/dist/cli.js +688 -566
  54. package/dist/cli.mjs +4 -88
  55. package/dist/index.js +889 -773
  56. package/dist/index.mjs +21 -14
  57. package/dist/orchestrator-3L3NAZYP.mjs +10 -0
  58. package/dist/orchestrator-MONOZHVW.mjs +10 -0
  59. package/dist/orchestrator-ZR7JSKWI.mjs +10 -0
  60. package/dist/summary-7PZVW72O.mjs +7 -0
  61. package/dist/summary-LKUCJAIS.mjs +7 -0
  62. package/package.json +2 -2
  63. package/src/__tests__/analyzer.test.ts +1 -1
  64. package/src/__tests__/enhanced-cohesion.test.ts +4 -1
  65. package/src/__tests__/orchestrator.test.ts +19 -4
  66. package/src/__tests__/python-context.test.ts +6 -0
  67. package/src/__tests__/report/html-report.test.ts +8 -2
  68. package/src/ast-utils.ts +1 -26
  69. package/src/cli-definition.ts +4 -2
  70. package/src/issue-analyzer.ts +4 -19
  71. package/src/metrics.ts +1 -2
  72. package/src/provider.ts +4 -4
  73. package/src/report/html-report.ts +43 -59
  74. package/coverage/dist/chunk-64U3PNO3.mjs.html +0 -367
  75. package/coverage/dist/chunk-J3MUOWHC.mjs.html +0 -5326
  76. package/coverage/dist/index.html +0 -146
  77. package/coverage/dist/index.mjs.html +0 -1396
  78. package/coverage/src/analyzer.ts.html +0 -88
package/dist/index.js CHANGED
@@ -30,6 +30,263 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
30
  ));
31
31
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
32
 
33
+ // src/metrics.ts
34
+ function calculateEnhancedCohesion(exports2, filePath, options) {
35
+ if (exports2.length <= 1) return 1;
36
+ if (filePath && (0, import_core2.isTestFile)(filePath)) return 1;
37
+ const domains = exports2.map((e) => e.inferredDomain || "unknown");
38
+ const domainCounts = /* @__PURE__ */ new Map();
39
+ for (const domain of domains)
40
+ domainCounts.set(domain, (domainCounts.get(domain) || 0) + 1);
41
+ if (domainCounts.size === 1 && domains[0] !== "unknown") {
42
+ if (!options?.weights) return 1;
43
+ }
44
+ const probs = Array.from(domainCounts.values()).map(
45
+ (count) => count / exports2.length
46
+ );
47
+ let domainEntropy = 0;
48
+ for (const prob of probs) {
49
+ if (prob > 0) domainEntropy -= prob * Math.log2(prob);
50
+ }
51
+ const maxEntropy = Math.log2(Math.max(2, domainCounts.size));
52
+ const domainScore = 1 - domainEntropy / maxEntropy;
53
+ let importScoreTotal = 0;
54
+ let pairsWithData = 0;
55
+ let anyImportData = false;
56
+ for (let i = 0; i < exports2.length; i++) {
57
+ for (let j = i + 1; j < exports2.length; j++) {
58
+ const exp1Imports = exports2[i].imports;
59
+ const exp2Imports = exports2[j].imports;
60
+ if (exp1Imports || exp2Imports) {
61
+ anyImportData = true;
62
+ const sim = (0, import_core2.calculateImportSimilarity)(
63
+ { ...exports2[i], imports: exp1Imports || [] },
64
+ { ...exports2[j], imports: exp2Imports || [] }
65
+ );
66
+ importScoreTotal += sim;
67
+ pairsWithData++;
68
+ }
69
+ }
70
+ }
71
+ const avgImportScore = pairsWithData > 0 ? importScoreTotal / pairsWithData : 0;
72
+ let score = anyImportData ? domainScore * 0.4 + avgImportScore * 0.6 : domainScore;
73
+ if (anyImportData && score === 0 && domainScore === 0) {
74
+ score = 0.1;
75
+ }
76
+ let structuralScore = 0;
77
+ for (const exp of exports2) {
78
+ if (exp.dependencies && exp.dependencies.length > 0) {
79
+ structuralScore += 1;
80
+ }
81
+ }
82
+ if (structuralScore > 0) {
83
+ score = Math.min(1, score + 0.1);
84
+ }
85
+ if (!options?.weights && !anyImportData && domainCounts.size === 1) return 1;
86
+ return score;
87
+ }
88
+ function calculateStructuralCohesionFromCoUsage(file, coUsageMatrix) {
89
+ if (!coUsageMatrix) return 1;
90
+ const coUsages = coUsageMatrix.get(file);
91
+ if (!coUsages || coUsages.size === 0) return 1;
92
+ let total = 0;
93
+ for (const count of coUsages.values()) total += count;
94
+ if (total === 0) return 1;
95
+ const probs = [];
96
+ for (const count of coUsages.values()) {
97
+ if (count > 0) probs.push(count / total);
98
+ }
99
+ if (probs.length <= 1) return 1;
100
+ let entropy = 0;
101
+ for (const prob of probs) {
102
+ entropy -= prob * Math.log2(prob);
103
+ }
104
+ const maxEntropy = Math.log2(probs.length);
105
+ return maxEntropy > 0 ? 1 - entropy / maxEntropy : 1;
106
+ }
107
+ function calculateFragmentation(files, domain, options) {
108
+ if (files.length <= 1) return 0;
109
+ const directories = new Set(
110
+ files.map((file) => file.split("/").slice(0, -1).join("/"))
111
+ );
112
+ const uniqueDirs = directories.size;
113
+ let score = options?.useLogScale ? uniqueDirs <= 1 ? 0 : Math.log(uniqueDirs) / Math.log(options.logBase || Math.E) / (Math.log(files.length) / Math.log(options.logBase || Math.E)) : (uniqueDirs - 1) / (files.length - 1);
114
+ if (options?.sharedImportRatio && options.sharedImportRatio > 0.5) {
115
+ const discount = (options.sharedImportRatio - 0.5) * 0.4;
116
+ score = score * (1 - discount);
117
+ }
118
+ return score;
119
+ }
120
+ function calculatePathEntropy(files) {
121
+ if (!files || files.length === 0) return 0;
122
+ const dirCounts = /* @__PURE__ */ new Map();
123
+ for (const file of files) {
124
+ const dir = file.split("/").slice(0, -1).join("/") || ".";
125
+ dirCounts.set(dir, (dirCounts.get(dir) || 0) + 1);
126
+ }
127
+ const counts = Array.from(dirCounts.values());
128
+ if (counts.length <= 1) return 0;
129
+ const total = counts.reduce((sum, value) => sum + value, 0);
130
+ let entropy = 0;
131
+ for (const count of counts) {
132
+ const prob = count / total;
133
+ entropy -= prob * Math.log2(prob);
134
+ }
135
+ const maxEntropy = Math.log2(counts.length);
136
+ return maxEntropy > 0 ? entropy / maxEntropy : 0;
137
+ }
138
+ function calculateDirectoryDistance(files) {
139
+ if (!files || files.length <= 1) return 0;
140
+ const pathSegments = (pathStr) => pathStr.split("/").filter(Boolean);
141
+ const commonAncestorDepth = (pathA, pathB) => {
142
+ const minLen = Math.min(pathA.length, pathB.length);
143
+ let i = 0;
144
+ while (i < minLen && pathA[i] === pathB[i]) i++;
145
+ return i;
146
+ };
147
+ let totalNormalized = 0;
148
+ let comparisons = 0;
149
+ for (let i = 0; i < files.length; i++) {
150
+ for (let j = i + 1; j < files.length; j++) {
151
+ const segA = pathSegments(files[i]);
152
+ const segB = pathSegments(files[j]);
153
+ const shared = commonAncestorDepth(segA, segB);
154
+ const maxDepth = Math.max(segA.length, segB.length);
155
+ totalNormalized += 1 - (maxDepth > 0 ? shared / maxDepth : 0);
156
+ comparisons++;
157
+ }
158
+ }
159
+ return comparisons > 0 ? totalNormalized / comparisons : 0;
160
+ }
161
+ var import_core2;
162
+ var init_metrics = __esm({
163
+ "src/metrics.ts"() {
164
+ "use strict";
165
+ import_core2 = require("@aiready/core");
166
+ }
167
+ });
168
+
169
+ // src/issue-analyzer.ts
170
+ function analyzeIssues(params) {
171
+ const {
172
+ file,
173
+ importDepth,
174
+ contextBudget,
175
+ cohesionScore,
176
+ fragmentationScore,
177
+ maxDepth,
178
+ maxContextBudget,
179
+ minCohesion,
180
+ maxFragmentation,
181
+ circularDeps
182
+ } = params;
183
+ const issues = [];
184
+ const recommendations = [];
185
+ let severity = import_core3.Severity.Info;
186
+ let potentialSavings = 0;
187
+ if (circularDeps.length > 0) {
188
+ severity = import_core3.Severity.Critical;
189
+ issues.push(`Part of ${circularDeps.length} circular dependency chain(s)`);
190
+ recommendations.push(
191
+ "Break circular dependencies by extracting interfaces or using dependency injection"
192
+ );
193
+ potentialSavings += contextBudget * 0.2;
194
+ }
195
+ if (importDepth > maxDepth * 1.5) {
196
+ severity = import_core3.Severity.Critical;
197
+ issues.push(`Import depth ${importDepth} exceeds limit by 50%`);
198
+ recommendations.push("Flatten dependency tree or use facade pattern");
199
+ potentialSavings += contextBudget * 0.3;
200
+ } else if (importDepth > maxDepth) {
201
+ if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
202
+ issues.push(
203
+ `Import depth ${importDepth} exceeds recommended maximum ${maxDepth}`
204
+ );
205
+ recommendations.push("Consider reducing dependency depth");
206
+ potentialSavings += contextBudget * 0.15;
207
+ }
208
+ if (contextBudget > maxContextBudget * 1.5) {
209
+ severity = import_core3.Severity.Critical;
210
+ issues.push(
211
+ `Context budget ${contextBudget.toLocaleString()} tokens is 50% over limit`
212
+ );
213
+ recommendations.push(
214
+ "Split into smaller modules or reduce dependency tree"
215
+ );
216
+ potentialSavings += contextBudget * 0.4;
217
+ } else if (contextBudget > maxContextBudget) {
218
+ if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
219
+ issues.push(
220
+ `Context budget ${contextBudget.toLocaleString()} exceeds ${maxContextBudget.toLocaleString()}`
221
+ );
222
+ recommendations.push("Reduce file size or dependencies");
223
+ potentialSavings += contextBudget * 0.2;
224
+ }
225
+ if (cohesionScore < minCohesion * 0.5) {
226
+ if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
227
+ issues.push(
228
+ `Very low cohesion (${(cohesionScore * 100).toFixed(0)}%) - mixed concerns`
229
+ );
230
+ recommendations.push(
231
+ "Split file by domain - separate unrelated functionality"
232
+ );
233
+ potentialSavings += contextBudget * 0.25;
234
+ } else if (cohesionScore < minCohesion) {
235
+ if (severity === import_core3.Severity.Info) severity = import_core3.Severity.Minor;
236
+ issues.push(`Low cohesion (${(cohesionScore * 100).toFixed(0)}%)`);
237
+ recommendations.push("Consider grouping related exports together");
238
+ potentialSavings += contextBudget * 0.1;
239
+ }
240
+ if (fragmentationScore > maxFragmentation) {
241
+ if (severity === import_core3.Severity.Info || severity === import_core3.Severity.Minor)
242
+ severity = import_core3.Severity.Minor;
243
+ issues.push(
244
+ `High fragmentation (${(fragmentationScore * 100).toFixed(0)}%) - scattered implementation`
245
+ );
246
+ recommendations.push("Consolidate with related files in same domain");
247
+ potentialSavings += contextBudget * 0.3;
248
+ }
249
+ if ((0, import_core3.isBuildArtifact)(file)) {
250
+ issues.push("Detected build artifact (bundled/output file)");
251
+ recommendations.push("Exclude build outputs from analysis");
252
+ severity = import_core3.Severity.Info;
253
+ potentialSavings = 0;
254
+ }
255
+ return {
256
+ severity,
257
+ issues,
258
+ recommendations,
259
+ potentialSavings: Math.floor(potentialSavings)
260
+ };
261
+ }
262
+ var import_core3;
263
+ var init_issue_analyzer = __esm({
264
+ "src/issue-analyzer.ts"() {
265
+ "use strict";
266
+ import_core3 = require("@aiready/core");
267
+ }
268
+ });
269
+
270
+ // src/utils/string-utils.ts
271
+ function singularize(word) {
272
+ const irregulars = {
273
+ people: "person",
274
+ children: "child",
275
+ men: "man",
276
+ women: "woman"
277
+ };
278
+ if (irregulars[word]) return irregulars[word];
279
+ if (word.endsWith("ies")) return word.slice(0, -3) + "y";
280
+ if (word.endsWith("ses")) return word.slice(0, -2);
281
+ if (word.endsWith("s") && word.length > 3) return word.slice(0, -1);
282
+ return word;
283
+ }
284
+ var init_string_utils = __esm({
285
+ "src/utils/string-utils.ts"() {
286
+ "use strict";
287
+ }
288
+ });
289
+
33
290
  // src/utils/dependency-graph-utils.ts
34
291
  function calculateImportDepthFromEdges(file, edges, visited = /* @__PURE__ */ new Set(), depth = 0) {
35
292
  if (visited.has(file)) return depth;
@@ -123,264 +380,77 @@ var init_dependency_graph_utils = __esm({
123
380
  }
124
381
  });
125
382
 
126
- // src/analyzers/python-context.ts
127
- var python_context_exports = {};
128
- __export(python_context_exports, {
129
- analyzePythonContext: () => analyzePythonContext
130
- });
131
- async function analyzePythonContext(files, rootDir) {
132
- const results = [];
133
- const parser = await (0, import_core5.getParser)("dummy.py");
134
- if (!parser) {
135
- console.warn("Python parser not available");
136
- return results;
137
- }
138
- const pythonFiles = files.filter((f) => f.toLowerCase().endsWith(".py"));
139
- void import_path2.relative;
140
- void import_path2.join;
141
- const dependencyGraph = await buildPythonDependencyGraph(
142
- pythonFiles,
143
- rootDir
144
- );
145
- for (const file of pythonFiles) {
146
- try {
147
- const code = await import_fs.default.promises.readFile(file, "utf-8");
148
- const result = parser.parse(code, file);
149
- const imports = result.imports.map((imp) => ({
150
- source: imp.source,
151
- specifiers: imp.specifiers,
152
- isRelative: imp.source.startsWith("."),
153
- resolvedPath: resolvePythonImport(file, imp.source, rootDir)
154
- }));
155
- const exports2 = result.exports.map((exp) => ({
156
- name: exp.name,
157
- type: exp.type
158
- }));
159
- const linesOfCode = code.split("\n").length;
160
- const importDepth = calculateImportDepthFromEdges(
161
- file,
162
- dependencyGraph,
163
- /* @__PURE__ */ new Set()
164
- );
165
- const contextBudget = estimateContextBudget(
166
- code,
167
- imports,
168
- dependencyGraph
169
- );
170
- const cohesion = calculatePythonCohesion(exports2, imports);
171
- const circularDependencies = detectGraphCyclesFromFile(
172
- file,
173
- dependencyGraph
174
- ).map((cycle) => cycle.join(" -> "));
175
- results.push({
176
- file,
177
- importDepth,
178
- contextBudget,
179
- cohesion,
180
- imports,
181
- exports: exports2,
182
- metrics: {
183
- linesOfCode,
184
- importCount: imports.length,
185
- exportCount: exports2.length,
186
- circularDependencies
187
- }
188
- });
189
- } catch (error) {
190
- console.warn(`Failed to analyze ${file}:`, error);
191
- }
192
- }
193
- return results;
194
- }
195
- async function buildPythonDependencyGraph(files, rootDir) {
196
- const graph = /* @__PURE__ */ new Map();
197
- const parser = await (0, import_core5.getParser)("dummy.py");
198
- if (!parser) return graph;
199
- for (const file of files) {
200
- try {
201
- const code = await import_fs.default.promises.readFile(file, "utf-8");
202
- const result = parser.parse(code, file);
203
- const dependencies = /* @__PURE__ */ new Set();
204
- for (const imp of result.imports) {
205
- const resolved = resolvePythonImport(file, imp.source, rootDir);
206
- if (resolved && files.includes(resolved)) {
207
- dependencies.add(resolved);
208
- }
383
+ // src/semantic/co-usage.ts
384
+ function buildCoUsageMatrix(graph) {
385
+ const coUsageMatrix = /* @__PURE__ */ new Map();
386
+ for (const [, node] of graph.nodes) {
387
+ const imports = node.imports;
388
+ for (let i = 0; i < imports.length; i++) {
389
+ const fileA = imports[i];
390
+ if (!coUsageMatrix.has(fileA)) coUsageMatrix.set(fileA, /* @__PURE__ */ new Map());
391
+ for (let j = i + 1; j < imports.length; j++) {
392
+ const fileB = imports[j];
393
+ const fileAUsage = coUsageMatrix.get(fileA);
394
+ fileAUsage.set(fileB, (fileAUsage.get(fileB) || 0) + 1);
395
+ if (!coUsageMatrix.has(fileB)) coUsageMatrix.set(fileB, /* @__PURE__ */ new Map());
396
+ const fileBUsage = coUsageMatrix.get(fileB);
397
+ fileBUsage.set(fileA, (fileBUsage.get(fileA) || 0) + 1);
209
398
  }
210
- graph.set(file, dependencies);
211
- } catch (error) {
212
- void error;
213
399
  }
214
400
  }
215
- return graph;
401
+ return coUsageMatrix;
216
402
  }
217
- function resolvePythonImport(fromFile, importPath, rootDir) {
218
- const dir = (0, import_path2.dirname)(fromFile);
219
- if (importPath.startsWith(".")) {
220
- const parts = importPath.split(".");
221
- let upCount = 0;
222
- while (parts[0] === "") {
223
- upCount++;
224
- parts.shift();
225
- }
226
- let targetDir = dir;
227
- for (let i = 0; i < upCount - 1; i++) {
228
- targetDir = (0, import_path2.dirname)(targetDir);
229
- }
230
- const modulePath = parts.join("/");
231
- const possiblePaths = [
232
- (0, import_path2.resolve)(targetDir, `${modulePath}.py`),
233
- (0, import_path2.resolve)(targetDir, modulePath, "__init__.py")
234
- ];
235
- for (const path of possiblePaths) {
236
- if (import_fs.default.existsSync(path)) {
237
- return path;
238
- }
239
- }
240
- } else {
241
- const modulePath = importPath.replace(/\./g, "/");
242
- const possiblePaths = [
243
- (0, import_path2.resolve)(rootDir, `${modulePath}.py`),
244
- (0, import_path2.resolve)(rootDir, modulePath, "__init__.py")
245
- ];
246
- for (const path of possiblePaths) {
247
- if (import_fs.default.existsSync(path)) {
248
- return path;
403
+ function findSemanticClusters(coUsageMatrix, minCoUsage = 3) {
404
+ const clusters = /* @__PURE__ */ new Map();
405
+ const visited = /* @__PURE__ */ new Set();
406
+ for (const [file, coUsages] of coUsageMatrix) {
407
+ if (visited.has(file)) continue;
408
+ const cluster = [file];
409
+ visited.add(file);
410
+ for (const [relatedFile, count] of coUsages) {
411
+ if (count >= minCoUsage && !visited.has(relatedFile)) {
412
+ cluster.push(relatedFile);
413
+ visited.add(relatedFile);
249
414
  }
250
415
  }
416
+ if (cluster.length > 1) clusters.set(file, cluster);
251
417
  }
252
- return void 0;
418
+ return clusters;
253
419
  }
254
- function estimateContextBudget(code, imports, dependencyGraph) {
255
- void dependencyGraph;
256
- let budget = (0, import_core5.estimateTokens)(code);
257
- const avgTokensPerDep = 500;
258
- budget += imports.length * avgTokensPerDep;
259
- return budget;
420
+ function getCoUsageData(file, coUsageMatrix) {
421
+ return {
422
+ file,
423
+ coImportedWith: coUsageMatrix.get(file) || /* @__PURE__ */ new Map(),
424
+ sharedImporters: []
425
+ };
260
426
  }
261
- function calculatePythonCohesion(exports2, imports) {
262
- if (exports2.length === 0) return 1;
263
- const exportCount = exports2.length;
264
- const importCount = imports.length;
265
- let cohesion = 1;
266
- if (exportCount > 10) {
267
- cohesion *= 0.6;
268
- } else if (exportCount > 5) {
269
- cohesion *= 0.8;
427
+ var init_co_usage = __esm({
428
+ "src/semantic/co-usage.ts"() {
429
+ "use strict";
270
430
  }
271
- if (exportCount > 0) {
272
- const ratio = importCount / exportCount;
273
- if (ratio > 2) {
274
- cohesion *= 1.1;
275
- } else if (ratio < 0.5) {
276
- cohesion *= 0.9;
431
+ });
432
+
433
+ // src/semantic/type-graph.ts
434
+ function buildTypeGraph(graph) {
435
+ const typeGraph = /* @__PURE__ */ new Map();
436
+ for (const [file, node] of graph.nodes) {
437
+ for (const exp of node.exports) {
438
+ if (exp.typeReferences) {
439
+ for (const typeRef of exp.typeReferences) {
440
+ if (!typeGraph.has(typeRef)) typeGraph.set(typeRef, /* @__PURE__ */ new Set());
441
+ typeGraph.get(typeRef).add(file);
442
+ }
443
+ }
277
444
  }
278
445
  }
279
- return Math.min(1, Math.max(0, cohesion));
446
+ return typeGraph;
280
447
  }
281
- var import_core5, import_path2, import_fs;
282
- var init_python_context = __esm({
283
- "src/analyzers/python-context.ts"() {
448
+ var init_type_graph = __esm({
449
+ "src/semantic/type-graph.ts"() {
284
450
  "use strict";
285
- import_core5 = require("@aiready/core");
286
- import_path2 = require("path");
287
- import_fs = __toESM(require("fs"));
288
- init_dependency_graph_utils();
289
451
  }
290
452
  });
291
453
 
292
- // src/index.ts
293
- var index_exports = {};
294
- __export(index_exports, {
295
- BARREL_EXPORT_MIN_EXPORTS: () => BARREL_EXPORT_MIN_EXPORTS,
296
- BARREL_EXPORT_TOKEN_LIMIT: () => BARREL_EXPORT_TOKEN_LIMIT,
297
- CONFIG_NAME_PATTERNS: () => CONFIG_NAME_PATTERNS,
298
- Classification: () => Classification,
299
- ContextAnalyzerProvider: () => ContextAnalyzerProvider,
300
- EMAIL_NAME_PATTERNS: () => EMAIL_NAME_PATTERNS,
301
- HANDLER_NAME_PATTERNS: () => HANDLER_NAME_PATTERNS,
302
- NEXTJS_METADATA_EXPORTS: () => NEXTJS_METADATA_EXPORTS,
303
- PARSER_NAME_PATTERNS: () => PARSER_NAME_PATTERNS,
304
- SERVICE_NAME_PATTERNS: () => SERVICE_NAME_PATTERNS,
305
- SESSION_NAME_PATTERNS: () => SESSION_NAME_PATTERNS,
306
- adjustCohesionForClassification: () => adjustCohesionForClassification,
307
- adjustFragmentationForClassification: () => adjustFragmentationForClassification,
308
- analyzeContext: () => analyzeContext,
309
- buildCoUsageMatrix: () => buildCoUsageMatrix,
310
- buildDependencyGraph: () => buildDependencyGraph,
311
- buildTypeGraph: () => buildTypeGraph,
312
- calculateCohesion: () => calculateCohesion,
313
- calculateContextBudget: () => calculateContextBudget,
314
- calculateContextScore: () => calculateContextScore,
315
- calculateDirectoryDistance: () => calculateDirectoryDistance,
316
- calculateDomainConfidence: () => calculateDomainConfidence,
317
- calculateEnhancedCohesion: () => calculateEnhancedCohesion,
318
- calculateFragmentation: () => calculateFragmentation,
319
- calculateImportDepth: () => calculateImportDepth,
320
- calculatePathEntropy: () => calculatePathEntropy,
321
- calculateStructuralCohesionFromCoUsage: () => calculateStructuralCohesionFromCoUsage,
322
- classifyFile: () => classifyFile,
323
- detectCircularDependencies: () => detectCircularDependencies,
324
- detectModuleClusters: () => detectModuleClusters,
325
- displayConsoleReport: () => displayConsoleReport,
326
- extractDomainKeywordsFromPaths: () => extractDomainKeywordsFromPaths,
327
- extractExports: () => extractExports,
328
- findConsolidationCandidates: () => findConsolidationCandidates,
329
- findSemanticClusters: () => findSemanticClusters,
330
- generateHTMLReport: () => generateHTMLReport,
331
- generateSummary: () => generateSummary,
332
- getClassificationRecommendations: () => getClassificationRecommendations,
333
- getCoUsageData: () => getCoUsageData,
334
- getGeneralRecommendations: () => getGeneralRecommendations,
335
- getSmartDefaults: () => getSmartDefaults,
336
- getTransitiveDependencies: () => getTransitiveDependencies,
337
- inferDomain: () => inferDomain,
338
- inferDomainFromSemantics: () => inferDomainFromSemantics,
339
- isBarrelExport: () => isBarrelExport,
340
- isBoilerplateBarrel: () => isBoilerplateBarrel,
341
- isConfigFile: () => isConfigFile,
342
- isEmailTemplate: () => isEmailTemplate,
343
- isHubAndSpokeFile: () => isHubAndSpokeFile,
344
- isLambdaHandler: () => isLambdaHandler,
345
- isNextJsPage: () => isNextJsPage,
346
- isParserFile: () => isParserFile,
347
- isServiceFile: () => isServiceFile,
348
- isSessionFile: () => isSessionFile,
349
- isTypeDefinition: () => isTypeDefinition,
350
- isUtilityModule: () => isUtilityModule,
351
- mapScoreToRating: () => mapScoreToRating,
352
- runInteractiveSetup: () => runInteractiveSetup
353
- });
354
- module.exports = __toCommonJS(index_exports);
355
- var import_core12 = require("@aiready/core");
356
-
357
- // src/provider.ts
358
- var import_core9 = require("@aiready/core");
359
-
360
- // src/orchestrator.ts
361
- var import_core6 = require("@aiready/core");
362
-
363
- // src/metrics.ts
364
- var import_core2 = require("@aiready/core");
365
-
366
- // src/ast-utils.ts
367
- var import_core = require("@aiready/core");
368
-
369
- // src/utils/string-utils.ts
370
- function singularize(word) {
371
- const irregulars = {
372
- people: "person",
373
- children: "child",
374
- men: "man",
375
- women: "woman"
376
- };
377
- if (irregulars[word]) return irregulars[word];
378
- if (word.endsWith("ies")) return word.slice(0, -3) + "y";
379
- if (word.endsWith("ses")) return word.slice(0, -2);
380
- if (word.endsWith("s") && word.length > 3) return word.slice(0, -1);
381
- return word;
382
- }
383
-
384
454
  // src/semantic/domain-inference.ts
385
455
  function calculateDomainConfidence(signals) {
386
456
  const weights = {
@@ -544,337 +614,53 @@ function inferDomain(name, filePath, domainOptions, fileImports) {
544
614
  const segLower = segment.toLowerCase();
545
615
  const singularSegment = singularize(segLower);
546
616
  for (const keyword of domainKeywords) {
547
- if (singularSegment === keyword || segLower === keyword) return keyword;
548
- }
549
- }
550
- }
551
- return "unknown";
552
- }
553
-
554
- // src/ast-utils.ts
555
- async function extractExportsWithAST(content, filePath, domainOptions, fileImports) {
556
- try {
557
- const { exports: astExports } = await (0, import_core.parseFileExports)(content, filePath);
558
- if (astExports.length === 0 && !isTestFile(filePath)) {
559
- return extractExports(content, filePath, domainOptions, fileImports);
560
- }
561
- return astExports.map((exp) => ({
562
- name: exp.name,
563
- type: exp.type,
564
- inferredDomain: inferDomain(
565
- exp.name,
566
- filePath,
567
- domainOptions,
568
- fileImports
569
- ),
570
- imports: exp.imports,
571
- dependencies: exp.dependencies,
572
- typeReferences: exp.typeReferences
573
- }));
574
- } catch {
575
- return extractExports(content, filePath, domainOptions, fileImports);
576
- }
577
- }
578
- function isTestFile(filePath) {
579
- const lower = filePath.toLowerCase();
580
- return lower.includes(".test.") || lower.includes(".spec.") || lower.includes("/__tests__/") || lower.includes("/tests/") || lower.includes("/test/") || lower.includes("test-") || lower.includes("-test") || lower.includes("/__mocks__/") || lower.includes("/mocks/") || lower.includes("/fixtures/") || lower.includes(".mock.") || lower.includes(".fixture.") || lower.includes("/test-utils/");
581
- }
582
-
583
- // src/metrics.ts
584
- function calculateEnhancedCohesion(exports2, filePath, options) {
585
- if (exports2.length <= 1) return 1;
586
- if (filePath && isTestFile(filePath)) return 1;
587
- const domains = exports2.map((e) => e.inferredDomain || "unknown");
588
- const domainCounts = /* @__PURE__ */ new Map();
589
- for (const domain of domains)
590
- domainCounts.set(domain, (domainCounts.get(domain) || 0) + 1);
591
- if (domainCounts.size === 1 && domains[0] !== "unknown") {
592
- if (!options?.weights) return 1;
593
- }
594
- const probs = Array.from(domainCounts.values()).map(
595
- (count) => count / exports2.length
596
- );
597
- let domainEntropy = 0;
598
- for (const prob of probs) {
599
- if (prob > 0) domainEntropy -= prob * Math.log2(prob);
600
- }
601
- const maxEntropy = Math.log2(Math.max(2, domainCounts.size));
602
- const domainScore = 1 - domainEntropy / maxEntropy;
603
- let importScoreTotal = 0;
604
- let pairsWithData = 0;
605
- let anyImportData = false;
606
- for (let i = 0; i < exports2.length; i++) {
607
- for (let j = i + 1; j < exports2.length; j++) {
608
- const exp1Imports = exports2[i].imports;
609
- const exp2Imports = exports2[j].imports;
610
- if (exp1Imports || exp2Imports) {
611
- anyImportData = true;
612
- const sim = (0, import_core2.calculateImportSimilarity)(
613
- { ...exports2[i], imports: exp1Imports || [] },
614
- { ...exports2[j], imports: exp2Imports || [] }
615
- );
616
- importScoreTotal += sim;
617
- pairsWithData++;
618
- }
619
- }
620
- }
621
- const avgImportScore = pairsWithData > 0 ? importScoreTotal / pairsWithData : 0;
622
- let score = anyImportData ? domainScore * 0.4 + avgImportScore * 0.6 : domainScore;
623
- if (anyImportData && score === 0 && domainScore === 0) {
624
- score = 0.1;
625
- }
626
- let structuralScore = 0;
627
- for (const exp of exports2) {
628
- if (exp.dependencies && exp.dependencies.length > 0) {
629
- structuralScore += 1;
630
- }
631
- }
632
- if (structuralScore > 0) {
633
- score = Math.min(1, score + 0.1);
634
- }
635
- if (!options?.weights && !anyImportData && domainCounts.size === 1) return 1;
636
- return score;
637
- }
638
- function calculateStructuralCohesionFromCoUsage(file, coUsageMatrix) {
639
- if (!coUsageMatrix) return 1;
640
- const coUsages = coUsageMatrix.get(file);
641
- if (!coUsages || coUsages.size === 0) return 1;
642
- let total = 0;
643
- for (const count of coUsages.values()) total += count;
644
- if (total === 0) return 1;
645
- const probs = [];
646
- for (const count of coUsages.values()) {
647
- if (count > 0) probs.push(count / total);
648
- }
649
- if (probs.length <= 1) return 1;
650
- let entropy = 0;
651
- for (const prob of probs) {
652
- entropy -= prob * Math.log2(prob);
653
- }
654
- const maxEntropy = Math.log2(probs.length);
655
- return maxEntropy > 0 ? 1 - entropy / maxEntropy : 1;
656
- }
657
- function calculateFragmentation(files, domain, options) {
658
- if (files.length <= 1) return 0;
659
- const directories = new Set(
660
- files.map((file) => file.split("/").slice(0, -1).join("/"))
661
- );
662
- const uniqueDirs = directories.size;
663
- let score = options?.useLogScale ? uniqueDirs <= 1 ? 0 : Math.log(uniqueDirs) / Math.log(options.logBase || Math.E) / (Math.log(files.length) / Math.log(options.logBase || Math.E)) : (uniqueDirs - 1) / (files.length - 1);
664
- if (options?.sharedImportRatio && options.sharedImportRatio > 0.5) {
665
- const discount = (options.sharedImportRatio - 0.5) * 0.4;
666
- score = score * (1 - discount);
667
- }
668
- return score;
669
- }
670
- function calculatePathEntropy(files) {
671
- if (!files || files.length === 0) return 0;
672
- const dirCounts = /* @__PURE__ */ new Map();
673
- for (const file of files) {
674
- const dir = file.split("/").slice(0, -1).join("/") || ".";
675
- dirCounts.set(dir, (dirCounts.get(dir) || 0) + 1);
676
- }
677
- const counts = Array.from(dirCounts.values());
678
- if (counts.length <= 1) return 0;
679
- const total = counts.reduce((sum, value) => sum + value, 0);
680
- let entropy = 0;
681
- for (const count of counts) {
682
- const prob = count / total;
683
- entropy -= prob * Math.log2(prob);
684
- }
685
- const maxEntropy = Math.log2(counts.length);
686
- return maxEntropy > 0 ? entropy / maxEntropy : 0;
687
- }
688
- function calculateDirectoryDistance(files) {
689
- if (!files || files.length <= 1) return 0;
690
- const pathSegments = (pathStr) => pathStr.split("/").filter(Boolean);
691
- const commonAncestorDepth = (pathA, pathB) => {
692
- const minLen = Math.min(pathA.length, pathB.length);
693
- let i = 0;
694
- while (i < minLen && pathA[i] === pathB[i]) i++;
695
- return i;
696
- };
697
- let totalNormalized = 0;
698
- let comparisons = 0;
699
- for (let i = 0; i < files.length; i++) {
700
- for (let j = i + 1; j < files.length; j++) {
701
- const segA = pathSegments(files[i]);
702
- const segB = pathSegments(files[j]);
703
- const shared = commonAncestorDepth(segA, segB);
704
- const maxDepth = Math.max(segA.length, segB.length);
705
- totalNormalized += 1 - (maxDepth > 0 ? shared / maxDepth : 0);
706
- comparisons++;
707
- }
708
- }
709
- return comparisons > 0 ? totalNormalized / comparisons : 0;
710
- }
711
-
712
- // src/issue-analyzer.ts
713
- var import_core3 = require("@aiready/core");
714
- function analyzeIssues(params) {
715
- const {
716
- file,
717
- importDepth,
718
- contextBudget,
719
- cohesionScore,
720
- fragmentationScore,
721
- maxDepth,
722
- maxContextBudget,
723
- minCohesion,
724
- maxFragmentation,
725
- circularDeps
726
- } = params;
727
- const issues = [];
728
- const recommendations = [];
729
- let severity = import_core3.Severity.Info;
730
- let potentialSavings = 0;
731
- if (circularDeps.length > 0) {
732
- severity = import_core3.Severity.Critical;
733
- issues.push(`Part of ${circularDeps.length} circular dependency chain(s)`);
734
- recommendations.push(
735
- "Break circular dependencies by extracting interfaces or using dependency injection"
736
- );
737
- potentialSavings += contextBudget * 0.2;
738
- }
739
- if (importDepth > maxDepth * 1.5) {
740
- severity = import_core3.Severity.Critical;
741
- issues.push(`Import depth ${importDepth} exceeds limit by 50%`);
742
- recommendations.push("Flatten dependency tree or use facade pattern");
743
- potentialSavings += contextBudget * 0.3;
744
- } else if (importDepth > maxDepth) {
745
- if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
746
- issues.push(
747
- `Import depth ${importDepth} exceeds recommended maximum ${maxDepth}`
748
- );
749
- recommendations.push("Consider reducing dependency depth");
750
- potentialSavings += contextBudget * 0.15;
751
- }
752
- if (contextBudget > maxContextBudget * 1.5) {
753
- severity = import_core3.Severity.Critical;
754
- issues.push(
755
- `Context budget ${contextBudget.toLocaleString()} tokens is 50% over limit`
756
- );
757
- recommendations.push(
758
- "Split into smaller modules or reduce dependency tree"
759
- );
760
- potentialSavings += contextBudget * 0.4;
761
- } else if (contextBudget > maxContextBudget) {
762
- if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
763
- issues.push(
764
- `Context budget ${contextBudget.toLocaleString()} exceeds ${maxContextBudget.toLocaleString()}`
765
- );
766
- recommendations.push("Reduce file size or dependencies");
767
- potentialSavings += contextBudget * 0.2;
768
- }
769
- if (cohesionScore < minCohesion * 0.5) {
770
- if (severity !== import_core3.Severity.Critical) severity = import_core3.Severity.Major;
771
- issues.push(
772
- `Very low cohesion (${(cohesionScore * 100).toFixed(0)}%) - mixed concerns`
773
- );
774
- recommendations.push(
775
- "Split file by domain - separate unrelated functionality"
776
- );
777
- potentialSavings += contextBudget * 0.25;
778
- } else if (cohesionScore < minCohesion) {
779
- if (severity === import_core3.Severity.Info) severity = import_core3.Severity.Minor;
780
- issues.push(`Low cohesion (${(cohesionScore * 100).toFixed(0)}%)`);
781
- recommendations.push("Consider grouping related exports together");
782
- potentialSavings += contextBudget * 0.1;
783
- }
784
- if (fragmentationScore > maxFragmentation) {
785
- if (severity === import_core3.Severity.Info || severity === import_core3.Severity.Minor)
786
- severity = import_core3.Severity.Minor;
787
- issues.push(
788
- `High fragmentation (${(fragmentationScore * 100).toFixed(0)}%) - scattered implementation`
789
- );
790
- recommendations.push("Consolidate with related files in same domain");
791
- potentialSavings += contextBudget * 0.3;
792
- }
793
- if (isBuildArtifact(file)) {
794
- issues.push("Detected build artifact (bundled/output file)");
795
- recommendations.push("Exclude build outputs from analysis");
796
- severity = import_core3.Severity.Info;
797
- potentialSavings = 0;
798
- }
799
- return {
800
- severity,
801
- issues,
802
- recommendations,
803
- potentialSavings: Math.floor(potentialSavings)
804
- };
805
- }
806
- function isBuildArtifact(filePath) {
807
- const lower = filePath.toLowerCase();
808
- return lower.includes("/node_modules/") || lower.includes("/dist/") || lower.includes("/build/") || lower.includes("/out/") || lower.includes("/.next/");
809
- }
810
-
811
- // src/graph-builder.ts
812
- var import_core4 = require("@aiready/core");
813
- init_dependency_graph_utils();
814
-
815
- // src/semantic/co-usage.ts
816
- function buildCoUsageMatrix(graph) {
817
- const coUsageMatrix = /* @__PURE__ */ new Map();
818
- for (const [, node] of graph.nodes) {
819
- const imports = node.imports;
820
- for (let i = 0; i < imports.length; i++) {
821
- const fileA = imports[i];
822
- if (!coUsageMatrix.has(fileA)) coUsageMatrix.set(fileA, /* @__PURE__ */ new Map());
823
- for (let j = i + 1; j < imports.length; j++) {
824
- const fileB = imports[j];
825
- const fileAUsage = coUsageMatrix.get(fileA);
826
- fileAUsage.set(fileB, (fileAUsage.get(fileB) || 0) + 1);
827
- if (!coUsageMatrix.has(fileB)) coUsageMatrix.set(fileB, /* @__PURE__ */ new Map());
828
- const fileBUsage = coUsageMatrix.get(fileB);
829
- fileBUsage.set(fileA, (fileBUsage.get(fileA) || 0) + 1);
617
+ if (singularSegment === keyword || segLower === keyword) return keyword;
830
618
  }
831
619
  }
832
620
  }
833
- return coUsageMatrix;
621
+ return "unknown";
834
622
  }
835
- function findSemanticClusters(coUsageMatrix, minCoUsage = 3) {
836
- const clusters = /* @__PURE__ */ new Map();
837
- const visited = /* @__PURE__ */ new Set();
838
- for (const [file, coUsages] of coUsageMatrix) {
839
- if (visited.has(file)) continue;
840
- const cluster = [file];
841
- visited.add(file);
842
- for (const [relatedFile, count] of coUsages) {
843
- if (count >= minCoUsage && !visited.has(relatedFile)) {
844
- cluster.push(relatedFile);
845
- visited.add(relatedFile);
846
- }
847
- }
848
- if (cluster.length > 1) clusters.set(file, cluster);
623
+ var init_domain_inference = __esm({
624
+ "src/semantic/domain-inference.ts"() {
625
+ "use strict";
626
+ init_string_utils();
849
627
  }
850
- return clusters;
851
- }
852
- function getCoUsageData(file, coUsageMatrix) {
853
- return {
854
- file,
855
- coImportedWith: coUsageMatrix.get(file) || /* @__PURE__ */ new Map(),
856
- sharedImporters: []
857
- };
858
- }
628
+ });
859
629
 
860
- // src/semantic/type-graph.ts
861
- function buildTypeGraph(graph) {
862
- const typeGraph = /* @__PURE__ */ new Map();
863
- for (const [file, node] of graph.nodes) {
864
- for (const exp of node.exports) {
865
- if (exp.typeReferences) {
866
- for (const typeRef of exp.typeReferences) {
867
- if (!typeGraph.has(typeRef)) typeGraph.set(typeRef, /* @__PURE__ */ new Set());
868
- typeGraph.get(typeRef).add(file);
869
- }
870
- }
630
+ // src/ast-utils.ts
631
+ async function extractExportsWithAST(content, filePath, domainOptions, fileImports) {
632
+ try {
633
+ const { exports: astExports } = await (0, import_core4.parseFileExports)(content, filePath);
634
+ if (astExports.length === 0 && !(0, import_core4.isTestFile)(filePath)) {
635
+ return extractExports(content, filePath, domainOptions, fileImports);
871
636
  }
637
+ return astExports.map((exp) => ({
638
+ name: exp.name,
639
+ type: exp.type,
640
+ inferredDomain: inferDomain(
641
+ exp.name,
642
+ filePath,
643
+ domainOptions,
644
+ fileImports
645
+ ),
646
+ imports: exp.imports,
647
+ dependencies: exp.dependencies,
648
+ typeReferences: exp.typeReferences
649
+ }));
650
+ } catch {
651
+ return extractExports(content, filePath, domainOptions, fileImports);
872
652
  }
873
- return typeGraph;
874
653
  }
654
+ var import_core4;
655
+ var init_ast_utils = __esm({
656
+ "src/ast-utils.ts"() {
657
+ "use strict";
658
+ import_core4 = require("@aiready/core");
659
+ init_domain_inference();
660
+ }
661
+ });
875
662
 
876
663
  // src/graph-builder.ts
877
- var import_path = require("path");
878
664
  function resolveImport(source, importingFile, allFiles) {
879
665
  if (!source.startsWith(".") && !source.startsWith("/")) {
880
666
  if (source.startsWith("@aiready/")) {
@@ -954,7 +740,7 @@ async function buildDependencyGraph(files, options) {
954
740
  const autoDetectedKeywords = options?.domainKeywords ?? extractDomainKeywordsFromPaths(files);
955
741
  const allFilePaths = new Set(files.map((f) => f.file));
956
742
  for (const { file, content } of files) {
957
- const { imports: astImports } = await (0, import_core4.parseFileExports)(content, file);
743
+ const { imports: astImports } = await (0, import_core5.parseFileExports)(content, file);
958
744
  const resolvedImports = astImports.map((i) => resolveImport(i.source, file, allFilePaths)).filter((path) => path !== null);
959
745
  const importSources = astImports.map((i) => i.source);
960
746
  const exports2 = await extractExportsWithAST(
@@ -963,7 +749,7 @@ async function buildDependencyGraph(files, options) {
963
749
  { domainKeywords: autoDetectedKeywords },
964
750
  importSources
965
751
  );
966
- const tokenCost = (0, import_core4.estimateTokens)(content);
752
+ const tokenCost = (0, import_core5.estimateTokens)(content);
967
753
  const linesOfCode = content.split("\n").length;
968
754
  nodes.set(file, {
969
755
  file,
@@ -1019,61 +805,81 @@ function calculateContextBudget(file, graph) {
1019
805
  function detectCircularDependencies(graph) {
1020
806
  return detectGraphCycles(graph.edges);
1021
807
  }
808
+ var import_core5, import_path;
809
+ var init_graph_builder = __esm({
810
+ "src/graph-builder.ts"() {
811
+ "use strict";
812
+ import_core5 = require("@aiready/core");
813
+ init_string_utils();
814
+ init_dependency_graph_utils();
815
+ init_co_usage();
816
+ init_type_graph();
817
+ init_domain_inference();
818
+ init_ast_utils();
819
+ import_path = require("path");
820
+ }
821
+ });
1022
822
 
1023
823
  // src/classify/classification-patterns.ts
1024
- var BARREL_EXPORT_MIN_EXPORTS = 5;
1025
- var BARREL_EXPORT_TOKEN_LIMIT = 1e3;
1026
- var HANDLER_NAME_PATTERNS = [
1027
- "handler",
1028
- ".handler.",
1029
- "-handler.",
1030
- "lambda",
1031
- ".lambda.",
1032
- "-lambda."
1033
- ];
1034
- var SERVICE_NAME_PATTERNS = [
1035
- "service",
1036
- ".service.",
1037
- "-service.",
1038
- "_service."
1039
- ];
1040
- var EMAIL_NAME_PATTERNS = [
1041
- "-email-",
1042
- ".email.",
1043
- "_email_",
1044
- "-template",
1045
- ".template.",
1046
- "_template",
1047
- "-mail.",
1048
- ".mail."
1049
- ];
1050
- var PARSER_NAME_PATTERNS = [
1051
- "parser",
1052
- ".parser.",
1053
- "-parser.",
1054
- "_parser.",
1055
- "transform",
1056
- "converter",
1057
- "mapper",
1058
- "serializer"
1059
- ];
1060
- var SESSION_NAME_PATTERNS = ["session", "state", "context", "store"];
1061
- var NEXTJS_METADATA_EXPORTS = [
1062
- "metadata",
1063
- "generatemetadata",
1064
- "faqjsonld",
1065
- "jsonld",
1066
- "icon"
1067
- ];
1068
- var CONFIG_NAME_PATTERNS = [
1069
- ".config.",
1070
- "tsconfig",
1071
- "jest.config",
1072
- "package.json",
1073
- "aiready.json",
1074
- "next.config",
1075
- "sst.config"
1076
- ];
824
+ var BARREL_EXPORT_MIN_EXPORTS, BARREL_EXPORT_TOKEN_LIMIT, HANDLER_NAME_PATTERNS, SERVICE_NAME_PATTERNS, EMAIL_NAME_PATTERNS, PARSER_NAME_PATTERNS, SESSION_NAME_PATTERNS, NEXTJS_METADATA_EXPORTS, CONFIG_NAME_PATTERNS;
825
+ var init_classification_patterns = __esm({
826
+ "src/classify/classification-patterns.ts"() {
827
+ "use strict";
828
+ BARREL_EXPORT_MIN_EXPORTS = 5;
829
+ BARREL_EXPORT_TOKEN_LIMIT = 1e3;
830
+ HANDLER_NAME_PATTERNS = [
831
+ "handler",
832
+ ".handler.",
833
+ "-handler.",
834
+ "lambda",
835
+ ".lambda.",
836
+ "-lambda."
837
+ ];
838
+ SERVICE_NAME_PATTERNS = [
839
+ "service",
840
+ ".service.",
841
+ "-service.",
842
+ "_service."
843
+ ];
844
+ EMAIL_NAME_PATTERNS = [
845
+ "-email-",
846
+ ".email.",
847
+ "_email_",
848
+ "-template",
849
+ ".template.",
850
+ "_template",
851
+ "-mail.",
852
+ ".mail."
853
+ ];
854
+ PARSER_NAME_PATTERNS = [
855
+ "parser",
856
+ ".parser.",
857
+ "-parser.",
858
+ "_parser.",
859
+ "transform",
860
+ "converter",
861
+ "mapper",
862
+ "serializer"
863
+ ];
864
+ SESSION_NAME_PATTERNS = ["session", "state", "context", "store"];
865
+ NEXTJS_METADATA_EXPORTS = [
866
+ "metadata",
867
+ "generatemetadata",
868
+ "faqjsonld",
869
+ "jsonld",
870
+ "icon"
871
+ ];
872
+ CONFIG_NAME_PATTERNS = [
873
+ ".config.",
874
+ "tsconfig",
875
+ "jest.config",
876
+ "package.json",
877
+ "aiready.json",
878
+ "next.config",
879
+ "sst.config"
880
+ ];
881
+ }
882
+ });
1077
883
 
1078
884
  // src/classify/file-classifiers.ts
1079
885
  function isBoilerplateBarrel(node) {
@@ -1215,23 +1021,14 @@ function isHubAndSpokeFile(node) {
1215
1021
  const { file } = node;
1216
1022
  return /\/packages\/[a-zA-Z0-9-]+\/src\//.test(file);
1217
1023
  }
1024
+ var init_file_classifiers = __esm({
1025
+ "src/classify/file-classifiers.ts"() {
1026
+ "use strict";
1027
+ init_classification_patterns();
1028
+ }
1029
+ });
1218
1030
 
1219
1031
  // src/classifier.ts
1220
- var Classification = {
1221
- BARREL: "barrel-export",
1222
- BOILERPLATE: "boilerplate-barrel",
1223
- TYPE_DEFINITION: "type-definition",
1224
- NEXTJS_PAGE: "nextjs-page",
1225
- LAMBDA_HANDLER: "lambda-handler",
1226
- SERVICE: "service-file",
1227
- EMAIL_TEMPLATE: "email-template",
1228
- PARSER: "parser-file",
1229
- COHESIVE_MODULE: "cohesive-module",
1230
- UTILITY_MODULE: "utility-module",
1231
- SPOKE_MODULE: "spoke-module",
1232
- MIXED_CONCERNS: "mixed-concerns",
1233
- UNKNOWN: "unknown"
1234
- };
1235
1032
  function classifyFile(node, cohesionScore = 1, domains = []) {
1236
1033
  if (isBoilerplateBarrel(node)) {
1237
1034
  return Classification.BOILERPLATE;
@@ -1387,6 +1184,28 @@ function adjustFragmentationForClassification(baseFragmentation, classification)
1387
1184
  return baseFragmentation * 0.7;
1388
1185
  }
1389
1186
  }
1187
+ var Classification;
1188
+ var init_classifier = __esm({
1189
+ "src/classifier.ts"() {
1190
+ "use strict";
1191
+ init_file_classifiers();
1192
+ Classification = {
1193
+ BARREL: "barrel-export",
1194
+ BOILERPLATE: "boilerplate-barrel",
1195
+ TYPE_DEFINITION: "type-definition",
1196
+ NEXTJS_PAGE: "nextjs-page",
1197
+ LAMBDA_HANDLER: "lambda-handler",
1198
+ SERVICE: "service-file",
1199
+ EMAIL_TEMPLATE: "email-template",
1200
+ PARSER: "parser-file",
1201
+ COHESIVE_MODULE: "cohesive-module",
1202
+ UTILITY_MODULE: "utility-module",
1203
+ SPOKE_MODULE: "spoke-module",
1204
+ MIXED_CONCERNS: "mixed-concerns",
1205
+ UNKNOWN: "unknown"
1206
+ };
1207
+ }
1208
+ });
1390
1209
 
1391
1210
  // src/cluster-detector.ts
1392
1211
  function detectModuleClusters(graph, options) {
@@ -1469,6 +1288,13 @@ function detectModuleClusters(graph, options) {
1469
1288
  }
1470
1289
  return clusters;
1471
1290
  }
1291
+ var init_cluster_detector = __esm({
1292
+ "src/cluster-detector.ts"() {
1293
+ "use strict";
1294
+ init_metrics();
1295
+ init_classifier();
1296
+ }
1297
+ });
1472
1298
 
1473
1299
  // src/remediation.ts
1474
1300
  function getClassificationRecommendations(classification, file, issues) {
@@ -1573,91 +1399,277 @@ function getGeneralRecommendations(metrics, thresholds) {
1573
1399
  );
1574
1400
  if (severity === "info") severity = "minor";
1575
1401
  }
1576
- if (metrics.fragmentationScore > thresholds.maxFragmentation) {
1577
- issues.push(
1578
- `High domain fragmentation: ${metrics.fragmentationScore.toFixed(2)}`
1579
- );
1580
- recommendations.push(
1581
- "Consolidate domain-related files into fewer directories"
1582
- );
1583
- if (severity === "info") severity = "minor";
1402
+ if (metrics.fragmentationScore > thresholds.maxFragmentation) {
1403
+ issues.push(
1404
+ `High domain fragmentation: ${metrics.fragmentationScore.toFixed(2)}`
1405
+ );
1406
+ recommendations.push(
1407
+ "Consolidate domain-related files into fewer directories"
1408
+ );
1409
+ if (severity === "info") severity = "minor";
1410
+ }
1411
+ return { recommendations, issues, severity };
1412
+ }
1413
+ var init_remediation = __esm({
1414
+ "src/remediation.ts"() {
1415
+ "use strict";
1416
+ }
1417
+ });
1418
+
1419
+ // src/mapper.ts
1420
+ function mapNodeToResult(node, graph, clusters, allCircularDeps, options) {
1421
+ const file = node.file;
1422
+ const tokenCost = node.tokenCost;
1423
+ const importDepth = calculateImportDepth(file, graph);
1424
+ const transitiveDeps = getTransitiveDependencies(file, graph);
1425
+ const contextBudget = calculateContextBudget(file, graph);
1426
+ const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
1427
+ const cluster = clusters.find((c) => c.files.includes(file));
1428
+ const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
1429
+ const rawCohesionScore = calculateEnhancedCohesion(
1430
+ node.exports,
1431
+ file,
1432
+ options
1433
+ );
1434
+ const fileClassification = classifyFile(node, rawCohesionScore);
1435
+ const cohesionScore = adjustCohesionForClassification(
1436
+ rawCohesionScore,
1437
+ fileClassification
1438
+ );
1439
+ const fragmentationScore = adjustFragmentationForClassification(
1440
+ rawFragmentationScore,
1441
+ fileClassification
1442
+ );
1443
+ const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
1444
+ {
1445
+ file,
1446
+ importDepth,
1447
+ contextBudget,
1448
+ cohesionScore,
1449
+ fragmentationScore,
1450
+ maxDepth: options.maxDepth,
1451
+ maxContextBudget: options.maxContextBudget,
1452
+ minCohesion: options.minCohesion,
1453
+ maxFragmentation: options.maxFragmentation,
1454
+ circularDeps
1455
+ }
1456
+ );
1457
+ const classRecs = getClassificationRecommendations(
1458
+ fileClassification,
1459
+ file,
1460
+ issues
1461
+ );
1462
+ const allRecommendations = Array.from(
1463
+ /* @__PURE__ */ new Set([...recommendations, ...classRecs])
1464
+ );
1465
+ return {
1466
+ file,
1467
+ tokenCost,
1468
+ linesOfCode: node.linesOfCode,
1469
+ importDepth,
1470
+ dependencyCount: transitiveDeps.length,
1471
+ dependencyList: transitiveDeps,
1472
+ circularDeps,
1473
+ cohesionScore,
1474
+ domains: Array.from(
1475
+ new Set(
1476
+ node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
1477
+ )
1478
+ ),
1479
+ exportCount: node.exports.length,
1480
+ contextBudget,
1481
+ fragmentationScore,
1482
+ relatedFiles: cluster ? cluster.files : [],
1483
+ fileClassification,
1484
+ severity,
1485
+ issues,
1486
+ recommendations: allRecommendations,
1487
+ potentialSavings
1488
+ };
1489
+ }
1490
+ var init_mapper = __esm({
1491
+ "src/mapper.ts"() {
1492
+ "use strict";
1493
+ init_metrics();
1494
+ init_issue_analyzer();
1495
+ init_graph_builder();
1496
+ init_classifier();
1497
+ init_remediation();
1498
+ }
1499
+ });
1500
+
1501
+ // src/analyzers/python-context.ts
1502
+ var python_context_exports = {};
1503
+ __export(python_context_exports, {
1504
+ analyzePythonContext: () => analyzePythonContext
1505
+ });
1506
+ async function analyzePythonContext(files, rootDir) {
1507
+ const results = [];
1508
+ const parser = await (0, import_core6.getParser)("dummy.py");
1509
+ if (!parser) {
1510
+ console.warn("Python parser not available");
1511
+ return results;
1512
+ }
1513
+ const pythonFiles = files.filter((f) => f.toLowerCase().endsWith(".py"));
1514
+ void import_path2.relative;
1515
+ void import_path2.join;
1516
+ const dependencyGraph = await buildPythonDependencyGraph(
1517
+ pythonFiles,
1518
+ rootDir
1519
+ );
1520
+ for (const file of pythonFiles) {
1521
+ try {
1522
+ const code = await import_fs.default.promises.readFile(file, "utf-8");
1523
+ const result = parser.parse(code, file);
1524
+ const imports = result.imports.map((imp) => ({
1525
+ source: imp.source,
1526
+ specifiers: imp.specifiers,
1527
+ isRelative: imp.source.startsWith("."),
1528
+ resolvedPath: resolvePythonImport(file, imp.source, rootDir)
1529
+ }));
1530
+ const exports2 = result.exports.map((exp) => ({
1531
+ name: exp.name,
1532
+ type: exp.type
1533
+ }));
1534
+ const linesOfCode = code.split("\n").length;
1535
+ const importDepth = calculateImportDepthFromEdges(
1536
+ file,
1537
+ dependencyGraph,
1538
+ /* @__PURE__ */ new Set()
1539
+ );
1540
+ const contextBudget = estimateContextBudget(
1541
+ code,
1542
+ imports,
1543
+ dependencyGraph
1544
+ );
1545
+ const cohesion = calculatePythonCohesion(exports2, imports);
1546
+ const circularDependencies = detectGraphCyclesFromFile(
1547
+ file,
1548
+ dependencyGraph
1549
+ ).map((cycle) => cycle.join(" -> "));
1550
+ results.push({
1551
+ file,
1552
+ importDepth,
1553
+ contextBudget,
1554
+ cohesion,
1555
+ imports,
1556
+ exports: exports2,
1557
+ metrics: {
1558
+ linesOfCode,
1559
+ importCount: imports.length,
1560
+ exportCount: exports2.length,
1561
+ circularDependencies
1562
+ }
1563
+ });
1564
+ } catch (error) {
1565
+ console.warn(`Failed to analyze ${file}:`, error);
1566
+ }
1567
+ }
1568
+ return results;
1569
+ }
1570
+ async function buildPythonDependencyGraph(files, rootDir) {
1571
+ const graph = /* @__PURE__ */ new Map();
1572
+ const parser = await (0, import_core6.getParser)("dummy.py");
1573
+ if (!parser) return graph;
1574
+ for (const file of files) {
1575
+ try {
1576
+ const code = await import_fs.default.promises.readFile(file, "utf-8");
1577
+ const result = parser.parse(code, file);
1578
+ const dependencies = /* @__PURE__ */ new Set();
1579
+ for (const imp of result.imports) {
1580
+ const resolved = resolvePythonImport(file, imp.source, rootDir);
1581
+ if (resolved && files.includes(resolved)) {
1582
+ dependencies.add(resolved);
1583
+ }
1584
+ }
1585
+ graph.set(file, dependencies);
1586
+ } catch (error) {
1587
+ void error;
1588
+ }
1589
+ }
1590
+ return graph;
1591
+ }
1592
+ function resolvePythonImport(fromFile, importPath, rootDir) {
1593
+ const dir = (0, import_path2.dirname)(fromFile);
1594
+ if (importPath.startsWith(".")) {
1595
+ const parts = importPath.split(".");
1596
+ let upCount = 0;
1597
+ while (parts[0] === "") {
1598
+ upCount++;
1599
+ parts.shift();
1600
+ }
1601
+ let targetDir = dir;
1602
+ for (let i = 0; i < upCount - 1; i++) {
1603
+ targetDir = (0, import_path2.dirname)(targetDir);
1604
+ }
1605
+ const modulePath = parts.join("/");
1606
+ const possiblePaths = [
1607
+ (0, import_path2.resolve)(targetDir, `${modulePath}.py`),
1608
+ (0, import_path2.resolve)(targetDir, modulePath, "__init__.py")
1609
+ ];
1610
+ for (const path of possiblePaths) {
1611
+ if (import_fs.default.existsSync(path)) {
1612
+ return path;
1613
+ }
1614
+ }
1615
+ } else {
1616
+ const modulePath = importPath.replace(/\./g, "/");
1617
+ const possiblePaths = [
1618
+ (0, import_path2.resolve)(rootDir, `${modulePath}.py`),
1619
+ (0, import_path2.resolve)(rootDir, modulePath, "__init__.py")
1620
+ ];
1621
+ for (const path of possiblePaths) {
1622
+ if (import_fs.default.existsSync(path)) {
1623
+ return path;
1624
+ }
1625
+ }
1584
1626
  }
1585
- return { recommendations, issues, severity };
1627
+ return void 0;
1586
1628
  }
1587
-
1588
- // src/mapper.ts
1589
- function mapNodeToResult(node, graph, clusters, allCircularDeps, options) {
1590
- const file = node.file;
1591
- const tokenCost = node.tokenCost;
1592
- const importDepth = calculateImportDepth(file, graph);
1593
- const transitiveDeps = getTransitiveDependencies(file, graph);
1594
- const contextBudget = calculateContextBudget(file, graph);
1595
- const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
1596
- const cluster = clusters.find((c) => c.files.includes(file));
1597
- const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
1598
- const rawCohesionScore = calculateEnhancedCohesion(
1599
- node.exports,
1600
- file,
1601
- options
1602
- );
1603
- const fileClassification = classifyFile(node, rawCohesionScore);
1604
- const cohesionScore = adjustCohesionForClassification(
1605
- rawCohesionScore,
1606
- fileClassification
1607
- );
1608
- const fragmentationScore = adjustFragmentationForClassification(
1609
- rawFragmentationScore,
1610
- fileClassification
1611
- );
1612
- const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
1613
- {
1614
- file,
1615
- importDepth,
1616
- contextBudget,
1617
- cohesionScore,
1618
- fragmentationScore,
1619
- maxDepth: options.maxDepth,
1620
- maxContextBudget: options.maxContextBudget,
1621
- minCohesion: options.minCohesion,
1622
- maxFragmentation: options.maxFragmentation,
1623
- circularDeps
1629
+ function estimateContextBudget(code, imports, dependencyGraph) {
1630
+ void dependencyGraph;
1631
+ let budget = (0, import_core6.estimateTokens)(code);
1632
+ const avgTokensPerDep = 500;
1633
+ budget += imports.length * avgTokensPerDep;
1634
+ return budget;
1635
+ }
1636
+ function calculatePythonCohesion(exports2, imports) {
1637
+ if (exports2.length === 0) return 1;
1638
+ const exportCount = exports2.length;
1639
+ const importCount = imports.length;
1640
+ let cohesion = 1;
1641
+ if (exportCount > 10) {
1642
+ cohesion *= 0.6;
1643
+ } else if (exportCount > 5) {
1644
+ cohesion *= 0.8;
1645
+ }
1646
+ if (exportCount > 0) {
1647
+ const ratio = importCount / exportCount;
1648
+ if (ratio > 2) {
1649
+ cohesion *= 1.1;
1650
+ } else if (ratio < 0.5) {
1651
+ cohesion *= 0.9;
1624
1652
  }
1625
- );
1626
- const classRecs = getClassificationRecommendations(
1627
- fileClassification,
1628
- file,
1629
- issues
1630
- );
1631
- const allRecommendations = Array.from(
1632
- /* @__PURE__ */ new Set([...recommendations, ...classRecs])
1633
- );
1634
- return {
1635
- file,
1636
- tokenCost,
1637
- linesOfCode: node.linesOfCode,
1638
- importDepth,
1639
- dependencyCount: transitiveDeps.length,
1640
- dependencyList: transitiveDeps,
1641
- circularDeps,
1642
- cohesionScore,
1643
- domains: Array.from(
1644
- new Set(
1645
- node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
1646
- )
1647
- ),
1648
- exportCount: node.exports.length,
1649
- contextBudget,
1650
- fragmentationScore,
1651
- relatedFiles: cluster ? cluster.files : [],
1652
- fileClassification,
1653
- severity,
1654
- issues,
1655
- recommendations: allRecommendations,
1656
- potentialSavings
1657
- };
1653
+ }
1654
+ return Math.min(1, Math.max(0, cohesion));
1658
1655
  }
1656
+ var import_core6, import_path2, import_fs;
1657
+ var init_python_context = __esm({
1658
+ "src/analyzers/python-context.ts"() {
1659
+ "use strict";
1660
+ import_core6 = require("@aiready/core");
1661
+ import_path2 = require("path");
1662
+ import_fs = __toESM(require("fs"));
1663
+ init_dependency_graph_utils();
1664
+ }
1665
+ });
1659
1666
 
1660
1667
  // src/orchestrator.ts
1668
+ var orchestrator_exports = {};
1669
+ __export(orchestrator_exports, {
1670
+ analyzeContext: () => analyzeContext,
1671
+ calculateCohesion: () => calculateCohesion
1672
+ });
1661
1673
  function calculateCohesion(exports2, filePath, options) {
1662
1674
  return calculateEnhancedCohesion(exports2, filePath, options);
1663
1675
  }
@@ -1670,7 +1682,7 @@ async function analyzeContext(options) {
1670
1682
  includeNodeModules = false,
1671
1683
  ...scanOptions
1672
1684
  } = options;
1673
- const files = await (0, import_core6.scanFiles)({
1685
+ const files = await (0, import_core7.scanFiles)({
1674
1686
  ...scanOptions,
1675
1687
  exclude: includeNodeModules && scanOptions.exclude ? scanOptions.exclude.filter(
1676
1688
  (pattern) => pattern !== "**/node_modules/**"
@@ -1680,7 +1692,7 @@ async function analyzeContext(options) {
1680
1692
  const fileContents = await Promise.all(
1681
1693
  files.map(async (file) => ({
1682
1694
  file,
1683
- content: await (0, import_core6.readFileContent)(file)
1695
+ content: await (0, import_core7.readFileContent)(file)
1684
1696
  }))
1685
1697
  );
1686
1698
  const graph = await buildDependencyGraph(
@@ -1740,13 +1752,28 @@ async function analyzeContext(options) {
1740
1752
  );
1741
1753
  return [...results, ...pythonResults];
1742
1754
  }
1755
+ var import_core7;
1756
+ var init_orchestrator = __esm({
1757
+ "src/orchestrator.ts"() {
1758
+ "use strict";
1759
+ import_core7 = require("@aiready/core");
1760
+ init_metrics();
1761
+ init_issue_analyzer();
1762
+ init_graph_builder();
1763
+ init_cluster_detector();
1764
+ init_mapper();
1765
+ }
1766
+ });
1743
1767
 
1744
1768
  // src/summary.ts
1745
- var import_core7 = require("@aiready/core");
1769
+ var summary_exports = {};
1770
+ __export(summary_exports, {
1771
+ generateSummary: () => generateSummary
1772
+ });
1746
1773
  function generateSummary(results, options = {}) {
1747
1774
  const config = options ? Object.fromEntries(
1748
1775
  Object.entries(options).filter(
1749
- ([key]) => !import_core7.GLOBAL_SCAN_OPTIONS.includes(key) || key === "rootDir"
1776
+ ([key]) => !import_core8.GLOBAL_SCAN_OPTIONS.includes(key) || key === "rootDir"
1750
1777
  )
1751
1778
  ) : {};
1752
1779
  const totalFiles = results.length;
@@ -1824,9 +1851,85 @@ function generateSummary(results, options = {}) {
1824
1851
  config
1825
1852
  };
1826
1853
  }
1854
+ var import_core8;
1855
+ var init_summary = __esm({
1856
+ "src/summary.ts"() {
1857
+ "use strict";
1858
+ import_core8 = require("@aiready/core");
1859
+ init_metrics();
1860
+ }
1861
+ });
1862
+
1863
+ // src/index.ts
1864
+ var index_exports = {};
1865
+ __export(index_exports, {
1866
+ BARREL_EXPORT_MIN_EXPORTS: () => BARREL_EXPORT_MIN_EXPORTS,
1867
+ BARREL_EXPORT_TOKEN_LIMIT: () => BARREL_EXPORT_TOKEN_LIMIT,
1868
+ CONFIG_NAME_PATTERNS: () => CONFIG_NAME_PATTERNS,
1869
+ Classification: () => Classification,
1870
+ ContextAnalyzerProvider: () => ContextAnalyzerProvider,
1871
+ EMAIL_NAME_PATTERNS: () => EMAIL_NAME_PATTERNS,
1872
+ HANDLER_NAME_PATTERNS: () => HANDLER_NAME_PATTERNS,
1873
+ NEXTJS_METADATA_EXPORTS: () => NEXTJS_METADATA_EXPORTS,
1874
+ PARSER_NAME_PATTERNS: () => PARSER_NAME_PATTERNS,
1875
+ SERVICE_NAME_PATTERNS: () => SERVICE_NAME_PATTERNS,
1876
+ SESSION_NAME_PATTERNS: () => SESSION_NAME_PATTERNS,
1877
+ adjustCohesionForClassification: () => adjustCohesionForClassification,
1878
+ adjustFragmentationForClassification: () => adjustFragmentationForClassification,
1879
+ analyzeContext: () => analyzeContext,
1880
+ buildCoUsageMatrix: () => buildCoUsageMatrix,
1881
+ buildDependencyGraph: () => buildDependencyGraph,
1882
+ buildTypeGraph: () => buildTypeGraph,
1883
+ calculateCohesion: () => calculateCohesion,
1884
+ calculateContextBudget: () => calculateContextBudget,
1885
+ calculateContextScore: () => calculateContextScore,
1886
+ calculateDirectoryDistance: () => calculateDirectoryDistance,
1887
+ calculateDomainConfidence: () => calculateDomainConfidence,
1888
+ calculateEnhancedCohesion: () => calculateEnhancedCohesion,
1889
+ calculateFragmentation: () => calculateFragmentation,
1890
+ calculateImportDepth: () => calculateImportDepth,
1891
+ calculatePathEntropy: () => calculatePathEntropy,
1892
+ calculateStructuralCohesionFromCoUsage: () => calculateStructuralCohesionFromCoUsage,
1893
+ classifyFile: () => classifyFile,
1894
+ detectCircularDependencies: () => detectCircularDependencies,
1895
+ detectModuleClusters: () => detectModuleClusters,
1896
+ displayConsoleReport: () => displayConsoleReport,
1897
+ extractDomainKeywordsFromPaths: () => extractDomainKeywordsFromPaths,
1898
+ extractExports: () => extractExports,
1899
+ findConsolidationCandidates: () => findConsolidationCandidates,
1900
+ findSemanticClusters: () => findSemanticClusters,
1901
+ generateHTMLReport: () => generateHTMLReport,
1902
+ generateSummary: () => generateSummary,
1903
+ getClassificationRecommendations: () => getClassificationRecommendations,
1904
+ getCoUsageData: () => getCoUsageData,
1905
+ getGeneralRecommendations: () => getGeneralRecommendations,
1906
+ getSmartDefaults: () => getSmartDefaults,
1907
+ getTransitiveDependencies: () => getTransitiveDependencies,
1908
+ inferDomain: () => inferDomain,
1909
+ inferDomainFromSemantics: () => inferDomainFromSemantics,
1910
+ isBarrelExport: () => isBarrelExport,
1911
+ isBoilerplateBarrel: () => isBoilerplateBarrel,
1912
+ isConfigFile: () => isConfigFile,
1913
+ isEmailTemplate: () => isEmailTemplate,
1914
+ isHubAndSpokeFile: () => isHubAndSpokeFile,
1915
+ isLambdaHandler: () => isLambdaHandler,
1916
+ isNextJsPage: () => isNextJsPage,
1917
+ isParserFile: () => isParserFile,
1918
+ isServiceFile: () => isServiceFile,
1919
+ isSessionFile: () => isSessionFile,
1920
+ isTypeDefinition: () => isTypeDefinition,
1921
+ isUtilityModule: () => isUtilityModule,
1922
+ mapScoreToRating: () => mapScoreToRating,
1923
+ runInteractiveSetup: () => runInteractiveSetup
1924
+ });
1925
+ module.exports = __toCommonJS(index_exports);
1926
+ var import_core12 = require("@aiready/core");
1927
+
1928
+ // src/provider.ts
1929
+ var import_core9 = require("@aiready/core");
1827
1930
 
1828
1931
  // src/scoring.ts
1829
- var import_core8 = require("@aiready/core");
1932
+ var import_core = require("@aiready/core");
1830
1933
  var BUDGET_EXCELLENT_THRESHOLD = 8e3;
1831
1934
  var BUDGET_PENALTY_RATE = 200;
1832
1935
  var DEPTH_EXCELLENT_THRESHOLD = 8;
@@ -1976,8 +2079,8 @@ function calculateContextScore(summary, costConfig) {
1976
2079
  priority: "high"
1977
2080
  });
1978
2081
  }
1979
- const cfg = { ...import_core8.DEFAULT_COST_CONFIG, ...costConfig };
1980
- const estimatedMonthlyCost = (0, import_core8.calculateMonthlyCost)(
2082
+ const cfg = { ...import_core.DEFAULT_COST_CONFIG, ...costConfig };
2083
+ const estimatedMonthlyCost = (0, import_core.calculateMonthlyCost)(
1981
2084
  avgContextBudget * (totalFiles || 1),
1982
2085
  cfg
1983
2086
  );
@@ -1985,9 +2088,9 @@ function calculateContextScore(summary, costConfig) {
1985
2088
  ...Array(criticalIssues).fill({ severity: "critical" }),
1986
2089
  ...Array(majorIssues).fill({ severity: "major" })
1987
2090
  ];
1988
- const productivityImpact = (0, import_core8.calculateProductivityImpact)(issues);
2091
+ const productivityImpact = (0, import_core.calculateProductivityImpact)(issues);
1989
2092
  return {
1990
- toolName: import_core8.ToolName.ContextAnalyzer,
2093
+ toolName: import_core.ToolName.ContextAnalyzer,
1991
2094
  score,
1992
2095
  rawMetrics: {
1993
2096
  avgContextBudget: Math.round(avgContextBudget),
@@ -2005,7 +2108,7 @@ function calculateContextScore(summary, costConfig) {
2005
2108
  };
2006
2109
  }
2007
2110
  function mapScoreToRating(score) {
2008
- return (0, import_core8.getRatingSlug)(score).replace("-", " ");
2111
+ return (0, import_core.getRatingSlug)(score).replace("-", " ");
2009
2112
  }
2010
2113
 
2011
2114
  // src/provider.ts
@@ -2013,8 +2116,10 @@ var ContextAnalyzerProvider = {
2013
2116
  id: import_core9.ToolName.ContextAnalyzer,
2014
2117
  alias: ["context", "fragmentation", "budget"],
2015
2118
  async analyze(options) {
2016
- const results = await analyzeContext(options);
2017
- const summary = generateSummary(results, options);
2119
+ const { analyzeContext: analyzeContext2 } = await Promise.resolve().then(() => (init_orchestrator(), orchestrator_exports));
2120
+ const { generateSummary: generateSummary2 } = await Promise.resolve().then(() => (init_summary(), summary_exports));
2121
+ const results = await analyzeContext2(options);
2122
+ const summary = generateSummary2(results, options);
2018
2123
  const normalizedResults = results.map(
2019
2124
  (r) => ({
2020
2125
  fileName: r.file,
@@ -2028,7 +2133,6 @@ var ContextAnalyzerProvider = {
2028
2133
  metrics: {
2029
2134
  tokenCost: r.tokenCost,
2030
2135
  complexityScore: r.importDepth
2031
- // Map other context-specific metrics if needed
2032
2136
  }
2033
2137
  })
2034
2138
  );
@@ -2051,6 +2155,14 @@ var ContextAnalyzerProvider = {
2051
2155
  defaultWeight: 19
2052
2156
  };
2053
2157
 
2158
+ // src/index.ts
2159
+ init_orchestrator();
2160
+ init_graph_builder();
2161
+ init_metrics();
2162
+ init_classifier();
2163
+ init_cluster_detector();
2164
+ init_remediation();
2165
+
2054
2166
  // src/defaults.ts
2055
2167
  var import_core10 = require("@aiready/core");
2056
2168
  async function getSmartDefaults(directory, userOptions) {
@@ -2098,6 +2210,12 @@ async function getSmartDefaults(directory, userOptions) {
2098
2210
  };
2099
2211
  }
2100
2212
 
2213
+ // src/index.ts
2214
+ init_summary();
2215
+ init_co_usage();
2216
+ init_type_graph();
2217
+ init_domain_inference();
2218
+
2101
2219
  // src/semantic/consolidation.ts
2102
2220
  function findConsolidationCandidates(graph, coUsageMatrix, typeGraph, minCoUsage = 5, minSharedTypes = 2) {
2103
2221
  const candidates = [];
@@ -2127,6 +2245,10 @@ function findConsolidationCandidates(graph, coUsageMatrix, typeGraph, minCoUsage
2127
2245
  return candidates.sort((a, b) => b.strength - a.strength);
2128
2246
  }
2129
2247
 
2248
+ // src/index.ts
2249
+ init_classification_patterns();
2250
+ init_file_classifiers();
2251
+
2130
2252
  // src/report/console-report.ts
2131
2253
  var import_chalk = __toESM(require("chalk"));
2132
2254
  function displayConsoleReport(summary, results, maxResults = 10) {
@@ -2204,8 +2326,7 @@ var import_core11 = require("@aiready/core");
2204
2326
  function generateHTMLReport(summary, results) {
2205
2327
  const totalIssues = summary.criticalIssues + summary.majorIssues + summary.minorIssues;
2206
2328
  void results;
2207
- const head = (0, import_core11.generateReportHead)("AIReady Context Analysis Report");
2208
- const stats = (0, import_core11.generateStatCards)([
2329
+ const stats = [
2209
2330
  { value: summary.totalFiles, label: "Files Analyzed" },
2210
2331
  { value: summary.totalTokens.toLocaleString(), label: "Total Tokens" },
2211
2332
  { value: summary.avgContextBudget.toFixed(0), label: "Avg Context Budget" },
@@ -2214,62 +2335,57 @@ function generateHTMLReport(summary, results) {
2214
2335
  label: "Total Issues",
2215
2336
  color: totalIssues > 0 ? "#f39c12" : void 0
2216
2337
  }
2217
- ]);
2218
- const hero = (0, import_core11.generateReportHero)(
2219
- "\u{1F50D} AIReady Context Analysis Report",
2220
- `Generated on ${(/* @__PURE__ */ new Date()).toLocaleString()}`
2221
- );
2222
- let body = `${hero}
2223
- ${stats}`;
2338
+ ];
2339
+ const sections = [];
2224
2340
  if (totalIssues > 0) {
2225
- body += (0, import_core11.generateIssueSummary)(
2226
- summary.criticalIssues,
2227
- summary.majorIssues,
2228
- summary.minorIssues,
2229
- summary.totalPotentialSavings
2230
- );
2341
+ sections.push({
2342
+ title: "\u26A0\uFE0F Issues Summary",
2343
+ content: (0, import_core11.generateIssueSummary)(
2344
+ summary.criticalIssues,
2345
+ summary.majorIssues,
2346
+ summary.minorIssues,
2347
+ summary.totalPotentialSavings
2348
+ )
2349
+ });
2231
2350
  }
2232
2351
  if (summary.fragmentedModules.length > 0) {
2233
- const fragmentedRows = summary.fragmentedModules.map((m) => [
2234
- m.domain,
2235
- String(m.files.length),
2236
- `${(m.fragmentationScore * 100).toFixed(0)}%`,
2237
- m.totalTokens.toLocaleString()
2238
- ]);
2239
- body += (0, import_core11.wrapInCard)(
2240
- (0, import_core11.generateTable)({
2352
+ sections.push({
2353
+ title: "\u{1F9E9} Fragmented Modules",
2354
+ content: (0, import_core11.generateTable)({
2241
2355
  headers: ["Domain", "Files", "Fragmentation", "Token Cost"],
2242
- rows: fragmentedRows
2243
- }),
2244
- "\u{1F9E9} Fragmented Modules"
2245
- );
2356
+ rows: summary.fragmentedModules.map((m) => [
2357
+ m.domain,
2358
+ String(m.files.length),
2359
+ `${(m.fragmentationScore * 100).toFixed(0)}%`,
2360
+ m.totalTokens.toLocaleString()
2361
+ ])
2362
+ })
2363
+ });
2246
2364
  }
2247
2365
  if (summary.topExpensiveFiles.length > 0) {
2248
- const expensiveRows = summary.topExpensiveFiles.map((f) => [
2249
- f.file,
2250
- `${f.contextBudget.toLocaleString()} tokens`,
2251
- `<span class="issue-${f.severity}">${f.severity.toUpperCase()}</span>`
2252
- ]);
2253
- body += (0, import_core11.wrapInCard)(
2254
- (0, import_core11.generateTable)({
2366
+ sections.push({
2367
+ title: "\u{1F4B8} Most Expensive Files",
2368
+ content: (0, import_core11.generateTable)({
2255
2369
  headers: ["File", "Context Budget", "Severity"],
2256
- rows: expensiveRows
2257
- }),
2258
- "\u{1F4B8} Most Expensive Files"
2259
- );
2370
+ rows: summary.topExpensiveFiles.map((f) => [
2371
+ f.file,
2372
+ `${f.contextBudget.toLocaleString()} tokens`,
2373
+ `<span class="issue-${f.severity}">${f.severity.toUpperCase()}</span>`
2374
+ ])
2375
+ })
2376
+ });
2260
2377
  }
2261
- const footer = (0, import_core11.generateReportFooter)({
2262
- title: "Context Analysis Report",
2263
- packageName: "context-analyzer",
2264
- packageUrl: "https://github.com/caopengau/aiready-context-analyzer",
2265
- bugUrl: "https://github.com/caopengau/aiready-context-analyzer/issues"
2266
- });
2267
- return `${head}
2268
- <body>
2269
- ${body}
2270
- ${footer}
2271
- </body>
2272
- </html>`;
2378
+ return (0, import_core11.generateStandardHtmlReport)(
2379
+ {
2380
+ title: "Context Analysis Report",
2381
+ packageName: "context-analyzer",
2382
+ packageUrl: "https://github.com/caopengau/aiready-context-analyzer",
2383
+ bugUrl: "https://github.com/caopengau/aiready-context-analyzer/issues",
2384
+ emoji: "\u{1F9E0}"
2385
+ },
2386
+ stats,
2387
+ sections
2388
+ );
2273
2389
  }
2274
2390
 
2275
2391
  // src/report/interactive-setup.ts