Summary
Two related robustness gaps in afx cleanup (packages/codev/src/agent-farm/commands/cleanup.ts):
1. No row-less / by-worktree teardown path
cleanup() resolves the builder only via the state.builders row and fatal()s when it's absent (cleanup.ts:196, :235). When the row is gone but the worktree + terminal + shellper survive (see companion SPLIT-state issue), there is no sanctioned way to tear it down — even though the building block already exists: killShellperProcesses(worktreePath) works purely by path.
Ask: add afx cleanup --worktree <path> (or --orphan) that tears down by worktree path when no row exists: kill shellpers by path, git worktree remove --force, delete local/remote branches, prune. Makes SPLIT states directly recoverable without the current afx spawn --resume (re-register) → afx cleanup dance.
2. -i <issue> never matches a bugfix builder
afx cleanup -i <issue> fails on a present, healthy bugfix builder:
cleanup.ts:188 looks for id === "bugfix-<n>", but the real id is builder-bugfix-<n> → miss.
- Fallback
cleanup.ts:193: b.issueNumber === options.issue. But issue_number is stored as TEXT ('1094') and options.issue is a number (1094), so strict === is always false → "not found".
Reproduced: afx cleanup -i 1094 → Bugfix builder not found for issue #1094 while the builder was healthy and present; afx cleanup -p builder-bugfix-1094 worked. Fix: coerce types in the comparison (String(b.issueNumber) === String(options.issue)), and/or match id === "builder-bugfix-<n>".
Companion to the SPLIT-state root-cause issue.
Summary
Two related robustness gaps in
afx cleanup(packages/codev/src/agent-farm/commands/cleanup.ts):1. No row-less / by-worktree teardown path
cleanup()resolves the builder only via thestate.buildersrow andfatal()s when it's absent (cleanup.ts:196,:235). When the row is gone but the worktree + terminal + shellper survive (see companion SPLIT-state issue), there is no sanctioned way to tear it down — even though the building block already exists:killShellperProcesses(worktreePath)works purely by path.Ask: add
afx cleanup --worktree <path>(or--orphan) that tears down by worktree path when no row exists: kill shellpers by path,git worktree remove --force, delete local/remote branches, prune. Makes SPLIT states directly recoverable without the currentafx spawn --resume(re-register) →afx cleanupdance.2.
-i <issue>never matches a bugfix builderafx cleanup -i <issue>fails on a present, healthy bugfix builder:cleanup.ts:188looks forid === "bugfix-<n>", but the real id isbuilder-bugfix-<n>→ miss.cleanup.ts:193:b.issueNumber === options.issue. Butissue_numberis stored as TEXT ('1094') andoptions.issueis a number (1094), so strict===is always false → "not found".Reproduced:
afx cleanup -i 1094→Bugfix builder not found for issue #1094while the builder was healthy and present;afx cleanup -p builder-bugfix-1094worked. Fix: coerce types in the comparison (String(b.issueNumber) === String(options.issue)), and/or matchid === "builder-bugfix-<n>".Companion to the SPLIT-state root-cause issue.