Background daemon: reaped spare re-claimed from stale roster; duplicate 'settled' events (2.1.220)
What happened
On the background/agents daemon (CLI 2.1.220, macOS), the spare-pool roster
can advertise a spare that has already been reaped, so the fleet later "claims"
a dead worker. The user-visible symptom: claude stop <id> reports success, but
the same id reappears as a live session minutes later and is then killed
again. Two related roster-consistency defects, both from the daemon log:
1. Reaped spare re-claimed (stale roster entry). A spare is spawned, reaped
while still unclaimed, then claimed ~78 min after it was already killed:
17:22:53 bg spawned 9bceedd8 (spare) # pre-warmed, never claimed
17:45:23 bg settled 9bceedd8 (killed) # reaped as an idle spare
19:03:41 bg claimed-spare 9bceedd8 (fleet) # fleet claims an ALREADY-DEAD spare
19:06:52 bg settled 9bceedd8 (killed) # re-killed
The claim at 19:03 should be impossible — 9bceedd8 was settled/killed at 17:45
and should have left the available-spare set.
2. Duplicate settled events for one worker. The same worker id settles
multiple times in a single lifecycle, e.g.:
bg settled a6844776 (killed) # x2, ~5s apart
bg settled f34d166e (crashed: working directory no longer exists ...) # x3, identical
A worker should settle exactly once. The repeats suggest the reap path runs
more than once against the same (already-terminal) worker.
Impact
claude stop <id>is not trustworthy: the id can be re-served from the stale
roster and reappear as "live", so stopping a session and confirming it's gone
requires re-checking the roster rather than trusting the stop result.
- Ghost/duplicate lifecycle events make external fleet-management tooling
(that keys off claimed-spare / settled) double-count and mis-track state.
Expected
- A settled/reaped spare is removed from the available-spare set atomically, so
it can never be claimed-spare afterward.
- Each worker emits exactly one terminal
settledevent.
Notes
Repro is timing-dependent (idle spare gets reaped, then a claim races against
the stale roster entry), so I don't have a deterministic trigger — but the log
signature above is stable and reproduces across days on 2.1.220. Happy to share
additional (redacted) daemon-log excerpts if useful.