Field incident
On an adopter workspace, afx cleanup -p <n> printed [ok] Builder ... cleaned up! while leaving the worktree on disk AND both the local and remote branches alive. Reproduced on two AIR-type builders in one batch in which sibling BUGFIX builders in the SAME invocation cleaned correctly; the reporter finished the two by hand (merged-ancestor verified first). Whether the process exit code signalled failure is unverified by the reporter (the command was piped), but the success MESSAGE is the thing consumers read, and it over-reported.
Verified against source
packages/codev/src/agent-farm/commands/cleanup.ts: the actual removals — git worktree remove --force (line ~313), git branch -D (~324), and the remote branch delete (~336/361) — are each wrapped in try/catch blocks that swallow failure (some print a "To remove:" hint, but execution continues), and logger.success('Builder ... cleaned up!') at ~428 prints unconditionally. The success line is not evidence of completion by construction.
Principle (shared with the half-registered-spawn issue)
A tool must never render an unknown or partial state as a determinate result. Cleanup renders PARTIAL as a determinate positive. Note the sharp corollary from the reporting workspace's analysis: this defect and the half-registration defect have opposite signs (status/registry UNDER-reports there, cleanup OVER-reports here), so a consumer cannot compensate by calibrating trust in either direction — only independent observation of the substrate resolves both, which is the argument for the reconciliation check filed separately.
Fix shape (hypothesis, for the builder to validate)
- Track the outcome of each removal step; print
[ok] cleaned up only when the post-conditions verifiably hold (worktree path gone, local branch gone, remote branch gone or explicitly skipped with reason).
- On partial completion: exit non-zero and print exactly what remains and the commands to finish by hand (the "To remove:" hints already exist; they must be accompanied by a failure verdict, not a success line).
- Also investigate WHY the two AIR builders failed to remove while BUGFIX siblings in the same batch succeeded (protocol-specific worktree state? lock? unmerged-branch check?) — the transcript offer stands.
Field incident
On an adopter workspace,
afx cleanup -p <n>printed[ok] Builder ... cleaned up!while leaving the worktree on disk AND both the local and remote branches alive. Reproduced on two AIR-type builders in one batch in which sibling BUGFIX builders in the SAME invocation cleaned correctly; the reporter finished the two by hand (merged-ancestor verified first). Whether the process exit code signalled failure is unverified by the reporter (the command was piped), but the success MESSAGE is the thing consumers read, and it over-reported.Verified against source
packages/codev/src/agent-farm/commands/cleanup.ts: the actual removals —git worktree remove --force(line ~313),git branch -D(~324), and the remote branch delete (~336/361) — are each wrapped in try/catch blocks that swallow failure (some print a "To remove:" hint, but execution continues), andlogger.success('Builder ... cleaned up!')at ~428 prints unconditionally. The success line is not evidence of completion by construction.Principle (shared with the half-registered-spawn issue)
A tool must never render an unknown or partial state as a determinate result. Cleanup renders PARTIAL as a determinate positive. Note the sharp corollary from the reporting workspace's analysis: this defect and the half-registration defect have opposite signs (status/registry UNDER-reports there, cleanup OVER-reports here), so a consumer cannot compensate by calibrating trust in either direction — only independent observation of the substrate resolves both, which is the argument for the reconciliation check filed separately.
Fix shape (hypothesis, for the builder to validate)
[ok] cleaned uponly when the post-conditions verifiably hold (worktree path gone, local branch gone, remote branch gone or explicitly skipped with reason).