fix: use rig prefixes for agent bead IDs
Align rig-scoped agent beads with route prefixes so crew add/prime/status resolve the same IDs across rigs. Add tests that assert rig-prefixed agent IDs in prime and status. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,8 @@ func runCrewAdd(cmd *cobra.Command, args []string) error {
|
|||||||
fmt.Printf(" Branch: %s\n", worker.Branch)
|
fmt.Printf(" Branch: %s\n", worker.Branch)
|
||||||
|
|
||||||
// Create agent bead for the crew worker
|
// Create agent bead for the crew worker
|
||||||
crewID := beads.CrewBeadID(rigName, name)
|
prefix := beads.GetPrefixForRig(townRoot, rigName)
|
||||||
|
crewID := beads.CrewBeadIDWithPrefix(prefix, rigName, name)
|
||||||
if _, err := bd.Show(crewID); err != nil {
|
if _, err := bd.Show(crewID); err != nil {
|
||||||
// Agent bead doesn't exist, create it
|
// Agent bead doesn't exist, create it
|
||||||
fields := &beads.AgentFields{
|
fields := &beads.AgentFields{
|
||||||
|
|||||||
@@ -1195,9 +1195,7 @@ func getAgentFields(ctx RoleContext, state string) *beads.AgentFields {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// getAgentBeadID returns the agent bead ID for the current role.
|
// getAgentBeadID returns the agent bead ID for the current role.
|
||||||
// Uses canonical naming: gt-rig-role-name
|
// Rig-scoped agents use the rig's configured prefix; town agents remain gt-.
|
||||||
// Agent beads always use "gt-" prefix (required by beads validation).
|
|
||||||
// Only issue beads use rig-specific prefixes.
|
|
||||||
// Returns empty string for unknown roles.
|
// Returns empty string for unknown roles.
|
||||||
func getAgentBeadID(ctx RoleContext) string {
|
func getAgentBeadID(ctx RoleContext) string {
|
||||||
switch ctx.Role {
|
switch ctx.Role {
|
||||||
@@ -1207,22 +1205,26 @@ func getAgentBeadID(ctx RoleContext) string {
|
|||||||
return beads.DeaconBeadID()
|
return beads.DeaconBeadID()
|
||||||
case RoleWitness:
|
case RoleWitness:
|
||||||
if ctx.Rig != "" {
|
if ctx.Rig != "" {
|
||||||
return beads.WitnessBeadID(ctx.Rig)
|
prefix := beads.GetPrefixForRig(ctx.TownRoot, ctx.Rig)
|
||||||
|
return beads.WitnessBeadIDWithPrefix(prefix, ctx.Rig)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
case RoleRefinery:
|
case RoleRefinery:
|
||||||
if ctx.Rig != "" {
|
if ctx.Rig != "" {
|
||||||
return beads.RefineryBeadID(ctx.Rig)
|
prefix := beads.GetPrefixForRig(ctx.TownRoot, ctx.Rig)
|
||||||
|
return beads.RefineryBeadIDWithPrefix(prefix, ctx.Rig)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
case RolePolecat:
|
case RolePolecat:
|
||||||
if ctx.Rig != "" && ctx.Polecat != "" {
|
if ctx.Rig != "" && ctx.Polecat != "" {
|
||||||
return beads.PolecatBeadID(ctx.Rig, ctx.Polecat)
|
prefix := beads.GetPrefixForRig(ctx.TownRoot, ctx.Rig)
|
||||||
|
return beads.PolecatBeadIDWithPrefix(prefix, ctx.Rig, ctx.Polecat)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
case RoleCrew:
|
case RoleCrew:
|
||||||
if ctx.Rig != "" && ctx.Polecat != "" {
|
if ctx.Rig != "" && ctx.Polecat != "" {
|
||||||
return beads.CrewBeadID(ctx.Rig, ctx.Polecat)
|
prefix := beads.GetPrefixForRig(ctx.TownRoot, ctx.Rig)
|
||||||
|
return beads.CrewBeadIDWithPrefix(prefix, ctx.Rig, ctx.Polecat)
|
||||||
}
|
}
|
||||||
return ""
|
return ""
|
||||||
default:
|
default:
|
||||||
|
|||||||
97
internal/cmd/prime_test.go
Normal file
97
internal/cmd/prime_test.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/steveyegge/gastown/internal/beads"
|
||||||
|
)
|
||||||
|
|
||||||
|
func writeTestRoutes(t *testing.T, townRoot string, routes []beads.Route) {
|
||||||
|
t.Helper()
|
||||||
|
beadsDir := filepath.Join(townRoot, ".beads")
|
||||||
|
if err := os.MkdirAll(beadsDir, 0755); err != nil {
|
||||||
|
t.Fatalf("create beads dir: %v", err)
|
||||||
|
}
|
||||||
|
if err := beads.WriteRoutes(beadsDir, routes); err != nil {
|
||||||
|
t.Fatalf("write routes: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAgentBeadID_UsesRigPrefix(t *testing.T) {
|
||||||
|
townRoot := t.TempDir()
|
||||||
|
writeTestRoutes(t, townRoot, []beads.Route{
|
||||||
|
{Prefix: "bd-", Path: "beads/mayor/rig"},
|
||||||
|
})
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
ctx RoleContext
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "mayor",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RoleMayor,
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "gt-mayor",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deacon",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RoleDeacon,
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "gt-deacon",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "witness",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RoleWitness,
|
||||||
|
Rig: "beads",
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "bd-beads-witness",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "refinery",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RoleRefinery,
|
||||||
|
Rig: "beads",
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "bd-beads-refinery",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "polecat",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RolePolecat,
|
||||||
|
Rig: "beads",
|
||||||
|
Polecat: "lex",
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "bd-beads-polecat-lex",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "crew",
|
||||||
|
ctx: RoleContext{
|
||||||
|
Role: RoleCrew,
|
||||||
|
Rig: "beads",
|
||||||
|
Polecat: "lex",
|
||||||
|
TownRoot: townRoot,
|
||||||
|
},
|
||||||
|
want: "bd-beads-crew-lex",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
got := getAgentBeadID(tc.ctx)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("getAgentBeadID() = %q, want %q", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -163,27 +163,42 @@ func runStatus(cmd *cobra.Command, args []string) error {
|
|||||||
return fmt.Errorf("discovering rigs: %w", err)
|
return fmt.Errorf("discovering rigs: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create beads instance for agent bead lookups (gastown rig holds gt- prefix beads)
|
// Pre-fetch agent beads across all rig-specific beads DBs.
|
||||||
gastownBeadsPath := filepath.Join(townRoot, "gastown", "mayor", "rig")
|
allAgentBeads := make(map[string]*beads.Issue)
|
||||||
agentBeads := beads.New(gastownBeadsPath)
|
allHookBeads := make(map[string]*beads.Issue)
|
||||||
|
for _, r := range rigs {
|
||||||
// Pre-fetch all agent beads in a single query for performance
|
rigBeadsPath := filepath.Join(r.Path, "mayor", "rig")
|
||||||
allAgentBeads, _ := agentBeads.ListAgentBeads()
|
rigBeads := beads.New(rigBeadsPath)
|
||||||
if allAgentBeads == nil {
|
rigAgentBeads, _ := rigBeads.ListAgentBeads()
|
||||||
allAgentBeads = make(map[string]*beads.Issue)
|
if rigAgentBeads == nil {
|
||||||
}
|
continue
|
||||||
|
}
|
||||||
// Pre-fetch all hook beads (referenced in agent beads) in a single query
|
for id, issue := range rigAgentBeads {
|
||||||
// Use the HookBead field from the database column, not parsed from description.
|
allAgentBeads[id] = issue
|
||||||
var allHookIDs []string
|
}
|
||||||
for _, issue := range allAgentBeads {
|
|
||||||
if issue.HookBead != "" {
|
var hookIDs []string
|
||||||
allHookIDs = append(allHookIDs, issue.HookBead)
|
for _, issue := range rigAgentBeads {
|
||||||
|
// Use the HookBead field from the database column; fall back for legacy beads.
|
||||||
|
hookID := issue.HookBead
|
||||||
|
if hookID == "" {
|
||||||
|
fields := beads.ParseAgentFields(issue.Description)
|
||||||
|
if fields != nil {
|
||||||
|
hookID = fields.HookBead
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if hookID != "" {
|
||||||
|
hookIDs = append(hookIDs, hookID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(hookIDs) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
hookBeads, _ := rigBeads.ShowMultiple(hookIDs)
|
||||||
|
for id, issue := range hookBeads {
|
||||||
|
allHookBeads[id] = issue
|
||||||
}
|
}
|
||||||
}
|
|
||||||
allHookBeads, _ := agentBeads.ShowMultiple(allHookIDs)
|
|
||||||
if allHookBeads == nil {
|
|
||||||
allHookBeads = make(map[string]*beads.Issue)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create mail router for inbox lookups
|
// Create mail router for inbox lookups
|
||||||
@@ -336,7 +351,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
icon = roleIcons[agent.Name]
|
icon = roleIcons[agent.Name]
|
||||||
}
|
}
|
||||||
fmt.Printf("%s %s\n", icon, style.Bold.Render(capitalizeFirst(agent.Name)))
|
fmt.Printf("%s %s\n", icon, style.Bold.Render(capitalizeFirst(agent.Name)))
|
||||||
renderAgentDetails(agent, " ", nil)
|
renderAgentDetails(agent, " ", nil, status.Location)
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -369,7 +384,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
if len(witnesses) > 0 {
|
if len(witnesses) > 0 {
|
||||||
fmt.Printf("%s %s\n", roleIcons["witness"], style.Bold.Render("Witness"))
|
fmt.Printf("%s %s\n", roleIcons["witness"], style.Bold.Render("Witness"))
|
||||||
for _, agent := range witnesses {
|
for _, agent := range witnesses {
|
||||||
renderAgentDetails(agent, " ", r.Hooks)
|
renderAgentDetails(agent, " ", r.Hooks, status.Location)
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
@@ -378,7 +393,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
if len(refineries) > 0 {
|
if len(refineries) > 0 {
|
||||||
fmt.Printf("%s %s\n", roleIcons["refinery"], style.Bold.Render("Refinery"))
|
fmt.Printf("%s %s\n", roleIcons["refinery"], style.Bold.Render("Refinery"))
|
||||||
for _, agent := range refineries {
|
for _, agent := range refineries {
|
||||||
renderAgentDetails(agent, " ", r.Hooks)
|
renderAgentDetails(agent, " ", r.Hooks, status.Location)
|
||||||
}
|
}
|
||||||
// MQ summary (shown under refinery)
|
// MQ summary (shown under refinery)
|
||||||
if r.MQ != nil {
|
if r.MQ != nil {
|
||||||
@@ -416,7 +431,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
if len(crews) > 0 {
|
if len(crews) > 0 {
|
||||||
fmt.Printf("%s %s (%d)\n", roleIcons["crew"], style.Bold.Render("Crew"), len(crews))
|
fmt.Printf("%s %s (%d)\n", roleIcons["crew"], style.Bold.Render("Crew"), len(crews))
|
||||||
for _, agent := range crews {
|
for _, agent := range crews {
|
||||||
renderAgentDetails(agent, " ", r.Hooks)
|
renderAgentDetails(agent, " ", r.Hooks, status.Location)
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
@@ -425,7 +440,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
if len(polecats) > 0 {
|
if len(polecats) > 0 {
|
||||||
fmt.Printf("%s %s (%d)\n", roleIcons["polecat"], style.Bold.Render("Polecats"), len(polecats))
|
fmt.Printf("%s %s (%d)\n", roleIcons["polecat"], style.Bold.Render("Polecats"), len(polecats))
|
||||||
for _, agent := range polecats {
|
for _, agent := range polecats {
|
||||||
renderAgentDetails(agent, " ", r.Hooks)
|
renderAgentDetails(agent, " ", r.Hooks, status.Location)
|
||||||
}
|
}
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
}
|
}
|
||||||
@@ -440,7 +455,7 @@ func outputStatusText(status TownStatus) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// renderAgentDetails renders full agent bead details
|
// renderAgentDetails renders full agent bead details
|
||||||
func renderAgentDetails(agent AgentRuntime, indent string, hooks []AgentHookInfo) {
|
func renderAgentDetails(agent AgentRuntime, indent string, hooks []AgentHookInfo, townRoot string) {
|
||||||
// Line 1: Agent bead ID + status
|
// Line 1: Agent bead ID + status
|
||||||
statusStr := style.Success.Render("running")
|
statusStr := style.Success.Render("running")
|
||||||
if !agent.Running {
|
if !agent.Running {
|
||||||
@@ -463,15 +478,16 @@ func renderAgentDetails(agent AgentRuntime, indent string, hooks []AgentHookInfo
|
|||||||
agentBeadID = beads.AgentBeadID("", parts[0], "")
|
agentBeadID = beads.AgentBeadID("", parts[0], "")
|
||||||
} else if len(parts) >= 2 {
|
} else if len(parts) >= 2 {
|
||||||
rig := parts[0]
|
rig := parts[0]
|
||||||
|
prefix := beads.GetPrefixForRig(townRoot, rig)
|
||||||
if parts[1] == "crew" && len(parts) >= 3 {
|
if parts[1] == "crew" && len(parts) >= 3 {
|
||||||
agentBeadID = beads.CrewBeadID(rig, parts[2])
|
agentBeadID = beads.CrewBeadIDWithPrefix(prefix, rig, parts[2])
|
||||||
} else if parts[1] == "witness" {
|
} else if parts[1] == "witness" {
|
||||||
agentBeadID = beads.WitnessBeadID(rig)
|
agentBeadID = beads.WitnessBeadIDWithPrefix(prefix, rig)
|
||||||
} else if parts[1] == "refinery" {
|
} else if parts[1] == "refinery" {
|
||||||
agentBeadID = beads.RefineryBeadID(rig)
|
agentBeadID = beads.RefineryBeadIDWithPrefix(prefix, rig)
|
||||||
} else if len(parts) == 2 {
|
} else if len(parts) == 2 {
|
||||||
// polecat: rig/name
|
// polecat: rig/name
|
||||||
agentBeadID = beads.PolecatBeadID(rig, parts[1])
|
agentBeadID = beads.PolecatBeadIDWithPrefix(prefix, rig, parts[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,6 +711,8 @@ type agentDef struct {
|
|||||||
func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string, allAgentBeads map[string]*beads.Issue, allHookBeads map[string]*beads.Issue, mailRouter *mail.Router, skipMail bool) []AgentRuntime {
|
func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string, allAgentBeads map[string]*beads.Issue, allHookBeads map[string]*beads.Issue, mailRouter *mail.Router, skipMail bool) []AgentRuntime {
|
||||||
// Build list of all agents to discover
|
// Build list of all agents to discover
|
||||||
var defs []agentDef
|
var defs []agentDef
|
||||||
|
townRoot := filepath.Dir(r.Path)
|
||||||
|
prefix := beads.GetPrefixForRig(townRoot, r.Name)
|
||||||
|
|
||||||
// Witness
|
// Witness
|
||||||
if r.HasWitness {
|
if r.HasWitness {
|
||||||
@@ -703,7 +721,7 @@ func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string,
|
|||||||
address: r.Name + "/witness",
|
address: r.Name + "/witness",
|
||||||
session: witnessSessionName(r.Name),
|
session: witnessSessionName(r.Name),
|
||||||
role: "witness",
|
role: "witness",
|
||||||
beadID: beads.WitnessBeadID(r.Name),
|
beadID: beads.WitnessBeadIDWithPrefix(prefix, r.Name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -714,7 +732,7 @@ func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string,
|
|||||||
address: r.Name + "/refinery",
|
address: r.Name + "/refinery",
|
||||||
session: fmt.Sprintf("gt-%s-refinery", r.Name),
|
session: fmt.Sprintf("gt-%s-refinery", r.Name),
|
||||||
role: "refinery",
|
role: "refinery",
|
||||||
beadID: beads.RefineryBeadID(r.Name),
|
beadID: beads.RefineryBeadIDWithPrefix(prefix, r.Name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -725,7 +743,7 @@ func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string,
|
|||||||
address: r.Name + "/" + name,
|
address: r.Name + "/" + name,
|
||||||
session: fmt.Sprintf("gt-%s-%s", r.Name, name),
|
session: fmt.Sprintf("gt-%s-%s", r.Name, name),
|
||||||
role: "polecat",
|
role: "polecat",
|
||||||
beadID: beads.PolecatBeadID(r.Name, name),
|
beadID: beads.PolecatBeadIDWithPrefix(prefix, r.Name, name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -736,7 +754,7 @@ func discoverRigAgents(allSessions map[string]bool, r *rig.Rig, crews []string,
|
|||||||
address: r.Name + "/crew/" + name,
|
address: r.Name + "/crew/" + name,
|
||||||
session: crewSessionName(r.Name, name),
|
session: crewSessionName(r.Name, name),
|
||||||
role: "crew",
|
role: "crew",
|
||||||
beadID: beads.CrewBeadID(r.Name, name),
|
beadID: beads.CrewBeadIDWithPrefix(prefix, r.Name, name),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
97
internal/cmd/status_test.go
Normal file
97
internal/cmd/status_test.go
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/steveyegge/gastown/internal/beads"
|
||||||
|
"github.com/steveyegge/gastown/internal/rig"
|
||||||
|
)
|
||||||
|
|
||||||
|
func captureStdout(t *testing.T, fn func()) string {
|
||||||
|
t.Helper()
|
||||||
|
old := os.Stdout
|
||||||
|
r, w, err := os.Pipe()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("create pipe: %v", err)
|
||||||
|
}
|
||||||
|
os.Stdout = w
|
||||||
|
|
||||||
|
fn()
|
||||||
|
|
||||||
|
_ = w.Close()
|
||||||
|
os.Stdout = old
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if _, err := io.Copy(&buf, r); err != nil {
|
||||||
|
t.Fatalf("read stdout: %v", err)
|
||||||
|
}
|
||||||
|
_ = r.Close()
|
||||||
|
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDiscoverRigAgents_UsesRigPrefix(t *testing.T) {
|
||||||
|
townRoot := t.TempDir()
|
||||||
|
writeTestRoutes(t, townRoot, []beads.Route{
|
||||||
|
{Prefix: "bd-", Path: "beads/mayor/rig"},
|
||||||
|
})
|
||||||
|
|
||||||
|
r := &rig.Rig{
|
||||||
|
Name: "beads",
|
||||||
|
Path: filepath.Join(townRoot, "beads"),
|
||||||
|
HasWitness: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
allAgentBeads := map[string]*beads.Issue{
|
||||||
|
"bd-beads-witness": {
|
||||||
|
ID: "bd-beads-witness",
|
||||||
|
AgentState: "running",
|
||||||
|
HookBead: "bd-hook",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
allHookBeads := map[string]*beads.Issue{
|
||||||
|
"bd-hook": {ID: "bd-hook", Title: "Pinned"},
|
||||||
|
}
|
||||||
|
|
||||||
|
agents := discoverRigAgents(map[string]bool{}, r, nil, allAgentBeads, allHookBeads, nil, true)
|
||||||
|
if len(agents) != 1 {
|
||||||
|
t.Fatalf("discoverRigAgents() returned %d agents, want 1", len(agents))
|
||||||
|
}
|
||||||
|
|
||||||
|
if agents[0].State != "running" {
|
||||||
|
t.Fatalf("agent state = %q, want %q", agents[0].State, "running")
|
||||||
|
}
|
||||||
|
if !agents[0].HasWork {
|
||||||
|
t.Fatalf("agent HasWork = false, want true")
|
||||||
|
}
|
||||||
|
if agents[0].WorkTitle != "Pinned" {
|
||||||
|
t.Fatalf("agent WorkTitle = %q, want %q", agents[0].WorkTitle, "Pinned")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderAgentDetails_UsesRigPrefix(t *testing.T) {
|
||||||
|
townRoot := t.TempDir()
|
||||||
|
writeTestRoutes(t, townRoot, []beads.Route{
|
||||||
|
{Prefix: "bd-", Path: "beads/mayor/rig"},
|
||||||
|
})
|
||||||
|
|
||||||
|
agent := AgentRuntime{
|
||||||
|
Name: "witness",
|
||||||
|
Address: "beads/witness",
|
||||||
|
Role: "witness",
|
||||||
|
Running: true,
|
||||||
|
}
|
||||||
|
|
||||||
|
output := captureStdout(t, func() {
|
||||||
|
renderAgentDetails(agent, "", nil, townRoot)
|
||||||
|
})
|
||||||
|
|
||||||
|
if !strings.Contains(output, "bd-beads-witness") {
|
||||||
|
t.Fatalf("output %q does not contain rig-prefixed bead ID", output)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user