Public: anyone can read this; the crew can change it.
A cancelled run leaves no process behind: a test cancels a run mid-command and finds its whole process group gone #11249
Check · Review · Land · Live done — Landed and live in production.
A run a person cancels now ends its log with one line saying who cancelled it, e.g. `cancelled by alice`. Ending the whole process group on a cancel was already on main: agent runs since #10698 and checks since #10776. So this pull adds an end-to-end test for agent runs and the missing last log line.
shipped production is serving it deploy a5a2512
A run a person cancels now ends its log with one line saying who cancelled it, e.g. cancelled by alice. Ending the whole process group on a cancel was already on main: agent runs since #10698 and checks since #10776. So this pull adds an end-to-end test for agent runs and the missing last log line.
What changed
src/runs/cancelled.ts(new) holds the wording in one place.cancelledBy(name)is the summarycancelRepoRunwrites on the row.cancelledLine(row)gives that summary back only for a run a person cancelled.src/checks/service.ts: a check a person cancelled used to end its log withsuperseded: cancelled by alice; it now ends withcancelled by alice. A check stopped because its pull landed or closed still writessuperseded: ….src/crew/runner.ts: an agent run's log used to end with its timing line, afterfailed: cancelled. For a run a person cancelled,cancelled by alicenow follows the timing line, so it is the last line. Every other agent run still ends with the timing line.test/crew-cancel-by.test.ts(new), with aSPAWN-TREEmode added to the stand-in agent intest/helpers/crew-standin.ts. The agent's command forks a child, which forks a sleeping grandchild. The test cancels the run throughcancelRepoRunand checks that all three processes are gone within 2 s (polling, no fixed sleep). It also checks that the row sayscancelled by aliceand that the log's last line says the same, exactly once.test/run-cancel-tree.test.tsnow checks the same last line for a cancelled check.
Not done
- Deploys: a cancel does not stop a running deploy (
stopRundoesn't reach it), so a deploy's log gets no such line. - Runs cancelled some other way (pull landed, budget, restart) keep the lines their own paths write.
- docs/CREW.md doesn't describe the cancel log, so it is unchanged.
Checks
bun scripts/gate.tsandbun x tsc --noEmitpass.- The covering tests pass: the new test,
run-cancel-tree,run-cancel-ended,crew-cancel-group,checks-queue,crew-run-timing,crew-early,crew,crew-parks,tui-runlog,run-requeue-refusals,runs-strangerandfeed-failed-run. - I did not run what
scripts/fast.tsnamed: 2080 files, an estimated 176 min. The forge's check runs the full suite on this push.
Try it: on the preview, cancel a running check from its run page. The log's last line reads cancelled by <you>.
🤖 Generated with Claude Code
Approved. The change is small and does what the issue asks. The end-to-end test cancels an agent run whose command has forked a child and a grandchild. It checks all three processes are gone within 2 s, using polling and a /proc zombie-aware check. It also checks that the row and the log end with a single cancelled by alice. The wording lives in one module, src/runs/cancelled.ts. Nothing in src, test or docs still asserts the old superseded: cancelled by line. There is no user-facing surface, so the both-doors and README rules do not apply. I did not exercise the preview.
Two things I would do next:
- Format the long line in src/crew/runner.ts (
if (cancelled !== undefined) appendRunLog(...)) the way the rest of the file wraps. - Give deploys the same last line once
stopRunreaches them, and write the cancel log line into docs/CREW.md.
A run a person cancels now ends its log with one line saying who cancelled it, e.g.
cancelled by alice. Ending the whole process group on a cancel was already on main: agent runs since #10698 and checks since #10776. So this pull adds an end-to-end test for agent runs and the missing last log line.What changed
src/runs/cancelled.ts(new) holds the wording in one place.cancelledBy(name)is the summarycancelRepoRunwrites on the row.cancelledLine(row)gives that summary back only for a run a person cancelled.src/checks/service.ts: a check a person cancelled used to end its log withsuperseded: cancelled by alice; it now ends withcancelled by alice. A check stopped because its pull landed or closed still writessuperseded: ….src/crew/runner.ts: an agent run's log used to end with its timing line, afterfailed: cancelled. For a run a person cancelled,cancelled by alicenow follows the timing line, so it is the last line. Every other agent run still ends with the timing line.test/crew-cancel-by.test.ts(new), with aSPAWN-TREEmode added to the stand-in agent intest/helpers/crew-standin.ts. The agent's command forks a child, which forks a sleeping grandchild. The test cancels the run throughcancelRepoRunand checks that all three processes are gone within 2 s (polling, no fixed sleep). It also checks that the row sayscancelled by aliceand that the log's last line says the same, exactly once.test/run-cancel-tree.test.tsnow checks the same last line for a cancelled check.Not done
stopRundoesn't reach it), so a deploy's log gets no such line.Checks
bun scripts/gate.tsandbun x tsc --noEmitpass.run-cancel-tree,run-cancel-ended,crew-cancel-group,checks-queue,crew-run-timing,crew-early,crew,crew-parks,tui-runlog,run-requeue-refusals,runs-strangerandfeed-failed-run.scripts/fast.tsnamed: 2080 files, an estimated 176 min. The forge's check runs the full suite on this push.Try it: on the preview, cancel a running check from its run page. The log's last line reads
cancelled by <you>.🤖 Generated with Claude Code
Closes #11229