backlog-burndown's cleanup step covers the worktrees, the local branches, and the merged remote branches a round leaves. It does not cover the third thing a worker leaves, which is the shells it started. #1589's incident was seven of those surviving a six-worker run by hours.
A draft of this step was written for #1622 and withdrawn, because two review rounds found it wrong in ways worth recording so the next attempt does not repeat them.
What the withdrawn draft got wrong
It offered ps -eo pid=,etimes=,args= | grep -E '(while|until).*sleep' | grep -v grep. Each clause of that is a defect:
- The
sleep children carry no loop text in their own argv, so only a parent whose loop was passed on the command line matches at all. A loop in a script file, or typed into an interactive shell, matches nothing.
| grep -v grep drops the ordinary wait shape, since a wait whose condition greps something has grep in its own command line. The filter removes the likeliest survivor.
etimes is a procps keyword. On a BSD ps the pipeline fails and prints nothing, which reads identically to a clean sweep.
- The pattern matches any process whose argv merely contains both words, an editor on a file named for them included.
- "end only what this run started" had nothing in the output to decide that by.
A second draft pointed at the agent-safety kit's own sweep instead. That was wrong differently: python3 <missing path> exits 2, which is the same status the sweep uses for "found strays", so an absent script and a real finding were indistinguishable.
What a correct step needs
The kit's stray-process-sweep.py is the tested mechanism and its limits are written down in host-setup/agent-safety/README.md requirement 8. A per-round step still has a reason to exist, because a run dispatching workers finishes many rounds inside one session and the hook fires once at the end.
So the step needs: a way to run the sweep that tells "not installed" from "found something", a way to attribute a survivor to this run rather than to a concurrent one, and a stated platform scope.
backlog-burndown's cleanup step covers the worktrees, the local branches, and the merged remote branches a round leaves. It does not cover the third thing a worker leaves, which is the shells it started. #1589's incident was seven of those surviving a six-worker run by hours.A draft of this step was written for #1622 and withdrawn, because two review rounds found it wrong in ways worth recording so the next attempt does not repeat them.
What the withdrawn draft got wrong
It offered
ps -eo pid=,etimes=,args= | grep -E '(while|until).*sleep' | grep -v grep. Each clause of that is a defect:sleepchildren carry no loop text in their own argv, so only a parent whose loop was passed on the command line matches at all. A loop in a script file, or typed into an interactive shell, matches nothing.| grep -v grepdrops the ordinary wait shape, since a wait whose condition greps something hasgrepin its own command line. The filter removes the likeliest survivor.etimesis a procps keyword. On a BSDpsthe pipeline fails and prints nothing, which reads identically to a clean sweep.A second draft pointed at the agent-safety kit's own sweep instead. That was wrong differently:
python3 <missing path>exits 2, which is the same status the sweep uses for "found strays", so an absent script and a real finding were indistinguishable.What a correct step needs
The kit's
stray-process-sweep.pyis the tested mechanism and its limits are written down inhost-setup/agent-safety/README.mdrequirement 8. A per-round step still has a reason to exist, because a run dispatching workers finishes many rounds inside one session and the hook fires once at the end.So the step needs: a way to run the sweep that tells "not installed" from "found something", a way to attribute a survivor to this run rather than to a concurrent one, and a stated platform scope.