From 04f0e46619e18fe081c9f0a733eefbd75be1b6c0 Mon Sep 17 00:00:00 2001 From: Steve Yegge Date: Tue, 30 Dec 2025 01:50:29 -0800 Subject: [PATCH] Add MQ summary to gt status output (gt-tvwnz) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Shows merge queue status under the Refinery section: - pending: Open MRs ready to merge (no blockers) - in-flight: MRs currently being processed - blocked: MRs waiting on dependencies Output appears as: MQ: 4 pending, 1 in-flight Also adds MQ summary to JSON output in RigStatus.mq field. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- internal/cmd/status.go | 78 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/internal/cmd/status.go b/internal/cmd/status.go index 7345ffc0..b3634199 100644 --- a/internal/cmd/status.go +++ b/internal/cmd/status.go @@ -83,6 +83,14 @@ type RigStatus struct { HasRefinery bool `json:"has_refinery"` Hooks []AgentHookInfo `json:"hooks,omitempty"` Agents []AgentRuntime `json:"agents,omitempty"` // Runtime state of all agents in rig + MQ *MQSummary `json:"mq,omitempty"` // Merge queue summary +} + +// MQSummary represents the merge queue status for a rig. +type MQSummary struct { + Pending int `json:"pending"` // Open MRs ready to merge (no blockers) + InFlight int `json:"in_flight"` // MRs currently being processed + Blocked int `json:"blocked"` // MRs waiting on dependencies } // AgentHookInfo represents an agent's hook (pinned work) status. @@ -202,6 +210,9 @@ func runStatus(cmd *cobra.Command, args []string) error { // Discover runtime state for all agents in this rig rs.Agents = discoverRigAgents(t, r, rs.Crews, agentBeads, mailRouter) + // Get MQ summary if rig has a refinery + rs.MQ = getMQSummary(r) + status.Rigs = append(status.Rigs, rs) // Update summary @@ -312,6 +323,22 @@ func outputStatusText(status TownStatus) error { for _, agent := range refineries { renderAgentDetails(agent, " ", r.Hooks) } + // MQ summary (shown under refinery) + if r.MQ != nil { + mqParts := []string{} + if r.MQ.Pending > 0 { + mqParts = append(mqParts, fmt.Sprintf("%d pending", r.MQ.Pending)) + } + if r.MQ.InFlight > 0 { + mqParts = append(mqParts, style.Warning.Render(fmt.Sprintf("%d in-flight", r.MQ.InFlight))) + } + if r.MQ.Blocked > 0 { + mqParts = append(mqParts, style.Dim.Render(fmt.Sprintf("%d blocked", r.MQ.Blocked))) + } + if len(mqParts) > 0 { + fmt.Printf(" MQ: %s\n", strings.Join(mqParts, ", ")) + } + } fmt.Println() } @@ -675,6 +702,57 @@ func discoverRigAgents(t *tmux.Tmux, r *rig.Rig, crews []string, agentBeads *bea return agents } +// getMQSummary queries beads for merge-request issues and returns a summary. +// Returns nil if the rig has no refinery or no MQ issues. +func getMQSummary(r *rig.Rig) *MQSummary { + if !r.HasRefinery { + return nil + } + + // Create beads instance for the rig + b := beads.New(r.BeadsPath()) + + // Query for all open merge-request type issues + opts := beads.ListOptions{ + Type: "merge-request", + Status: "open", + Priority: -1, // No priority filter + } + openMRs, err := b.List(opts) + if err != nil { + return nil + } + + // Query for in-progress merge-requests + opts.Status = "in_progress" + inProgressMRs, err := b.List(opts) + if err != nil { + return nil + } + + // Count pending (open with no blockers) vs blocked + pending := 0 + blocked := 0 + for _, mr := range openMRs { + if len(mr.BlockedBy) > 0 || mr.BlockedByCount > 0 { + blocked++ + } else { + pending++ + } + } + + // Only return summary if there's something to show + if pending == 0 && len(inProgressMRs) == 0 && blocked == 0 { + return nil + } + + return &MQSummary{ + Pending: pending, + InFlight: len(inProgressMRs), + Blocked: blocked, + } +} + // getAgentHook retrieves hook status for a specific agent. func getAgentHook(b *beads.Beads, role, agentAddress, roleType string) AgentHookInfo { hook := AgentHookInfo{