fix(agent-status): restore inventory-confirmed workflow lanes

This commit is contained in:
Brennan Benson
2026-07-21 20:40:27 -07:00
parent df6ebf24be
commit 05e65fbde0
3 changed files with 25 additions and 2 deletions
+2 -2
View File
@@ -35,8 +35,8 @@ export const CLAUDE_EVENTS = [
{ eventName: 'StopFailure', definition: { hooks: [{ type: 'command', command: '' }] } },
// Why: subagent/teammate lifecycle feeds the sidebar's child rows and keeps
// a pane 'working' while background children outlive the lead's turn.
// TeammateIdle retires the working-only row when SubagentStop is lost;
// idle teammates still report status "running" in Stop's background_tasks.
// TeammateIdle parks turn-based teammates without trusting their permanently
// "running" background_tasks entry to gate the pane.
// Older Claude builds ignore unregistered event names (StopFailure precedent).
{ eventName: 'SubagentStart', definition: { hooks: [{ type: 'command', command: '' }] } },
{ eventName: 'SubagentStop', definition: { hooks: [{ type: 'command', command: '' }] } },
+20
View File
@@ -65,6 +65,26 @@ describe('claude-subagent-roster', () => {
expect(roster.has('alane-hooks-6d3cb5b5')).toBe(false)
})
it('restores a parked workflow lane to working when the inventory reports it running', () => {
const roster: ClaudeSubagentRoster = new Map()
upsertWorkingClaudeSubagent(roster, 'alane-hooks-6d3cb5b5', { agentType: 'lane-hooks' }, 100)
stopClaudeSubagent(roster, 'alane-hooks-6d3cb5b5')
// Why: lifecycle hooks and the lead Stop inventory can arrive around the
// same boundary; an authoritative running task must keep the pane gated.
foldClaudeBackgroundTasksIntoRoster(
roster,
[task({ id: 'alane-hooks-6d3cb5b5', agentType: 'lane-hooks' })],
150
)
expect(roster.get('alane-hooks-6d3cb5b5')).toMatchObject({
state: 'working',
listedAsSubagentTask: true
})
expect(claudeRosterHasWorkingSubagent(roster)).toBe(true)
})
it('revives an idle teammate as working while keeping its first-observed startedAt', () => {
const roster: ClaudeSubagentRoster = new Map()
upsertWorkingClaudeSubagent(roster, 'aprobe1-6d3cb5b5', { agentType: 'probe1' }, 100)
+3
View File
@@ -221,6 +221,9 @@ export function foldClaudeBackgroundTasksIntoRoster(
pendingRunningTasks.delete(task.id)
continue
}
// Why: a Stop can park the row before the lead inventory confirms the
// same workflow lane is still running; the authoritative task wins.
existing.state = 'working'
existing.agentType = task.agentType ?? existing.agentType
existing.description = task.description ?? existing.description
existing.listedAsSubagentTask = true