()
| 136 | } |
| 137 | |
| 138 | function runTests() { |
| 139 | console.log('\n=== Testing loop-status.js ===\n'); |
| 140 | |
| 141 | let passed = 0; |
| 142 | let failed = 0; |
| 143 | |
| 144 | if (test('reports overdue ScheduleWakeup calls from Claude transcripts', () => { |
| 145 | const homeDir = createTempHome(); |
| 146 | |
| 147 | try { |
| 148 | const transcriptPath = writeTranscript(homeDir, '-Users-affoon-project-a', 'session-a.jsonl', [ |
| 149 | toolUse('2026-04-30T09:00:00.000Z', 'session-a', 'toolu_wake', 'ScheduleWakeup', { |
| 150 | delaySeconds: 300, |
| 151 | reason: 'Iter 15: continue autonomous loop', |
| 152 | }), |
| 153 | ]); |
| 154 | |
| 155 | const result = run(['--home', homeDir, '--now', NOW, '--json']); |
| 156 | |
| 157 | assert.strictEqual(result.code, 0, result.stderr); |
| 158 | const payload = parsePayload(result.stdout); |
| 159 | assert.strictEqual(payload.schemaVersion, 'ecc.loop-status.v1'); |
| 160 | assert.strictEqual(payload.sessions.length, 1); |
| 161 | assert.strictEqual(payload.sessions[0].sessionId, 'session-a'); |
| 162 | assert.strictEqual(payload.sessions[0].transcriptPath, transcriptPath); |
| 163 | assert.strictEqual(payload.sessions[0].state, 'attention'); |
| 164 | assert.ok(payload.sessions[0].signals.some(signal => signal.type === 'schedule_wakeup_overdue')); |
| 165 | assert.strictEqual(payload.sessions[0].latestWake.dueAt, '2026-04-30T09:05:00.000Z'); |
| 166 | } finally { |
| 167 | fs.rmSync(homeDir, { recursive: true, force: true }); |
| 168 | } |
| 169 | })) passed++; else failed++; |
| 170 | |
| 171 | if (test('analyzeTranscript applies default thresholds when called directly', () => { |
| 172 | const homeDir = createTempHome(); |
| 173 | |
| 174 | try { |
| 175 | const transcriptPath = writeTranscript(homeDir, '-Users-affoon-project-direct', 'session-direct.jsonl', [ |
| 176 | toolUse('2026-04-30T09:00:00.000Z', 'session-direct', 'toolu_direct_wake', 'ScheduleWakeup', { |
| 177 | delaySeconds: 300, |
| 178 | reason: 'Direct API default threshold check', |
| 179 | }), |
| 180 | ]); |
| 181 | |
| 182 | const session = analyzeTranscript(transcriptPath, { now: NOW }); |
| 183 | |
| 184 | assert.strictEqual(session.state, 'attention'); |
| 185 | assert.ok(session.signals.some(signal => signal.type === 'schedule_wakeup_overdue')); |
| 186 | } finally { |
| 187 | fs.rmSync(homeDir, { recursive: true, force: true }); |
| 188 | } |
| 189 | })) passed++; else failed++; |
| 190 | |
| 191 | if (test('reports stale Bash tool_use entries without matching tool_result', () => { |
| 192 | const homeDir = createTempHome(); |
| 193 | |
| 194 | try { |
| 195 | writeTranscript(homeDir, '-Users-affoon-project-b', 'session-b.jsonl', [ |
no test coverage detected