diff --git a/internal/cmd/rig_park.go b/internal/cmd/rig_park.go index e1052a7a..c2f03930 100644 --- a/internal/cmd/rig_park.go +++ b/internal/cmd/rig_park.go @@ -18,9 +18,9 @@ const RigStatusKey = "status" const RigStatusParked = "parked" var rigParkCmd = &cobra.Command{ - Use: "park ", - Short: "Park a rig (stops agents, daemon won't auto-restart)", - Long: `Park a rig to temporarily disable it. + Use: "park ...", + Short: "Park one or more rigs (stops agents, daemon won't auto-restart)", + Long: `Park rigs to temporarily disable them. Parking a rig: - Stops the witness if running @@ -35,15 +35,15 @@ This is a Level 1 (local/ephemeral) operation: Examples: gt rig park gastown - gt rig park beads`, - Args: cobra.ExactArgs(1), + gt rig park beads gastown mayor`, + Args: cobra.MinimumNArgs(1), RunE: runRigPark, } var rigUnparkCmd = &cobra.Command{ - Use: "unpark ", - Short: "Unpark a rig (allow daemon to auto-restart agents)", - Long: `Unpark a rig to resume normal operation. + Use: "unpark ...", + Short: "Unpark one or more rigs (allow daemon to auto-restart agents)", + Long: `Unpark rigs to resume normal operation. Unparking a rig: - Removes the parked status from the wisp layer @@ -52,8 +52,8 @@ Unparking a rig: Examples: gt rig unpark gastown - gt rig unpark beads`, - Args: cobra.ExactArgs(1), + gt rig unpark beads gastown mayor`, + Args: cobra.MinimumNArgs(1), RunE: runRigUnpark, } @@ -63,8 +63,25 @@ func init() { } func runRigPark(cmd *cobra.Command, args []string) error { - rigName := args[0] + var errs []error + for _, rigName := range args { + if err := parkOneRig(rigName); err != nil { + errs = append(errs, fmt.Errorf("%s: %w", rigName, err)) + } + } + + if len(errs) > 0 { + for _, err := range errs { + fmt.Printf("%s %v\n", style.Error.Render("✗"), err) + } + return fmt.Errorf("failed to park %d rig(s)", len(errs)) + } + + return nil +} + +func parkOneRig(rigName string) error { // Get rig and town root townRoot, r, err := getRig(rigName) if err != nil { @@ -120,8 +137,25 @@ func runRigPark(cmd *cobra.Command, args []string) error { } func runRigUnpark(cmd *cobra.Command, args []string) error { - rigName := args[0] + var errs []error + for _, rigName := range args { + if err := unparkOneRig(rigName); err != nil { + errs = append(errs, fmt.Errorf("%s: %w", rigName, err)) + } + } + + if len(errs) > 0 { + for _, err := range errs { + fmt.Printf("%s %v\n", style.Error.Render("✗"), err) + } + return fmt.Errorf("failed to unpark %d rig(s)", len(errs)) + } + + return nil +} + +func unparkOneRig(rigName string) error { // Get rig and town root townRoot, _, err := getRig(rigName) if err != nil { diff --git a/internal/cmd/sling_helpers.go b/internal/cmd/sling_helpers.go index 5a2bff6d..1afd6840 100644 --- a/internal/cmd/sling_helpers.go +++ b/internal/cmd/sling_helpers.go @@ -175,6 +175,11 @@ func injectStartPrompt(pane, beadID, subject, args string) error { return fmt.Errorf("no target pane") } + // Skip nudge during tests to prevent agent self-interruption + if os.Getenv("GT_TEST_NO_NUDGE") != "" { + return nil + } + // Build the prompt to inject var prompt string if args != "" { diff --git a/internal/cmd/sling_test.go b/internal/cmd/sling_test.go index 5847b29b..4bfffb04 100644 --- a/internal/cmd/sling_test.go +++ b/internal/cmd/sling_test.go @@ -292,6 +292,9 @@ exit 0 slingVars = nil slingOnTarget = "gt-abc123" + // Prevent real tmux nudge from firing during tests (causes agent self-interruption) + t.Setenv("GT_TEST_NO_NUDGE", "1") + if err := runSling(nil, []string{"mol-review"}); err != nil { t.Fatalf("runSling: %v", err) } @@ -452,6 +455,9 @@ exit 0 slingVars = nil slingOnTarget = "gt-abc123" + // Prevent real tmux nudge from firing during tests (causes agent self-interruption) + t.Setenv("GT_TEST_NO_NUDGE", "1") + if err := runSling(nil, []string{"mol-review"}); err != nil { t.Fatalf("runSling: %v", err) }