refactor: replace ensureRefinerySession with refinery.Manager.Start()
Replaces inline ensureRefinerySession function with refinery.NewManager(r).Start(false) in gt start --all. Gains zombie detection, proper state tracking, and WaitForShellReady fix. CI failures (lint in beads.go, integration tests) are pre-existing issues unrelated to this PR's changes. Co-Authored-By: julianknutsen <julianknutsen@users.noreply.github.com>
This commit is contained in:
@@ -10,7 +10,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/steveyegge/gastown/internal/claude"
|
|
||||||
"github.com/steveyegge/gastown/internal/config"
|
"github.com/steveyegge/gastown/internal/config"
|
||||||
"github.com/steveyegge/gastown/internal/constants"
|
"github.com/steveyegge/gastown/internal/constants"
|
||||||
"github.com/steveyegge/gastown/internal/crew"
|
"github.com/steveyegge/gastown/internal/crew"
|
||||||
@@ -18,8 +17,8 @@ import (
|
|||||||
"github.com/steveyegge/gastown/internal/git"
|
"github.com/steveyegge/gastown/internal/git"
|
||||||
"github.com/steveyegge/gastown/internal/mayor"
|
"github.com/steveyegge/gastown/internal/mayor"
|
||||||
"github.com/steveyegge/gastown/internal/polecat"
|
"github.com/steveyegge/gastown/internal/polecat"
|
||||||
|
"github.com/steveyegge/gastown/internal/refinery"
|
||||||
"github.com/steveyegge/gastown/internal/rig"
|
"github.com/steveyegge/gastown/internal/rig"
|
||||||
"github.com/steveyegge/gastown/internal/session"
|
|
||||||
"github.com/steveyegge/gastown/internal/style"
|
"github.com/steveyegge/gastown/internal/style"
|
||||||
"github.com/steveyegge/gastown/internal/tmux"
|
"github.com/steveyegge/gastown/internal/tmux"
|
||||||
"github.com/steveyegge/gastown/internal/witness"
|
"github.com/steveyegge/gastown/internal/witness"
|
||||||
@@ -246,17 +245,15 @@ func startRigAgents(t *tmux.Tmux, townRoot string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Start Refinery
|
// Start Refinery
|
||||||
refinerySession := fmt.Sprintf("gt-%s-refinery", r.Name)
|
refineryMgr := refinery.NewManager(r)
|
||||||
refineryRunning, _ := t.HasSession(refinerySession)
|
if err := refineryMgr.Start(false); err != nil {
|
||||||
if refineryRunning {
|
if errors.Is(err, refinery.ErrAlreadyRunning) {
|
||||||
fmt.Printf(" %s %s refinery already running\n", style.Dim.Render("○"), r.Name)
|
fmt.Printf(" %s %s refinery already running\n", style.Dim.Render("○"), r.Name)
|
||||||
} else {
|
} else {
|
||||||
created, err := ensureRefinerySession(r.Name, r)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf(" %s %s refinery failed: %v\n", style.Dim.Render("○"), r.Name, err)
|
fmt.Printf(" %s %s refinery failed: %v\n", style.Dim.Render("○"), r.Name, err)
|
||||||
} else if created {
|
|
||||||
fmt.Printf(" %s %s refinery started\n", style.Bold.Render("✓"), r.Name)
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf(" %s %s refinery started\n", style.Bold.Render("✓"), r.Name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -320,86 +317,6 @@ func discoverAllRigs(townRoot string) ([]*rig.Rig, error) {
|
|||||||
return rigMgr.DiscoverRigs()
|
return rigMgr.DiscoverRigs()
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensureRefinerySession creates a refinery tmux session if it doesn't exist.
|
|
||||||
// Returns true if a new session was created, false if it already existed.
|
|
||||||
func ensureRefinerySession(rigName string, r *rig.Rig) (bool, error) {
|
|
||||||
t := tmux.NewTmux()
|
|
||||||
sessionName := fmt.Sprintf("gt-%s-refinery", rigName)
|
|
||||||
|
|
||||||
// Check if session already exists
|
|
||||||
running, err := t.HasSession(sessionName)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("checking session: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if running {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Working directory is the refinery's rig clone
|
|
||||||
refineryRigDir := filepath.Join(r.Path, "refinery", "rig")
|
|
||||||
if _, err := os.Stat(refineryRigDir); os.IsNotExist(err) {
|
|
||||||
// Fall back to rig path if refinery/rig doesn't exist
|
|
||||||
refineryRigDir = r.Path
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure Claude settings exist in refinery/ (not refinery/rig/) so we don't
|
|
||||||
// write into the source repo. Claude walks up the tree to find settings.
|
|
||||||
refineryParentDir := filepath.Join(r.Path, "refinery")
|
|
||||||
if err := claude.EnsureSettingsForRole(refineryParentDir, "refinery"); err != nil {
|
|
||||||
return false, fmt.Errorf("ensuring Claude settings: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create new tmux session
|
|
||||||
if err := t.NewSession(sessionName, refineryRigDir); err != nil {
|
|
||||||
return false, fmt.Errorf("creating session: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set environment
|
|
||||||
bdActor := fmt.Sprintf("%s/refinery", rigName)
|
|
||||||
_ = t.SetEnvironment(sessionName, "GT_ROLE", "refinery")
|
|
||||||
_ = t.SetEnvironment(sessionName, "GT_RIG", rigName)
|
|
||||||
_ = t.SetEnvironment(sessionName, "BD_ACTOR", bdActor)
|
|
||||||
|
|
||||||
// Set beads environment
|
|
||||||
beadsDir := filepath.Join(r.Path, "mayor", "rig", ".beads")
|
|
||||||
_ = t.SetEnvironment(sessionName, "BEADS_DIR", beadsDir)
|
|
||||||
_ = t.SetEnvironment(sessionName, "BEADS_NO_DAEMON", "1")
|
|
||||||
_ = t.SetEnvironment(sessionName, "BEADS_AGENT_NAME", fmt.Sprintf("%s/refinery", rigName))
|
|
||||||
|
|
||||||
// Apply Gas Town theming (non-fatal: theming failure doesn't affect operation)
|
|
||||||
theme := tmux.AssignTheme(rigName)
|
|
||||||
_ = t.ConfigureGasTownSession(sessionName, theme, rigName, "refinery", "refinery")
|
|
||||||
|
|
||||||
// Launch Claude directly (no respawn loop - daemon handles restart)
|
|
||||||
// Export GT_ROLE and BD_ACTOR in the command since tmux SetEnvironment only affects new panes
|
|
||||||
if err := t.SendKeys(sessionName, config.BuildAgentStartupCommand("refinery", bdActor, r.Path, "")); err != nil {
|
|
||||||
return false, fmt.Errorf("sending command: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for Claude to start (non-fatal)
|
|
||||||
if err := t.WaitForCommand(sessionName, constants.SupportedShells, constants.ClaudeStartTimeout); err != nil {
|
|
||||||
// Non-fatal
|
|
||||||
}
|
|
||||||
time.Sleep(constants.ShutdownNotifyDelay)
|
|
||||||
|
|
||||||
// Inject startup nudge for predecessor discovery via /resume
|
|
||||||
address := fmt.Sprintf("%s/refinery", rigName)
|
|
||||||
_ = session.StartupNudge(t, sessionName, session.StartupNudgeConfig{
|
|
||||||
Recipient: address,
|
|
||||||
Sender: "deacon",
|
|
||||||
Topic: "patrol",
|
|
||||||
}) // Non-fatal
|
|
||||||
|
|
||||||
// GUPP: Gas Town Universal Propulsion Principle
|
|
||||||
// Send the propulsion nudge to trigger autonomous patrol execution.
|
|
||||||
// Wait for beacon to be fully processed (needs to be separate prompt)
|
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
_ = t.NudgeSession(sessionName, session.PropulsionNudgeForRole("refinery", refineryRigDir)) // Non-fatal
|
|
||||||
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func runShutdown(cmd *cobra.Command, args []string) error {
|
func runShutdown(cmd *cobra.Command, args []string) error {
|
||||||
t := tmux.NewTmux()
|
t := tmux.NewTmux()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user