@aiready/context-analyzer 0.17.0 → 0.17.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.
package/dist/cli.js CHANGED
@@ -37,7 +37,7 @@ __export(python_context_exports, {
37
37
  });
38
38
  async function analyzePythonContext(files, rootDir) {
39
39
  const results = [];
40
- const parser = (0, import_core6.getParser)("dummy.py");
40
+ const parser = (0, import_core7.getParser)("dummy.py");
41
41
  if (!parser) {
42
42
  console.warn("Python parser not available");
43
43
  return results;
@@ -101,7 +101,7 @@ async function analyzePythonContext(files, rootDir) {
101
101
  }
102
102
  async function buildPythonDependencyGraph(files, rootDir) {
103
103
  const graph = /* @__PURE__ */ new Map();
104
- const parser = (0, import_core6.getParser)("dummy.py");
104
+ const parser = (0, import_core7.getParser)("dummy.py");
105
105
  if (!parser) return graph;
106
106
  for (const file of files) {
107
107
  try {
@@ -181,7 +181,7 @@ async function calculatePythonImportDepth(file, dependencyGraph, visited, depth
181
181
  }
182
182
  function estimateContextBudget(code, imports, dependencyGraph) {
183
183
  void dependencyGraph;
184
- let budget = (0, import_core6.estimateTokens)(code);
184
+ let budget = (0, import_core7.estimateTokens)(code);
185
185
  const avgTokensPerDep = 500;
186
186
  budget += imports.length * avgTokensPerDep;
187
187
  return budget;
@@ -231,11 +231,11 @@ function detectCircularDependencies2(file, dependencyGraph) {
231
231
  dfs(file, []);
232
232
  return [...new Set(circular)];
233
233
  }
234
- var import_core6, import_path, import_fs;
234
+ var import_core7, import_path, import_fs;
235
235
  var init_python_context = __esm({
236
236
  "src/analyzers/python-context.ts"() {
237
237
  "use strict";
238
- import_core6 = require("@aiready/core");
238
+ import_core7 = require("@aiready/core");
239
239
  import_path = require("path");
240
240
  import_fs = __toESM(require("fs"));
241
241
  }
@@ -245,7 +245,10 @@ var init_python_context = __esm({
245
245
  var import_commander = require("commander");
246
246
 
247
247
  // src/index.ts
248
- var import_core7 = require("@aiready/core");
248
+ var import_core8 = require("@aiready/core");
249
+
250
+ // src/analyzer.ts
251
+ var import_core4 = require("@aiready/core");
249
252
 
250
253
  // src/metrics.ts
251
254
  var import_core2 = require("@aiready/core");
@@ -1255,10 +1258,10 @@ function analyzeIssues(params) {
1255
1258
  } = params;
1256
1259
  const issues = [];
1257
1260
  const recommendations = [];
1258
- let severity = "info";
1261
+ let severity = import_core4.Severity.Info;
1259
1262
  let potentialSavings = 0;
1260
1263
  if (circularDeps.length > 0) {
1261
- severity = "critical";
1264
+ severity = import_core4.Severity.Critical;
1262
1265
  issues.push(`Part of ${circularDeps.length} circular dependency chain(s)`);
1263
1266
  recommendations.push(
1264
1267
  "Break circular dependencies by extracting interfaces or using dependency injection"
@@ -1266,12 +1269,12 @@ function analyzeIssues(params) {
1266
1269
  potentialSavings += contextBudget * 0.2;
1267
1270
  }
1268
1271
  if (importDepth > maxDepth * 1.5) {
1269
- severity = "critical";
1272
+ severity = import_core4.Severity.Critical;
1270
1273
  issues.push(`Import depth ${importDepth} exceeds limit by 50%`);
1271
1274
  recommendations.push("Flatten dependency tree or use facade pattern");
1272
1275
  potentialSavings += contextBudget * 0.3;
1273
1276
  } else if (importDepth > maxDepth) {
1274
- if (severity !== "critical") severity = "major";
1277
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1275
1278
  issues.push(
1276
1279
  `Import depth ${importDepth} exceeds recommended maximum ${maxDepth}`
1277
1280
  );
@@ -1279,7 +1282,7 @@ function analyzeIssues(params) {
1279
1282
  potentialSavings += contextBudget * 0.15;
1280
1283
  }
1281
1284
  if (contextBudget > maxContextBudget * 1.5) {
1282
- severity = "critical";
1285
+ severity = import_core4.Severity.Critical;
1283
1286
  issues.push(
1284
1287
  `Context budget ${contextBudget.toLocaleString()} tokens is 50% over limit`
1285
1288
  );
@@ -1288,7 +1291,7 @@ function analyzeIssues(params) {
1288
1291
  );
1289
1292
  potentialSavings += contextBudget * 0.4;
1290
1293
  } else if (contextBudget > maxContextBudget) {
1291
- if (severity !== "critical") severity = "major";
1294
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1292
1295
  issues.push(
1293
1296
  `Context budget ${contextBudget.toLocaleString()} exceeds ${maxContextBudget.toLocaleString()}`
1294
1297
  );
@@ -1296,7 +1299,7 @@ function analyzeIssues(params) {
1296
1299
  potentialSavings += contextBudget * 0.2;
1297
1300
  }
1298
1301
  if (cohesionScore < minCohesion * 0.5) {
1299
- if (severity !== "critical") severity = "major";
1302
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1300
1303
  issues.push(
1301
1304
  `Very low cohesion (${(cohesionScore * 100).toFixed(0)}%) - mixed concerns`
1302
1305
  );
@@ -1305,13 +1308,14 @@ function analyzeIssues(params) {
1305
1308
  );
1306
1309
  potentialSavings += contextBudget * 0.25;
1307
1310
  } else if (cohesionScore < minCohesion) {
1308
- if (severity === "info") severity = "minor";
1311
+ if (severity === import_core4.Severity.Info) severity = import_core4.Severity.Minor;
1309
1312
  issues.push(`Low cohesion (${(cohesionScore * 100).toFixed(0)}%)`);
1310
1313
  recommendations.push("Consider grouping related exports together");
1311
1314
  potentialSavings += contextBudget * 0.1;
1312
1315
  }
1313
1316
  if (fragmentationScore > maxFragmentation) {
1314
- if (severity === "info" || severity === "minor") severity = "minor";
1317
+ if (severity === import_core4.Severity.Info || severity === import_core4.Severity.Minor)
1318
+ severity = import_core4.Severity.Minor;
1315
1319
  issues.push(
1316
1320
  `High fragmentation (${(fragmentationScore * 100).toFixed(0)}%) - scattered implementation`
1317
1321
  );
@@ -1325,7 +1329,7 @@ function analyzeIssues(params) {
1325
1329
  if (isBuildArtifact(file)) {
1326
1330
  issues.push("Detected build artifact (bundled/output file)");
1327
1331
  recommendations.push("Exclude build outputs from analysis");
1328
- severity = "info";
1332
+ severity = import_core4.Severity.Info;
1329
1333
  potentialSavings = 0;
1330
1334
  }
1331
1335
  return {
@@ -1341,10 +1345,10 @@ function isBuildArtifact(filePath) {
1341
1345
  }
1342
1346
 
1343
1347
  // src/scoring.ts
1344
- var import_core4 = require("@aiready/core");
1348
+ var import_core5 = require("@aiready/core");
1345
1349
 
1346
1350
  // src/defaults.ts
1347
- var import_core5 = require("@aiready/core");
1351
+ var import_core6 = require("@aiready/core");
1348
1352
 
1349
1353
  // src/summary.ts
1350
1354
  function generateSummary(results) {
@@ -1484,7 +1488,7 @@ async function analyzeContext(options) {
1484
1488
  includeNodeModules = false,
1485
1489
  ...scanOptions
1486
1490
  } = options;
1487
- const files = await (0, import_core7.scanFiles)({
1491
+ const files = await (0, import_core8.scanFiles)({
1488
1492
  ...scanOptions,
1489
1493
  exclude: includeNodeModules && scanOptions.exclude ? scanOptions.exclude.filter(
1490
1494
  (pattern) => pattern !== "**/node_modules/**"
@@ -1494,7 +1498,7 @@ async function analyzeContext(options) {
1494
1498
  const fileContents = await Promise.all(
1495
1499
  files.map(async (file) => ({
1496
1500
  file,
1497
- content: await (0, import_core7.readFileContent)(file)
1501
+ content: await (0, import_core8.readFileContent)(file)
1498
1502
  }))
1499
1503
  );
1500
1504
  const graph = buildDependencyGraph(
@@ -1661,7 +1665,7 @@ async function analyzeContext(options) {
1661
1665
  var import_chalk = __toESM(require("chalk"));
1662
1666
  var import_fs2 = require("fs");
1663
1667
  var import_path2 = require("path");
1664
- var import_core8 = require("@aiready/core");
1668
+ var import_core9 = require("@aiready/core");
1665
1669
  var import_prompts = __toESM(require("prompts"));
1666
1670
  var program = new import_commander.Command();
1667
1671
  program.name("aiready-context").description("Analyze AI context window cost and code structure").version("0.1.0").addHelpText(
@@ -1701,7 +1705,7 @@ program.name("aiready-context").description("Analyze AI context window cost and
1701
1705
  exclude: void 0,
1702
1706
  maxResults: 10
1703
1707
  };
1704
- let finalOptions = await (0, import_core8.loadMergedConfig)(directory, defaults, {
1708
+ let finalOptions = await (0, import_core9.loadMergedConfig)(directory, defaults, {
1705
1709
  maxDepth: options.maxDepth ? parseInt(options.maxDepth) : void 0,
1706
1710
  maxContextBudget: options.maxContext ? parseInt(options.maxContext) : void 0,
1707
1711
  minCohesion: options.minCohesion ? parseFloat(options.minCohesion) : void 0,
@@ -1716,7 +1720,7 @@ program.name("aiready-context").description("Analyze AI context window cost and
1716
1720
  finalOptions = await runInteractiveSetup(directory, finalOptions);
1717
1721
  }
1718
1722
  const results = await analyzeContext(finalOptions);
1719
- const elapsedTime = (0, import_core8.getElapsedTime)(startTime);
1723
+ const elapsedTime = (0, import_core9.getElapsedTime)(startTime);
1720
1724
  const summary = generateSummary(results);
1721
1725
  if (options.output === "json") {
1722
1726
  const jsonOutput = {
@@ -1725,12 +1729,12 @@ program.name("aiready-context").description("Analyze AI context window cost and
1725
1729
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1726
1730
  analysisTime: elapsedTime
1727
1731
  };
1728
- const outputPath = (0, import_core8.resolveOutputPath)(
1732
+ const outputPath = (0, import_core9.resolveOutputPath)(
1729
1733
  options.outputFile,
1730
1734
  `context-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.json`,
1731
1735
  directory
1732
1736
  );
1733
- (0, import_core8.handleJSONOutput)(
1737
+ (0, import_core9.handleJSONOutput)(
1734
1738
  jsonOutput,
1735
1739
  outputPath,
1736
1740
  `
@@ -1740,7 +1744,7 @@ program.name("aiready-context").description("Analyze AI context window cost and
1740
1744
  }
1741
1745
  if (options.output === "html") {
1742
1746
  const html = generateHTMLReport(summary, results);
1743
- const outputPath = (0, import_core8.resolveOutputPath)(
1747
+ const outputPath = (0, import_core9.resolveOutputPath)(
1744
1748
  options.outputFile,
1745
1749
  `context-report-${(/* @__PURE__ */ new Date()).toISOString().split("T")[0]}.html`,
1746
1750
  directory
@@ -1762,7 +1766,7 @@ program.name("aiready-context").description("Analyze AI context window cost and
1762
1766
  );
1763
1767
  displayTuningGuidance(results, finalOptions);
1764
1768
  } catch (error) {
1765
- (0, import_core8.handleCLIError)(error, "Analysis");
1769
+ (0, import_core9.handleCLIError)(error, "Analysis");
1766
1770
  }
1767
1771
  });
1768
1772
  program.parse();
package/dist/cli.mjs CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  analyzeContext,
4
4
  generateSummary
5
- } from "./chunk-GFADGYXZ.mjs";
5
+ } from "./chunk-7VK3XTSH.mjs";
6
6
 
7
7
  // src/cli.ts
8
8
  import { Command } from "commander";
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { ScanOptions, CostConfig, ToolScoringOutput } from '@aiready/core';
1
+ import { Severity, ScanOptions, CostConfig, ToolScoringOutput } from '@aiready/core';
2
2
 
3
3
  interface ContextAnalyzerOptions extends ScanOptions {
4
4
  maxDepth?: number;
@@ -23,7 +23,7 @@ interface ContextAnalysisResult {
23
23
  fragmentationScore: number;
24
24
  relatedFiles: string[];
25
25
  fileClassification: FileClassification;
26
- severity: 'critical' | 'major' | 'minor' | 'info';
26
+ severity: Severity | 'critical' | 'major' | 'minor' | 'info';
27
27
  issues: string[];
28
28
  recommendations: string[];
29
29
  potentialSavings: number;
@@ -294,7 +294,7 @@ declare function analyzeIssues(params: {
294
294
  maxFragmentation: number;
295
295
  circularDeps: string[][];
296
296
  }): {
297
- severity: ContextAnalysisResult['severity'];
297
+ severity: Severity;
298
298
  issues: string[];
299
299
  recommendations: string[];
300
300
  potentialSavings: number;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ScanOptions, CostConfig, ToolScoringOutput } from '@aiready/core';
1
+ import { Severity, ScanOptions, CostConfig, ToolScoringOutput } from '@aiready/core';
2
2
 
3
3
  interface ContextAnalyzerOptions extends ScanOptions {
4
4
  maxDepth?: number;
@@ -23,7 +23,7 @@ interface ContextAnalysisResult {
23
23
  fragmentationScore: number;
24
24
  relatedFiles: string[];
25
25
  fileClassification: FileClassification;
26
- severity: 'critical' | 'major' | 'minor' | 'info';
26
+ severity: Severity | 'critical' | 'major' | 'minor' | 'info';
27
27
  issues: string[];
28
28
  recommendations: string[];
29
29
  potentialSavings: number;
@@ -294,7 +294,7 @@ declare function analyzeIssues(params: {
294
294
  maxFragmentation: number;
295
295
  circularDeps: string[][];
296
296
  }): {
297
- severity: ContextAnalysisResult['severity'];
297
+ severity: Severity;
298
298
  issues: string[];
299
299
  recommendations: string[];
300
300
  potentialSavings: number;
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ __export(python_context_exports, {
37
37
  });
38
38
  async function analyzePythonContext(files, rootDir) {
39
39
  const results = [];
40
- const parser = (0, import_core6.getParser)("dummy.py");
40
+ const parser = (0, import_core7.getParser)("dummy.py");
41
41
  if (!parser) {
42
42
  console.warn("Python parser not available");
43
43
  return results;
@@ -101,7 +101,7 @@ async function analyzePythonContext(files, rootDir) {
101
101
  }
102
102
  async function buildPythonDependencyGraph(files, rootDir) {
103
103
  const graph = /* @__PURE__ */ new Map();
104
- const parser = (0, import_core6.getParser)("dummy.py");
104
+ const parser = (0, import_core7.getParser)("dummy.py");
105
105
  if (!parser) return graph;
106
106
  for (const file of files) {
107
107
  try {
@@ -181,7 +181,7 @@ async function calculatePythonImportDepth(file, dependencyGraph, visited, depth
181
181
  }
182
182
  function estimateContextBudget(code, imports, dependencyGraph) {
183
183
  void dependencyGraph;
184
- let budget = (0, import_core6.estimateTokens)(code);
184
+ let budget = (0, import_core7.estimateTokens)(code);
185
185
  const avgTokensPerDep = 500;
186
186
  budget += imports.length * avgTokensPerDep;
187
187
  return budget;
@@ -231,11 +231,11 @@ function detectCircularDependencies2(file, dependencyGraph) {
231
231
  dfs(file, []);
232
232
  return [...new Set(circular)];
233
233
  }
234
- var import_core6, import_path, import_fs;
234
+ var import_core7, import_path, import_fs;
235
235
  var init_python_context = __esm({
236
236
  "src/analyzers/python-context.ts"() {
237
237
  "use strict";
238
- import_core6 = require("@aiready/core");
238
+ import_core7 = require("@aiready/core");
239
239
  import_path = require("path");
240
240
  import_fs = __toESM(require("fs"));
241
241
  }
@@ -290,7 +290,10 @@ __export(index_exports, {
290
290
  mapScoreToRating: () => mapScoreToRating
291
291
  });
292
292
  module.exports = __toCommonJS(index_exports);
293
- var import_core7 = require("@aiready/core");
293
+ var import_core8 = require("@aiready/core");
294
+
295
+ // src/analyzer.ts
296
+ var import_core4 = require("@aiready/core");
294
297
 
295
298
  // src/metrics.ts
296
299
  var import_core2 = require("@aiready/core");
@@ -1415,10 +1418,10 @@ function analyzeIssues(params) {
1415
1418
  } = params;
1416
1419
  const issues = [];
1417
1420
  const recommendations = [];
1418
- let severity = "info";
1421
+ let severity = import_core4.Severity.Info;
1419
1422
  let potentialSavings = 0;
1420
1423
  if (circularDeps.length > 0) {
1421
- severity = "critical";
1424
+ severity = import_core4.Severity.Critical;
1422
1425
  issues.push(`Part of ${circularDeps.length} circular dependency chain(s)`);
1423
1426
  recommendations.push(
1424
1427
  "Break circular dependencies by extracting interfaces or using dependency injection"
@@ -1426,12 +1429,12 @@ function analyzeIssues(params) {
1426
1429
  potentialSavings += contextBudget * 0.2;
1427
1430
  }
1428
1431
  if (importDepth > maxDepth * 1.5) {
1429
- severity = "critical";
1432
+ severity = import_core4.Severity.Critical;
1430
1433
  issues.push(`Import depth ${importDepth} exceeds limit by 50%`);
1431
1434
  recommendations.push("Flatten dependency tree or use facade pattern");
1432
1435
  potentialSavings += contextBudget * 0.3;
1433
1436
  } else if (importDepth > maxDepth) {
1434
- if (severity !== "critical") severity = "major";
1437
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1435
1438
  issues.push(
1436
1439
  `Import depth ${importDepth} exceeds recommended maximum ${maxDepth}`
1437
1440
  );
@@ -1439,7 +1442,7 @@ function analyzeIssues(params) {
1439
1442
  potentialSavings += contextBudget * 0.15;
1440
1443
  }
1441
1444
  if (contextBudget > maxContextBudget * 1.5) {
1442
- severity = "critical";
1445
+ severity = import_core4.Severity.Critical;
1443
1446
  issues.push(
1444
1447
  `Context budget ${contextBudget.toLocaleString()} tokens is 50% over limit`
1445
1448
  );
@@ -1448,7 +1451,7 @@ function analyzeIssues(params) {
1448
1451
  );
1449
1452
  potentialSavings += contextBudget * 0.4;
1450
1453
  } else if (contextBudget > maxContextBudget) {
1451
- if (severity !== "critical") severity = "major";
1454
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1452
1455
  issues.push(
1453
1456
  `Context budget ${contextBudget.toLocaleString()} exceeds ${maxContextBudget.toLocaleString()}`
1454
1457
  );
@@ -1456,7 +1459,7 @@ function analyzeIssues(params) {
1456
1459
  potentialSavings += contextBudget * 0.2;
1457
1460
  }
1458
1461
  if (cohesionScore < minCohesion * 0.5) {
1459
- if (severity !== "critical") severity = "major";
1462
+ if (severity !== import_core4.Severity.Critical) severity = import_core4.Severity.Major;
1460
1463
  issues.push(
1461
1464
  `Very low cohesion (${(cohesionScore * 100).toFixed(0)}%) - mixed concerns`
1462
1465
  );
@@ -1465,13 +1468,14 @@ function analyzeIssues(params) {
1465
1468
  );
1466
1469
  potentialSavings += contextBudget * 0.25;
1467
1470
  } else if (cohesionScore < minCohesion) {
1468
- if (severity === "info") severity = "minor";
1471
+ if (severity === import_core4.Severity.Info) severity = import_core4.Severity.Minor;
1469
1472
  issues.push(`Low cohesion (${(cohesionScore * 100).toFixed(0)}%)`);
1470
1473
  recommendations.push("Consider grouping related exports together");
1471
1474
  potentialSavings += contextBudget * 0.1;
1472
1475
  }
1473
1476
  if (fragmentationScore > maxFragmentation) {
1474
- if (severity === "info" || severity === "minor") severity = "minor";
1477
+ if (severity === import_core4.Severity.Info || severity === import_core4.Severity.Minor)
1478
+ severity = import_core4.Severity.Minor;
1475
1479
  issues.push(
1476
1480
  `High fragmentation (${(fragmentationScore * 100).toFixed(0)}%) - scattered implementation`
1477
1481
  );
@@ -1485,7 +1489,7 @@ function analyzeIssues(params) {
1485
1489
  if (isBuildArtifact(file)) {
1486
1490
  issues.push("Detected build artifact (bundled/output file)");
1487
1491
  recommendations.push("Exclude build outputs from analysis");
1488
- severity = "info";
1492
+ severity = import_core4.Severity.Info;
1489
1493
  potentialSavings = 0;
1490
1494
  }
1491
1495
  return {
@@ -1501,7 +1505,7 @@ function isBuildArtifact(filePath) {
1501
1505
  }
1502
1506
 
1503
1507
  // src/scoring.ts
1504
- var import_core4 = require("@aiready/core");
1508
+ var import_core5 = require("@aiready/core");
1505
1509
  function calculateContextScore(summary, costConfig) {
1506
1510
  const {
1507
1511
  avgContextBudget,
@@ -1597,8 +1601,8 @@ function calculateContextScore(summary, costConfig) {
1597
1601
  priority: "high"
1598
1602
  });
1599
1603
  }
1600
- const cfg = { ...import_core4.DEFAULT_COST_CONFIG, ...costConfig };
1601
- const estimatedMonthlyCost = (0, import_core4.calculateMonthlyCost)(
1604
+ const cfg = { ...import_core5.DEFAULT_COST_CONFIG, ...costConfig };
1605
+ const estimatedMonthlyCost = (0, import_core5.calculateMonthlyCost)(
1602
1606
  avgContextBudget * (summary.totalFiles || 1),
1603
1607
  cfg
1604
1608
  );
@@ -1606,7 +1610,7 @@ function calculateContextScore(summary, costConfig) {
1606
1610
  ...Array(criticalIssues).fill({ severity: "critical" }),
1607
1611
  ...Array(majorIssues).fill({ severity: "major" })
1608
1612
  ];
1609
- const productivityImpact = (0, import_core4.calculateProductivityImpact)(issues);
1613
+ const productivityImpact = (0, import_core5.calculateProductivityImpact)(issues);
1610
1614
  return {
1611
1615
  toolName: "context-analyzer",
1612
1616
  score,
@@ -1634,9 +1638,9 @@ function mapScoreToRating(score) {
1634
1638
  }
1635
1639
 
1636
1640
  // src/defaults.ts
1637
- var import_core5 = require("@aiready/core");
1641
+ var import_core6 = require("@aiready/core");
1638
1642
  async function getSmartDefaults(directory, userOptions) {
1639
- const files = await (0, import_core5.scanFiles)({
1643
+ const files = await (0, import_core6.scanFiles)({
1640
1644
  rootDir: directory,
1641
1645
  include: userOptions.include,
1642
1646
  exclude: userOptions.exclude
@@ -1818,7 +1822,7 @@ async function analyzeContext(options) {
1818
1822
  includeNodeModules = false,
1819
1823
  ...scanOptions
1820
1824
  } = options;
1821
- const files = await (0, import_core7.scanFiles)({
1825
+ const files = await (0, import_core8.scanFiles)({
1822
1826
  ...scanOptions,
1823
1827
  exclude: includeNodeModules && scanOptions.exclude ? scanOptions.exclude.filter(
1824
1828
  (pattern) => pattern !== "**/node_modules/**"
@@ -1828,7 +1832,7 @@ async function analyzeContext(options) {
1828
1832
  const fileContents = await Promise.all(
1829
1833
  files.map(async (file) => ({
1830
1834
  file,
1831
- content: await (0, import_core7.readFileContent)(file)
1835
+ content: await (0, import_core8.readFileContent)(file)
1832
1836
  }))
1833
1837
  );
1834
1838
  const graph = buildDependencyGraph(
package/dist/index.mjs CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  isTypeDefinition,
44
44
  isUtilityModule,
45
45
  mapScoreToRating
46
- } from "./chunk-GFADGYXZ.mjs";
46
+ } from "./chunk-7VK3XTSH.mjs";
47
47
  export {
48
48
  adjustCohesionForClassification,
49
49
  adjustFragmentationForClassification,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiready/context-analyzer",
3
- "version": "0.17.0",
3
+ "version": "0.17.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.19.0"
52
+ "@aiready/core": "0.19.3"
53
53
  },
54
54
  "devDependencies": {
55
55
  "@types/node": "^24.0.0",
@@ -1,6 +1,11 @@
1
1
  import { describe, it, expect, vi } from 'vitest';
2
2
  import { analyzeContext, generateSummary } from '../index';
3
- import { validateSpokeOutput } from '../../../core/src/types/contract';
3
+ import {
4
+ validateSpokeOutput,
5
+ SpokeOutputSchema,
6
+ Severity,
7
+ IssueType,
8
+ } from '@aiready/core';
4
9
 
5
10
  // Mock core functions
6
11
  vi.mock('@aiready/core', async (importOriginal) => {
@@ -22,17 +27,49 @@ describe('Context Analyzer Contract Validation', () => {
22
27
 
23
28
  const summary = generateSummary(results);
24
29
 
30
+ // Context analyzer results need mapping to meet the strict AnalysisResult contract
31
+ // because it uses 'file' instead of 'fileName' and 'issues: string[]' instead of 'issues: Issue[]'
32
+ const mappedResults = results.map((r) => ({
33
+ fileName: r.file,
34
+ issues: r.issues.map((msg) => ({
35
+ type: IssueType.ContextFragmentation,
36
+ severity: r.severity as Severity,
37
+ message: msg,
38
+ location: { file: r.file, line: 1 },
39
+ })),
40
+ metrics: {
41
+ tokenCost: r.tokenCost,
42
+ complexityScore: r.cohesionScore * 100,
43
+ },
44
+ }));
45
+
25
46
  const fullOutput = {
26
- results,
47
+ results: mappedResults,
27
48
  summary,
49
+ metadata: {
50
+ toolName: 'context-analyzer',
51
+ version: '0.1.0',
52
+ timestamp: new Date().toISOString(),
53
+ },
28
54
  };
29
55
 
56
+ // 1. Legacy validation
30
57
  const validation = validateSpokeOutput('context-analyzer', fullOutput);
31
58
 
32
59
  if (!validation.valid) {
33
- console.error('Contract Validation Errors:', validation.errors);
60
+ console.error('Contract Validation Errors (Legacy):', validation.errors);
34
61
  }
35
62
 
36
63
  expect(validation.valid).toBe(true);
64
+
65
+ // 2. Zod validation
66
+ const zodResult = SpokeOutputSchema.safeParse(fullOutput);
67
+ if (!zodResult.success) {
68
+ console.error(
69
+ 'Contract Validation Errors (Zod):',
70
+ zodResult.error.format()
71
+ );
72
+ }
73
+ expect(zodResult.success).toBe(true);
37
74
  });
38
75
  });
package/src/analyzer.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { estimateTokens } from '@aiready/core';
1
+ import { estimateTokens, Severity } from '@aiready/core';
2
2
  import type {
3
3
  DependencyGraph,
4
4
  DependencyNode,
@@ -58,7 +58,7 @@ export function analyzeIssues(params: {
58
58
  maxFragmentation: number;
59
59
  circularDeps: string[][];
60
60
  }): {
61
- severity: ContextAnalysisResult['severity'];
61
+ severity: Severity;
62
62
  issues: string[];
63
63
  recommendations: string[];
64
64
  potentialSavings: number;
@@ -78,12 +78,12 @@ export function analyzeIssues(params: {
78
78
 
79
79
  const issues: string[] = [];
80
80
  const recommendations: string[] = [];
81
- let severity: ContextAnalysisResult['severity'] = 'info';
81
+ let severity: Severity = Severity.Info;
82
82
  let potentialSavings = 0;
83
83
 
84
84
  // Check circular dependencies (CRITICAL)
85
85
  if (circularDeps.length > 0) {
86
- severity = 'critical';
86
+ severity = Severity.Critical;
87
87
  issues.push(`Part of ${circularDeps.length} circular dependency chain(s)`);
88
88
  recommendations.push(
89
89
  'Break circular dependencies by extracting interfaces or using dependency injection'
@@ -93,12 +93,12 @@ export function analyzeIssues(params: {
93
93
 
94
94
  // Check import depth
95
95
  if (importDepth > maxDepth * 1.5) {
96
- severity = 'critical';
96
+ severity = Severity.Critical;
97
97
  issues.push(`Import depth ${importDepth} exceeds limit by 50%`);
98
98
  recommendations.push('Flatten dependency tree or use facade pattern');
99
99
  potentialSavings += contextBudget * 0.3;
100
100
  } else if (importDepth > maxDepth) {
101
- if (severity !== 'critical') severity = 'major';
101
+ if (severity !== Severity.Critical) severity = Severity.Major;
102
102
  issues.push(
103
103
  `Import depth ${importDepth} exceeds recommended maximum ${maxDepth}`
104
104
  );
@@ -108,7 +108,7 @@ export function analyzeIssues(params: {
108
108
 
109
109
  // Check context budget
110
110
  if (contextBudget > maxContextBudget * 1.5) {
111
- severity = 'critical';
111
+ severity = Severity.Critical;
112
112
  issues.push(
113
113
  `Context budget ${contextBudget.toLocaleString()} tokens is 50% over limit`
114
114
  );
@@ -117,7 +117,7 @@ export function analyzeIssues(params: {
117
117
  );
118
118
  potentialSavings += contextBudget * 0.4;
119
119
  } else if (contextBudget > maxContextBudget) {
120
- if (severity !== 'critical') severity = 'major';
120
+ if (severity !== Severity.Critical) severity = Severity.Major;
121
121
  issues.push(
122
122
  `Context budget ${contextBudget.toLocaleString()} exceeds ${maxContextBudget.toLocaleString()}`
123
123
  );
@@ -127,7 +127,7 @@ export function analyzeIssues(params: {
127
127
 
128
128
  // Check cohesion
129
129
  if (cohesionScore < minCohesion * 0.5) {
130
- if (severity !== 'critical') severity = 'major';
130
+ if (severity !== Severity.Critical) severity = Severity.Major;
131
131
  issues.push(
132
132
  `Very low cohesion (${(cohesionScore * 100).toFixed(0)}%) - mixed concerns`
133
133
  );
@@ -136,7 +136,7 @@ export function analyzeIssues(params: {
136
136
  );
137
137
  potentialSavings += contextBudget * 0.25;
138
138
  } else if (cohesionScore < minCohesion) {
139
- if (severity === 'info') severity = 'minor';
139
+ if (severity === Severity.Info) severity = Severity.Minor;
140
140
  issues.push(`Low cohesion (${(cohesionScore * 100).toFixed(0)}%)`);
141
141
  recommendations.push('Consider grouping related exports together');
142
142
  potentialSavings += contextBudget * 0.1;
@@ -144,7 +144,8 @@ export function analyzeIssues(params: {
144
144
 
145
145
  // Check fragmentation
146
146
  if (fragmentationScore > maxFragmentation) {
147
- if (severity === 'info' || severity === 'minor') severity = 'minor';
147
+ if (severity === Severity.Info || severity === Severity.Minor)
148
+ severity = Severity.Minor;
148
149
  issues.push(
149
150
  `High fragmentation (${(fragmentationScore * 100).toFixed(0)}%) - scattered implementation`
150
151
  );
@@ -161,7 +162,7 @@ export function analyzeIssues(params: {
161
162
  if (isBuildArtifact(file)) {
162
163
  issues.push('Detected build artifact (bundled/output file)');
163
164
  recommendations.push('Exclude build outputs from analysis');
164
- severity = 'info';
165
+ severity = Severity.Info;
165
166
  potentialSavings = 0;
166
167
  }
167
168
 
package/src/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { ScanOptions } from '@aiready/core';
1
+ import type { ScanOptions, Severity } from '@aiready/core';
2
2
 
3
3
  export interface ContextAnalyzerOptions extends ScanOptions {
4
4
  maxDepth?: number; // Maximum acceptable import depth, default 5
@@ -36,7 +36,7 @@ export interface ContextAnalysisResult {
36
36
  fileClassification: FileClassification; // Type of file for analysis context
37
37
 
38
38
  // Recommendations
39
- severity: 'critical' | 'major' | 'minor' | 'info';
39
+ severity: Severity | 'critical' | 'major' | 'minor' | 'info';
40
40
  issues: string[]; // List of specific problems
41
41
  recommendations: string[]; // Actionable suggestions
42
42
  potentialSavings: number; // Estimated token savings if fixed