Standardize warning output to use style.PrintWarning (gt-g6kor)

- Add PrintWarning helper in internal/style/style.go
- Update 35 warning message outputs across 16 files to use consistent format
- All warnings now display as "⚠ Warning: <message>" in yellow/bold

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-28 16:38:04 -08:00
parent d953aa19e3
commit 5e9ca4c618
17 changed files with 49 additions and 42 deletions
+1 -1
View File
@@ -93,7 +93,7 @@ func runCrewAdd(cmd *cobra.Command, args []string) error {
desc := fmt.Sprintf("Crew worker %s in %s - human-managed persistent workspace.", name, rigName) desc := fmt.Sprintf("Crew worker %s in %s - human-managed persistent workspace.", name, rigName)
if _, err := bd.CreateAgentBead(crewID, desc, fields); err != nil { if _, err := bd.CreateAgentBead(crewID, desc, fields); err != nil {
// Non-fatal: warn but don't fail the add // Non-fatal: warn but don't fail the add
fmt.Printf(" %s\n", style.Dim.Render(fmt.Sprintf("Warning: could not create agent bead: %v", err))) style.PrintWarning("could not create agent bead: %v", err)
} else { } else {
fmt.Printf(" Agent bead: %s\n", crewID) fmt.Printf(" Agent bead: %s\n", crewID)
} }
+3 -3
View File
@@ -250,13 +250,13 @@ func runCrewRestart(cmd *cobra.Command, args []string) error {
// Wait for Claude to start, then prime it // Wait for Claude to start, then prime it
shells := []string{"bash", "zsh", "sh", "fish", "tcsh", "ksh"} shells := []string{"bash", "zsh", "sh", "fish", "tcsh", "ksh"}
if err := t.WaitForCommand(sessionID, shells, 15*time.Second); err != nil { if err := t.WaitForCommand(sessionID, shells, 15*time.Second); err != nil {
fmt.Printf("Warning: Timeout waiting for Claude to start: %v\n", err) style.PrintWarning("Timeout waiting for Claude to start: %v", err)
} }
// Give Claude time to initialize after process starts // Give Claude time to initialize after process starts
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
if err := t.SendKeys(sessionID, "gt prime"); err != nil { if err := t.SendKeys(sessionID, "gt prime"); err != nil {
// Non-fatal: Claude started but priming failed // Non-fatal: Claude started but priming failed
fmt.Printf("Warning: Could not send prime command: %v\n", err) style.PrintWarning("Could not send prime command: %v", err)
} }
// Send crew resume prompt after prime completes // Send crew resume prompt after prime completes
@@ -265,7 +265,7 @@ func runCrewRestart(cmd *cobra.Command, args []string) error {
time.Sleep(5 * time.Second) time.Sleep(5 * time.Second)
crewPrompt := "Read your mail, act on anything urgent, else await instructions." crewPrompt := "Read your mail, act on anything urgent, else await instructions."
if err := t.NudgeSession(sessionID, crewPrompt); err != nil { if err := t.NudgeSession(sessionID, crewPrompt); err != nil {
fmt.Printf("Warning: Could not send resume prompt: %v\n", err) style.PrintWarning("Could not send resume prompt: %v", err)
} }
fmt.Printf("%s Restarted crew workspace: %s/%s\n", fmt.Printf("%s Restarted crew workspace: %s/%s\n",
+2 -2
View File
@@ -171,7 +171,7 @@ func startDeaconSession(t *tmux.Tmux) error {
// Ensure deacon has patrol hooks (idempotent) // Ensure deacon has patrol hooks (idempotent)
if err := ensurePatrolHooks(deaconDir); err != nil { if err := ensurePatrolHooks(deaconDir); err != nil {
fmt.Printf("%s Warning: Could not create deacon hooks: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("Could not create deacon hooks: %v", err)
} }
// Create session in deacon directory // Create session in deacon directory
@@ -300,7 +300,7 @@ func runDeaconRestart(cmd *cobra.Command, args []string) error {
if running { if running {
// Kill existing session // Kill existing session
if err := t.KillSession(DeaconSessionName); err != nil { if err := t.KillSession(DeaconSessionName); err != nil {
fmt.Printf("%s Warning: failed to kill session: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("failed to kill session: %v", err)
} }
} }
+1 -1
View File
@@ -208,7 +208,7 @@ func runDone(cmd *cobra.Command, args []string) error {
fmt.Printf("\nNotifying Witness...\n") fmt.Printf("\nNotifying Witness...\n")
if err := townRouter.Send(doneNotification); err != nil { if err := townRouter.Send(doneNotification); err != nil {
fmt.Printf(" %s\n", style.Dim.Render(fmt.Sprintf("Warning: could not notify witness: %v", err))) style.PrintWarning("could not notify witness: %v", err)
} else { } else {
fmt.Printf("%s Witness notified of %s\n", style.Bold.Render("✓"), exitType) fmt.Printf("%s Witness notified of %s\n", style.Bold.Render("✓"), exitType)
} }
+3 -3
View File
@@ -148,7 +148,7 @@ func runHandoff(cmd *cobra.Command, args []string) error {
// If subject/message provided, send handoff mail to self first // If subject/message provided, send handoff mail to self first
if handoffSubject != "" || handoffMessage != "" { if handoffSubject != "" || handoffMessage != "" {
if err := sendHandoffMail(handoffSubject, handoffMessage); err != nil { if err := sendHandoffMail(handoffSubject, handoffMessage); err != nil {
fmt.Printf("%s Warning: could not send handoff mail: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not send handoff mail: %v", err)
// Continue anyway - the respawn is more important // Continue anyway - the respawn is more important
} else { } else {
fmt.Printf("%s Sent handoff mail\n", style.Bold.Render("📬")) fmt.Printf("%s Sent handoff mail\n", style.Bold.Render("📬"))
@@ -172,7 +172,7 @@ func runHandoff(cmd *cobra.Command, args []string) error {
// Clear scrollback history before respawn (resets copy-mode from [0/N] to [0/0]) // Clear scrollback history before respawn (resets copy-mode from [0/N] to [0/0])
if err := t.ClearHistory(pane); err != nil { if err := t.ClearHistory(pane); err != nil {
// Non-fatal - continue with respawn even if clear fails // Non-fatal - continue with respawn even if clear fails
fmt.Printf("%s Warning: could not clear history: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not clear history: %v", err)
} }
// Use exec to respawn the pane - this kills us and restarts // Use exec to respawn the pane - this kills us and restarts
@@ -458,7 +458,7 @@ func handoffRemoteSession(t *tmux.Tmux, targetSession, restartCmd string) error
// Clear scrollback history before respawn (resets copy-mode from [0/N] to [0/0]) // Clear scrollback history before respawn (resets copy-mode from [0/N] to [0/0])
if err := t.ClearHistory(targetPane); err != nil { if err := t.ClearHistory(targetPane); err != nil {
// Non-fatal - continue with respawn even if clear fails // Non-fatal - continue with respawn even if clear fails
fmt.Printf("%s Warning: could not clear history: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not clear history: %v", err)
} }
// Respawn the remote session's pane // Respawn the remote session's pane
+1 -2
View File
@@ -97,8 +97,7 @@ func runInstall(cmd *cobra.Command, args []string) error {
// Check if inside an existing workspace // Check if inside an existing workspace
if existingRoot, _ := workspace.Find(absPath); existingRoot != "" && existingRoot != absPath { if existingRoot, _ := workspace.Find(absPath); existingRoot != "" && existingRoot != absPath {
fmt.Printf("%s Warning: Creating HQ inside existing workspace at %s\n", style.PrintWarning("Creating HQ inside existing workspace at %s", existingRoot)
style.Dim.Render("⚠"), existingRoot)
} }
fmt.Printf("%s Creating Gas Town HQ at %s\n\n", fmt.Printf("%s Creating Gas Town HQ at %s\n\n",
+1 -1
View File
@@ -111,7 +111,7 @@ func runMoleculeAttachFromMail(cmd *cobra.Command, args []string) error {
// Mark mail as read // Mark mail as read
if err := mailbox.MarkRead(mailID); err != nil { if err := mailbox.MarkRead(mailID); err != nil {
// Non-fatal: log warning but don't fail // Non-fatal: log warning but don't fail
fmt.Fprintf(os.Stderr, "Warning: could not mark mail as read: %v\n", err) style.PrintWarning("could not mark mail as read: %v", err)
} }
// Output success // Output success
+3 -6
View File
@@ -238,8 +238,7 @@ squashed_at: %s
Status: &closedStatus, Status: &closedStatus,
}) })
if err != nil { if err != nil {
fmt.Printf("%s Created digest but couldn't close it: %v\n", style.PrintWarning("Created digest but couldn't close it: %v", err)
style.Dim.Render("Warning:"), err)
} }
// Detach the molecule from the handoff bead with audit logging // Detach the molecule from the handoff bead with audit logging
@@ -282,8 +281,7 @@ func closeDescendants(b *beads.Beads, parentID string) int {
Status: "all", Status: "all",
}) })
if err != nil { if err != nil {
fmt.Printf("%s Warning: could not list children of %s: %v\n", style.PrintWarning("could not list children of %s: %v", parentID, err)
style.Dim.Render("⚠"), parentID, err)
return 0 return 0
} }
@@ -307,8 +305,7 @@ func closeDescendants(b *beads.Beads, parentID string) int {
if len(idsToClose) > 0 { if len(idsToClose) > 0 {
if closeErr := b.Close(idsToClose...); closeErr != nil { if closeErr := b.Close(idsToClose...); closeErr != nil {
fmt.Printf("%s Warning: could not close children of %s: %v\n", style.PrintWarning("could not close children of %s: %v", parentID, closeErr)
style.Dim.Render("⚠"), parentID, closeErr)
} else { } else {
totalClosed += len(idsToClose) totalClosed += len(idsToClose)
} }
+2 -2
View File
@@ -325,7 +325,7 @@ func handleStepContinue(cwd, townRoot, workDir string, nextStep *beads.Issue, dr
// Clear history before respawn // Clear history before respawn
if err := t.ClearHistory(pane); err != nil { if err := t.ClearHistory(pane); err != nil {
// Non-fatal // Non-fatal
fmt.Printf("%s Warning: could not clear history: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not clear history: %v", err)
} }
return t.RespawnPane(pane, restartCmd) return t.RespawnPane(pane, restartCmd)
@@ -377,7 +377,7 @@ func handleMoleculeComplete(cwd, townRoot, moleculeID string, dryRun bool) error
unpinCmd.Dir = gitRoot unpinCmd.Dir = gitRoot
unpinCmd.Stderr = os.Stderr unpinCmd.Stderr = os.Stderr
if err := unpinCmd.Run(); err != nil { if err := unpinCmd.Run(); err != nil {
fmt.Printf("%s Warning: could not unpin bead: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not unpin bead: %v", err)
} else { } else {
fmt.Printf("%s Work unpinned\n", style.Bold.Render("✓")) fmt.Printf("%s Work unpinned\n", style.Bold.Render("✓"))
} }
+1 -1
View File
@@ -167,7 +167,7 @@ func runMqSubmit(cmd *cobra.Command, args []string) error {
fmt.Printf("%s Auto-cleanup: polecat work submitted\n", style.Bold.Render("✓")) fmt.Printf("%s Auto-cleanup: polecat work submitted\n", style.Bold.Render("✓"))
if err := polecatCleanup(rigName, worker, townRoot); err != nil { if err := polecatCleanup(rigName, worker, townRoot); err != nil {
// Non-fatal: warn but return success (MR was created) // Non-fatal: warn but return success (MR was created)
fmt.Printf("%s Could not auto-cleanup: %v\n", style.Warning.Render("Warning:"), err) style.PrintWarning("Could not auto-cleanup: %v", err)
fmt.Println(style.Dim.Render(" You may need to run 'gt handoff --shutdown' manually")) fmt.Println(style.Dim.Render(" You may need to run 'gt handoff --shutdown' manually"))
return nil return nil
} }
+3 -3
View File
@@ -567,7 +567,7 @@ func runPolecatRemove(cmd *cobra.Command, args []string) error {
// Report results // Report results
if len(removeErrors) > 0 { if len(removeErrors) > 0 {
fmt.Printf("\n%s Some removals failed:\n", style.Warning.Render("Warning:")) style.PrintWarning("Some removals failed:")
for _, e := range removeErrors { for _, e := range removeErrors {
fmt.Printf(" - %s\n", e) fmt.Printf(" - %s\n", e)
} }
@@ -760,7 +760,7 @@ func runPolecatSync(cmd *cobra.Command, args []string) error {
} }
if len(syncErrors) > 0 { if len(syncErrors) > 0 {
fmt.Printf("\n%s Some syncs failed:\n", style.Warning.Render("Warning:")) style.PrintWarning("Some syncs failed:")
for _, e := range syncErrors { for _, e := range syncErrors {
fmt.Printf(" - %s\n", e) fmt.Printf(" - %s\n", e)
} }
@@ -1364,7 +1364,7 @@ func runPolecatNuke(cmd *cobra.Command, args []string) error {
} }
if len(nukeErrors) > 0 { if len(nukeErrors) > 0 {
fmt.Printf("\n%s Some nukes failed:\n", style.Warning.Render("Warning:")) style.PrintWarning("Some nukes failed:")
for _, e := range nukeErrors { for _, e := range nukeErrors {
fmt.Printf(" - %s\n", e) fmt.Printf(" - %s\n", e)
} }
+1 -1
View File
@@ -165,7 +165,7 @@ func runResume(cmd *cobra.Command, args []string) error {
// Clear parked work state // Clear parked work state
if err := clearParkedWork(cloneRoot, agentID); err != nil { if err := clearParkedWork(cloneRoot, agentID); err != nil {
// Non-fatal // Non-fatal
fmt.Printf("%s Warning: could not clear parked state: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("could not clear parked state: %v", err)
} }
fmt.Printf("\n%s Ready to continue!\n", style.Bold.Render("✓")) fmt.Printf("\n%s Ready to continue!\n", style.Bold.Render("✓"))
+3 -3
View File
@@ -257,7 +257,7 @@ func runSling(cmd *cobra.Command, args []string) error {
if slingArgs != "" { if slingArgs != "" {
if err := storeArgsInBead(beadID, slingArgs); err != nil { if err := storeArgsInBead(beadID, slingArgs); err != nil {
// Warn but don't fail - args will still be in the nudge prompt // Warn but don't fail - args will still be in the nudge prompt
fmt.Printf("%s Could not store args in bead: %v\n", style.Dim.Render("Warning:"), err) style.PrintWarning("Could not store args in bead: %v", err)
} else { } else {
fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓")) fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓"))
} }
@@ -614,7 +614,7 @@ func runSlingFormula(args []string) error {
} }
if err := json.Unmarshal(wispOut, &wispResult); err != nil { if err := json.Unmarshal(wispOut, &wispResult); err != nil {
// Fallback: use formula name as identifier, but warn user // Fallback: use formula name as identifier, but warn user
fmt.Printf("%s Could not parse wisp output, using formula name as ID\n", style.Dim.Render("Warning:")) style.PrintWarning("Could not parse wisp output, using formula name as ID")
wispResult.RootID = formulaName wispResult.RootID = formulaName
} }
@@ -634,7 +634,7 @@ func runSlingFormula(args []string) error {
// Store args in wisp bead if provided (no-tmux mode: beads as data plane) // Store args in wisp bead if provided (no-tmux mode: beads as data plane)
if slingArgs != "" { if slingArgs != "" {
if err := storeArgsInBead(wispResult.RootID, slingArgs); err != nil { if err := storeArgsInBead(wispResult.RootID, slingArgs); err != nil {
fmt.Printf("%s Could not store args in bead: %v\n", style.Dim.Render("Warning:"), err) style.PrintWarning("Could not store args in bead: %v", err)
} else { } else {
fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓")) fmt.Printf("%s Args stored in bead (durable)\n", style.Bold.Render("✓"))
} }
+6 -6
View File
@@ -753,7 +753,7 @@ func runStartCrew(cmd *cobra.Command, args []string) error {
} }
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
if err := t.SendKeys(sessionID, "gt prime"); err != nil { if err := t.SendKeys(sessionID, "gt prime"); err != nil {
fmt.Printf("Warning: Could not send prime command: %v\n", err) style.PrintWarning("Could not send prime command: %v", err)
} }
} else { } else {
fmt.Printf("%s Session already running: %s\n", style.Dim.Render("○"), sessionID) fmt.Printf("%s Session already running: %s\n", style.Dim.Render("○"), sessionID)
@@ -801,7 +801,7 @@ func runStartCrew(cmd *cobra.Command, args []string) error {
// Send gt prime to initialize context // Send gt prime to initialize context
if err := t.SendKeys(sessionID, "gt prime"); err != nil { if err := t.SendKeys(sessionID, "gt prime"); err != nil {
fmt.Printf("Warning: Could not send prime command: %v\n", err) style.PrintWarning("Could not send prime command: %v", err)
} }
fmt.Printf("%s Started crew workspace: %s/%s\n", fmt.Printf("%s Started crew workspace: %s/%s\n",
@@ -903,15 +903,15 @@ func startCrewMember(rigName, crewName, townRoot string) error {
return fmt.Errorf("creating session: %w", err) return fmt.Errorf("creating session: %w", err)
} }
// Set environment // Set environment (non-fatal: session works without these)
_ = t.SetEnvironment(sessionID, "GT_RIG", rigName) _ = t.SetEnvironment(sessionID, "GT_RIG", rigName)
_ = t.SetEnvironment(sessionID, "GT_CREW", crewName) _ = t.SetEnvironment(sessionID, "GT_CREW", crewName)
// Apply rig-based theming // Apply rig-based theming (non-fatal: theming failure doesn't affect operation)
theme := getThemeForRig(rigName) theme := getThemeForRig(rigName)
_ = t.ConfigureGasTownSession(sessionID, theme, rigName, crewName, "crew") _ = t.ConfigureGasTownSession(sessionID, theme, rigName, crewName, "crew")
// Set up C-b n/p keybindings for crew session cycling // Set up C-b n/p keybindings for crew session cycling (non-fatal)
_ = t.SetCrewCycleBindings(sessionID) _ = t.SetCrewCycleBindings(sessionID)
// Wait for shell to be ready // Wait for shell to be ready
@@ -933,7 +933,7 @@ func startCrewMember(rigName, crewName, townRoot string) error {
// Give Claude time to initialize // Give Claude time to initialize
time.Sleep(500 * time.Millisecond) time.Sleep(500 * time.Millisecond)
// Send gt prime to initialize context // Send gt prime to initialize context (non-fatal: session works without priming)
_ = t.SendKeys(sessionID, "gt prime") _ = t.SendKeys(sessionID, "gt prime")
return nil return nil
+4 -4
View File
@@ -375,7 +375,7 @@ func runSwarmStart(cmd *cobra.Command, args []string) error {
if len(sw.Workers) > 0 && len(sw.Tasks) > 0 { if len(sw.Workers) > 0 && len(sw.Tasks) > 0 {
fmt.Printf("\nSpawning workers...\n") fmt.Printf("\nSpawning workers...\n")
if err := spawnSwarmWorkers(foundRig, sw); err != nil { if err := spawnSwarmWorkers(foundRig, sw); err != nil {
fmt.Printf("Warning: failed to spawn some workers: %v\n", err) style.PrintWarning("failed to spawn some workers: %v", err)
} }
} }
@@ -409,7 +409,7 @@ func spawnSwarmWorkers(r *rig.Rig, sw *swarm.Swarm) error {
// Update polecat state // Update polecat state
if err := polecatMgr.AssignIssue(worker, task.IssueID); err != nil { if err := polecatMgr.AssignIssue(worker, task.IssueID); err != nil {
fmt.Printf(" Warning: couldn't assign %s to %s: %v\n", task.IssueID, worker, err) style.PrintWarning(" couldn't assign %s to %s: %v", task.IssueID, worker, err)
continue continue
} }
@@ -420,7 +420,7 @@ func spawnSwarmWorkers(r *rig.Rig, sw *swarm.Swarm) error {
} else { } else {
fmt.Printf(" Starting %s...\n", worker) fmt.Printf(" Starting %s...\n", worker)
if err := sessMgr.Start(worker, session.StartOptions{}); err != nil { if err := sessMgr.Start(worker, session.StartOptions{}); err != nil {
fmt.Printf(" Warning: couldn't start %s: %v\n", worker, err) style.PrintWarning(" couldn't start %s: %v", worker, err)
continue continue
} }
// Wait for Claude to initialize // Wait for Claude to initialize
@@ -431,7 +431,7 @@ func spawnSwarmWorkers(r *rig.Rig, sw *swarm.Swarm) error {
context := fmt.Sprintf("[SWARM] You are part of swarm %s.\n\nAssigned task: %s\nTitle: %s\n\nWork on this task. When complete, commit and signal DONE.", context := fmt.Sprintf("[SWARM] You are part of swarm %s.\n\nAssigned task: %s\nTitle: %s\n\nWork on this task. When complete, commit and signal DONE.",
sw.ID, task.IssueID, task.Title) sw.ID, task.IssueID, task.Title)
if err := sessMgr.Inject(worker, context); err != nil { if err := sessMgr.Inject(worker, context); err != nil {
fmt.Printf(" Warning: couldn't inject to %s: %v\n", worker, err) style.PrintWarning(" couldn't inject to %s: %v", worker, err)
} else { } else {
fmt.Printf(" %s → %s ✓\n", worker, task.IssueID) fmt.Printf(" %s → %s ✓\n", worker, task.IssueID)
} }
+2 -2
View File
@@ -186,7 +186,7 @@ func runWitnessStop(cmd *cobra.Command, args []string) error {
running, _ := t.HasSession(sessionName) running, _ := t.HasSession(sessionName)
if running { if running {
if err := t.KillSession(sessionName); err != nil { if err := t.KillSession(sessionName); err != nil {
fmt.Printf("%s Warning: failed to kill session: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("failed to kill session: %v", err)
} }
} }
@@ -412,7 +412,7 @@ func runWitnessRestart(cmd *cobra.Command, args []string) error {
running, _ := t.HasSession(sessionName) running, _ := t.HasSession(sessionName)
if running { if running {
if err := t.KillSession(sessionName); err != nil { if err := t.KillSession(sessionName); err != nil {
fmt.Printf("%s Warning: failed to kill session: %v\n", style.Dim.Render("⚠"), err) style.PrintWarning("failed to kill session: %v", err)
} }
} }
+12 -1
View File
@@ -1,7 +1,11 @@
// Package style provides consistent terminal styling using Lipgloss. // Package style provides consistent terminal styling using Lipgloss.
package style package style
import "github.com/charmbracelet/lipgloss" import (
"fmt"
"github.com/charmbracelet/lipgloss"
)
var ( var (
// Success style for positive outcomes // Success style for positive outcomes
@@ -43,3 +47,10 @@ var (
// ArrowPrefix for action indicators // ArrowPrefix for action indicators
ArrowPrefix = Info.Render("→") ArrowPrefix = Info.Render("→")
) )
// PrintWarning prints a warning message with consistent formatting.
// The format and args work like fmt.Printf.
func PrintWarning(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
fmt.Printf("%s %s\n", Warning.Render("⚠ Warning:"), msg)
}