You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A builder's state.dbbuilders row can disappear while its runtime artifacts survive — the Tower terminal session (in global.db terminal_sessions), the shellper + PTY child processes, the .builders/<id>/ worktree, and the local + remote branches all remain. This leaves an uncleanable SPLIT state.
Observed
A bugfix builder whose PR had merged and issue closed:
global.db terminal_sessions: row still present (type=builder, with pid).
shellper + bash processes: still alive (cwd = the worktree).
worktree + local branch + origin/<branch>: all still present.
Tower UI: still lists the builder ALIVE ("Blocked: PR review", no owner).
Why it matters
Uncleanable:afx cleanup resolves a builder only via the state.builders row (cleanup.ts:196/235 → fatal("not found")), and every teardown step is keyed off that row. No row → no sanctioned teardown.
Find and fix whatever removes the builders row while the terminal/shellper/worktree persist (a partial cleanup, a race, or a premature row delete). The row should not be deleted until the runtime artifacts are torn down (or vice-versa — make teardown atomic). Companion issue covers a row-less cleanup escape hatch.
Summary
A builder's
state.dbbuildersrow can disappear while its runtime artifacts survive — the Tower terminal session (in global.dbterminal_sessions), the shellper + PTY child processes, the.builders/<id>/worktree, and the local + remote branches all remain. This leaves an uncleanable SPLIT state.Observed
A bugfix builder whose PR had merged and issue closed:
state.dbbuilders row: gone (allafx cleanuplookups return "not found").terminal_sessions: row still present (type=builder, with pid).origin/<branch>: all still present.Why it matters
afx cleanupresolves a builder only via thestate.buildersrow (cleanup.ts:196/235→fatal("not found")), and every teardown step is keyed off that row. No row → no sanctioned teardown.lookupBuilderSpawningArchitect(sender)returnsundefined, soresolveAgentInWorkspacefalls through to the "non-builder sender → main first" branch — the builder'safx send architectsilently lands onmain. The missing row is also why the UI shows "no owner" (owner =spawned_by_architect, which lives in that row). This is the same class as the afx send: detectCurrentBuilderId silently falls back to bare worktree name on state.db read failure → builder messages misroute to main #1094 routing fault.Ask
Find and fix whatever removes the
buildersrow while the terminal/shellper/worktree persist (a partial cleanup, a race, or a premature row delete). The row should not be deleted until the runtime artifacts are torn down (or vice-versa — make teardown atomic). Companion issue covers a row-less cleanup escape hatch.