diff --git a/internal/cmd/spawn.go b/internal/cmd/spawn.go index 854f3ea9..04dea0f0 100644 --- a/internal/cmd/spawn.go +++ b/internal/cmd/spawn.go @@ -60,7 +60,7 @@ type BeadsIssue struct { Title string `json:"title"` Description string `json:"description"` Priority int `json:"priority"` - Type string `json:"type"` + Type string `json:"issue_type"` Status string `json:"status"` } @@ -256,12 +256,16 @@ func fetchBeadsIssue(rigPath, issueID string) (*BeadsIssue, error) { return nil, err } - var issue BeadsIssue - if err := json.Unmarshal(stdout.Bytes(), &issue); err != nil { + // bd show --json returns an array, take the first element + var issues []BeadsIssue + if err := json.Unmarshal(stdout.Bytes(), &issues); err != nil { 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. diff --git a/internal/session/manager.go b/internal/session/manager.go index c5bf290c..44eadcc9 100644 --- a/internal/session/manager.go +++ b/internal/session/manager.go @@ -4,6 +4,7 @@ package session import ( "errors" "fmt" + "os" "path/filepath" "strings" "time" @@ -72,12 +73,13 @@ func (m *Manager) polecatDir(polecat string) string { // hasPolecat checks if the polecat exists in this rig. func (m *Manager) hasPolecat(polecat string) bool { - for _, p := range m.rig.Polecats { - if p == polecat { - return true - } + // Check filesystem directly to handle newly-created polecats + polecatPath := m.polecatDir(polecat) + 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. diff --git a/internal/swarm/manager.go b/internal/swarm/manager.go index d5753633..74b8ac55 100644 --- a/internal/swarm/manager.go +++ b/internal/swarm/manager.go @@ -278,8 +278,8 @@ func isValidTransition(from, to SwarmState) bool { // loadTasksFromBeads loads child issues from beads CLI. func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) { - // Run: bd list --parent --json - cmd := exec.Command("bd", "list", "--parent", epicID, "--json") + // Run: bd show --json to get epic with children + cmd := exec.Command("bd", "show", epicID, "--json") cmd.Dir = m.workDir var stdout, stderr bytes.Buffer @@ -287,24 +287,39 @@ func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) { cmd.Stderr = &stderr 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 { - ID string `json:"id"` - Title string `json:"title"` - Status string `json:"status"` + ID string `json:"id"` + Title string `json:"title"` + 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 { 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 - for _, issue := range issues { + for _, dep := range issues[0].Dependents { + if dep.DependencyType != "parent-child" { + continue + } + state := TaskPending - switch issue.Status { + switch dep.Status { case "in_progress": state = TaskInProgress case "closed": @@ -312,8 +327,8 @@ func (m *Manager) loadTasksFromBeads(epicID string) ([]SwarmTask, error) { } tasks = append(tasks, SwarmTask{ - IssueID: issue.ID, - Title: issue.Title, + IssueID: dep.ID, + Title: dep.Title, State: state, }) }