feat(spawn): migrate to NewSessionWithCommand pattern

Migrate witness, boot, and deacon spawns to use NewSessionWithCommand
instead of NewSession+SendKeys to ensure BD_ACTOR is visible in the
process tree for orphan detection via ps.

Refs: gt-emi5b

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
dementus
2026-01-13 01:27:03 -08:00
committed by beads/crew/emma
parent 278b2f2d4d
commit 87fde4b4fd
3 changed files with 36 additions and 58 deletions

View File

@@ -170,8 +170,13 @@ func (b *Boot) spawnTmux() error {
return fmt.Errorf("ensuring boot dir: %w", err)
}
// Create new session in boot directory (not deacon dir) so Claude reads Boot's CLAUDE.md
if err := b.tmux.NewSession(SessionName, b.bootDir); err != nil {
// Build startup command first
// The "gt boot triage" prompt tells Boot to immediately start triage (GUPP principle)
startCmd := config.BuildAgentStartupCommand("boot", "deacon-boot", "", "gt boot triage")
// Create session with command directly to avoid send-keys race condition.
// See: https://github.com/anthropics/gastown/issues/280
if err := b.tmux.NewSessionWithCommand(SessionName, b.bootDir, startCmd); err != nil {
return fmt.Errorf("creating boot session: %w", err)
}
@@ -185,18 +190,6 @@ func (b *Boot) spawnTmux() error {
_ = b.tmux.SetEnvironment(SessionName, k, v)
}
// Launch Claude with environment exported inline and initial triage prompt
// The "gt boot triage" prompt tells Boot to immediately start triage (GUPP principle)
startCmd := config.BuildAgentStartupCommand("boot", "deacon-boot", "", "gt boot triage")
// Wait for shell to be ready before sending keys (prevents "can't find pane" under load)
if err := b.tmux.WaitForShellReady(SessionName, 5*time.Second); err != nil {
_ = b.tmux.KillSession(SessionName)
return fmt.Errorf("waiting for shell: %w", err)
}
if err := b.tmux.SendKeys(SessionName, startCmd); err != nil {
return fmt.Errorf("sending startup command: %w", err)
}
return nil
}