fix: spawn and swarm bug fixes from MVP testing
- spawn.go: Parse bd show --json as array, fix issue_type json tag - session/manager.go: Check filesystem directly in hasPolecat() to handle newly-created polecats - swarm/manager.go: Use bd show to get children via dependents field instead of non-existent bd list --parent flag 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -60,7 +60,7 @@ type BeadsIssue struct {
|
|||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Description string `json:"description"`
|
Description string `json:"description"`
|
||||||
Priority int `json:"priority"`
|
Priority int `json:"priority"`
|
||||||
Type string `json:"type"`
|
Type string `json:"issue_type"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,12 +256,16 @@ func fetchBeadsIssue(rigPath, issueID string) (*BeadsIssue, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var issue BeadsIssue
|
// bd show --json returns an array, take the first element
|
||||||
if err := json.Unmarshal(stdout.Bytes(), &issue); err != nil {
|
var issues []BeadsIssue
|
||||||
|
if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil {
|
||||||
return nil, fmt.Errorf("parsing issue: %w", err)
|
return nil, fmt.Errorf("parsing issue: %w", err)
|
||||||
}
|
}
|
||||||
|
if len(issues) == 0 {
|
||||||
|
return nil, fmt.Errorf("issue not found: %s", issueID)
|
||||||
|
}
|
||||||
|
|
||||||
return &issue, nil
|
return &issues[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildSpawnContext creates the initial context message for the polecat.
|
// buildSpawnContext creates the initial context message for the polecat.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ package session
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -72,12 +73,13 @@ func (m *Manager) polecatDir(polecat string) string {
|
|||||||
|
|
||||||
// hasPolecat checks if the polecat exists in this rig.
|
// hasPolecat checks if the polecat exists in this rig.
|
||||||
func (m *Manager) hasPolecat(polecat string) bool {
|
func (m *Manager) hasPolecat(polecat string) bool {
|
||||||
for _, p := range m.rig.Polecats {
|
// Check filesystem directly to handle newly-created polecats
|
||||||
if p == polecat {
|
polecatPath := m.polecatDir(polecat)
|
||||||
return true
|
info, err := os.Stat(polecatPath)
|
||||||
}
|
if err != nil {
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
return false
|
return info.IsDir()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start creates and starts a new session for a polecat.
|
// Start creates and starts a new session for a polecat.
|
||||||
|
|||||||
@@ -278,8 +278,8 @@ func isValidTransition(from, to SwarmState) bool {
|
|||||||
|
|
||||||
// loadTasksFromBeads loads child issues from beads CLI.
|
// loadTasksFromBeads loads child issues from beads CLI.
|
||||||
func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) {
|
func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) {
|
||||||
// Run: bd list --parent <epicID> --json
|
// Run: bd show <epicID> --json to get epic with children
|
||||||
cmd := exec.Command("bd", "list", "--parent", epicID, "--json")
|
cmd := exec.Command("bd", "show", epicID, "--json")
|
||||||
cmd.Dir = m.workDir
|
cmd.Dir = m.workDir
|
||||||
|
|
||||||
var stdout, stderr bytes.Buffer
|
var stdout, stderr bytes.Buffer
|
||||||
@@ -287,24 +287,39 @@ func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) {
|
|||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
|
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
return nil, fmt.Errorf("bd list: %s", strings.TrimSpace(stderr.String()))
|
return nil, fmt.Errorf("bd show: %s", strings.TrimSpace(stderr.String()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse JSON output
|
// Parse JSON output - bd show returns an array
|
||||||
var issues []struct {
|
var issues []struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Title string `json:"title"`
|
Title string `json:"title"`
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
|
Dependents []struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Title string `json:"title"`
|
||||||
|
Status string `json:"status"`
|
||||||
|
DependencyType string `json:"dependency_type"`
|
||||||
|
} `json:"dependents"`
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil {
|
if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil {
|
||||||
return nil, fmt.Errorf("parsing bd output: %w", err)
|
return nil, fmt.Errorf("parsing bd output: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(issues) == 0 {
|
||||||
|
return nil, fmt.Errorf("epic not found: %s", epicID)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract parent-child dependents as tasks
|
||||||
var tasks []SwarmTask
|
var tasks []SwarmTask
|
||||||
for _, issue := range issues {
|
for _, dep := range issues[0].Dependents {
|
||||||
|
if dep.DependencyType != "parent-child" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
state := TaskPending
|
state := TaskPending
|
||||||
switch issue.Status {
|
switch dep.Status {
|
||||||
case "in_progress":
|
case "in_progress":
|
||||||
state = TaskInProgress
|
state = TaskInProgress
|
||||||
case "closed":
|
case "closed":
|
||||||
@@ -312,8 +327,8 @@ func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tasks = append(tasks, SwarmTask{
|
tasks = append(tasks, SwarmTask{
|
||||||
IssueID: issue.ID,
|
IssueID: dep.ID,
|
||||||
Title: issue.Title,
|
Title: dep.Title,
|
||||||
State: state,
|
State: state,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user