Found while deliberately proving the drain lease on the shipped 0.1.64, during the #311 end-to-end rerun. Not a #311 regression — that fix holds — but it is a path where one staged message never arrives.
What happens
When a drain exceeds drainLeaseDuration (300 s), the next drain records drain-stall and takes the queue over. The takeover clears drainInFlight, and the old drain's owner-guard then skips its fold-back. So the item whose presence read was in flight at the moment of takeover is left in drainDeferred — a field only ever read at the next ≥300 s expiry.
Observed:
drain held 305.9s (7 hung targets × 45s presence deadline)
event=drain-stall held_ms=305882.1 queued=1
The 6 deferred items flushed once the hang was released. The in-flight one never delivered — its memory log says follow-up staged, and a control message sent minutes later delivered instantly, so the target was healthy and the queue was moving.
Severity
Narrow, and I agree with the reporter's rating of follow-up rather than blocker:
But it is still a staged message that never reaches its session while the target is idle and answering, which is the shape this series has been closing.
Suggested
Fold the in-flight item back on takeover rather than relying on the superseded drain's guard, or have the taking drain adopt drainInFlight along with the rest of the queue. Either makes drainDeferred reachable without waiting for another 300 s expiry.
Also confirmed in the same run, no action needed
delivery-stall fires correctly at exactly 45000.0 ms per attempt on a hung send — 3 attempts logged, re-staged, delivered once the hang cleared.
Related: #311, #322, #289
🤖 Generated with Claude Code
https://claude.ai/code/session_01BP43ags4cn8fq2ZZdv85J9
Found while deliberately proving the drain lease on the shipped 0.1.64, during the #311 end-to-end rerun. Not a #311 regression — that fix holds — but it is a path where one staged message never arrives.
What happens
When a drain exceeds
drainLeaseDuration(300 s), the next drain recordsdrain-stalland takes the queue over. The takeover clearsdrainInFlight, and the old drain's owner-guard then skips its fold-back. So the item whose presence read was in flight at the moment of takeover is left indrainDeferred— a field only ever read at the next ≥300 s expiry.Observed:
The 6 deferred items flushed once the hang was released. The in-flight one never delivered — its memory log says
follow-up staged, and a control message sent minutes later delivered instantly, so the target was healthy and the queue was moving.Severity
Narrow, and I agree with the reporter's rating of follow-up rather than blocker:
drain-stallline is right there, unlike A follow-up staged later can jump the queue, and the presence read it depends on has no deadline #311 which was silentBut it is still a staged message that never reaches its session while the target is idle and answering, which is the shape this series has been closing.
Suggested
Fold the in-flight item back on takeover rather than relying on the superseded drain's guard, or have the taking drain adopt
drainInFlightalong with the rest of the queue. Either makesdrainDeferredreachable without waiting for another 300 s expiry.Also confirmed in the same run, no action needed
delivery-stallfires correctly at exactly45000.0 msper attempt on a hung send — 3 attempts logged, re-staged, delivered once the hang cleared.Related: #311, #322, #289
🤖 Generated with Claude Code
https://claude.ai/code/session_01BP43ags4cn8fq2ZZdv85J9