vibecodingmachine-core 2026.1.23-1010 → 2026.1.29-1432
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/package.json +10 -1
- package/src/database/user-database-client.js +8 -3
- package/.babelrc +0 -13
- package/ERROR_REPORTING_API.md +0 -212
- package/ERROR_REPORTING_USAGE.md +0 -380
- package/__tests__/applescript-manager-claude-fix.test.js +0 -286
- package/__tests__/provider-manager-fallback.test.js +0 -43
- package/__tests__/provider-manager-rate-limit.test.js +0 -61
- package/__tests__/requirement-2-auto-start-looping.test.js +0 -69
- package/__tests__/requirement-3-auto-start-looping.test.js +0 -69
- package/__tests__/requirement-4-auto-start-looping.test.js +0 -69
- package/__tests__/requirement-6-auto-start-looping.test.js +0 -73
- package/__tests__/requirement-7-status-tracking.test.js +0 -332
- package/__tests__/utils/git-branch-manager.test.js +0 -61
- package/jest.config.js +0 -18
- package/jest.setup.js +0 -12
- package/scripts/setup-database.js +0 -108
- package/src/health-tracking/__tests__/ide-health-tracker.test.js +0 -420
- package/src/health-tracking/__tests__/interaction-recorder.test.js +0 -392
- package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +0 -227
- package/src/ui/StateManager.test.js +0 -0
- package/test-quota-system.js +0 -67
- package/test-requirement-stats.js +0 -66
- package/tests/health-tracking/health-reporter.test.js +0 -329
- package/tests/health-tracking/ide-health-tracker.test.js +0 -368
- package/tests/health-tracking/interaction-recorder.test.js +0 -309
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
const { getProjectRequirementStats } = require('./src/utils/requirement-helpers');
|
|
5
|
-
|
|
6
|
-
async function testStats() {
|
|
7
|
-
const testRepo = path.join(os.tmpdir(), 'vbc-test-stats-repo');
|
|
8
|
-
const hostname = os.hostname();
|
|
9
|
-
const vibecodingmachineDir = path.join(testRepo, '.vibecodingmachine');
|
|
10
|
-
const reqPath = path.join(vibecodingmachineDir, `REQUIREMENTS-${hostname}.md`);
|
|
11
|
-
const changelogPath = path.join(testRepo, 'CHANGELOG.md');
|
|
12
|
-
|
|
13
|
-
try {
|
|
14
|
-
await fs.ensureDir(vibecodingmachineDir);
|
|
15
|
-
|
|
16
|
-
const reqContent = `# Requirements
|
|
17
|
-
## ⏳ Requirements not yet completed
|
|
18
|
-
### Req 1
|
|
19
|
-
Details 1
|
|
20
|
-
### Req 2
|
|
21
|
-
Details 2
|
|
22
|
-
|
|
23
|
-
## ✅ Verified by AI screenshot
|
|
24
|
-
### Req 3
|
|
25
|
-
Details 3
|
|
26
|
-
`;
|
|
27
|
-
await fs.writeFile(reqPath, reqContent);
|
|
28
|
-
|
|
29
|
-
const changelogContent = `# Changelog
|
|
30
|
-
## Verified Requirements
|
|
31
|
-
- Req 4 (2025-12-18)
|
|
32
|
-
- Req 5 (2025-12-18)
|
|
33
|
-
`;
|
|
34
|
-
await fs.writeFile(changelogPath, changelogContent);
|
|
35
|
-
|
|
36
|
-
console.log('🧪 Testing getProjectRequirementStats...');
|
|
37
|
-
const stats = await getProjectRequirementStats(testRepo);
|
|
38
|
-
|
|
39
|
-
console.log('Result:', JSON.stringify(stats, null, 2));
|
|
40
|
-
|
|
41
|
-
const expected = {
|
|
42
|
-
todoCount: 2,
|
|
43
|
-
toVerifyCount: 1,
|
|
44
|
-
verifiedCount: 2,
|
|
45
|
-
total: 5
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
if (stats.todoCount === expected.todoCount &&
|
|
49
|
-
stats.toVerifyCount === expected.toVerifyCount &&
|
|
50
|
-
stats.verifiedCount === expected.verifiedCount &&
|
|
51
|
-
stats.total === expected.total) {
|
|
52
|
-
console.log('✅ PASS: Stats match expected values');
|
|
53
|
-
} else {
|
|
54
|
-
console.error('❌ FAIL: Stats do not match expected values');
|
|
55
|
-
process.exit(1);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error('❌ Error in test:', error);
|
|
60
|
-
process.exit(1);
|
|
61
|
-
} finally {
|
|
62
|
-
await fs.remove(testRepo);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
testStats();
|
|
@@ -1,329 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Unit Tests for HealthReporter
|
|
3
|
-
*
|
|
4
|
-
* Tests for formatting health data for CLI and Electron UI display.
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const { HealthReporter } = require('../../../src/health-tracking/health-reporter');
|
|
8
|
-
|
|
9
|
-
describe('HealthReporter', () => {
|
|
10
|
-
let reporter;
|
|
11
|
-
let mockMetrics;
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
reporter = new HealthReporter();
|
|
15
|
-
|
|
16
|
-
mockMetrics = {
|
|
17
|
-
cursor: {
|
|
18
|
-
successCount: 42,
|
|
19
|
-
failureCount: 3,
|
|
20
|
-
successRate: 0.933,
|
|
21
|
-
averageResponseTime: 121500,
|
|
22
|
-
currentTimeout: 170100,
|
|
23
|
-
consecutiveFailures: 0,
|
|
24
|
-
lastSuccess: '2026-01-21T09:15:00.000Z',
|
|
25
|
-
lastFailure: '2026-01-20T23:45:00.000Z',
|
|
26
|
-
totalInteractions: 45,
|
|
27
|
-
recentInteractions: [
|
|
28
|
-
{
|
|
29
|
-
timestamp: '2026-01-21T09:15:00.000Z',
|
|
30
|
-
outcome: 'success',
|
|
31
|
-
responseTime: 120000,
|
|
32
|
-
timeoutUsed: 180000,
|
|
33
|
-
continuationPromptsDetected: 1,
|
|
34
|
-
requirementId: 'req-042',
|
|
35
|
-
errorMessage: null
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
},
|
|
39
|
-
windsurf: {
|
|
40
|
-
successCount: 28,
|
|
41
|
-
failureCount: 15,
|
|
42
|
-
successRate: 0.651,
|
|
43
|
-
averageResponseTime: 1490000,
|
|
44
|
-
currentTimeout: 2086000,
|
|
45
|
-
consecutiveFailures: 2,
|
|
46
|
-
lastSuccess: '2026-01-21T08:30:00.000Z',
|
|
47
|
-
lastFailure: '2026-01-21T07:15:00.000Z',
|
|
48
|
-
totalInteractions: 43,
|
|
49
|
-
recentInteractions: [
|
|
50
|
-
{
|
|
51
|
-
timestamp: '2026-01-21T08:30:00.000Z',
|
|
52
|
-
outcome: 'failure',
|
|
53
|
-
responseTime: null,
|
|
54
|
-
timeoutUsed: 1800000,
|
|
55
|
-
continuationPromptsDetected: 0,
|
|
56
|
-
requirementId: 'req-041',
|
|
57
|
-
errorMessage: 'Timeout exceeded'
|
|
58
|
-
}
|
|
59
|
-
]
|
|
60
|
-
}
|
|
61
|
-
};
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
describe('formatForCLI', () => {
|
|
65
|
-
it('should format health metrics for CLI display', () => {
|
|
66
|
-
const formatted = reporter.formatForCLI(mockMetrics);
|
|
67
|
-
|
|
68
|
-
expect(formatted).toContain('🖥️ Cursor');
|
|
69
|
-
expect(formatted).toContain('+42 -3');
|
|
70
|
-
expect(formatted).toContain('93.3%');
|
|
71
|
-
expect(formatted).toContain('2.0m');
|
|
72
|
-
expect(formatted).toContain('✅ Healthy');
|
|
73
|
-
|
|
74
|
-
expect(formatted).toContain('🌊 Windsurf');
|
|
75
|
-
expect(formatted).toContain('+28 -15');
|
|
76
|
-
expect(formatted).toContain('65.1%');
|
|
77
|
-
expect(formatted).toContain('24.9m');
|
|
78
|
-
expect(formatted).toContain('⚠️ 2 consecutive failures');
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
it('should handle empty metrics', () => {
|
|
82
|
-
const formatted = reporter.formatForCLI({});
|
|
83
|
-
|
|
84
|
-
expect(formatted).toContain('No IDE health data available');
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should show warning for IDEs with consecutive failures', () => {
|
|
88
|
-
const metricsWithFailures = {
|
|
89
|
-
cursor: {
|
|
90
|
-
...mockMetrics.cursor,
|
|
91
|
-
consecutiveFailures: 3
|
|
92
|
-
}
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
const formatted = reporter.formatForCLI(metricsWithFailures);
|
|
96
|
-
|
|
97
|
-
expect(formatted).toContain('⚠️ 3 consecutive failures');
|
|
98
|
-
expect(formatted).not.toContain('✅ Healthy');
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
it('should format timestamps relative to now', () => {
|
|
102
|
-
const now = new Date('2026-01-21T10:00:00.000Z');
|
|
103
|
-
const formatted = reporter.formatForCLI(mockMetrics, now);
|
|
104
|
-
|
|
105
|
-
expect(formatted).toContain('Last success: 45m ago');
|
|
106
|
-
expect(formatted).toContain('Last failure: 10h ago');
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it('should show "Never" for null timestamps', () => {
|
|
110
|
-
const metricsWithNulls = {
|
|
111
|
-
cursor: {
|
|
112
|
-
...mockMetrics.cursor,
|
|
113
|
-
lastSuccess: null,
|
|
114
|
-
lastFailure: null
|
|
115
|
-
}
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
const formatted = reporter.formatForCLI(metricsWithNulls);
|
|
119
|
-
|
|
120
|
-
expect(formatted).toContain('Last success: Never');
|
|
121
|
-
expect(formatted).toContain('Last failure: Never');
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
describe('formatForElectron', () => {
|
|
126
|
-
it('should format health metrics for Electron UI', () => {
|
|
127
|
-
const formatted = reporter.formatForElectron(mockMetrics);
|
|
128
|
-
|
|
129
|
-
expect(formatted).toHaveProperty('cursor');
|
|
130
|
-
expect(formatted).toHaveProperty('windsurf');
|
|
131
|
-
|
|
132
|
-
const cursorData = formatted.cursor;
|
|
133
|
-
expect(cursorData.ide).toBe('Cursor');
|
|
134
|
-
expect(cursorData.successCount).toBe(42);
|
|
135
|
-
expect(cursorData.failureCount).toBe(3);
|
|
136
|
-
expect(cursorData.successRate).toBe(93.3);
|
|
137
|
-
expect(cursorData.averageResponseTime).toBe('2.0m');
|
|
138
|
-
expect(cursorData.currentTimeout).toBe('2.8m');
|
|
139
|
-
expect(cursorData.status).toBe('healthy');
|
|
140
|
-
expect(cursorData.lastSuccess).toBe('45m ago');
|
|
141
|
-
expect(cursorData.lastFailure).toBe('10h ago');
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it('should include recent interactions in Electron format', () => {
|
|
145
|
-
const formatted = reporter.formatForElectron(mockMetrics);
|
|
146
|
-
|
|
147
|
-
const cursorData = formatted.cursor;
|
|
148
|
-
expect(cursorData.recentInteractions).toHaveLength(1);
|
|
149
|
-
|
|
150
|
-
const interaction = cursorData.recentInteractions[0];
|
|
151
|
-
expect(interaction.outcome).toBe('success');
|
|
152
|
-
expect(interaction.displayTime).toBe('2.0m');
|
|
153
|
-
expect(interaction.requirementId).toBe('req-042');
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should handle IDEs with no interactions', () => {
|
|
157
|
-
const metricsWithNoInteractions = {
|
|
158
|
-
vscode: {
|
|
159
|
-
successCount: 0,
|
|
160
|
-
failureCount: 0,
|
|
161
|
-
successRate: 0,
|
|
162
|
-
averageResponseTime: 0,
|
|
163
|
-
currentTimeout: 1800000,
|
|
164
|
-
consecutiveFailures: 0,
|
|
165
|
-
lastSuccess: null,
|
|
166
|
-
lastFailure: null,
|
|
167
|
-
totalInteractions: 0,
|
|
168
|
-
recentInteractions: []
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
const formatted = reporter.formatForElectron(metricsWithNoInteractions);
|
|
173
|
-
|
|
174
|
-
const vscodeData = formatted.vscode;
|
|
175
|
-
expect(vscodeData.status).toBe('no-data');
|
|
176
|
-
expect(vscodeData.successRate).toBe(0);
|
|
177
|
-
expect(vscodeData.averageResponseTime).toBe('N/A');
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should format response times in human-readable units', () => {
|
|
181
|
-
const formatted = reporter.formatForElectron(mockMetrics);
|
|
182
|
-
|
|
183
|
-
expect(formatted.cursor.averageResponseTime).toBe('2.0m'); // 121.5s
|
|
184
|
-
expect(formatted.windsurf.averageResponseTime).toBe('24.9m'); // 1490s
|
|
185
|
-
expect(formatted.cursor.currentTimeout).toBe('2.8m'); // 170.1s
|
|
186
|
-
expect(formatted.windsurf.currentTimeout).toBe('34.8m'); // 2086s
|
|
187
|
-
});
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
describe('generateSummary', () => {
|
|
191
|
-
it('should generate overall health summary', () => {
|
|
192
|
-
const summary = reporter.generateSummary(mockMetrics);
|
|
193
|
-
|
|
194
|
-
expect(summary.totalIDEs).toBe(2);
|
|
195
|
-
expect(summary.healthyIDEs).toBe(1);
|
|
196
|
-
expect(summary.problematicIDEs).toBe(1);
|
|
197
|
-
expect(summary.totalInteractions).toBe(88);
|
|
198
|
-
expect(summary.overallSuccessRate).toBe(79.5);
|
|
199
|
-
expect(summary.averageResponseTime).toBe(805750); // Weighted average
|
|
200
|
-
expect(summary.recommendedIDE).toBe('cursor');
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should handle empty metrics in summary', () => {
|
|
204
|
-
const summary = reporter.generateSummary({});
|
|
205
|
-
|
|
206
|
-
expect(summary.totalIDEs).toBe(0);
|
|
207
|
-
expect(summary.healthyIDEs).toBe(0);
|
|
208
|
-
expect(summary.problematicIDEs).toBe(0);
|
|
209
|
-
expect(summary.totalInteractions).toBe(0);
|
|
210
|
-
expect(summary.overallSuccessRate).toBe(0);
|
|
211
|
-
expect(summary.averageResponseTime).toBe(0);
|
|
212
|
-
expect(summary.recommendedIDE).toBeNull();
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should calculate weighted average response time', () => {
|
|
216
|
-
const summary = reporter.generateSummary(mockMetrics);
|
|
217
|
-
|
|
218
|
-
// Weighted average: (45 * 121500 + 43 * 1490000) / 88
|
|
219
|
-
const expected = (45 * 121500 + 43 * 1490000) / 88;
|
|
220
|
-
expect(summary.averageResponseTime).toBeCloseTo(expected, 0);
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('should identify recommended IDE based on success rate', () => {
|
|
224
|
-
const summary = reporter.generateSummary(mockMetrics);
|
|
225
|
-
|
|
226
|
-
expect(summary.recommendedIDE).toBe('cursor'); // 93.3% vs 65.1%
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
it('should return null for recommendation when no IDE has sufficient data', () => {
|
|
230
|
-
const metricsWithInsufficientData = {
|
|
231
|
-
cursor: {
|
|
232
|
-
successCount: 1,
|
|
233
|
-
failureCount: 0,
|
|
234
|
-
successRate: 1.0,
|
|
235
|
-
totalInteractions: 1
|
|
236
|
-
}
|
|
237
|
-
};
|
|
238
|
-
|
|
239
|
-
const summary = reporter.generateSummary(metricsWithInsufficientData);
|
|
240
|
-
|
|
241
|
-
expect(summary.recommendedIDE).toBeNull();
|
|
242
|
-
});
|
|
243
|
-
});
|
|
244
|
-
|
|
245
|
-
describe('formatResponseTime', () => {
|
|
246
|
-
it('should format milliseconds to human readable format', () => {
|
|
247
|
-
expect(reporter.formatResponseTime(500)).toBe('500ms');
|
|
248
|
-
expect(reporter.formatResponseTime(1500)).toBe('1.5s');
|
|
249
|
-
expect(reporter.formatResponseTime(60000)).toBe('1.0m');
|
|
250
|
-
expect(reporter.formatResponseTime(121500)).toBe('2.0m');
|
|
251
|
-
expect(reporter.formatResponseTime(3600000)).toBe('1.0h');
|
|
252
|
-
expect(reporter.formatResponseTime(7200000)).toBe('2.0h');
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
it('should handle zero and null values', () => {
|
|
256
|
-
expect(reporter.formatResponseTime(0)).toBe('0ms');
|
|
257
|
-
expect(reporter.formatResponseTime(null)).toBe('N/A');
|
|
258
|
-
expect(reporter.formatResponseTime(undefined)).toBe('N/A');
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
|
|
262
|
-
describe('formatTimestamp', () => {
|
|
263
|
-
it('should format timestamps relative to now', () => {
|
|
264
|
-
const now = new Date('2026-01-21T10:00:00.000Z');
|
|
265
|
-
|
|
266
|
-
expect(reporter.formatTimestamp('2026-01-21T09:15:00.000Z', now))
|
|
267
|
-
.toBe('45m ago');
|
|
268
|
-
|
|
269
|
-
expect(reporter.formatTimestamp('2026-01-21T08:00:00.000Z', now))
|
|
270
|
-
.toBe('2h ago');
|
|
271
|
-
|
|
272
|
-
expect(reporter.formatTimestamp('2026-01-20T10:00:00.000Z', now))
|
|
273
|
-
.toBe('24h ago');
|
|
274
|
-
|
|
275
|
-
expect(reporter.formatTimestamp('2026-01-19T10:00:00.000Z', now))
|
|
276
|
-
.toBe('2d ago');
|
|
277
|
-
});
|
|
278
|
-
|
|
279
|
-
it('should handle null timestamps', () => {
|
|
280
|
-
expect(reporter.formatTimestamp(null)).toBe('Never');
|
|
281
|
-
expect(reporter.formatTimestamp(undefined)).toBe('Never');
|
|
282
|
-
});
|
|
283
|
-
|
|
284
|
-
it('should use current time when no reference provided', () => {
|
|
285
|
-
const timestamp = new Date(Date.now() - 5 * 60 * 1000).toISOString(); // 5 minutes ago
|
|
286
|
-
const formatted = reporter.formatTimestamp(timestamp);
|
|
287
|
-
|
|
288
|
-
expect(formatted).toBe('5m ago');
|
|
289
|
-
});
|
|
290
|
-
});
|
|
291
|
-
|
|
292
|
-
describe('getHealthStatus', () => {
|
|
293
|
-
it('should return healthy for IDEs with no consecutive failures', () => {
|
|
294
|
-
const status = reporter.getHealthStatus({
|
|
295
|
-
consecutiveFailures: 0,
|
|
296
|
-
totalInteractions: 10
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
expect(status).toBe('healthy');
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should return warning for IDEs with consecutive failures', () => {
|
|
303
|
-
const status = reporter.getHealthStatus({
|
|
304
|
-
consecutiveFailures: 3,
|
|
305
|
-
totalInteractions: 10
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
expect(status).toBe('warning');
|
|
309
|
-
});
|
|
310
|
-
|
|
311
|
-
it('should return critical for IDEs with many consecutive failures', () => {
|
|
312
|
-
const status = reporter.getHealthStatus({
|
|
313
|
-
consecutiveFailures: 6,
|
|
314
|
-
totalInteractions: 10
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
expect(status).toBe('critical');
|
|
318
|
-
});
|
|
319
|
-
|
|
320
|
-
it('should return no-data for IDEs with no interactions', () => {
|
|
321
|
-
const status = reporter.getHealthStatus({
|
|
322
|
-
consecutiveFailures: 0,
|
|
323
|
-
totalInteractions: 0
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
expect(status).toBe('no-data');
|
|
327
|
-
});
|
|
328
|
-
});
|
|
329
|
-
});
|