import assert from 'node:assert/strict' import { test } from 'node:test' import fc from 'fast-check' import { claimHeartbeatHour, hasPendingHeartbeat, orderWakes, type Wake, type WakeKind, wakePriority, } from './wake.ts' function wake(kind: WakeKind, seq: number, deferredUntil?: string): Wake { return { id: `w${seq}`, seq, kind, createdAt: new Date(seq).toISOString(), payload: null, attempts: 0, deferredUntil, } } test('failure wakes outrank chat which outranks heartbeat', () => { const ordered = orderWakes([wake('heartbeat', 1), wake('chat', 2), wake('deploy_failure', 3)], 0) assert.deepEqual( ordered.map((w) => w.kind), ['deploy_failure', 'chat', 'heartbeat'], ) }) test('FIFO inside a class', () => { const ordered = orderWakes([wake('chat', 5), wake('chat', 4), wake('chat', 6)], 0) assert.deepEqual( ordered.map((w) => w.seq), [4, 5, 6], ) }) test('deferred wakes are skipped until their time', () => { const now = 1_000_000 const ordered = orderWakes( [wake('chat', 1, new Date(now + 1000).toISOString()), wake('chat', 2)], now, ) assert.deepEqual( ordered.map((w) => w.seq), [2], ) }) test('heartbeat coalescing predicate', () => { assert.equal(hasPendingHeartbeat([wake('chat', 1)]), false) assert.equal(hasPendingHeartbeat([wake('chat', 1), wake('heartbeat', 2)]), true) }) test('heartbeat hour is claimed at most once and never replayed', () => { const first = claimHeartbeatHour({}, '2026-09-12T03') assert.equal(first.claimed, true) const second = claimHeartbeatHour(first.state, '2026-09-12T03') assert.equal(second.claimed, false) const older = claimHeartbeatHour(second.state, '2026-09-12T02') assert.equal(older.claimed, false) const next = claimHeartbeatHour(second.state, '2026-09-12T04') assert.equal(next.claimed, true) }) test('property: ordering is stable sort by (priority, seq)', () => { const kinds: WakeKind[] = ['deploy_failure', 'ci_failure', 'recovery', 'chat', 'heartbeat'] const arbWake = fc .record({ kind: fc.constantFrom(...kinds), seq: fc.nat({ max: 500 }) }) .map((r) => wake(r.kind, r.seq)) fc.assert( fc.property(fc.array(arbWake, { maxLength: 50 }), (wakes) => { const ordered = orderWakes(wakes, 0) for (let i = 1; i < ordered.length; i++) { const a = ordered[i - 1] as Wake const b = ordered[i] as Wake if (a.kind === b.kind) assert.ok(a.seq <= b.seq) else assert.ok(wakePriority(a.kind) <= wakePriority(b.kind)) } }), ) })