fix: Refinery queue uses beads MQ as source of truth (hq-eggh5)

The refinery was checking git branches instead of the beads merge queue.
This caused MRs to pile up when branches were deleted but MR beads remained.

- manager.go: Queue() now queries beads for type=merge-request issues
- refinery.md.tmpl: Updated queue-scan to use gt mq list
- mol-refinery-patrol.formula.toml: Updated queue-scan step instructions
This commit is contained in:
mayor
2025-12-31 02:02:26 -08:00
committed by beads/crew/dave
parent 7069f762e5
commit 36f17bbadd
3 changed files with 75 additions and 24 deletions

View File

@@ -13,6 +13,7 @@ import (
"strings"
"time"
"github.com/steveyegge/gastown/internal/beads"
"github.com/steveyegge/gastown/internal/claude"
"github.com/steveyegge/gastown/internal/config"
"github.com/steveyegge/gastown/internal/events"
@@ -239,14 +240,21 @@ func (m *Manager) Stop() error {
}
// Queue returns the current merge queue.
// Uses beads merge-request issues as the source of truth (not git branches).
func (m *Manager) Queue() ([]QueueItem, error) {
// Discover branches that look like polecat work branches
branches, err := m.discoverWorkBranches()
// Query beads for open merge-request type issues
// BeadsPath() returns the git-synced beads location
b := beads.New(m.rig.BeadsPath())
issues, err := b.List(beads.ListOptions{
Type: "merge-request",
Status: "open",
Priority: -1, // No priority filter
})
if err != nil {
return nil, err
return nil, fmt.Errorf("querying merge queue from beads: %w", err)
}
// Load any pending MRs from state
// Load any current processing state
ref, err := m.loadState()
if err != nil {
return nil, err
@@ -265,10 +273,14 @@ func (m *Manager) Queue() ([]QueueItem, error) {
})
}
// Add discovered branches as pending
for _, branch := range branches {
mr := m.branchToMR(branch)
// Convert beads issues to queue items
for _, issue := range issues {
mr := m.issueToBead(issue)
if mr != nil {
// Skip if this is the currently processing MR
if ref.CurrentMR != nil && ref.CurrentMR.ID == mr.ID {
continue
}
items = append(items, QueueItem{
Position: pos,
MR: mr,
@@ -281,6 +293,44 @@ func (m *Manager) Queue() ([]QueueItem, error) {
return items, nil
}
// issueToBead converts a beads issue to a MergeRequest.
func (m *Manager) issueToBead(issue *beads.Issue) *MergeRequest {
if issue == nil {
return nil
}
fields := beads.ParseMRFields(issue)
if fields == nil {
// No MR fields in description, construct from title/ID
return &MergeRequest{
ID: issue.ID,
IssueID: issue.ID,
Status: MROpen,
CreatedAt: parseTime(issue.CreatedAt),
TargetBranch: "main",
}
}
return &MergeRequest{
ID: issue.ID,
Branch: fields.Branch,
Worker: fields.Worker,
IssueID: fields.SourceIssue,
TargetBranch: fields.Target,
Status: MROpen,
CreatedAt: parseTime(issue.CreatedAt),
}
}
// parseTime parses a time string, returning zero time on error.
func parseTime(s string) time.Time {
t, err := time.Parse(time.RFC3339, s)
if err != nil {
t, _ = time.Parse("2006-01-02T15:04:05Z", s)
}
return t
}
// discoverWorkBranches finds branches that look like polecat work.
func (m *Manager) discoverWorkBranches() ([]string, error) {
cmd := exec.Command("git", "branch", "-r", "--list", "origin/polecat/*")

View File

@@ -198,12 +198,12 @@ gt mail inbox
# Process each message: lifecycle requests, escalations
```
**queue-scan**: Fetch remote and identify branches
**queue-scan**: Check beads merge queue (source of truth)
```bash
git fetch origin
git branch -r | grep polecat
gt refinery queue {{ .RigName }}
git fetch --prune origin
gt mq list {{ .RigName }}
```
The beads MQ is the source of truth for pending merges, not git branches.
If queue empty, skip to context-check step.
**process-branch**: Pick next branch, rebase on main