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.
@@ -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
- });