fix(handoff): don't KillPaneProcesses on self-handoff

For self-handoff, calling KillPaneProcesses kills the gt handoff
process itself before it can execute RespawnPane, leaving the pane
dead with no respawn. The fix is to rely on respawn-pane -k which
handles killing and respawning atomically.

The remote handoff path is unaffected - it correctly calls
KillPaneProcesses because the caller is in a different session.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
max
2026-01-25 15:56:15 -08:00
committed by beads/crew/emma
parent 2ee5e1c5ad
commit 0c791a4d40

View File

@@ -211,14 +211,17 @@ func runHandoff(cmd *cobra.Command, args []string) error {
style.PrintWarning("could not set remain-on-exit: %v", err)
}
// Kill all processes in the pane before respawning to prevent orphan leaks
// RespawnPane's -k flag only sends SIGHUP which Claude/Node may ignore
if err := t.KillPaneProcesses(pane); err != nil {
// Non-fatal but log the warning
style.PrintWarning("could not kill pane processes: %v", err)
}
// NOTE: For self-handoff, we do NOT call KillPaneProcesses here.
// That would kill the gt handoff process itself before it can call RespawnPane,
// leaving the pane dead with no respawn. RespawnPane's -k flag handles killing
// atomically - tmux kills the old process and spawns the new one together.
// See: https://github.com/steveyegge/gastown/issues/859 (pane is dead bug)
//
// For orphan prevention, we rely on respawn-pane -k which sends SIGHUP/SIGTERM.
// If orphans still occur, the solution is to adjust the restart command to
// kill orphans at startup, not to kill ourselves before respawning.
// Use exec to respawn the pane - this kills us and restarts
// Use respawn-pane -k to atomically kill current process and start new one
// Note: respawn-pane automatically resets remain-on-exit to off
return t.RespawnPane(pane, restartCmd)
}