From 3b9d1a113ce39ea4e2a615a39fcfd0b159765f65 Mon Sep 17 00:00:00 2001 From: nux Date: Sun, 4 Jan 2026 16:28:57 -0800 Subject: [PATCH] fix(sling): Set hook slot when creating agent beads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sync with mayor/rig fix: Set hook slot in CreateAgentBead and pass beadID to UpdateAgentState. Fixes: mi-619 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/beads/beads.go | 10 ++++++++++ internal/cmd/sling.go | 16 +++++++++------- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/internal/beads/beads.go b/internal/beads/beads.go index 70deca0e..e5375a0b 100644 --- a/internal/beads/beads.go +++ b/internal/beads/beads.go @@ -975,6 +975,16 @@ func (b *Beads) CreateAgentBead(id, title string, fields *AgentFields) (*Issue, } } + // Set the hook slot if specified (this is the authoritative storage) + // This fixes the slot inconsistency bug where bead status is 'hooked' but + // agent's hook slot is empty. See mi-619. + if fields != nil && fields.HookBead != "" { + if _, err := b.run("slot", "set", id, "hook", fields.HookBead); err != nil { + // Non-fatal: warn but continue - description text has the backup + fmt.Printf("Warning: could not set hook slot: %v\n", err) + } + } + return &issue, nil } diff --git a/internal/cmd/sling.go b/internal/cmd/sling.go index 39da5e46..17fbac6c 100644 --- a/internal/cmd/sling.go +++ b/internal/cmd/sling.go @@ -895,17 +895,17 @@ func runSlingFormula(args []string) error { return nil } -// updateAgentHookBead updates the agent bead's state when work is slung. +// updateAgentHookBead updates the agent bead's state and hook when work is slung. // This enables the witness to see that each agent is working. // // We run from the polecat's workDir (which redirects to the rig's beads database) // WITHOUT setting BEADS_DIR, so the redirect mechanism works for gt-* agent beads. // -// Note: We only update the agent_state field, not hook_bead. The hook_bead field -// requires cross-database access (agent in rig db, hook bead in town db), but -// bd slot set has a bug where it doesn't support this. See BD_BUG_AGENT_STATE_ROUTING.md. +// For rig-level beads (same database), we set the hook_bead slot directly. +// For cross-database scenarios (agent in rig db, hook bead in town db), +// the slot set may fail - this is handled gracefully with a warning. // The work is still correctly attached via `bd update --assignee=`. -func updateAgentHookBead(agentID, _, workDir, townBeadsDir string) { // beadID unused due to BD_BUG_AGENT_STATE_ROUTING +func updateAgentHookBead(agentID, beadID, workDir, townBeadsDir string) { _ = townBeadsDir // Not used - BEADS_DIR breaks redirect mechanism // Convert agent ID to agent bead ID @@ -934,9 +934,11 @@ func updateAgentHookBead(agentID, _, workDir, townBeadsDir string) { // beadID u } // Run from workDir WITHOUT BEADS_DIR to enable redirect-based routing. - // Only update agent_state (not hook_bead) due to bd cross-database bug. + // Update agent_state to "running" and set hook_bead to the slung work. + // For same-database beads, the hook slot is set via `bd slot set`. + // For cross-database scenarios, slot set may fail gracefully (warning only). bd := beads.New(bdWorkDir) - if err := bd.UpdateAgentState(agentBeadID, "running", nil); err != nil { + if err := bd.UpdateAgentState(agentBeadID, "running", &beadID); err != nil { // Log warning instead of silent ignore - helps debug cross-beads issues fmt.Fprintf(os.Stderr, "Warning: couldn't update agent %s state: %v\n", agentBeadID, err) return