Skip to content

The drain fans out one agent short: a live-agent count of 1 with no agent visibleΒ #1646

Description

@suleimansh

πŸ€– automated

Found dogfooding #1640/#1644/#1645 on main (chain write-up: #1204 (comment)).

What happened. Concurrent agents: 3, three entries on the queue, no agent running on the project β€” the Agents panel said "No agents working right now", the last run on the project had been DONE for ten minutes. The drain's Run now reported:

tf-1334-dogfood: started 2 agents: draining the queue entry "[Add a root `.gitignore` …"; draining the queue entry "[Add a `package.json` …"

Two of three. The third entry sat on the queue.

Why two. The fan-out is picks = open.slice(0, concurrency - activeAgents) (auto-pm.ts:922), so activeAgents read 1 at 01:20:55. activeAgentCount (daemon-runtime.ts:840) is live pids on the project plus the starting set:

for (const [key, pid] of activeAgents) { if (keyBelongsTo(key, targetProjectId) && isPidAlive(pid)) live++ }
return live + [...starting].filter(key => keyBelongsTo(key, targetProjectId)).length

The pid half is re-checked against the OS, so a dead process cannot hold a slot. The starting half is not: a key that is added on spawn and never removed β€” a spawn path that throws between the two, or a refused start that skips the cleanup β€” costs the project one slot for the rest of the daemon's life, invisibly. Not diagnosed which it was; by 01:27 no process of the earlier runs was alive, and the daemon does not log the count.

Timeline on that project: 01:03 three planners via the sweep (all DONE by 01:06, locks released); 01:06 one triage via the card's plain start (DONE 01:10); 01:20 the drain click β†’ count 1.

Fix shape. Either log the breakdown on every stand-down/fan-out decision (live=N starting=M), so the next occurrence names itself β€” or make starting self-healing the way activeAgents is (a key older than the spawn timeout is dropped). Both are small; the first is what would have made this an answer instead of a question.

Repro. Not reliable yet. Three sweep-started runs, one card-started run, then a drain click on a project the panel shows idle.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions