refactor(session): extract town session helpers for DRY shutdown

Previously, town-level session stopping (Mayor, Boot, Deacon) was
implemented inline in gt down with separate code blocks for each
session. The shutdown order (Boot must stop before Deacon to prevent
the watchdog from restarting Deacon) was implicit in the code ordering.

Add session.TownSessions() and session.StopTownSession() to centralize
town-level session management. This provides a single source of truth
for the session list, shutdown order, and graceful/force logic.

Refactor gt down to use these helpers instead of inline logic.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
PV
2026-01-04 00:17:37 -08:00
parent 60ecf1ff76
commit c299f44aea
2 changed files with 67 additions and 29 deletions

View File

@@ -5,9 +5,9 @@ import (
"time"
"github.com/spf13/cobra"
"github.com/steveyegge/gastown/internal/boot"
"github.com/steveyegge/gastown/internal/daemon"
"github.com/steveyegge/gastown/internal/events"
"github.com/steveyegge/gastown/internal/session"
"github.com/steveyegge/gastown/internal/style"
"github.com/steveyegge/gastown/internal/tmux"
"github.com/steveyegge/gastown/internal/workspace"
@@ -73,35 +73,20 @@ func runDown(cmd *cobra.Command, args []string) error {
}
}
// Get session names
mayorSession := getMayorSessionName()
deaconSession := getDeaconSessionName()
// 2. Stop Mayor
if err := stopSession(t, mayorSession); err != nil {
printDownStatus("Mayor", false, err.Error())
allOK = false
} else {
printDownStatus("Mayor", true, "stopped")
// 2. Stop town-level sessions (Mayor, Boot, Deacon) in correct order
for _, ts := range session.TownSessions() {
stopped, err := session.StopTownSession(t, ts, downForce)
if err != nil {
printDownStatus(ts.Name, false, err.Error())
allOK = false
} else if stopped {
printDownStatus(ts.Name, true, "stopped")
} else {
printDownStatus(ts.Name, true, "not running")
}
}
// 3. Stop Boot (Deacon's watchdog)
if err := stopSession(t, boot.SessionName); err != nil {
printDownStatus("Boot", false, err.Error())
allOK = false
} else {
printDownStatus("Boot", true, "stopped")
}
// 4. Stop Deacon
if err := stopSession(t, deaconSession); err != nil {
printDownStatus("Deacon", false, err.Error())
allOK = false
} else {
printDownStatus("Deacon", true, "stopped")
}
// 5. Stop Daemon last
// 3. Stop Daemon last
running, _, _ := daemon.IsRunning(townRoot)
if running {
if err := daemon.StopDaemon(townRoot); err != nil {
@@ -114,7 +99,7 @@ func runDown(cmd *cobra.Command, args []string) error {
printDownStatus("Daemon", true, "not running")
}
// 6. Kill tmux server if --all
// 4. Kill tmux server if --all
if downAll {
if err := t.KillServer(); err != nil {
printDownStatus("Tmux server", false, err.Error())