claude-mycelium 2.0.0
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/.claude/settings.local.json +14 -0
- package/README.md +304 -0
- package/dist/coordination/gradient-cache.d.ts +48 -0
- package/dist/coordination/gradient-cache.d.ts.map +1 -0
- package/dist/coordination/gradient-cache.js +145 -0
- package/dist/coordination/gradient-cache.js.map +1 -0
- package/dist/coordination/index.d.ts +10 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +10 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/core/agent-executor.d.ts +31 -0
- package/dist/core/agent-executor.d.ts.map +1 -0
- package/dist/core/agent-executor.js +257 -0
- package/dist/core/agent-executor.js.map +1 -0
- package/dist/core/change-applier.d.ts +10 -0
- package/dist/core/change-applier.d.ts.map +1 -0
- package/dist/core/change-applier.js +32 -0
- package/dist/core/change-applier.js.map +1 -0
- package/dist/core/gradient.d.ts +60 -0
- package/dist/core/gradient.d.ts.map +1 -0
- package/dist/core/gradient.js +191 -0
- package/dist/core/gradient.js.map +1 -0
- package/dist/core/index.d.ts +24 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +24 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/mode-selector.d.ts +44 -0
- package/dist/core/mode-selector.d.ts.map +1 -0
- package/dist/core/mode-selector.js +208 -0
- package/dist/core/mode-selector.js.map +1 -0
- package/dist/core/signals/centrality.d.ts +44 -0
- package/dist/core/signals/centrality.d.ts.map +1 -0
- package/dist/core/signals/centrality.js +264 -0
- package/dist/core/signals/centrality.js.map +1 -0
- package/dist/core/signals/churn.d.ts +41 -0
- package/dist/core/signals/churn.d.ts.map +1 -0
- package/dist/core/signals/churn.js +188 -0
- package/dist/core/signals/churn.js.map +1 -0
- package/dist/core/signals/complexity.d.ts +29 -0
- package/dist/core/signals/complexity.d.ts.map +1 -0
- package/dist/core/signals/complexity.js +169 -0
- package/dist/core/signals/complexity.js.map +1 -0
- package/dist/core/signals/debt.d.ts +27 -0
- package/dist/core/signals/debt.d.ts.map +1 -0
- package/dist/core/signals/debt.js +80 -0
- package/dist/core/signals/debt.js.map +1 -0
- package/dist/core/signals/errors.d.ts +32 -0
- package/dist/core/signals/errors.d.ts.map +1 -0
- package/dist/core/signals/errors.js +73 -0
- package/dist/core/signals/errors.js.map +1 -0
- package/dist/core/signals/index.d.ts +19 -0
- package/dist/core/signals/index.d.ts.map +1 -0
- package/dist/core/signals/index.js +19 -0
- package/dist/core/signals/index.js.map +1 -0
- package/dist/cost/cost-tracker.d.ts +90 -0
- package/dist/cost/cost-tracker.d.ts.map +1 -0
- package/dist/cost/cost-tracker.js +305 -0
- package/dist/cost/cost-tracker.js.map +1 -0
- package/dist/cost/index.d.ts +56 -0
- package/dist/cost/index.d.ts.map +1 -0
- package/dist/cost/index.js +111 -0
- package/dist/cost/index.js.map +1 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +40 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/anthropic-client.d.ts +52 -0
- package/dist/llm/anthropic-client.d.ts.map +1 -0
- package/dist/llm/anthropic-client.js +310 -0
- package/dist/llm/anthropic-client.js.map +1 -0
- package/dist/llm/index.d.ts +27 -0
- package/dist/llm/index.d.ts.map +1 -0
- package/dist/llm/index.js +34 -0
- package/dist/llm/index.js.map +1 -0
- package/dist/prompts/complexity-reducer.d.ts +7 -0
- package/dist/prompts/complexity-reducer.d.ts.map +1 -0
- package/dist/prompts/complexity-reducer.js +55 -0
- package/dist/prompts/complexity-reducer.js.map +1 -0
- package/dist/prompts/debt-payer.d.ts +7 -0
- package/dist/prompts/debt-payer.d.ts.map +1 -0
- package/dist/prompts/debt-payer.js +55 -0
- package/dist/prompts/debt-payer.js.map +1 -0
- package/dist/prompts/error-reducer.d.ts +7 -0
- package/dist/prompts/error-reducer.d.ts.map +1 -0
- package/dist/prompts/error-reducer.js +54 -0
- package/dist/prompts/error-reducer.js.map +1 -0
- package/dist/prompts/index.d.ts +22 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +112 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/prompts/stabilizer.d.ts +7 -0
- package/dist/prompts/stabilizer.d.ts.map +1 -0
- package/dist/prompts/stabilizer.js +55 -0
- package/dist/prompts/stabilizer.js.map +1 -0
- package/dist/prompts/types.d.ts +14 -0
- package/dist/prompts/types.d.ts.map +1 -0
- package/dist/prompts/types.js +5 -0
- package/dist/prompts/types.js.map +1 -0
- package/dist/trace/index.d.ts +51 -0
- package/dist/trace/index.d.ts.map +1 -0
- package/dist/trace/index.js +60 -0
- package/dist/trace/index.js.map +1 -0
- package/dist/trace/trace-event.d.ts +72 -0
- package/dist/trace/trace-event.d.ts.map +1 -0
- package/dist/trace/trace-event.js +244 -0
- package/dist/trace/trace-event.js.map +1 -0
- package/dist/types/index.d.ts +206 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +6 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/ci-provider.d.ts +43 -0
- package/dist/utils/ci-provider.d.ts.map +1 -0
- package/dist/utils/ci-provider.js +130 -0
- package/dist/utils/ci-provider.js.map +1 -0
- package/dist/utils/config.d.ts +31 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +85 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/error-provider.d.ts +51 -0
- package/dist/utils/error-provider.d.ts.map +1 -0
- package/dist/utils/error-provider.js +123 -0
- package/dist/utils/error-provider.js.map +1 -0
- package/dist/utils/file-utils.d.ts +18 -0
- package/dist/utils/file-utils.d.ts.map +1 -0
- package/dist/utils/file-utils.js +95 -0
- package/dist/utils/file-utils.js.map +1 -0
- package/dist/utils/index.d.ts +10 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/logger.d.ts +36 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +74 -0
- package/dist/utils/logger.js.map +1 -0
- package/docs/IMPLEMENTATION-STATUS.md +199 -0
- package/docs/PHASE-0-COMPLETE.md +252 -0
- package/docs/PHASE-1-COMPLETE.md +204 -0
- package/docs/PHASE-2-COMPLETE.md +233 -0
- package/docs/PHASE2_COMPLETION_CHECKLIST.md +290 -0
- package/docs/PHASE2_INTEGRATION_SUMMARY.md +255 -0
- package/docs/PHASE2_QUICK_REFERENCE.md +365 -0
- package/docs/PHASE2_TEST_RESULTS.md +282 -0
- package/docs/ROADMAP.md +746 -0
- package/docs/SNAPSHOT.md +376 -0
- package/docs/adrs/ADR-001-signal-computation.md +76 -0
- package/docs/adrs/ADR-002-inhibitor-signals.md +108 -0
- package/docs/adrs/ADR-003-llm-integration.md +156 -0
- package/docs/adrs/ADR-004-process-architecture.md +175 -0
- package/docs/adrs/ADR-005-testing-strategy.md +243 -0
- package/docs/pitch.md +94 -0
- package/docs/specs/fourth-spec.md +1973 -0
- package/docs/specs/initial-spec.md +2096 -0
- package/docs/specs/second-spec.md +2690 -0
- package/package.json +50 -0
- package/src/coordination/gradient-cache.ts +185 -0
- package/src/coordination/index.ts +10 -0
- package/src/core/agent-executor.ts +327 -0
- package/src/core/change-applier.ts +338 -0
- package/src/core/gradient.ts +258 -0
- package/src/core/index.ts +24 -0
- package/src/core/mode-selector.ts +243 -0
- package/src/core/signals/centrality.ts +328 -0
- package/src/core/signals/churn.ts +239 -0
- package/src/core/signals/complexity.ts +206 -0
- package/src/core/signals/debt.ts +111 -0
- package/src/core/signals/errors.ts +93 -0
- package/src/core/signals/index.ts +19 -0
- package/src/cost/cost-tracker.ts +410 -0
- package/src/cost/index.ts +143 -0
- package/src/index.ts +43 -0
- package/src/llm/anthropic-client.ts +415 -0
- package/src/llm/index.ts +43 -0
- package/src/prompts/complexity-reducer.ts +59 -0
- package/src/prompts/debt-payer.ts +59 -0
- package/src/prompts/error-reducer.ts +58 -0
- package/src/prompts/index.ts +128 -0
- package/src/prompts/stabilizer.ts +59 -0
- package/src/prompts/types.ts +15 -0
- package/src/trace/README.md +178 -0
- package/src/trace/index.ts +88 -0
- package/src/trace/trace-event.ts +324 -0
- package/src/types/index.ts +271 -0
- package/src/utils/ci-provider.ts +145 -0
- package/src/utils/config.ts +95 -0
- package/src/utils/error-provider.ts +138 -0
- package/src/utils/file-utils.ts +111 -0
- package/src/utils/index.ts +10 -0
- package/src/utils/logger.ts +94 -0
- package/test-8d713cc8-f4b7-403d-8153-57573172b94c.ts +3 -0
- package/tests/coordination/gradient-cache.test.ts +270 -0
- package/tests/core/agent-executor.test.ts +217 -0
- package/tests/core/change-applier.test.ts +336 -0
- package/tests/core/gradient.test.ts +263 -0
- package/tests/core/mode-selector.test.ts +239 -0
- package/tests/core/signals/centrality.test.ts +512 -0
- package/tests/core/signals/churn.test.ts +355 -0
- package/tests/core/signals/complexity.test.ts +284 -0
- package/tests/core/signals/debt.test.ts +437 -0
- package/tests/core/signals/errors.test.ts +350 -0
- package/tests/cost/cost-tracker.test.ts +475 -0
- package/tests/integration/phase2.test.ts +405 -0
- package/tests/llm/anthropic-client.test.ts +437 -0
- package/tests/prompts/prompts.test.ts +266 -0
- package/tests/trace/trace-event.test.ts +666 -0
- package/tests/utils/file-utils.test.ts +148 -0
- package/tsconfig.json +24 -0
- package/vitest.config.ts +28 -0
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
import { calculateErrorRate, calculateErrorRateBatch } from '../../../src/core/signals/errors';
|
|
5
|
+
|
|
6
|
+
const TEST_DIR = '.test-temp-errors';
|
|
7
|
+
const ERROR_FILE = path.join(TEST_DIR, '.agent-meta', '_errors.json');
|
|
8
|
+
|
|
9
|
+
describe('error signal', () => {
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
// Create test directories
|
|
12
|
+
if (!fs.existsSync(TEST_DIR)) {
|
|
13
|
+
fs.mkdirSync(TEST_DIR, { recursive: true });
|
|
14
|
+
}
|
|
15
|
+
const metaDir = path.join(TEST_DIR, '.agent-meta');
|
|
16
|
+
if (!fs.existsSync(metaDir)) {
|
|
17
|
+
fs.mkdirSync(metaDir, { recursive: true });
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
afterEach(() => {
|
|
22
|
+
if (fs.existsSync(TEST_DIR)) {
|
|
23
|
+
fs.rmSync(TEST_DIR, { recursive: true, force: true });
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
describe('calculateErrorRate', () => {
|
|
28
|
+
it('calculates error rate for file with errors', async () => {
|
|
29
|
+
// Create test file
|
|
30
|
+
const testFile = path.join(TEST_DIR, 'buggy.ts');
|
|
31
|
+
const content = `
|
|
32
|
+
function broken(): void {
|
|
33
|
+
// This file has errors
|
|
34
|
+
console.log('test');
|
|
35
|
+
}
|
|
36
|
+
`.trim();
|
|
37
|
+
fs.writeFileSync(testFile, content);
|
|
38
|
+
|
|
39
|
+
// Create error data
|
|
40
|
+
const errorData = {
|
|
41
|
+
updated_at: new Date().toISOString(),
|
|
42
|
+
errors: [
|
|
43
|
+
{
|
|
44
|
+
file: testFile,
|
|
45
|
+
count: 5,
|
|
46
|
+
types: ['TypeError', 'ReferenceError'],
|
|
47
|
+
},
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
51
|
+
|
|
52
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
53
|
+
|
|
54
|
+
expect(result.count).toBe(5);
|
|
55
|
+
expect(result.types).toEqual(['TypeError', 'ReferenceError']);
|
|
56
|
+
expect(result.normalized).toBeGreaterThan(0);
|
|
57
|
+
expect(result.normalized).toBeLessThanOrEqual(1.0);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('returns zero for file not in error data', async () => {
|
|
61
|
+
const testFile = path.join(TEST_DIR, 'clean.ts');
|
|
62
|
+
const content = `function good(): void { console.log('test'); }`;
|
|
63
|
+
fs.writeFileSync(testFile, content);
|
|
64
|
+
|
|
65
|
+
// Create error data for different file
|
|
66
|
+
const errorData = {
|
|
67
|
+
updated_at: new Date().toISOString(),
|
|
68
|
+
errors: [
|
|
69
|
+
{
|
|
70
|
+
file: path.join(TEST_DIR, 'other.ts'),
|
|
71
|
+
count: 3,
|
|
72
|
+
types: ['TypeError'],
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
77
|
+
|
|
78
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
79
|
+
|
|
80
|
+
expect(result.count).toBe(0);
|
|
81
|
+
expect(result.types).toEqual([]);
|
|
82
|
+
expect(result.normalized).toBe(0);
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
it('returns zero when error file does not exist', async () => {
|
|
86
|
+
const testFile = path.join(TEST_DIR, 'noerrors.ts');
|
|
87
|
+
const content = `function test(): void { console.log('test'); }`;
|
|
88
|
+
fs.writeFileSync(testFile, content);
|
|
89
|
+
|
|
90
|
+
// Don't create error file
|
|
91
|
+
|
|
92
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
93
|
+
|
|
94
|
+
expect(result.count).toBe(0);
|
|
95
|
+
expect(result.types).toEqual([]);
|
|
96
|
+
expect(result.normalized).toBe(0);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('normalizes error rate correctly - low errors', async () => {
|
|
100
|
+
const testFile = path.join(TEST_DIR, 'low-errors.ts');
|
|
101
|
+
// Create file with 100 LOC
|
|
102
|
+
const lines = Array(100)
|
|
103
|
+
.fill('console.log("line");')
|
|
104
|
+
.join('\n');
|
|
105
|
+
fs.writeFileSync(testFile, lines);
|
|
106
|
+
|
|
107
|
+
// 2 errors in 100 LOC = 0.02 errors/LOC
|
|
108
|
+
// (0.02) / 0.1 = 0.2
|
|
109
|
+
const errorData = {
|
|
110
|
+
updated_at: new Date().toISOString(),
|
|
111
|
+
errors: [
|
|
112
|
+
{
|
|
113
|
+
file: testFile,
|
|
114
|
+
count: 2,
|
|
115
|
+
types: ['TypeError'],
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
};
|
|
119
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
120
|
+
|
|
121
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
122
|
+
|
|
123
|
+
expect(result.count).toBe(2);
|
|
124
|
+
expect(result.normalized).toBeCloseTo(0.2, 1);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it('normalizes error rate correctly - high errors', async () => {
|
|
128
|
+
const testFile = path.join(TEST_DIR, 'high-errors.ts');
|
|
129
|
+
// Create file with 50 LOC
|
|
130
|
+
const lines = Array(50)
|
|
131
|
+
.fill('console.log("line");')
|
|
132
|
+
.join('\n');
|
|
133
|
+
fs.writeFileSync(testFile, lines);
|
|
134
|
+
|
|
135
|
+
// 10 errors in 50 LOC = 0.2 errors/LOC
|
|
136
|
+
// (0.2) / 0.1 = 2.0, capped at 1.0
|
|
137
|
+
const errorData = {
|
|
138
|
+
updated_at: new Date().toISOString(),
|
|
139
|
+
errors: [
|
|
140
|
+
{
|
|
141
|
+
file: testFile,
|
|
142
|
+
count: 10,
|
|
143
|
+
types: ['TypeError', 'ReferenceError', 'SyntaxError'],
|
|
144
|
+
},
|
|
145
|
+
],
|
|
146
|
+
};
|
|
147
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
148
|
+
|
|
149
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
150
|
+
|
|
151
|
+
expect(result.count).toBe(10);
|
|
152
|
+
expect(result.normalized).toBe(1.0); // Capped at 1.0
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it('normalizes error rate correctly - exact threshold', async () => {
|
|
156
|
+
const testFile = path.join(TEST_DIR, 'threshold.ts');
|
|
157
|
+
// Create file with 100 LOC
|
|
158
|
+
const lines = Array(100)
|
|
159
|
+
.fill('console.log("line");')
|
|
160
|
+
.join('\n');
|
|
161
|
+
fs.writeFileSync(testFile, lines);
|
|
162
|
+
|
|
163
|
+
// 10 errors in 100 LOC = 0.1 errors/LOC (exactly at threshold)
|
|
164
|
+
// (0.1) / 0.1 = 1.0
|
|
165
|
+
const errorData = {
|
|
166
|
+
updated_at: new Date().toISOString(),
|
|
167
|
+
errors: [
|
|
168
|
+
{
|
|
169
|
+
file: testFile,
|
|
170
|
+
count: 10,
|
|
171
|
+
types: ['TypeError'],
|
|
172
|
+
},
|
|
173
|
+
],
|
|
174
|
+
};
|
|
175
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
176
|
+
|
|
177
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
178
|
+
|
|
179
|
+
expect(result.count).toBe(10);
|
|
180
|
+
expect(result.normalized).toBe(1.0);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('handles file with single error', async () => {
|
|
184
|
+
const testFile = path.join(TEST_DIR, 'single-error.ts');
|
|
185
|
+
const content = `
|
|
186
|
+
function test(): void {
|
|
187
|
+
console.log('test');
|
|
188
|
+
}
|
|
189
|
+
`.trim();
|
|
190
|
+
fs.writeFileSync(testFile, content);
|
|
191
|
+
|
|
192
|
+
const errorData = {
|
|
193
|
+
updated_at: new Date().toISOString(),
|
|
194
|
+
errors: [
|
|
195
|
+
{
|
|
196
|
+
file: testFile,
|
|
197
|
+
count: 1,
|
|
198
|
+
types: ['TypeError'],
|
|
199
|
+
},
|
|
200
|
+
],
|
|
201
|
+
};
|
|
202
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
203
|
+
|
|
204
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
205
|
+
|
|
206
|
+
expect(result.count).toBe(1);
|
|
207
|
+
expect(result.types).toEqual(['TypeError']);
|
|
208
|
+
expect(result.normalized).toBeGreaterThan(0);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
it('handles file with multiple error types', async () => {
|
|
212
|
+
const testFile = path.join(TEST_DIR, 'multi-types.ts');
|
|
213
|
+
const content = `function test(): void { console.log('test'); }`;
|
|
214
|
+
fs.writeFileSync(testFile, content);
|
|
215
|
+
|
|
216
|
+
const errorData = {
|
|
217
|
+
updated_at: new Date().toISOString(),
|
|
218
|
+
errors: [
|
|
219
|
+
{
|
|
220
|
+
file: testFile,
|
|
221
|
+
count: 8,
|
|
222
|
+
types: ['TypeError', 'ReferenceError', 'SyntaxError', 'RangeError'],
|
|
223
|
+
},
|
|
224
|
+
],
|
|
225
|
+
};
|
|
226
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
227
|
+
|
|
228
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
229
|
+
|
|
230
|
+
expect(result.count).toBe(8);
|
|
231
|
+
expect(result.types).toHaveLength(4);
|
|
232
|
+
expect(result.types).toContain('TypeError');
|
|
233
|
+
expect(result.types).toContain('ReferenceError');
|
|
234
|
+
expect(result.types).toContain('SyntaxError');
|
|
235
|
+
expect(result.types).toContain('RangeError');
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
it('handles malformed error JSON gracefully', async () => {
|
|
239
|
+
const testFile = path.join(TEST_DIR, 'test.ts');
|
|
240
|
+
const content = `function test(): void { console.log('test'); }`;
|
|
241
|
+
fs.writeFileSync(testFile, content);
|
|
242
|
+
|
|
243
|
+
// Write invalid JSON
|
|
244
|
+
fs.writeFileSync(ERROR_FILE, '{invalid json}');
|
|
245
|
+
|
|
246
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
247
|
+
|
|
248
|
+
// Should fallback to zero
|
|
249
|
+
expect(result.count).toBe(0);
|
|
250
|
+
expect(result.types).toEqual([]);
|
|
251
|
+
expect(result.normalized).toBe(0);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
it('handles empty error array', async () => {
|
|
255
|
+
const testFile = path.join(TEST_DIR, 'empty.ts');
|
|
256
|
+
const content = `function test(): void { console.log('test'); }`;
|
|
257
|
+
fs.writeFileSync(testFile, content);
|
|
258
|
+
|
|
259
|
+
const errorData = {
|
|
260
|
+
updated_at: new Date().toISOString(),
|
|
261
|
+
errors: [],
|
|
262
|
+
};
|
|
263
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
264
|
+
|
|
265
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
266
|
+
|
|
267
|
+
expect(result.count).toBe(0);
|
|
268
|
+
expect(result.types).toEqual([]);
|
|
269
|
+
expect(result.normalized).toBe(0);
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
it('normalizes with very small LOC file', async () => {
|
|
273
|
+
const testFile = path.join(TEST_DIR, 'tiny.ts');
|
|
274
|
+
const content = `const x = 1;`; // 1 line
|
|
275
|
+
fs.writeFileSync(testFile, content);
|
|
276
|
+
|
|
277
|
+
const errorData = {
|
|
278
|
+
updated_at: new Date().toISOString(),
|
|
279
|
+
errors: [
|
|
280
|
+
{
|
|
281
|
+
file: testFile,
|
|
282
|
+
count: 1,
|
|
283
|
+
types: ['TypeError'],
|
|
284
|
+
},
|
|
285
|
+
],
|
|
286
|
+
};
|
|
287
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
288
|
+
|
|
289
|
+
const result = await calculateErrorRate(testFile, ERROR_FILE);
|
|
290
|
+
|
|
291
|
+
expect(result.count).toBe(1);
|
|
292
|
+
// 1 error in 1 LOC = 1.0 errors/LOC
|
|
293
|
+
// (1.0) / 0.1 = 10.0, capped at 1.0
|
|
294
|
+
expect(result.normalized).toBe(1.0);
|
|
295
|
+
});
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
describe('calculateErrorRateBatch', () => {
|
|
299
|
+
it('calculates error rates for multiple files', async () => {
|
|
300
|
+
// Create test files
|
|
301
|
+
const file1 = path.join(TEST_DIR, 'file1.ts');
|
|
302
|
+
const file2 = path.join(TEST_DIR, 'file2.ts');
|
|
303
|
+
const file3 = path.join(TEST_DIR, 'file3.ts');
|
|
304
|
+
|
|
305
|
+
fs.writeFileSync(file1, Array(50).fill('console.log("line");').join('\n'));
|
|
306
|
+
fs.writeFileSync(file2, Array(100).fill('console.log("line");').join('\n'));
|
|
307
|
+
fs.writeFileSync(file3, Array(25).fill('console.log("line");').join('\n'));
|
|
308
|
+
|
|
309
|
+
// Create error data
|
|
310
|
+
const errorData = {
|
|
311
|
+
updated_at: new Date().toISOString(),
|
|
312
|
+
errors: [
|
|
313
|
+
{
|
|
314
|
+
file: file1,
|
|
315
|
+
count: 5,
|
|
316
|
+
types: ['TypeError'],
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
file: file2,
|
|
320
|
+
count: 3,
|
|
321
|
+
types: ['ReferenceError'],
|
|
322
|
+
},
|
|
323
|
+
// file3 has no errors
|
|
324
|
+
],
|
|
325
|
+
};
|
|
326
|
+
fs.writeFileSync(ERROR_FILE, JSON.stringify(errorData, null, 2));
|
|
327
|
+
|
|
328
|
+
const results = await calculateErrorRateBatch([file1, file2, file3], ERROR_FILE);
|
|
329
|
+
|
|
330
|
+
expect(results.size).toBe(3);
|
|
331
|
+
|
|
332
|
+
const result1 = results.get(file1)!;
|
|
333
|
+
expect(result1.count).toBe(5);
|
|
334
|
+
expect(result1.normalized).toBeGreaterThan(0);
|
|
335
|
+
|
|
336
|
+
const result2 = results.get(file2)!;
|
|
337
|
+
expect(result2.count).toBe(3);
|
|
338
|
+
expect(result2.normalized).toBeGreaterThan(0);
|
|
339
|
+
|
|
340
|
+
const result3 = results.get(file3)!;
|
|
341
|
+
expect(result3.count).toBe(0);
|
|
342
|
+
expect(result3.normalized).toBe(0);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
it('handles empty file list', async () => {
|
|
346
|
+
const results = await calculateErrorRateBatch([]);
|
|
347
|
+
expect(results.size).toBe(0);
|
|
348
|
+
});
|
|
349
|
+
});
|
|
350
|
+
});
|