fix: gt unsling now correctly clears hooks for remote agents (gt-yea94)

The unsling command had two bugs:
1. It used the local beads directory instead of the target agent's rig
2. It looked for status=hooked beads instead of the agent bead's hook_bead field

Changes:
- unsling.go: Rewrote to use agent bead's hook_bead field (matches how sling works)
- unsling.go: Now uses target agent's rig beads path, not local
- status.go: Prefer SQLite columns (issue.HookBead, issue.AgentState) over
  parsing description text, with fallback for legacy beads
- beads.go: Added AgentState field to Issue struct for SQLite column access

This fixes the issue where `gt unsling gastown/crew/joe` would say "no work hooked"
even when gt status showed joe had a hook.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/max
2026-01-01 10:58:33 -08:00
committed by Steve Yegge
parent 4bafbfb0f7
commit 121150b49f
3 changed files with 90 additions and 51 deletions

View File

@@ -626,16 +626,22 @@ func discoverGlobalAgents(allSessions map[string]bool, allAgentBeads map[string]
// Look up agent bead from preloaded map (O(1))
if issue, ok := allAgentBeads[d.beadID]; ok {
fields := beads.ParseAgentFields(issue.Description)
if fields != nil {
agent.HookBead = fields.HookBead
agent.State = fields.AgentState
if fields.HookBead != "" {
agent.HasWork = true
// Get hook title from preloaded map
if pinnedIssue, ok := allHookBeads[fields.HookBead]; ok {
agent.WorkTitle = pinnedIssue.Title
}
// Prefer SQLite columns over description parsing
// HookBead column is authoritative (cleared by unsling)
agent.HookBead = issue.HookBead
agent.State = issue.AgentState
if agent.HookBead != "" {
agent.HasWork = true
// Get hook title from preloaded map
if pinnedIssue, ok := allHookBeads[agent.HookBead]; ok {
agent.WorkTitle = pinnedIssue.Title
}
}
// Fallback to description for legacy beads without SQLite columns
if agent.State == "" {
fields := beads.ParseAgentFields(issue.Description)
if fields != nil {
agent.State = fields.AgentState
}
}
}
@@ -758,16 +764,22 @@ func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string,
// Look up agent bead from preloaded map (O(1))
if issue, ok := allAgentBeads[d.beadID]; ok {
fields := beads.ParseAgentFields(issue.Description)
if fields != nil {
agent.HookBead = fields.HookBead
agent.State = fields.AgentState
if fields.HookBead != "" {
agent.HasWork = true
// Get hook title from preloaded map
if pinnedIssue, ok := allHookBeads[fields.HookBead]; ok {
agent.WorkTitle = pinnedIssue.Title
}
// Prefer SQLite columns over description parsing
// HookBead column is authoritative (cleared by unsling)
agent.HookBead = issue.HookBead
agent.State = issue.AgentState
if agent.HookBead != "" {
agent.HasWork = true
// Get hook title from preloaded map
if pinnedIssue, ok := allHookBeads[agent.HookBead]; ok {
agent.WorkTitle = pinnedIssue.Title
}
}
// Fallback to description for legacy beads without SQLite columns
if agent.State == "" {
fields := beads.ParseAgentFields(issue.Description)
if fields != nil {
agent.State = fields.AgentState
}
}
}