midas-mcp 2.9.0 → 3.2.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.
Files changed (87) hide show
  1. package/LICENSE +21 -0
  2. package/dist/ai.d.ts +2 -0
  3. package/dist/ai.d.ts.map +1 -1
  4. package/dist/ai.js +28 -45
  5. package/dist/ai.js.map +1 -1
  6. package/dist/analyzer.d.ts.map +1 -1
  7. package/dist/analyzer.js +37 -87
  8. package/dist/analyzer.js.map +1 -1
  9. package/dist/config.d.ts +16 -0
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +109 -15
  12. package/dist/config.js.map +1 -1
  13. package/dist/context.d.ts +8 -1
  14. package/dist/context.d.ts.map +1 -1
  15. package/dist/context.js +76 -7
  16. package/dist/context.js.map +1 -1
  17. package/dist/providers.d.ts +46 -0
  18. package/dist/providers.d.ts.map +1 -0
  19. package/dist/providers.js +287 -0
  20. package/dist/providers.js.map +1 -0
  21. package/dist/server.d.ts.map +1 -1
  22. package/dist/server.js +9 -2
  23. package/dist/server.js.map +1 -1
  24. package/dist/tools/config.d.ts +73 -0
  25. package/dist/tools/config.d.ts.map +1 -0
  26. package/dist/tools/config.js +94 -0
  27. package/dist/tools/config.js.map +1 -0
  28. package/dist/tools/index.d.ts +1 -0
  29. package/dist/tools/index.d.ts.map +1 -1
  30. package/dist/tools/index.js +2 -0
  31. package/dist/tools/index.js.map +1 -1
  32. package/dist/tui.d.ts.map +1 -1
  33. package/dist/tui.js +293 -210
  34. package/dist/tui.js.map +1 -1
  35. package/package.json +17 -5
  36. package/dist/tests/analyze.test.d.ts +0 -2
  37. package/dist/tests/analyze.test.d.ts.map +0 -1
  38. package/dist/tests/analyze.test.js +0 -120
  39. package/dist/tests/analyze.test.js.map +0 -1
  40. package/dist/tests/context.test.d.ts +0 -2
  41. package/dist/tests/context.test.d.ts.map +0 -1
  42. package/dist/tests/context.test.js +0 -213
  43. package/dist/tests/context.test.js.map +0 -1
  44. package/dist/tests/edge-cases.test.d.ts +0 -2
  45. package/dist/tests/edge-cases.test.d.ts.map +0 -1
  46. package/dist/tests/edge-cases.test.js +0 -234
  47. package/dist/tests/edge-cases.test.js.map +0 -1
  48. package/dist/tests/journal.test.d.ts +0 -2
  49. package/dist/tests/journal.test.d.ts.map +0 -1
  50. package/dist/tests/journal.test.js +0 -184
  51. package/dist/tests/journal.test.js.map +0 -1
  52. package/dist/tests/metrics.test.d.ts +0 -2
  53. package/dist/tests/metrics.test.d.ts.map +0 -1
  54. package/dist/tests/metrics.test.js +0 -178
  55. package/dist/tests/metrics.test.js.map +0 -1
  56. package/dist/tests/phase.test.d.ts +0 -2
  57. package/dist/tests/phase.test.d.ts.map +0 -1
  58. package/dist/tests/phase.test.js +0 -110
  59. package/dist/tests/phase.test.js.map +0 -1
  60. package/dist/tests/prompts.test.d.ts +0 -2
  61. package/dist/tests/prompts.test.d.ts.map +0 -1
  62. package/dist/tests/prompts.test.js +0 -157
  63. package/dist/tests/prompts.test.js.map +0 -1
  64. package/dist/tests/search.test.d.ts +0 -2
  65. package/dist/tests/search.test.d.ts.map +0 -1
  66. package/dist/tests/search.test.js +0 -228
  67. package/dist/tests/search.test.js.map +0 -1
  68. package/dist/tests/security.test.d.ts +0 -2
  69. package/dist/tests/security.test.d.ts.map +0 -1
  70. package/dist/tests/security.test.js +0 -105
  71. package/dist/tests/security.test.js.map +0 -1
  72. package/dist/tests/server.test.d.ts +0 -2
  73. package/dist/tests/server.test.d.ts.map +0 -1
  74. package/dist/tests/server.test.js +0 -93
  75. package/dist/tests/server.test.js.map +0 -1
  76. package/dist/tests/techstack.test.d.ts +0 -2
  77. package/dist/tests/techstack.test.d.ts.map +0 -1
  78. package/dist/tests/techstack.test.js +0 -187
  79. package/dist/tests/techstack.test.js.map +0 -1
  80. package/dist/tests/tools.test.d.ts +0 -2
  81. package/dist/tests/tools.test.d.ts.map +0 -1
  82. package/dist/tests/tools.test.js +0 -137
  83. package/dist/tests/tools.test.js.map +0 -1
  84. package/dist/tests/tracker.test.d.ts +0 -2
  85. package/dist/tests/tracker.test.d.ts.map +0 -1
  86. package/dist/tests/tracker.test.js +0 -197
  87. package/dist/tests/tracker.test.js.map +0 -1
@@ -1,234 +0,0 @@
1
- import { describe, it, beforeEach, afterEach } from 'node:test';
2
- import assert from 'node:assert';
3
- import { mkdirSync, rmSync, writeFileSync, existsSync } from 'fs';
4
- import { join } from 'path';
5
- import { tmpdir } from 'os';
6
- import { loadState, saveState, setPhase, getDefaultState } from '../state/phase.js';
7
- import { startProject, getPhase, setPhaseManually } from '../tools/phase.js';
8
- import { audit } from '../tools/audit.js';
9
- import { checkDocs } from '../tools/docs.js';
10
- import { loadTracker } from '../tracker.js';
11
- import { loadMetrics } from '../metrics.js';
12
- import { saveToJournal, getJournalEntries } from '../tools/journal.js';
13
- describe('Edge Cases and Error Handling', () => {
14
- const testDir = join(tmpdir(), 'midas-edge-test-' + Date.now());
15
- beforeEach(() => {
16
- mkdirSync(testDir, { recursive: true });
17
- });
18
- afterEach(() => {
19
- rmSync(testDir, { recursive: true, force: true });
20
- });
21
- describe('Corrupted State Files', () => {
22
- it('handles corrupted state.json gracefully', () => {
23
- mkdirSync(join(testDir, '.midas'), { recursive: true });
24
- writeFileSync(join(testDir, '.midas', 'state.json'), 'not valid json{{{');
25
- // Should return default state instead of crashing
26
- const state = loadState(testDir);
27
- assert.deepStrictEqual(state.current, { phase: 'IDLE' });
28
- });
29
- it('handles corrupted tracker.json gracefully', () => {
30
- mkdirSync(join(testDir, '.midas'), { recursive: true });
31
- writeFileSync(join(testDir, '.midas', 'tracker.json'), '{ broken');
32
- const tracker = loadTracker(testDir);
33
- assert.deepStrictEqual(tracker.inferredPhase, { phase: 'IDLE' });
34
- });
35
- it('handles corrupted metrics.json gracefully', () => {
36
- mkdirSync(join(testDir, '.midas'), { recursive: true });
37
- writeFileSync(join(testDir, '.midas', 'metrics.json'), '[[invalid]]');
38
- const metrics = loadMetrics(testDir);
39
- assert.strictEqual(metrics.totalSessions, 0);
40
- });
41
- it('handles empty state file', () => {
42
- mkdirSync(join(testDir, '.midas'), { recursive: true });
43
- writeFileSync(join(testDir, '.midas', 'state.json'), '');
44
- const state = loadState(testDir);
45
- assert.deepStrictEqual(state.current, { phase: 'IDLE' });
46
- });
47
- });
48
- describe('Missing Directories', () => {
49
- it('creates .midas directory on save', () => {
50
- const state = getDefaultState();
51
- saveState(testDir, state);
52
- assert.strictEqual(existsSync(join(testDir, '.midas')), true);
53
- });
54
- it('creates nested directory for journal', () => {
55
- saveToJournal({
56
- projectPath: testDir,
57
- title: 'Test',
58
- conversation: 'Content',
59
- });
60
- assert.strictEqual(existsSync(join(testDir, '.midas', 'journal')), true);
61
- });
62
- it('handles non-existent docs directory', () => {
63
- const result = checkDocs({ projectPath: testDir });
64
- assert.strictEqual(result.brainlift.exists, false);
65
- assert.strictEqual(result.prd.exists, false);
66
- assert.strictEqual(result.gameplan.exists, false);
67
- assert.strictEqual(result.ready, false);
68
- });
69
- });
70
- describe('Empty and Minimal Content', () => {
71
- it('handles project with no files', () => {
72
- const result = audit({ projectPath: testDir });
73
- assert.strictEqual(result.overall < 30, true);
74
- });
75
- it('handles empty package.json', () => {
76
- writeFileSync(join(testDir, 'package.json'), '{}');
77
- const result = audit({ projectPath: testDir });
78
- // Should not crash
79
- assert.strictEqual(typeof result.overall, 'number');
80
- });
81
- it('handles empty docs files', () => {
82
- mkdirSync(join(testDir, 'docs'), { recursive: true });
83
- writeFileSync(join(testDir, 'docs', 'brainlift.md'), '');
84
- const result = checkDocs({ projectPath: testDir });
85
- assert.strictEqual(result.brainlift.exists, true);
86
- assert.strictEqual(result.brainlift.complete, false);
87
- });
88
- it('handles journal with no entries', () => {
89
- const entries = getJournalEntries({ projectPath: testDir });
90
- assert.deepStrictEqual(entries, []);
91
- });
92
- });
93
- describe('Invalid Input Handling', () => {
94
- it('setPhaseManually handles invalid phase', () => {
95
- const result = setPhaseManually({
96
- projectPath: testDir,
97
- phase: 'INVALID_PHASE' // Type cast to simulate bad input
98
- });
99
- // Should handle gracefully - will set to provided value
100
- assert.strictEqual(result.success, true);
101
- });
102
- it('startProject with empty name still works', () => {
103
- const result = startProject({
104
- projectName: '',
105
- projectPath: testDir
106
- });
107
- assert.strictEqual(result.success, true);
108
- });
109
- it('audit with malformed package.json dependencies', () => {
110
- writeFileSync(join(testDir, 'package.json'), JSON.stringify({
111
- dependencies: 'not an object',
112
- }));
113
- const result = audit({ projectPath: testDir });
114
- // Should not crash
115
- assert.strictEqual(typeof result.level, 'string');
116
- });
117
- });
118
- describe('Concurrent Access Patterns', () => {
119
- it('handles rapid consecutive saves', () => {
120
- const state = getDefaultState();
121
- // Rapid saves should not corrupt state
122
- for (let i = 0; i < 10; i++) {
123
- state.current = { phase: 'EAGLE_SIGHT', step: 'IDEA' };
124
- saveState(testDir, state);
125
- }
126
- const loaded = loadState(testDir);
127
- assert.strictEqual(loaded.current.phase, 'EAGLE_SIGHT');
128
- });
129
- it('handles rapid phase changes', () => {
130
- setPhase(testDir, { phase: 'EAGLE_SIGHT', step: 'IDEA' });
131
- setPhase(testDir, { phase: 'EAGLE_SIGHT', step: 'RESEARCH' });
132
- setPhase(testDir, { phase: 'EAGLE_SIGHT', step: 'BRAINLIFT' });
133
- const state = loadState(testDir);
134
- assert.strictEqual(state.current.step, 'BRAINLIFT');
135
- assert.strictEqual(state.history.length, 3);
136
- });
137
- it('handles multiple journal entries quickly', () => {
138
- for (let i = 0; i < 5; i++) {
139
- saveToJournal({
140
- projectPath: testDir,
141
- title: `Entry ${i}`,
142
- conversation: `Content ${i}`,
143
- });
144
- }
145
- const entries = getJournalEntries({ projectPath: testDir });
146
- assert.strictEqual(entries.length, 5);
147
- });
148
- });
149
- describe('Special Characters in Content', () => {
150
- it('handles special characters in project name', () => {
151
- const result = startProject({
152
- projectName: 'my-project_v2.0 (beta)',
153
- projectPath: testDir,
154
- });
155
- assert.strictEqual(result.success, true);
156
- });
157
- it('handles markdown in journal entries', () => {
158
- const mdContent = '# Header\n```typescript\nconst x = 1;\n```\n- List item';
159
- saveToJournal({
160
- projectPath: testDir,
161
- title: 'Markdown Test',
162
- conversation: mdContent,
163
- });
164
- const entries = getJournalEntries({ projectPath: testDir });
165
- assert.strictEqual(entries[0].conversation.includes('```typescript'), true);
166
- });
167
- it('handles unicode in journal entries', () => {
168
- saveToJournal({
169
- projectPath: testDir,
170
- title: 'Unicode Test',
171
- conversation: 'Tested with emojis and symbols',
172
- });
173
- const entries = getJournalEntries({ projectPath: testDir });
174
- assert.strictEqual(entries.length, 1);
175
- });
176
- it('handles newlines in conversation content', () => {
177
- const multiline = 'Line 1\nLine 2\n\nLine 4';
178
- saveToJournal({
179
- projectPath: testDir,
180
- title: 'Multiline',
181
- conversation: multiline,
182
- });
183
- const entries = getJournalEntries({ projectPath: testDir });
184
- assert.strictEqual(entries[0].conversation.includes('\n'), true);
185
- });
186
- });
187
- describe('Path Edge Cases', () => {
188
- it('handles path with spaces', () => {
189
- const spacePath = join(testDir, 'path with spaces');
190
- mkdirSync(spacePath, { recursive: true });
191
- const state = getDefaultState();
192
- saveState(spacePath, state);
193
- const loaded = loadState(spacePath);
194
- assert.deepStrictEqual(loaded.current, { phase: 'IDLE' });
195
- });
196
- it('uses cwd when projectPath not provided', () => {
197
- const result = getPhase({});
198
- // Should not crash - uses process.cwd()
199
- assert.strictEqual(typeof result.current.phase, 'string');
200
- });
201
- });
202
- describe('Boundary Conditions', () => {
203
- it('handles very long journal entry', () => {
204
- const longContent = 'A'.repeat(100000);
205
- const result = saveToJournal({
206
- projectPath: testDir,
207
- title: 'Long Entry',
208
- conversation: longContent,
209
- });
210
- assert.strictEqual(result.success, true);
211
- });
212
- it('handles many tags with security limit', () => {
213
- // Security: Tags are limited to 20 max (LIMITS.MAX_TAGS)
214
- const manyTags = Array.from({ length: 50 }, (_, i) => `tag${i}`);
215
- const result = saveToJournal({
216
- projectPath: testDir,
217
- title: 'Many Tags',
218
- conversation: 'Content',
219
- tags: manyTags,
220
- });
221
- // Only first 20 tags should be stored (security limit)
222
- assert.strictEqual(result.entry.tags?.length, 20);
223
- });
224
- it('handles deep history', () => {
225
- // Create many phase transitions
226
- for (let i = 0; i < 100; i++) {
227
- setPhase(testDir, { phase: 'EAGLE_SIGHT', step: 'IDEA' });
228
- }
229
- const state = loadState(testDir);
230
- assert.strictEqual(state.history.length, 100);
231
- });
232
- });
233
- });
234
- //# sourceMappingURL=edge-cases.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"edge-cases.test.js","sourceRoot":"","sources":["../../src/tests/edge-cases.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=journal.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal.test.d.ts","sourceRoot":"","sources":["../../src/tests/journal.test.ts"],"names":[],"mappings":""}
@@ -1,184 +0,0 @@
1
- import { describe, it, beforeEach, afterEach } from 'node:test';
2
- import assert from 'node:assert';
3
- import { mkdirSync, rmSync, existsSync } from 'fs';
4
- import { join } from 'path';
5
- import { tmpdir } from 'os';
6
- import { saveToJournal, getJournalEntries, searchJournal } from '../tools/journal.js';
7
- describe('Journal Tools', () => {
8
- const testDir = join(tmpdir(), 'midas-journal-test-' + Date.now());
9
- beforeEach(() => {
10
- mkdirSync(testDir, { recursive: true });
11
- });
12
- afterEach(() => {
13
- rmSync(testDir, { recursive: true, force: true });
14
- });
15
- describe('saveToJournal', () => {
16
- it('creates journal directory if not exists', () => {
17
- saveToJournal({
18
- projectPath: testDir,
19
- title: 'Test Entry',
20
- conversation: 'User: Hello\nAI: Hi there!',
21
- });
22
- assert.strictEqual(existsSync(join(testDir, '.midas', 'journal')), true);
23
- });
24
- it('creates markdown file with correct structure', () => {
25
- const result = saveToJournal({
26
- projectPath: testDir,
27
- title: 'Auth Implementation',
28
- conversation: 'Implemented OAuth2 flow',
29
- });
30
- assert.strictEqual(result.success, true);
31
- assert.strictEqual(result.path.endsWith('.md'), true);
32
- assert.strictEqual(existsSync(result.path), true);
33
- });
34
- it('includes title in entry', () => {
35
- const result = saveToJournal({
36
- projectPath: testDir,
37
- title: 'Database Migration',
38
- conversation: 'Added user table',
39
- });
40
- assert.strictEqual(result.entry.title, 'Database Migration');
41
- });
42
- it('includes tags when provided', () => {
43
- const result = saveToJournal({
44
- projectPath: testDir,
45
- title: 'Bug Fix',
46
- conversation: 'Fixed null pointer',
47
- tags: ['bugfix', 'auth'],
48
- });
49
- assert.deepStrictEqual(result.entry.tags, ['bugfix', 'auth']);
50
- });
51
- it('generates unique ID for each entry', () => {
52
- const r1 = saveToJournal({
53
- projectPath: testDir,
54
- title: 'Entry 1',
55
- conversation: 'Content 1',
56
- });
57
- const r2 = saveToJournal({
58
- projectPath: testDir,
59
- title: 'Entry 2',
60
- conversation: 'Content 2',
61
- });
62
- assert.notStrictEqual(r1.entry.id, r2.entry.id);
63
- });
64
- it('stores full conversation content', () => {
65
- const conversation = 'User: How do I implement auth?\nAI: Here is how...';
66
- const result = saveToJournal({
67
- projectPath: testDir,
68
- title: 'Auth Discussion',
69
- conversation,
70
- });
71
- assert.strictEqual(result.entry.conversation, conversation);
72
- });
73
- });
74
- describe('getJournalEntries', () => {
75
- it('returns empty array for new project', () => {
76
- const entries = getJournalEntries({ projectPath: testDir });
77
- assert.deepStrictEqual(entries, []);
78
- });
79
- it('returns saved entries', () => {
80
- saveToJournal({
81
- projectPath: testDir,
82
- title: 'Entry 1',
83
- conversation: 'Content 1',
84
- });
85
- const entries = getJournalEntries({ projectPath: testDir });
86
- assert.strictEqual(entries.length, 1);
87
- assert.strictEqual(entries[0].title, 'Entry 1');
88
- });
89
- it('returns entries in reverse chronological order', async () => {
90
- // Add small delays to ensure distinct timestamps
91
- saveToJournal({ projectPath: testDir, title: 'First', conversation: 'A' });
92
- await new Promise(r => setTimeout(r, 5));
93
- saveToJournal({ projectPath: testDir, title: 'Second', conversation: 'B' });
94
- await new Promise(r => setTimeout(r, 5));
95
- saveToJournal({ projectPath: testDir, title: 'Third', conversation: 'C' });
96
- const entries = getJournalEntries({ projectPath: testDir });
97
- // Most recent should be first
98
- assert.strictEqual(entries[0].title, 'Third');
99
- assert.strictEqual(entries[2].title, 'First');
100
- });
101
- it('respects limit parameter', () => {
102
- for (let i = 0; i < 5; i++) {
103
- saveToJournal({
104
- projectPath: testDir,
105
- title: `Entry ${i}`,
106
- conversation: `Content ${i}`,
107
- });
108
- }
109
- const entries = getJournalEntries({ projectPath: testDir, limit: 2 });
110
- assert.strictEqual(entries.length, 2);
111
- });
112
- it('parses tags from saved files', () => {
113
- saveToJournal({
114
- projectPath: testDir,
115
- title: 'Tagged Entry',
116
- conversation: 'Content',
117
- tags: ['auth', 'frontend'],
118
- });
119
- const entries = getJournalEntries({ projectPath: testDir });
120
- assert.deepStrictEqual(entries[0].tags, ['auth', 'frontend']);
121
- });
122
- it('extracts conversation content correctly', () => {
123
- const conversation = 'This is the full\nmultiline\nconversation';
124
- saveToJournal({
125
- projectPath: testDir,
126
- title: 'Test',
127
- conversation,
128
- });
129
- const entries = getJournalEntries({ projectPath: testDir });
130
- assert.strictEqual(entries[0].conversation, conversation);
131
- });
132
- });
133
- describe('searchJournal', () => {
134
- beforeEach(() => {
135
- saveToJournal({
136
- projectPath: testDir,
137
- title: 'Authentication Flow',
138
- conversation: 'Implemented OAuth2 with JWT tokens',
139
- tags: ['auth', 'security'],
140
- });
141
- saveToJournal({
142
- projectPath: testDir,
143
- title: 'Database Schema',
144
- conversation: 'Created user and session tables',
145
- tags: ['database'],
146
- });
147
- saveToJournal({
148
- projectPath: testDir,
149
- title: 'API Endpoints',
150
- conversation: 'REST API for user management',
151
- tags: ['api', 'backend'],
152
- });
153
- });
154
- it('searches by title', () => {
155
- const results = searchJournal({ projectPath: testDir, query: 'Authentication' });
156
- assert.strictEqual(results.length, 1);
157
- assert.strictEqual(results[0].title, 'Authentication Flow');
158
- });
159
- it('searches by conversation content', () => {
160
- const results = searchJournal({ projectPath: testDir, query: 'JWT' });
161
- assert.strictEqual(results.length, 1);
162
- assert.strictEqual(results[0].title, 'Authentication Flow');
163
- });
164
- it('searches by tags', () => {
165
- const results = searchJournal({ projectPath: testDir, query: 'database' });
166
- assert.strictEqual(results.length, 1);
167
- assert.strictEqual(results[0].title, 'Database Schema');
168
- });
169
- it('is case insensitive', () => {
170
- const results = searchJournal({ projectPath: testDir, query: 'oauth2' });
171
- assert.strictEqual(results.length, 1);
172
- });
173
- it('returns multiple matches', () => {
174
- const results = searchJournal({ projectPath: testDir, query: 'user' });
175
- // Should match 'Database Schema' (user tables) and 'API Endpoints' (user management)
176
- assert.strictEqual(results.length, 2);
177
- });
178
- it('returns empty array for no matches', () => {
179
- const results = searchJournal({ projectPath: testDir, query: 'nonexistent' });
180
- assert.deepStrictEqual(results, []);
181
- });
182
- });
183
- });
184
- //# sourceMappingURL=journal.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"journal.test.js","sourceRoot":"","sources":["../../src/tests/journal.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=metrics.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"metrics.test.d.ts","sourceRoot":"","sources":["../../src/tests/metrics.test.ts"],"names":[],"mappings":""}
@@ -1,178 +0,0 @@
1
- import { describe, it, beforeEach, afterEach } from 'node:test';
2
- import assert from 'node:assert';
3
- import { mkdirSync, rmSync, existsSync, writeFileSync as fsWriteFileSync } from 'fs';
4
- import { join } from 'path';
5
- import { tmpdir } from 'os';
6
- import { loadMetrics, saveMetrics, startSession, endSession, recordToolCall, recordPromptCopied, recordPhaseChange, getMetricsSummary, } from '../metrics.js';
7
- describe('Metrics Module', () => {
8
- const testDir = join(tmpdir(), 'midas-metrics-test-' + Date.now());
9
- beforeEach(() => {
10
- mkdirSync(testDir, { recursive: true });
11
- });
12
- afterEach(() => {
13
- rmSync(testDir, { recursive: true, force: true });
14
- });
15
- describe('loadMetrics', () => {
16
- it('returns default metrics for new project', () => {
17
- const metrics = loadMetrics(testDir);
18
- assert.strictEqual(metrics.totalSessions, 0);
19
- assert.strictEqual(metrics.totalToolCalls, 0);
20
- assert.strictEqual(metrics.sessions.length, 0);
21
- assert.strictEqual(metrics.currentStreak, 0);
22
- });
23
- it('loads saved metrics', () => {
24
- const saved = {
25
- totalSessions: 5,
26
- totalToolCalls: 42,
27
- totalTornadoCycles: 3,
28
- totalJournalsSaved: 2,
29
- phaseHistory: [],
30
- sessions: [],
31
- averageSessionMinutes: 15,
32
- currentStreak: 3,
33
- lastSessionDate: '2026-01-12',
34
- };
35
- mkdirSync(join(testDir, '.midas'), { recursive: true });
36
- fsWriteFileSync(join(testDir, '.midas', 'metrics.json'), JSON.stringify(saved));
37
- const metrics = loadMetrics(testDir);
38
- assert.strictEqual(metrics.totalSessions, 5);
39
- assert.strictEqual(metrics.currentStreak, 3);
40
- });
41
- });
42
- describe('saveMetrics', () => {
43
- it('creates .midas directory', () => {
44
- saveMetrics(testDir, loadMetrics(testDir));
45
- assert.strictEqual(existsSync(join(testDir, '.midas')), true);
46
- });
47
- it('persists metrics', () => {
48
- const metrics = loadMetrics(testDir);
49
- metrics.totalToolCalls = 10;
50
- saveMetrics(testDir, metrics);
51
- const loaded = loadMetrics(testDir);
52
- assert.strictEqual(loaded.totalToolCalls, 10);
53
- });
54
- });
55
- describe('startSession', () => {
56
- it('returns unique session ID', () => {
57
- const id1 = startSession(testDir, { phase: 'IDLE' });
58
- const id2 = startSession(testDir, { phase: 'IDLE' });
59
- assert.notStrictEqual(id1, id2);
60
- });
61
- it('increments total sessions', () => {
62
- startSession(testDir, { phase: 'IDLE' });
63
- startSession(testDir, { phase: 'IDLE' });
64
- const metrics = loadMetrics(testDir);
65
- assert.strictEqual(metrics.totalSessions, 2);
66
- });
67
- it('records start phase', () => {
68
- startSession(testDir, { phase: 'BUILD', step: 'IMPLEMENT' });
69
- const metrics = loadMetrics(testDir);
70
- assert.strictEqual(metrics.sessions[0].startPhase.phase, 'BUILD');
71
- });
72
- it('starts streak at 1 for first session', () => {
73
- startSession(testDir, { phase: 'IDLE' });
74
- const metrics = loadMetrics(testDir);
75
- assert.strictEqual(metrics.currentStreak, 1);
76
- });
77
- it('updates last session date', () => {
78
- startSession(testDir, { phase: 'IDLE' });
79
- const metrics = loadMetrics(testDir);
80
- const today = new Date().toISOString().slice(0, 10);
81
- assert.strictEqual(metrics.lastSessionDate, today);
82
- });
83
- });
84
- describe('endSession', () => {
85
- it('records end time', () => {
86
- const sessionId = startSession(testDir, { phase: 'IDLE' });
87
- endSession(testDir, sessionId, { phase: 'BUILD', step: 'IMPLEMENT' });
88
- const metrics = loadMetrics(testDir);
89
- assert.strictEqual(typeof metrics.sessions[0].endTime, 'string');
90
- });
91
- it('records end phase', () => {
92
- const sessionId = startSession(testDir, { phase: 'IDLE' });
93
- endSession(testDir, sessionId, { phase: 'BUILD', step: 'TEST' });
94
- const metrics = loadMetrics(testDir);
95
- assert.strictEqual(metrics.sessions[0].endPhase?.phase, 'BUILD');
96
- });
97
- it('calculates average session time', () => {
98
- const sessionId = startSession(testDir, { phase: 'IDLE' });
99
- // End immediately
100
- endSession(testDir, sessionId, { phase: 'IDLE' });
101
- const metrics = loadMetrics(testDir);
102
- assert.strictEqual(typeof metrics.averageSessionMinutes, 'number');
103
- });
104
- });
105
- describe('recordToolCall', () => {
106
- it('increments session tool calls', () => {
107
- const sessionId = startSession(testDir, { phase: 'IDLE' });
108
- recordToolCall(testDir, sessionId, 'midas_audit');
109
- recordToolCall(testDir, sessionId, 'midas_check_docs');
110
- const metrics = loadMetrics(testDir);
111
- assert.strictEqual(metrics.sessions[0].toolCalls, 2);
112
- });
113
- it('increments total tool calls', () => {
114
- const sessionId = startSession(testDir, { phase: 'IDLE' });
115
- recordToolCall(testDir, sessionId, 'midas_audit');
116
- const metrics = loadMetrics(testDir);
117
- assert.strictEqual(metrics.totalToolCalls, 1);
118
- });
119
- it('tracks tornado cycles specifically', () => {
120
- const sessionId = startSession(testDir, { phase: 'IDLE' });
121
- recordToolCall(testDir, sessionId, 'midas_tornado');
122
- recordToolCall(testDir, sessionId, 'midas_tornado');
123
- const metrics = loadMetrics(testDir);
124
- assert.strictEqual(metrics.sessions[0].tornadoCycles, 2);
125
- assert.strictEqual(metrics.totalTornadoCycles, 2);
126
- });
127
- it('tracks journal saves specifically', () => {
128
- const sessionId = startSession(testDir, { phase: 'IDLE' });
129
- recordToolCall(testDir, sessionId, 'midas_journal_save');
130
- const metrics = loadMetrics(testDir);
131
- assert.strictEqual(metrics.sessions[0].journalsSaved, 1);
132
- assert.strictEqual(metrics.totalJournalsSaved, 1);
133
- });
134
- });
135
- describe('recordPromptCopied', () => {
136
- it('increments prompt copy count', () => {
137
- const sessionId = startSession(testDir, { phase: 'IDLE' });
138
- recordPromptCopied(testDir, sessionId);
139
- recordPromptCopied(testDir, sessionId);
140
- const metrics = loadMetrics(testDir);
141
- assert.strictEqual(metrics.sessions[0].promptsCopied, 2);
142
- });
143
- });
144
- describe('recordPhaseChange', () => {
145
- it('adds phase to history', () => {
146
- recordPhaseChange(testDir, { phase: 'EAGLE_SIGHT', step: 'IDEA' });
147
- const metrics = loadMetrics(testDir);
148
- assert.strictEqual(metrics.phaseHistory.length, 1);
149
- assert.strictEqual(metrics.phaseHistory[0].phase, 'EAGLE_SIGHT:IDEA');
150
- });
151
- it('records entry time', () => {
152
- recordPhaseChange(testDir, { phase: 'BUILD', step: 'RULES' });
153
- const metrics = loadMetrics(testDir);
154
- assert.strictEqual(typeof metrics.phaseHistory[0].enteredAt, 'string');
155
- });
156
- it('calculates duration when changing phases', () => {
157
- recordPhaseChange(testDir, { phase: 'BUILD', step: 'RULES' });
158
- recordPhaseChange(testDir, { phase: 'BUILD', step: 'INDEX' });
159
- const metrics = loadMetrics(testDir);
160
- assert.strictEqual(typeof metrics.phaseHistory[0].duration, 'number');
161
- });
162
- });
163
- describe('getMetricsSummary', () => {
164
- it('returns message for no sessions', () => {
165
- const summary = getMetricsSummary(testDir);
166
- assert.strictEqual(summary, 'No sessions yet');
167
- });
168
- it('returns formatted summary', () => {
169
- startSession(testDir, { phase: 'IDLE' });
170
- const sessionId = startSession(testDir, { phase: 'BUILD', step: 'IMPLEMENT' });
171
- recordToolCall(testDir, sessionId, 'midas_audit');
172
- const summary = getMetricsSummary(testDir);
173
- assert.strictEqual(summary.includes('Sessions:'), true);
174
- assert.strictEqual(summary.includes('Tool calls:'), true);
175
- });
176
- });
177
- });
178
- //# sourceMappingURL=metrics.test.js.map