From 81d5b8e75f42cd8cfdbe7d517fecf22888fe33d8 Mon Sep 17 00:00:00 2001 From: gastown/polecats/ace Date: Wed, 31 Dec 2025 12:05:57 -0800 Subject: [PATCH] fix: gt hook uses --status=hooked for consistency with gt sling (gt-frhcq.1) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The gt hook command was using --status=pinned while gt sling and the rest of the codebase use --status=hooked. This inconsistency meant gt hook would not find beads hooked by gt sling, and vice versa. Changes: - hook.go: Use beads.StatusHooked instead of beads.StatusPinned - hook.go: Update bd update command to use --status=hooked - unsling.go: Use beads.StatusHooked when finding hooked beads - Update error messages and comments to say "hooked" instead of "pinned" This fix ensures gt hook works uniformly for all bead types (molecules, issues, mail beads) since they all use the same beads system. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/cmd/hook.go | 26 +++++++++++++------------- internal/cmd/unsling.go | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/internal/cmd/hook.go b/internal/cmd/hook.go index 439b0ab0..b660892a 100644 --- a/internal/cmd/hook.go +++ b/internal/cmd/hook.go @@ -67,7 +67,7 @@ func init() { hookCmd.Flags().StringVarP(&hookSubject, "subject", "s", "", "Subject for handoff mail (optional)") hookCmd.Flags().StringVarP(&hookMessage, "message", "m", "", "Message for handoff mail (optional)") hookCmd.Flags().BoolVarP(&hookDryRun, "dry-run", "n", false, "Show what would be done") - hookCmd.Flags().BoolVarP(&hookForce, "force", "f", false, "Replace existing incomplete pinned bead") + hookCmd.Flags().BoolVarP(&hookForce, "force", "f", false, "Replace existing incomplete hooked bead") // --json flag for status output (used when no args, i.e., gt hook --json) hookCmd.Flags().BoolVar(&moleculeJSON, "json", false, "Output as JSON (for status)") @@ -114,17 +114,17 @@ func runHook(cmd *cobra.Command, args []string) error { b := beads.New(workDir) - // Check for existing pinned bead for this agent + // Check for existing hooked bead for this agent existingPinned, err := b.List(beads.ListOptions{ - Status: beads.StatusPinned, + Status: beads.StatusHooked, Assignee: agentID, Priority: -1, }) if err != nil { - return fmt.Errorf("checking existing pinned beads: %w", err) + return fmt.Errorf("checking existing hooked beads: %w", err) } - // If there's an existing pinned bead, check if we can auto-replace + // If there's an existing hooked bead, check if we can auto-replace if len(existingPinned) > 0 { existing := existingPinned[0] @@ -169,7 +169,7 @@ func runHook(cmd *cobra.Command, args []string) error { } } else { // Existing incomplete bead blocks new hook - return fmt.Errorf("existing pinned bead %s is incomplete (%s)\n Use --force to replace, or complete the existing work first", + return fmt.Errorf("existing hooked bead %s is incomplete (%s)\n Use --force to replace, or complete the existing work first", existing.ID, existing.Title) } } @@ -177,7 +177,7 @@ func runHook(cmd *cobra.Command, args []string) error { fmt.Printf("%s Hooking %s...\n", style.Bold.Render("🪝"), beadID) if hookDryRun { - fmt.Printf("Would run: bd update %s --status=pinned --assignee=%s\n", beadID, agentID) + fmt.Printf("Would run: bd update %s --status=hooked --assignee=%s\n", beadID, agentID) if hookSubject != "" { fmt.Printf(" subject (for handoff mail): %s\n", hookSubject) } @@ -187,14 +187,14 @@ func runHook(cmd *cobra.Command, args []string) error { return nil } - // Pin the bead using bd update (discovery-based approach) - pinCmd := exec.Command("bd", "update", beadID, "--status=pinned", "--assignee="+agentID) - pinCmd.Stderr = os.Stderr - if err := pinCmd.Run(); err != nil { - return fmt.Errorf("pinning bead: %w", err) + // Hook the bead using bd update (discovery-based approach) + hookCmd := exec.Command("bd", "update", beadID, "--status=hooked", "--assignee="+agentID) + hookCmd.Stderr = os.Stderr + if err := hookCmd.Run(); err != nil { + return fmt.Errorf("hooking bead: %w", err) } - fmt.Printf("%s Work attached to hook (pinned bead)\n", style.Bold.Render("✓")) + fmt.Printf("%s Work attached to hook (hooked bead)\n", style.Bold.Render("✓")) fmt.Printf(" Use 'gt handoff' to restart with this work\n") fmt.Printf(" Use 'gt hook' to see hook status\n") diff --git a/internal/cmd/unsling.go b/internal/cmd/unsling.go index fcc032b9..aca713a4 100644 --- a/internal/cmd/unsling.go +++ b/internal/cmd/unsling.go @@ -26,7 +26,7 @@ Examples: gt unsling greenplace/joe # Clear joe's hook gt unsling gt-abc greenplace/joe # Unsling gt-abc from joe -The bead's status changes from 'pinned' back to 'open'. +The bead's status changes from 'hooked' back to 'open'. Related commands: gt sling # Hook + start (inverse of unsling) @@ -92,14 +92,14 @@ func runUnsling(cmd *cobra.Command, args []string) error { b := beads.New(workDir) - // Find pinned bead for this agent + // Find hooked bead for this agent pinnedBeads, err := b.List(beads.ListOptions{ - Status: beads.StatusPinned, + Status: beads.StatusHooked, Assignee: agentID, Priority: -1, }) if err != nil { - return fmt.Errorf("checking pinned beads: %w", err) + return fmt.Errorf("checking hooked beads: %w", err) } if len(pinnedBeads) == 0 { @@ -139,7 +139,7 @@ func runUnsling(cmd *cobra.Command, args []string) error { // Unpin by setting status back to open status := "open" if err := b.Update(pinned.ID, beads.UpdateOptions{Status: &status}); err != nil { - return fmt.Errorf("unpinning bead %s: %w", pinned.ID, err) + return fmt.Errorf("unhooking bead %s: %w", pinned.ID, err) } // Log unhook event