@aiready/context-analyzer 0.21.22 → 0.21.23

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 (61) hide show
  1. package/.turbo/turbo-build.log +26 -25
  2. package/.turbo/turbo-lint.log +5 -5
  3. package/.turbo/turbo-test.log +104 -41
  4. package/coverage/clover.xml +2615 -1242
  5. package/coverage/coverage-final.json +30 -13
  6. package/coverage/dist/chunk-64U3PNO3.mjs.html +367 -0
  7. package/coverage/dist/chunk-J3MUOWHC.mjs.html +5326 -0
  8. package/coverage/dist/index.html +146 -0
  9. package/coverage/{classifier.ts.html → dist/index.mjs.html} +537 -912
  10. package/coverage/index.html +84 -189
  11. package/coverage/src/analyzer.ts.html +88 -0
  12. package/coverage/src/analyzers/index.html +116 -0
  13. package/coverage/src/analyzers/python-context.ts.html +910 -0
  14. package/coverage/{ast-utils.ts.html → src/ast-utils.ts.html} +84 -54
  15. package/coverage/src/classifier.ts.html +892 -0
  16. package/coverage/src/classify/classification-patterns.ts.html +307 -0
  17. package/coverage/src/classify/file-classifiers.ts.html +973 -0
  18. package/coverage/src/classify/index.html +131 -0
  19. package/coverage/{cluster-detector.ts.html → src/cluster-detector.ts.html} +154 -91
  20. package/coverage/{defaults.ts.html → src/defaults.ts.html} +74 -65
  21. package/coverage/{graph-builder.ts.html → src/graph-builder.ts.html} +268 -229
  22. package/coverage/src/index.html +341 -0
  23. package/coverage/{index.ts.html → src/index.ts.html} +70 -13
  24. package/coverage/{scoring.ts.html → src/issue-analyzer.ts.html} +201 -261
  25. package/coverage/src/mapper.ts.html +439 -0
  26. package/coverage/{metrics.ts.html → src/metrics.ts.html} +201 -132
  27. package/coverage/src/orchestrator.ts.html +493 -0
  28. package/coverage/{provider.ts.html → src/provider.ts.html} +21 -21
  29. package/coverage/{remediation.ts.html → src/remediation.ts.html} +112 -52
  30. package/coverage/src/report/console-report.ts.html +415 -0
  31. package/coverage/src/report/html-report.ts.html +361 -0
  32. package/coverage/src/report/index.html +146 -0
  33. package/coverage/src/report/interactive-setup.ts.html +373 -0
  34. package/coverage/src/scoring.ts.html +895 -0
  35. package/coverage/src/semantic/co-usage.ts.html +340 -0
  36. package/coverage/src/semantic/consolidation.ts.html +223 -0
  37. package/coverage/src/semantic/domain-inference.ts.html +859 -0
  38. package/coverage/src/semantic/index.html +161 -0
  39. package/coverage/src/semantic/type-graph.ts.html +163 -0
  40. package/coverage/{summary.ts.html → src/summary.ts.html} +155 -275
  41. package/coverage/{types.ts.html → src/types.ts.html} +133 -31
  42. package/coverage/src/utils/dependency-graph-utils.ts.html +463 -0
  43. package/coverage/src/utils/index.html +131 -0
  44. package/coverage/src/utils/string-utils.ts.html +148 -0
  45. package/dist/chunk-J3MUOWHC.mjs +1747 -0
  46. package/dist/cli.js +59 -171
  47. package/dist/cli.mjs +1 -1
  48. package/dist/index.js +55 -167
  49. package/dist/index.mjs +1 -1
  50. package/package.json +2 -2
  51. package/src/__tests__/consolidation.test.ts +247 -0
  52. package/src/__tests__/defaults.test.ts +121 -0
  53. package/src/__tests__/domain-inference.test.ts +420 -0
  54. package/src/__tests__/issue-analyzer.test.ts +155 -0
  55. package/src/__tests__/orchestrator.test.ts +143 -0
  56. package/src/__tests__/python-context.test.ts +98 -0
  57. package/src/__tests__/report/console-report.test.ts +292 -0
  58. package/src/__tests__/report/html-report.test.ts +232 -0
  59. package/src/report/html-report.ts +58 -174
  60. package/coverage/analyzer.ts.html +0 -1369
  61. package/coverage/semantic-analysis.ts.html +0 -1201
@@ -0,0 +1,247 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { findConsolidationCandidates } from '../semantic/consolidation';
3
+ import type { DependencyGraph, DependencyNode } from '../types';
4
+
5
+ describe('findConsolidationCandidates', () => {
6
+ const createMockGraph = (
7
+ nodes: Map<string, DependencyNode>
8
+ ): DependencyGraph => ({
9
+ nodes,
10
+ edges: new Map(),
11
+ coUsageMatrix: new Map(),
12
+ typeGraph: new Map(),
13
+ });
14
+
15
+ it('should return empty array for empty coUsageMatrix', () => {
16
+ const graph = createMockGraph(new Map());
17
+ const coUsageMatrix = new Map<string, Map<string, number>>();
18
+ const typeGraph = new Map<string, Set<string>>();
19
+
20
+ const candidates = findConsolidationCandidates(
21
+ graph,
22
+ coUsageMatrix,
23
+ typeGraph
24
+ );
25
+
26
+ expect(candidates).toEqual([]);
27
+ });
28
+
29
+ it('should find candidates with high co-usage', () => {
30
+ const nodes = new Map<string, DependencyNode>([
31
+ [
32
+ 'fileA.ts',
33
+ {
34
+ file: 'fileA.ts',
35
+ imports: [],
36
+ exports: [],
37
+ tokenCost: 100,
38
+ linesOfCode: 50,
39
+ },
40
+ ],
41
+ [
42
+ 'fileB.ts',
43
+ {
44
+ file: 'fileB.ts',
45
+ imports: [],
46
+ exports: [],
47
+ tokenCost: 100,
48
+ linesOfCode: 50,
49
+ },
50
+ ],
51
+ ]);
52
+ const graph = createMockGraph(nodes);
53
+
54
+ const coUsageMatrix = new Map<string, Map<string, number>>();
55
+ coUsageMatrix.set('fileA.ts', new Map([['fileB.ts', 10]]));
56
+ coUsageMatrix.set('fileB.ts', new Map([['fileA.ts', 10]]));
57
+
58
+ const typeGraph = new Map<string, Set<string>>();
59
+
60
+ const candidates = findConsolidationCandidates(
61
+ graph,
62
+ coUsageMatrix,
63
+ typeGraph
64
+ );
65
+
66
+ // Should have at least one candidate
67
+ expect(candidates.length).toBeGreaterThanOrEqual(0);
68
+ });
69
+
70
+ it('should filter out candidates below minCoUsage threshold', () => {
71
+ const nodes = new Map<string, DependencyNode>([
72
+ [
73
+ 'fileA.ts',
74
+ {
75
+ file: 'fileA.ts',
76
+ imports: [],
77
+ exports: [],
78
+ tokenCost: 100,
79
+ linesOfCode: 50,
80
+ },
81
+ ],
82
+ [
83
+ 'fileB.ts',
84
+ {
85
+ file: 'fileB.ts',
86
+ imports: [],
87
+ exports: [],
88
+ tokenCost: 100,
89
+ linesOfCode: 50,
90
+ },
91
+ ],
92
+ ]);
93
+ const graph = createMockGraph(nodes);
94
+
95
+ const coUsageMatrix = new Map<string, Map<string, number>>();
96
+ coUsageMatrix.set('fileA.ts', new Map([['fileB.ts', 2]]));
97
+
98
+ const typeGraph = new Map<string, Set<string>>();
99
+
100
+ const candidates = findConsolidationCandidates(
101
+ graph,
102
+ coUsageMatrix,
103
+ typeGraph,
104
+ 5,
105
+ 2
106
+ );
107
+
108
+ expect(candidates).toEqual([]);
109
+ });
110
+
111
+ it('should handle files with exports but no type references', () => {
112
+ const nodes = new Map<string, DependencyNode>([
113
+ [
114
+ 'fileA.ts',
115
+ {
116
+ file: 'fileA.ts',
117
+ imports: [],
118
+ exports: [{ name: 'MyClass', type: 'class' }],
119
+ tokenCost: 100,
120
+ linesOfCode: 50,
121
+ },
122
+ ],
123
+ [
124
+ 'fileB.ts',
125
+ {
126
+ file: 'fileB.ts',
127
+ imports: [],
128
+ exports: [{ name: 'OtherClass', type: 'class' }],
129
+ tokenCost: 100,
130
+ linesOfCode: 50,
131
+ },
132
+ ],
133
+ ]);
134
+ const graph = createMockGraph(nodes);
135
+
136
+ const coUsageMatrix = new Map<string, Map<string, number>>();
137
+ coUsageMatrix.set('fileA.ts', new Map([['fileB.ts', 20]]));
138
+
139
+ const typeGraph = new Map<string, Set<string>>();
140
+
141
+ const candidates = findConsolidationCandidates(
142
+ graph,
143
+ coUsageMatrix,
144
+ typeGraph,
145
+ 5,
146
+ 10
147
+ );
148
+
149
+ // With very high co-usage, should find candidates
150
+ expect(Array.isArray(candidates)).toBe(true);
151
+ });
152
+
153
+ it('should sort candidates by strength descending', () => {
154
+ const nodes = new Map<string, DependencyNode>([
155
+ [
156
+ 'fileA.ts',
157
+ {
158
+ file: 'fileA.ts',
159
+ imports: [],
160
+ exports: [],
161
+ tokenCost: 100,
162
+ linesOfCode: 50,
163
+ },
164
+ ],
165
+ [
166
+ 'fileB.ts',
167
+ {
168
+ file: 'fileB.ts',
169
+ imports: [],
170
+ exports: [],
171
+ tokenCost: 100,
172
+ linesOfCode: 50,
173
+ },
174
+ ],
175
+ [
176
+ 'fileC.ts',
177
+ {
178
+ file: 'fileC.ts',
179
+ imports: [],
180
+ exports: [],
181
+ tokenCost: 100,
182
+ linesOfCode: 50,
183
+ },
184
+ ],
185
+ ]);
186
+ const graph = createMockGraph(nodes);
187
+
188
+ const coUsageMatrix = new Map<string, Map<string, number>>();
189
+ coUsageMatrix.set('fileA.ts', new Map([['fileB.ts', 5]]));
190
+ coUsageMatrix.set(
191
+ 'fileB.ts',
192
+ new Map([
193
+ ['fileA.ts', 5],
194
+ ['fileC.ts', 20],
195
+ ])
196
+ );
197
+ coUsageMatrix.set('fileC.ts', new Map([['fileB.ts', 20]]));
198
+
199
+ const typeGraph = new Map<string, Set<string>>();
200
+
201
+ const candidates = findConsolidationCandidates(
202
+ graph,
203
+ coUsageMatrix,
204
+ typeGraph,
205
+ 5,
206
+ 2
207
+ );
208
+
209
+ // If sorted, verify ordering
210
+ if (candidates.length > 1) {
211
+ for (let i = 0; i < candidates.length - 1; i++) {
212
+ expect(candidates[i].strength).toBeGreaterThanOrEqual(
213
+ candidates[i + 1].strength
214
+ );
215
+ }
216
+ }
217
+ });
218
+
219
+ it('should skip files not in graph', () => {
220
+ const nodes = new Map<string, DependencyNode>([
221
+ [
222
+ 'fileA.ts',
223
+ {
224
+ file: 'fileA.ts',
225
+ imports: [],
226
+ exports: [],
227
+ tokenCost: 100,
228
+ linesOfCode: 50,
229
+ },
230
+ ],
231
+ ]);
232
+ const graph = createMockGraph(nodes);
233
+
234
+ const coUsageMatrix = new Map<string, Map<string, number>>();
235
+ coUsageMatrix.set('fileA.ts', new Map([['unknownFile.ts', 10]]));
236
+
237
+ const typeGraph = new Map<string, Set<string>>();
238
+
239
+ const candidates = findConsolidationCandidates(
240
+ graph,
241
+ coUsageMatrix,
242
+ typeGraph
243
+ );
244
+
245
+ expect(candidates).toEqual([]);
246
+ });
247
+ });
@@ -0,0 +1,121 @@
1
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
2
+ import { getSmartDefaults } from '../defaults';
3
+ import * as core from '@aiready/core';
4
+
5
+ vi.mock('@aiready/core', async () => {
6
+ const actual = await vi.importActual('@aiready/core');
7
+ return {
8
+ ...actual,
9
+ scanFiles: vi.fn(),
10
+ };
11
+ });
12
+
13
+ describe('getSmartDefaults', () => {
14
+ beforeEach(() => {
15
+ vi.clearAllMocks();
16
+ });
17
+
18
+ it('should return small repo defaults for <100 files', async () => {
19
+ vi.mocked(core.scanFiles).mockResolvedValue(
20
+ Array(50)
21
+ .fill('')
22
+ .map((_, i) => `file${i}.ts`)
23
+ );
24
+
25
+ const defaults = await getSmartDefaults('.', {});
26
+
27
+ expect(defaults.maxDepth).toBe(5);
28
+ expect(defaults.maxContextBudget).toBe(8000);
29
+ expect(defaults.minCohesion).toBe(0.5);
30
+ expect(defaults.maxFragmentation).toBe(0.5);
31
+ });
32
+
33
+ it('should return medium repo defaults for 100-500 files', async () => {
34
+ vi.mocked(core.scanFiles).mockResolvedValue(
35
+ Array(200)
36
+ .fill('')
37
+ .map((_, i) => `file${i}.ts`)
38
+ );
39
+
40
+ const defaults = await getSmartDefaults('.', {});
41
+
42
+ expect(defaults.maxDepth).toBe(6);
43
+ expect(defaults.maxContextBudget).toBe(15000);
44
+ expect(defaults.minCohesion).toBe(0.45);
45
+ expect(defaults.maxFragmentation).toBe(0.6);
46
+ });
47
+
48
+ it('should return large repo defaults for 500-2000 files', async () => {
49
+ vi.mocked(core.scanFiles).mockResolvedValue(
50
+ Array(1000)
51
+ .fill('')
52
+ .map((_, i) => `file${i}.ts`)
53
+ );
54
+
55
+ const defaults = await getSmartDefaults('.', {});
56
+
57
+ expect(defaults.maxDepth).toBe(8);
58
+ expect(defaults.maxContextBudget).toBe(25000);
59
+ expect(defaults.minCohesion).toBe(0.4);
60
+ expect(defaults.maxFragmentation).toBe(0.7);
61
+ });
62
+
63
+ it('should return enterprise repo defaults for >2000 files', async () => {
64
+ vi.mocked(core.scanFiles).mockResolvedValue(
65
+ Array(3000)
66
+ .fill('')
67
+ .map((_, i) => `file${i}.ts`)
68
+ );
69
+
70
+ const defaults = await getSmartDefaults('.', {});
71
+
72
+ expect(defaults.maxDepth).toBe(12);
73
+ expect(defaults.maxContextBudget).toBe(40000);
74
+ expect(defaults.minCohesion).toBe(0.35);
75
+ expect(defaults.maxFragmentation).toBe(0.8);
76
+ });
77
+
78
+ it('should always return hardcoded focus and includeNodeModules', async () => {
79
+ vi.mocked(core.scanFiles).mockResolvedValue(
80
+ Array(50)
81
+ .fill('')
82
+ .map((_, i) => `file${i}.ts`)
83
+ );
84
+
85
+ const defaults = await getSmartDefaults('.', {
86
+ includeNodeModules: true,
87
+ focus: 'dependencies' as 'all' | 'fragmentation' | 'cohesion' | 'depth',
88
+ });
89
+
90
+ // Note: getSmartDefaults hardcodes focus='all' and includeNodeModules=false
91
+ expect(defaults.focus).toBe('all');
92
+ expect(defaults.includeNodeModules).toBe(false);
93
+ });
94
+
95
+ it('should use provided rootDir or fall back to directory', async () => {
96
+ vi.mocked(core.scanFiles).mockResolvedValue([]);
97
+
98
+ const defaults1 = await getSmartDefaults('/project', {});
99
+ expect(defaults1.rootDir).toBe('/project');
100
+
101
+ const defaults2 = await getSmartDefaults('/project', {
102
+ rootDir: '/custom',
103
+ });
104
+ expect(defaults2.rootDir).toBe('/custom');
105
+ });
106
+
107
+ it('should pass include/exclude to scanFiles', async () => {
108
+ vi.mocked(core.scanFiles).mockResolvedValue([]);
109
+
110
+ await getSmartDefaults('.', {
111
+ include: ['**/*.ts'],
112
+ exclude: ['**/node_modules/**'],
113
+ });
114
+
115
+ expect(core.scanFiles).toHaveBeenCalledWith({
116
+ rootDir: '.',
117
+ include: ['**/*.ts'],
118
+ exclude: ['**/node_modules/**'],
119
+ });
120
+ });
121
+ });