diff --git a/src/store.test.ts b/src/store.test.ts index 8f6b5b3..d19e859 100644 --- a/src/store.test.ts +++ b/src/store.test.ts @@ -231,6 +231,55 @@ describe('InMemoryEventStore', () => { expect(worker?.beadsCompleted).toBe(0); }); + it('should set currentBead from bead.claim.succeeded event', () => { + store.add(createEvent({ worker: 'w-test', msg: 'bead.claim.succeeded', bead: 'bd-abc123' })); + + const worker = store.getWorker('w-test'); + expect(worker?.currentBead).toBe('bd-abc123'); + }); + + it('should clear currentBead to null on bead.released event', () => { + // First set currentBead + store.add(createEvent({ worker: 'w-test', msg: 'bead.claim.succeeded', bead: 'bd-abc123' })); + + const workerBefore = store.getWorker('w-test'); + expect(workerBefore?.currentBead).toBe('bd-abc123'); + + // Then release the bead + store.add(createEvent({ worker: 'w-test', msg: 'bead.released', bead: 'bd-abc123' })); + + const workerAfter = store.getWorker('w-test'); + expect(workerAfter?.currentBead).toBeNull(); + }); + + it('should clear currentBead on bead.released regardless of reason', () => { + // Set currentBead + store.add(createEvent({ worker: 'w-test', msg: 'bead.claim.succeeded', bead: 'bd-xyz' })); + + // Release with non-success reason + store.add(createEvent({ worker: 'w-test', msg: 'bead.released', reason: 'release_retry', bead: 'bd-xyz' })); + + const worker = store.getWorker('w-test'); + expect(worker?.currentBead).toBeNull(); + }); + + it('should update currentBead when worker claims another bead', () => { + // Claim first bead + store.add(createEvent({ worker: 'w-test', msg: 'bead.claim.succeeded', bead: 'bd-first' })); + expect(store.getWorker('w-test')?.currentBead).toBe('bd-first'); + + // Claim second bead + store.add(createEvent({ worker: 'w-test', msg: 'bead.claim.succeeded', bead: 'bd-second' })); + expect(store.getWorker('w-test')?.currentBead).toBe('bd-second'); + }); + + it('should initialize currentBead to null for new workers', () => { + store.add(createEvent({ worker: 'w-newbie', msg: 'worker.started' })); + + const worker = store.getWorker('w-newbie'); + expect(worker?.currentBead).toBeNull(); + }); + it('should track firstSeen timestamp', () => { const earlyTs = 1000; const lateTs = 5000; diff --git a/src/store.ts b/src/store.ts index 1fbd693..7cb6b5f 100644 --- a/src/store.ts +++ b/src/store.ts @@ -622,6 +622,7 @@ export class InMemoryEventStore implements EventStore { activeFiles: [], hasCollision: false, activeBead: event.bead, + currentBead: null, activeDirectories: [], collisionTypes: [], eventCount: 1, @@ -687,14 +688,18 @@ export class InMemoryEventStore implements EventStore { worker.activeDirectories = []; worker.activeBead = undefined; } - } else if (needleEvent === 'bead.released' && event['reason'] === 'release_success') { - worker.status = 'idle'; - if (event.bead) { - worker.beadsCompleted++; + } else if (needleEvent === 'bead.released') { + // Clear currentBead on any bead.released event (regardless of reason) + worker.currentBead = null; + if (event['reason'] === 'release_success') { + worker.status = 'idle'; + if (event.bead) { + worker.beadsCompleted++; + } + worker.activeFiles = []; + worker.activeDirectories = []; + worker.activeBead = undefined; } - worker.activeFiles = []; - worker.activeDirectories = []; - worker.activeBead = undefined; } else if ( needleEvent === 'worker.started' || needleEvent === 'bead.claimed' || @@ -705,6 +710,11 @@ export class InMemoryEventStore implements EventStore { } } + // Set currentBead from bead.claim.succeeded event + if (needleEvent === 'bead.claim.succeeded' && event.bead) { + worker.currentBead = event.bead; + } + // Update last event worker.lastEvent = event; diff --git a/src/types.ts b/src/types.ts index ef24b62..966c99d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -551,6 +551,9 @@ export interface WorkerInfo { /** Current bead/task being worked on */ activeBead?: string; + /** Current bead from bead.claim.succeeded, cleared on bead.released */ + currentBead: string | null; + /** Directories this worker is active in */ activeDirectories: string[];