@aiready/context-analyzer 0.22.1 → 0.22.3

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.
@@ -0,0 +1,95 @@
1
+ import {
2
+ displayConsoleReport,
3
+ generateHTMLReport,
4
+ runInteractiveSetup
5
+ } from "./chunk-J3SZQZNU.mjs";
6
+ import {
7
+ analyzeContext
8
+ } from "./chunk-ILMLGJGI.mjs";
9
+ import "./chunk-64U3PNO3.mjs";
10
+ import {
11
+ generateSummary
12
+ } from "./chunk-BQCISA2F.mjs";
13
+ import "./chunk-EMYD7NS6.mjs";
14
+
15
+ // src/cli-action.ts
16
+ import {
17
+ loadMergedConfig,
18
+ handleJSONOutput,
19
+ handleCLIError,
20
+ getElapsedTime,
21
+ resolveOutputPath
22
+ } from "@aiready/core";
23
+ import chalk from "chalk";
24
+ import { writeFileSync } from "fs";
25
+ async function contextActionHandler(directory, options) {
26
+ console.log(chalk.blue("\u{1F50D} Analyzing context window costs...\n"));
27
+ const startTime = Date.now();
28
+ try {
29
+ const defaults = {
30
+ maxDepth: 5,
31
+ maxContextBudget: 1e4,
32
+ minCohesion: 0.6,
33
+ maxFragmentation: 0.5,
34
+ focus: "all",
35
+ includeNodeModules: false,
36
+ include: void 0,
37
+ exclude: void 0,
38
+ maxResults: 10
39
+ };
40
+ let finalOptions = await loadMergedConfig(directory, defaults, {
41
+ maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
42
+ maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
43
+ minCohesion: options.minCohesion ? parseFloat(options.minCohesion) : void 0,
44
+ maxFragmentation: options.maxFragmentation ? parseFloat(options.maxFragmentation) : void 0,
45
+ focus: options.focus || void 0,
46
+ includeNodeModules: options.includeNodeModules,
47
+ include: options.include?.split(","),
48
+ exclude: options.exclude?.split(","),
49
+ maxResults: options.maxResults ? parseInt(options.maxResults) : void 0
50
+ });
51
+ if (options.interactive) {
52
+ finalOptions = await runInteractiveSetup(directory, finalOptions);
53
+ }
54
+ const results = await analyzeContext(finalOptions);
55
+ const summary = generateSummary(results, finalOptions);
56
+ const duration = getElapsedTime(startTime);
57
+ if (options.output === "json") {
58
+ handleJSONOutput(
59
+ {
60
+ summary: {
61
+ ...summary,
62
+ executionTime: duration,
63
+ config: {
64
+ scan: { tools: ["context"] },
65
+ tools: { context: finalOptions }
66
+ },
67
+ toolConfigs: { context: finalOptions }
68
+ },
69
+ context: { results }
70
+ },
71
+ options.outputFile
72
+ );
73
+ } else if (options.output === "html") {
74
+ const html = generateHTMLReport(summary, results);
75
+ const outputPath = resolveOutputPath(
76
+ directory,
77
+ options.outputFile,
78
+ "context-report.html"
79
+ );
80
+ writeFileSync(outputPath, html, "utf-8");
81
+ console.log(chalk.green(`
82
+ \u2705 HTML report saved to: ${outputPath}`));
83
+ } else {
84
+ displayConsoleReport(summary, results, finalOptions.maxResults);
85
+ console.log(chalk.dim(`
86
+ \u2728 Analysis completed in ${duration}ms
87
+ `));
88
+ }
89
+ } catch (error) {
90
+ handleCLIError(error, "context-analyzer");
91
+ }
92
+ }
93
+ export {
94
+ contextActionHandler
95
+ };
package/dist/cli.js CHANGED
@@ -1305,88 +1305,6 @@ var init_remediation = __esm({
1305
1305
  }
1306
1306
  });
1307
1307
 
1308
- // src/mapper.ts
1309
- function mapNodeToResult(node, graph, clusters, allCircularDeps, options) {
1310
- const file = node.file;
1311
- const tokenCost = node.tokenCost;
1312
- const importDepth = calculateImportDepth(file, graph);
1313
- const transitiveDeps = getTransitiveDependencies(file, graph);
1314
- const contextBudget = calculateContextBudget(file, graph);
1315
- const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
1316
- const cluster = clusters.find((c) => c.files.includes(file));
1317
- const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
1318
- const rawCohesionScore = calculateEnhancedCohesion(
1319
- node.exports,
1320
- file,
1321
- options
1322
- );
1323
- const fileClassification = classifyFile(node, rawCohesionScore);
1324
- const cohesionScore = adjustCohesionForClassification(
1325
- rawCohesionScore,
1326
- fileClassification
1327
- );
1328
- const fragmentationScore = adjustFragmentationForClassification(
1329
- rawFragmentationScore,
1330
- fileClassification
1331
- );
1332
- const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
1333
- {
1334
- file,
1335
- importDepth,
1336
- contextBudget,
1337
- cohesionScore,
1338
- fragmentationScore,
1339
- maxDepth: options.maxDepth,
1340
- maxContextBudget: options.maxContextBudget,
1341
- minCohesion: options.minCohesion,
1342
- maxFragmentation: options.maxFragmentation,
1343
- circularDeps
1344
- }
1345
- );
1346
- const classRecs = getClassificationRecommendations(
1347
- fileClassification,
1348
- file,
1349
- issues
1350
- );
1351
- const allRecommendations = Array.from(
1352
- /* @__PURE__ */ new Set([...recommendations, ...classRecs])
1353
- );
1354
- return {
1355
- file,
1356
- tokenCost,
1357
- linesOfCode: node.linesOfCode,
1358
- importDepth,
1359
- dependencyCount: transitiveDeps.length,
1360
- dependencyList: transitiveDeps,
1361
- circularDeps,
1362
- cohesionScore,
1363
- domains: Array.from(
1364
- new Set(
1365
- node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
1366
- )
1367
- ),
1368
- exportCount: node.exports.length,
1369
- contextBudget,
1370
- fragmentationScore,
1371
- relatedFiles: cluster ? cluster.files : [],
1372
- fileClassification,
1373
- severity,
1374
- issues,
1375
- recommendations: allRecommendations,
1376
- potentialSavings
1377
- };
1378
- }
1379
- var init_mapper = __esm({
1380
- "src/mapper.ts"() {
1381
- "use strict";
1382
- init_metrics();
1383
- init_issue_analyzer();
1384
- init_graph_builder();
1385
- init_classifier();
1386
- init_remediation();
1387
- }
1388
- });
1389
-
1390
1308
  // src/analyzers/python-context.ts
1391
1309
  var python_context_exports = {};
1392
1310
  __export(python_context_exports, {
@@ -1554,6 +1472,76 @@ var init_python_context = __esm({
1554
1472
  });
1555
1473
 
1556
1474
  // src/orchestrator.ts
1475
+ function mapNodeToResult(node, graph, clusters, allCircularDeps, options) {
1476
+ const file = node.file;
1477
+ const tokenCost = node.tokenCost;
1478
+ const importDepth = calculateImportDepth(file, graph);
1479
+ const transitiveDeps = getTransitiveDependencies(file, graph);
1480
+ const contextBudget = calculateContextBudget(file, graph);
1481
+ const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
1482
+ const cluster = clusters.find((c) => c.files.includes(file));
1483
+ const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
1484
+ const rawCohesionScore = calculateEnhancedCohesion(
1485
+ node.exports,
1486
+ file,
1487
+ options
1488
+ );
1489
+ const fileClassification = classifyFile(node, rawCohesionScore);
1490
+ const cohesionScore = adjustCohesionForClassification(
1491
+ rawCohesionScore,
1492
+ fileClassification
1493
+ );
1494
+ const fragmentationScore = adjustFragmentationForClassification(
1495
+ rawFragmentationScore,
1496
+ fileClassification
1497
+ );
1498
+ const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
1499
+ {
1500
+ file,
1501
+ importDepth,
1502
+ contextBudget,
1503
+ cohesionScore,
1504
+ fragmentationScore,
1505
+ maxDepth: options.maxDepth,
1506
+ maxContextBudget: options.maxContextBudget,
1507
+ minCohesion: options.minCohesion,
1508
+ maxFragmentation: options.maxFragmentation,
1509
+ circularDeps
1510
+ }
1511
+ );
1512
+ const classRecs = getClassificationRecommendations(
1513
+ fileClassification,
1514
+ file,
1515
+ issues
1516
+ );
1517
+ const allRecommendations = Array.from(
1518
+ /* @__PURE__ */ new Set([...recommendations, ...classRecs])
1519
+ );
1520
+ return {
1521
+ file,
1522
+ tokenCost,
1523
+ linesOfCode: node.linesOfCode,
1524
+ importDepth,
1525
+ dependencyCount: transitiveDeps.length,
1526
+ dependencyList: transitiveDeps,
1527
+ circularDeps,
1528
+ cohesionScore,
1529
+ domains: Array.from(
1530
+ new Set(
1531
+ node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
1532
+ )
1533
+ ),
1534
+ exportCount: node.exports.length,
1535
+ contextBudget,
1536
+ fragmentationScore,
1537
+ relatedFiles: cluster ? cluster.files : [],
1538
+ fileClassification,
1539
+ severity,
1540
+ issues,
1541
+ recommendations: allRecommendations,
1542
+ potentialSavings
1543
+ };
1544
+ }
1557
1545
  async function analyzeContext(options) {
1558
1546
  const {
1559
1547
  maxDepth = 5,
@@ -1642,7 +1630,8 @@ var init_orchestrator = __esm({
1642
1630
  init_issue_analyzer();
1643
1631
  init_graph_builder();
1644
1632
  init_cluster_detector();
1645
- init_mapper();
1633
+ init_classifier();
1634
+ init_remediation();
1646
1635
  }
1647
1636
  });
1648
1637
 
package/dist/cli.mjs CHANGED
@@ -37,7 +37,7 @@ function defineContextCommand(program2) {
37
37
  "--interactive",
38
38
  "Run interactive setup to suggest excludes and focus areas"
39
39
  ).action(async (directory, options) => {
40
- const { contextActionHandler } = await import("./cli-action-SA7SCYNV.mjs");
40
+ const { contextActionHandler } = await import("./cli-action-E7UGP4KE.mjs");
41
41
  await contextActionHandler(directory, options);
42
42
  });
43
43
  }
package/dist/index.d.mts CHANGED
@@ -160,6 +160,12 @@ interface TypeDependency {
160
160
  usedBy: string[];
161
161
  }
162
162
 
163
+ interface MappingOptions {
164
+ maxDepth: number;
165
+ maxContextBudget: number;
166
+ minCohesion: number;
167
+ maxFragmentation: number;
168
+ }
163
169
  /**
164
170
  * Calculate cohesion score (how related are exports in a file).
165
171
  * Legacy wrapper for backward compatibility with exact test expectations.
@@ -642,4 +648,4 @@ declare function generateHTMLReport(summary: ReturnType<typeof generateSummary>,
642
648
  */
643
649
  declare function runInteractiveSetup(directory: string, current: any): Promise<any>;
644
650
 
645
- export { BARREL_EXPORT_MIN_EXPORTS, BARREL_EXPORT_TOKEN_LIMIT, CONFIG_NAME_PATTERNS, Classification, type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, ContextAnalyzerProvider, type ContextSummary, type DependencyGraph, type DependencyNode, type DomainAssignment, type DomainSignals, EMAIL_NAME_PATTERNS, type ExportInfo, type FileClassification, HANDLER_NAME_PATTERNS, type ModuleCluster, NEXTJS_METADATA_EXPORTS, PARSER_NAME_PATTERNS, SERVICE_NAME_PATTERNS, SESSION_NAME_PATTERNS, type TypeDependency, adjustCohesionForClassification, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildDependencyGraph, buildTypeGraph, calculateCohesion, calculateContextBudget, calculateContextScore, calculateDirectoryDistance, calculateDomainConfidence, calculateEnhancedCohesion, calculateFragmentation, calculateImportDepth, calculatePathEntropy, calculateStructuralCohesionFromCoUsage, classifyFile, detectCircularDependencies, detectModuleClusters, displayConsoleReport, extractDomainKeywordsFromPaths, extractExports, findConsolidationCandidates, findSemanticClusters, generateHTMLReport, generateSummary, getClassificationRecommendations, getCoUsageData, getGeneralRecommendations, getSmartDefaults, getTransitiveDependencies, inferDomain, inferDomainFromSemantics, isBarrelExport, isBoilerplateBarrel, isConfigFile, isEmailTemplate, isHubAndSpokeFile, isLambdaHandler, isNextJsPage, isParserFile, isServiceFile, isSessionFile, isTypeDefinition, isUtilityModule, mapScoreToRating, runInteractiveSetup };
651
+ export { BARREL_EXPORT_MIN_EXPORTS, BARREL_EXPORT_TOKEN_LIMIT, CONFIG_NAME_PATTERNS, Classification, type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, ContextAnalyzerProvider, type ContextSummary, type DependencyGraph, type DependencyNode, type DomainAssignment, type DomainSignals, EMAIL_NAME_PATTERNS, type ExportInfo, type FileClassification, HANDLER_NAME_PATTERNS, type MappingOptions, type ModuleCluster, NEXTJS_METADATA_EXPORTS, PARSER_NAME_PATTERNS, SERVICE_NAME_PATTERNS, SESSION_NAME_PATTERNS, type TypeDependency, adjustCohesionForClassification, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildDependencyGraph, buildTypeGraph, calculateCohesion, calculateContextBudget, calculateContextScore, calculateDirectoryDistance, calculateDomainConfidence, calculateEnhancedCohesion, calculateFragmentation, calculateImportDepth, calculatePathEntropy, calculateStructuralCohesionFromCoUsage, classifyFile, detectCircularDependencies, detectModuleClusters, displayConsoleReport, extractDomainKeywordsFromPaths, extractExports, findConsolidationCandidates, findSemanticClusters, generateHTMLReport, generateSummary, getClassificationRecommendations, getCoUsageData, getGeneralRecommendations, getSmartDefaults, getTransitiveDependencies, inferDomain, inferDomainFromSemantics, isBarrelExport, isBoilerplateBarrel, isConfigFile, isEmailTemplate, isHubAndSpokeFile, isLambdaHandler, isNextJsPage, isParserFile, isServiceFile, isSessionFile, isTypeDefinition, isUtilityModule, mapScoreToRating, runInteractiveSetup };
package/dist/index.d.ts CHANGED
@@ -160,6 +160,12 @@ interface TypeDependency {
160
160
  usedBy: string[];
161
161
  }
162
162
 
163
+ interface MappingOptions {
164
+ maxDepth: number;
165
+ maxContextBudget: number;
166
+ minCohesion: number;
167
+ maxFragmentation: number;
168
+ }
163
169
  /**
164
170
  * Calculate cohesion score (how related are exports in a file).
165
171
  * Legacy wrapper for backward compatibility with exact test expectations.
@@ -642,4 +648,4 @@ declare function generateHTMLReport(summary: ReturnType<typeof generateSummary>,
642
648
  */
643
649
  declare function runInteractiveSetup(directory: string, current: any): Promise<any>;
644
650
 
645
- export { BARREL_EXPORT_MIN_EXPORTS, BARREL_EXPORT_TOKEN_LIMIT, CONFIG_NAME_PATTERNS, Classification, type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, ContextAnalyzerProvider, type ContextSummary, type DependencyGraph, type DependencyNode, type DomainAssignment, type DomainSignals, EMAIL_NAME_PATTERNS, type ExportInfo, type FileClassification, HANDLER_NAME_PATTERNS, type ModuleCluster, NEXTJS_METADATA_EXPORTS, PARSER_NAME_PATTERNS, SERVICE_NAME_PATTERNS, SESSION_NAME_PATTERNS, type TypeDependency, adjustCohesionForClassification, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildDependencyGraph, buildTypeGraph, calculateCohesion, calculateContextBudget, calculateContextScore, calculateDirectoryDistance, calculateDomainConfidence, calculateEnhancedCohesion, calculateFragmentation, calculateImportDepth, calculatePathEntropy, calculateStructuralCohesionFromCoUsage, classifyFile, detectCircularDependencies, detectModuleClusters, displayConsoleReport, extractDomainKeywordsFromPaths, extractExports, findConsolidationCandidates, findSemanticClusters, generateHTMLReport, generateSummary, getClassificationRecommendations, getCoUsageData, getGeneralRecommendations, getSmartDefaults, getTransitiveDependencies, inferDomain, inferDomainFromSemantics, isBarrelExport, isBoilerplateBarrel, isConfigFile, isEmailTemplate, isHubAndSpokeFile, isLambdaHandler, isNextJsPage, isParserFile, isServiceFile, isSessionFile, isTypeDefinition, isUtilityModule, mapScoreToRating, runInteractiveSetup };
651
+ export { BARREL_EXPORT_MIN_EXPORTS, BARREL_EXPORT_TOKEN_LIMIT, CONFIG_NAME_PATTERNS, Classification, type CoUsageData, type ContextAnalysisResult, type ContextAnalyzerOptions, ContextAnalyzerProvider, type ContextSummary, type DependencyGraph, type DependencyNode, type DomainAssignment, type DomainSignals, EMAIL_NAME_PATTERNS, type ExportInfo, type FileClassification, HANDLER_NAME_PATTERNS, type MappingOptions, type ModuleCluster, NEXTJS_METADATA_EXPORTS, PARSER_NAME_PATTERNS, SERVICE_NAME_PATTERNS, SESSION_NAME_PATTERNS, type TypeDependency, adjustCohesionForClassification, adjustFragmentationForClassification, analyzeContext, buildCoUsageMatrix, buildDependencyGraph, buildTypeGraph, calculateCohesion, calculateContextBudget, calculateContextScore, calculateDirectoryDistance, calculateDomainConfidence, calculateEnhancedCohesion, calculateFragmentation, calculateImportDepth, calculatePathEntropy, calculateStructuralCohesionFromCoUsage, classifyFile, detectCircularDependencies, detectModuleClusters, displayConsoleReport, extractDomainKeywordsFromPaths, extractExports, findConsolidationCandidates, findSemanticClusters, generateHTMLReport, generateSummary, getClassificationRecommendations, getCoUsageData, getGeneralRecommendations, getSmartDefaults, getTransitiveDependencies, inferDomain, inferDomainFromSemantics, isBarrelExport, isBoilerplateBarrel, isConfigFile, isEmailTemplate, isHubAndSpokeFile, isLambdaHandler, isNextJsPage, isParserFile, isServiceFile, isSessionFile, isTypeDefinition, isUtilityModule, mapScoreToRating, runInteractiveSetup };
package/dist/index.js CHANGED
@@ -1416,88 +1416,6 @@ var init_remediation = __esm({
1416
1416
  }
1417
1417
  });
1418
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
1419
  // src/analyzers/python-context.ts
1502
1420
  var python_context_exports = {};
1503
1421
  __export(python_context_exports, {
@@ -1670,6 +1588,76 @@ __export(orchestrator_exports, {
1670
1588
  analyzeContext: () => analyzeContext,
1671
1589
  calculateCohesion: () => calculateCohesion
1672
1590
  });
1591
+ function mapNodeToResult(node, graph, clusters, allCircularDeps, options) {
1592
+ const file = node.file;
1593
+ const tokenCost = node.tokenCost;
1594
+ const importDepth = calculateImportDepth(file, graph);
1595
+ const transitiveDeps = getTransitiveDependencies(file, graph);
1596
+ const contextBudget = calculateContextBudget(file, graph);
1597
+ const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
1598
+ const cluster = clusters.find((c) => c.files.includes(file));
1599
+ const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
1600
+ const rawCohesionScore = calculateEnhancedCohesion(
1601
+ node.exports,
1602
+ file,
1603
+ options
1604
+ );
1605
+ const fileClassification = classifyFile(node, rawCohesionScore);
1606
+ const cohesionScore = adjustCohesionForClassification(
1607
+ rawCohesionScore,
1608
+ fileClassification
1609
+ );
1610
+ const fragmentationScore = adjustFragmentationForClassification(
1611
+ rawFragmentationScore,
1612
+ fileClassification
1613
+ );
1614
+ const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
1615
+ {
1616
+ file,
1617
+ importDepth,
1618
+ contextBudget,
1619
+ cohesionScore,
1620
+ fragmentationScore,
1621
+ maxDepth: options.maxDepth,
1622
+ maxContextBudget: options.maxContextBudget,
1623
+ minCohesion: options.minCohesion,
1624
+ maxFragmentation: options.maxFragmentation,
1625
+ circularDeps
1626
+ }
1627
+ );
1628
+ const classRecs = getClassificationRecommendations(
1629
+ fileClassification,
1630
+ file,
1631
+ issues
1632
+ );
1633
+ const allRecommendations = Array.from(
1634
+ /* @__PURE__ */ new Set([...recommendations, ...classRecs])
1635
+ );
1636
+ return {
1637
+ file,
1638
+ tokenCost,
1639
+ linesOfCode: node.linesOfCode,
1640
+ importDepth,
1641
+ dependencyCount: transitiveDeps.length,
1642
+ dependencyList: transitiveDeps,
1643
+ circularDeps,
1644
+ cohesionScore,
1645
+ domains: Array.from(
1646
+ new Set(
1647
+ node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
1648
+ )
1649
+ ),
1650
+ exportCount: node.exports.length,
1651
+ contextBudget,
1652
+ fragmentationScore,
1653
+ relatedFiles: cluster ? cluster.files : [],
1654
+ fileClassification,
1655
+ severity,
1656
+ issues,
1657
+ recommendations: allRecommendations,
1658
+ potentialSavings
1659
+ };
1660
+ }
1673
1661
  function calculateCohesion(exports2, filePath, options) {
1674
1662
  return calculateEnhancedCohesion(exports2, filePath, options);
1675
1663
  }
@@ -1761,7 +1749,8 @@ var init_orchestrator = __esm({
1761
1749
  init_issue_analyzer();
1762
1750
  init_graph_builder();
1763
1751
  init_cluster_detector();
1764
- init_mapper();
1752
+ init_classifier();
1753
+ init_remediation();
1765
1754
  }
1766
1755
  });
1767
1756
 
package/dist/index.mjs CHANGED
@@ -48,7 +48,7 @@ import {
48
48
  isSessionFile,
49
49
  isTypeDefinition,
50
50
  isUtilityModule
51
- } from "./chunk-BCEZGRXI.mjs";
51
+ } from "./chunk-ILMLGJGI.mjs";
52
52
  import "./chunk-64U3PNO3.mjs";
53
53
  import {
54
54
  generateSummary
@@ -265,7 +265,7 @@ var ContextAnalyzerProvider = {
265
265
  id: ToolName2.ContextAnalyzer,
266
266
  alias: ["context", "fragmentation", "budget"],
267
267
  async analyze(options) {
268
- const { analyzeContext: analyzeContext2 } = await import("./orchestrator-3L3NAZYP.mjs");
268
+ const { analyzeContext: analyzeContext2 } = await import("./orchestrator-R6MZT4Z2.mjs");
269
269
  const { generateSummary: generateSummary2 } = await import("./summary-7PZVW72O.mjs");
270
270
  const results = await analyzeContext2(options);
271
271
  const summary = generateSummary2(results, options);
@@ -0,0 +1,10 @@
1
+ import {
2
+ analyzeContext,
3
+ calculateCohesion
4
+ } from "./chunk-ILMLGJGI.mjs";
5
+ import "./chunk-64U3PNO3.mjs";
6
+ import "./chunk-EMYD7NS6.mjs";
7
+ export {
8
+ analyzeContext,
9
+ calculateCohesion
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/context-analyzer",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
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",
@@ -49,7 +49,7 @@
49
49
  "commander": "^14.0.0",
50
50
  "chalk": "^5.3.0",
51
51
  "prompts": "^2.4.2",
52
- "@aiready/core": "0.24.1"
52
+ "@aiready/core": "0.24.3"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/node": "^24.0.0",
@@ -3,16 +3,125 @@ import type {
3
3
  ContextAnalysisResult,
4
4
  ContextAnalyzerOptions,
5
5
  FileClassification,
6
+ DependencyNode,
7
+ DependencyGraph,
8
+ ModuleCluster,
6
9
  } from './types';
7
10
  import { calculateEnhancedCohesion } from './metrics';
8
11
  import { analyzeIssues } from './issue-analyzer';
9
-
10
12
  import {
11
13
  buildDependencyGraph,
12
14
  detectCircularDependencies,
15
+ calculateImportDepth,
16
+ getTransitiveDependencies,
17
+ calculateContextBudget,
13
18
  } from './graph-builder';
14
19
  import { detectModuleClusters } from './cluster-detector';
15
- import { mapNodeToResult } from './mapper';
20
+ import {
21
+ classifyFile,
22
+ adjustCohesionForClassification,
23
+ adjustFragmentationForClassification,
24
+ } from './classifier';
25
+ import { getClassificationRecommendations } from './remediation';
26
+
27
+ export interface MappingOptions {
28
+ maxDepth: number;
29
+ maxContextBudget: number;
30
+ minCohesion: number;
31
+ maxFragmentation: number;
32
+ }
33
+
34
+ /**
35
+ * Maps a single dependency node to a comprehensive ContextAnalysisResult.
36
+ */
37
+ function mapNodeToResult(
38
+ node: DependencyNode,
39
+ graph: DependencyGraph,
40
+ clusters: ModuleCluster[],
41
+ allCircularDeps: string[][],
42
+ options: MappingOptions
43
+ ): ContextAnalysisResult {
44
+ const file = node.file;
45
+ const tokenCost = node.tokenCost;
46
+ const importDepth = calculateImportDepth(file, graph);
47
+ const transitiveDeps = getTransitiveDependencies(file, graph);
48
+ const contextBudget = calculateContextBudget(file, graph);
49
+ const circularDeps = allCircularDeps.filter((cycle) => cycle.includes(file));
50
+
51
+ // Find cluster for this file
52
+ const cluster = clusters.find((c) => c.files.includes(file));
53
+ const rawFragmentationScore = cluster ? cluster.fragmentationScore : 0;
54
+
55
+ // Cohesion
56
+ const rawCohesionScore = calculateEnhancedCohesion(
57
+ node.exports,
58
+ file,
59
+ options as any
60
+ );
61
+
62
+ // Initial classification
63
+ const fileClassification = classifyFile(node, rawCohesionScore);
64
+
65
+ // Adjust scores based on classification
66
+ const cohesionScore = adjustCohesionForClassification(
67
+ rawCohesionScore,
68
+ fileClassification
69
+ );
70
+ const fragmentationScore = adjustFragmentationForClassification(
71
+ rawFragmentationScore,
72
+ fileClassification
73
+ );
74
+
75
+ const { severity, issues, recommendations, potentialSavings } = analyzeIssues(
76
+ {
77
+ file,
78
+ importDepth,
79
+ contextBudget,
80
+ cohesionScore,
81
+ fragmentationScore,
82
+ maxDepth: options.maxDepth,
83
+ maxContextBudget: options.maxContextBudget,
84
+ minCohesion: options.minCohesion,
85
+ maxFragmentation: options.maxFragmentation,
86
+ circularDeps,
87
+ }
88
+ );
89
+
90
+ // Add classification-specific recommendations
91
+ const classRecs = getClassificationRecommendations(
92
+ fileClassification,
93
+ file,
94
+ issues
95
+ );
96
+ const allRecommendations = Array.from(
97
+ new Set([...recommendations, ...classRecs])
98
+ );
99
+
100
+ return {
101
+ file,
102
+ tokenCost,
103
+ linesOfCode: node.linesOfCode,
104
+ importDepth,
105
+ dependencyCount: transitiveDeps.length,
106
+ dependencyList: transitiveDeps,
107
+ circularDeps,
108
+ cohesionScore,
109
+ domains: Array.from(
110
+ new Set(
111
+ node.exports.flatMap((e) => e.domains?.map((d) => d.domain) || [])
112
+ )
113
+ ),
114
+ exportCount: node.exports.length,
115
+ contextBudget,
116
+ fragmentationScore,
117
+ relatedFiles: cluster ? cluster.files : [],
118
+ fileClassification,
119
+ severity,
120
+ issues,
121
+ recommendations: allRecommendations,
122
+ potentialSavings,
123
+ };
124
+ }
16
125
 
17
126
  /**
18
127
  * Calculate cohesion score (how related are exports in a file).