fix: Use rig's configured prefix for agent bead IDs (gt-kdy77, gt-ihvq0)
Added WithPrefix variants to agent bead ID functions: - AgentBeadIDWithPrefix(prefix, rig, role, name) - WitnessBeadIDWithPrefix, RefineryBeadIDWithPrefix - CrewBeadIDWithPrefix, PolecatBeadIDWithPrefix Updated callers to use rig's configured prefix: - crew_add.go: reads r.Config.Prefix for crew worker beads - rig/manager.go: uses prefix param for witness/refinery beads - doctor/agent_beads_check.go: uses prefix from routes.jsonl This allows non-gastown rigs (like beads with bd- prefix) to have properly-prefixed agent beads. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -719,21 +719,28 @@ func (b *Beads) GetAgentBead(id string) (*Issue, *AgentFields, error) {
|
||||
// - gt-gastown-crew-max (rig-level named agent)
|
||||
// - gt-gastown-polecat-Toast (rig-level named agent)
|
||||
|
||||
// AgentBeadID generates the canonical agent bead ID.
|
||||
// AgentBeadIDWithPrefix generates an agent bead ID using the specified prefix.
|
||||
// The prefix should NOT include the hyphen (e.g., "gt", "bd", not "gt-", "bd-").
|
||||
// For town-level agents (mayor, deacon), pass empty rig and name.
|
||||
// For rig-level singletons (witness, refinery), pass empty name.
|
||||
// For named agents (crew, polecat), pass all three.
|
||||
func AgentBeadID(rig, role, name string) string {
|
||||
func AgentBeadIDWithPrefix(prefix, rig, role, name string) string {
|
||||
if rig == "" {
|
||||
// Town-level agent: gt-mayor, gt-deacon
|
||||
return "gt-" + role
|
||||
// Town-level agent: prefix-mayor, prefix-deacon
|
||||
return prefix + "-" + role
|
||||
}
|
||||
if name == "" {
|
||||
// Rig-level singleton: gt-gastown-witness, gt-gastown-refinery
|
||||
return "gt-" + rig + "-" + role
|
||||
// Rig-level singleton: prefix-rig-witness, prefix-rig-refinery
|
||||
return prefix + "-" + rig + "-" + role
|
||||
}
|
||||
// Rig-level named agent: gt-gastown-crew-max, gt-gastown-polecat-Toast
|
||||
return "gt-" + rig + "-" + role + "-" + name
|
||||
// Rig-level named agent: prefix-rig-role-name
|
||||
return prefix + "-" + rig + "-" + role + "-" + name
|
||||
}
|
||||
|
||||
// AgentBeadID generates the canonical agent bead ID using "gt" prefix.
|
||||
// For non-gastown rigs, use AgentBeadIDWithPrefix with the rig's configured prefix.
|
||||
func AgentBeadID(rig, role, name string) string {
|
||||
return AgentBeadIDWithPrefix("gt", rig, role, name)
|
||||
}
|
||||
|
||||
// MayorBeadID returns the Mayor agent bead ID.
|
||||
@@ -746,24 +753,44 @@ func DeaconBeadID() string {
|
||||
return "gt-deacon"
|
||||
}
|
||||
|
||||
// WitnessBeadID returns the Witness agent bead ID for a rig.
|
||||
// WitnessBeadIDWithPrefix returns the Witness agent bead ID for a rig using the specified prefix.
|
||||
func WitnessBeadIDWithPrefix(prefix, rig string) string {
|
||||
return AgentBeadIDWithPrefix(prefix, rig, "witness", "")
|
||||
}
|
||||
|
||||
// WitnessBeadID returns the Witness agent bead ID for a rig using "gt" prefix.
|
||||
func WitnessBeadID(rig string) string {
|
||||
return AgentBeadID(rig, "witness", "")
|
||||
return WitnessBeadIDWithPrefix("gt", rig)
|
||||
}
|
||||
|
||||
// RefineryBeadID returns the Refinery agent bead ID for a rig.
|
||||
// RefineryBeadIDWithPrefix returns the Refinery agent bead ID for a rig using the specified prefix.
|
||||
func RefineryBeadIDWithPrefix(prefix, rig string) string {
|
||||
return AgentBeadIDWithPrefix(prefix, rig, "refinery", "")
|
||||
}
|
||||
|
||||
// RefineryBeadID returns the Refinery agent bead ID for a rig using "gt" prefix.
|
||||
func RefineryBeadID(rig string) string {
|
||||
return AgentBeadID(rig, "refinery", "")
|
||||
return RefineryBeadIDWithPrefix("gt", rig)
|
||||
}
|
||||
|
||||
// CrewBeadID returns a Crew worker agent bead ID.
|
||||
// CrewBeadIDWithPrefix returns a Crew worker agent bead ID using the specified prefix.
|
||||
func CrewBeadIDWithPrefix(prefix, rig, name string) string {
|
||||
return AgentBeadIDWithPrefix(prefix, rig, "crew", name)
|
||||
}
|
||||
|
||||
// CrewBeadID returns a Crew worker agent bead ID using "gt" prefix.
|
||||
func CrewBeadID(rig, name string) string {
|
||||
return AgentBeadID(rig, "crew", name)
|
||||
return CrewBeadIDWithPrefix("gt", rig, name)
|
||||
}
|
||||
|
||||
// PolecatBeadID returns a Polecat agent bead ID.
|
||||
// PolecatBeadIDWithPrefix returns a Polecat agent bead ID using the specified prefix.
|
||||
func PolecatBeadIDWithPrefix(prefix, rig, name string) string {
|
||||
return AgentBeadIDWithPrefix(prefix, rig, "polecat", name)
|
||||
}
|
||||
|
||||
// PolecatBeadID returns a Polecat agent bead ID using "gt" prefix.
|
||||
func PolecatBeadID(rig, name string) string {
|
||||
return AgentBeadID(rig, "polecat", name)
|
||||
return PolecatBeadIDWithPrefix("gt", rig, name)
|
||||
}
|
||||
|
||||
// ParseAgentBeadID parses an agent bead ID into its components.
|
||||
|
||||
@@ -81,7 +81,12 @@ func runCrewAdd(cmd *cobra.Command, args []string) error {
|
||||
// Create agent bead for the crew worker
|
||||
rigBeadsPath := filepath.Join(r.Path, "mayor", "rig")
|
||||
bd := beads.New(rigBeadsPath)
|
||||
crewID := beads.CrewBeadID(rigName, name)
|
||||
// Use the rig's configured prefix, defaulting to "gt" for backward compatibility
|
||||
prefix := "gt"
|
||||
if r.Config != nil && r.Config.Prefix != "" {
|
||||
prefix = r.Config.Prefix
|
||||
}
|
||||
crewID := beads.CrewBeadIDWithPrefix(prefix, rigName, name)
|
||||
if _, err := bd.Show(crewID); err != nil {
|
||||
// Agent bead doesn't exist, create it
|
||||
fields := &beads.AgentFields{
|
||||
|
||||
@@ -16,10 +16,7 @@ import (
|
||||
// - Crew workers - stored in each rig's beads
|
||||
//
|
||||
// Agent beads are created by gt rig add (see gt-h3hak, gt-pinkq) and gt crew add.
|
||||
//
|
||||
// NOTE: Currently, the beads library validates that agent IDs must start
|
||||
// with 'gt-'. Rigs with different prefixes (like 'bd-') cannot have agent
|
||||
// beads created until that validation is fixed in the beads repo.
|
||||
// Each rig uses its configured prefix (e.g., "gt-" for gastown, "bd-" for beads).
|
||||
type AgentBeadsCheck struct {
|
||||
FixableCheck
|
||||
}
|
||||
@@ -86,22 +83,14 @@ func (c *AgentBeadsCheck) Run(ctx *CheckContext) *CheckResult {
|
||||
}
|
||||
|
||||
// Check each rig for its agents
|
||||
var skipped []string
|
||||
for prefix, rigName := range prefixToRig {
|
||||
// Skip non-gt prefixes - beads library currently requires gt- prefix for agents
|
||||
// TODO: Remove this once beads validation is fixed to accept any prefix
|
||||
if prefix != "gt" {
|
||||
skipped = append(skipped, fmt.Sprintf("%s (%s-*)", rigName, prefix))
|
||||
continue
|
||||
}
|
||||
|
||||
// Get beads client for this rig
|
||||
rigBeadsPath := filepath.Join(ctx.TownRoot, rigName, "mayor", "rig")
|
||||
bd := beads.New(rigBeadsPath)
|
||||
|
||||
// Check rig-specific agents (using canonical naming: prefix-rig-role-name)
|
||||
witnessID := beads.WitnessBeadID(rigName)
|
||||
refineryID := beads.RefineryBeadID(rigName)
|
||||
witnessID := beads.WitnessBeadIDWithPrefix(prefix, rigName)
|
||||
refineryID := beads.RefineryBeadIDWithPrefix(prefix, rigName)
|
||||
|
||||
if _, err := bd.Show(witnessID); err != nil {
|
||||
missing = append(missing, witnessID)
|
||||
@@ -116,7 +105,7 @@ func (c *AgentBeadsCheck) Run(ctx *CheckContext) *CheckResult {
|
||||
// Check crew worker agents
|
||||
crewWorkers := listCrewWorkers(ctx.TownRoot, rigName)
|
||||
for _, workerName := range crewWorkers {
|
||||
crewID := beads.CrewBeadID(rigName, workerName)
|
||||
crewID := beads.CrewBeadIDWithPrefix(prefix, rigName, workerName)
|
||||
if _, err := bd.Show(crewID); err != nil {
|
||||
missing = append(missing, crewID)
|
||||
}
|
||||
@@ -141,31 +130,18 @@ func (c *AgentBeadsCheck) Run(ctx *CheckContext) *CheckResult {
|
||||
}
|
||||
|
||||
if len(missing) == 0 {
|
||||
msg := fmt.Sprintf("All %d agent beads exist", checked)
|
||||
var details []string
|
||||
if len(skipped) > 0 {
|
||||
details = append(details, fmt.Sprintf("Skipped %d rig(s) with non-gt prefix (beads library limitation): %s",
|
||||
len(skipped), strings.Join(skipped, ", ")))
|
||||
}
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusOK,
|
||||
Message: msg,
|
||||
Details: details,
|
||||
Message: fmt.Sprintf("All %d agent beads exist", checked),
|
||||
}
|
||||
}
|
||||
|
||||
details := missing
|
||||
if len(skipped) > 0 {
|
||||
details = append(details, fmt.Sprintf("Skipped %d rig(s) with non-gt prefix: %s",
|
||||
len(skipped), strings.Join(skipped, ", ")))
|
||||
}
|
||||
|
||||
return &CheckResult{
|
||||
Name: c.Name(),
|
||||
Status: StatusError,
|
||||
Message: fmt.Sprintf("%d agent bead(s) missing", len(missing)),
|
||||
Details: details,
|
||||
Details: missing,
|
||||
FixHint: "Run 'gt doctor --fix' to create missing agent beads",
|
||||
}
|
||||
}
|
||||
@@ -207,16 +183,11 @@ func (c *AgentBeadsCheck) Fix(ctx *CheckContext) error {
|
||||
|
||||
// Create missing agents for each rig
|
||||
for prefix, rigName := range prefixToRig {
|
||||
// Skip non-gt prefixes - beads library currently requires gt- prefix for agents
|
||||
if prefix != "gt" {
|
||||
continue
|
||||
}
|
||||
|
||||
rigBeadsPath := filepath.Join(ctx.TownRoot, rigName, "mayor", "rig")
|
||||
bd := beads.New(rigBeadsPath)
|
||||
|
||||
// Create rig-specific agents if missing (using canonical naming: prefix-rig-role-name)
|
||||
witnessID := beads.WitnessBeadID(rigName)
|
||||
witnessID := beads.WitnessBeadIDWithPrefix(prefix, rigName)
|
||||
if _, err := bd.Show(witnessID); err != nil {
|
||||
fields := &beads.AgentFields{
|
||||
RoleType: "witness",
|
||||
@@ -230,7 +201,7 @@ func (c *AgentBeadsCheck) Fix(ctx *CheckContext) error {
|
||||
}
|
||||
}
|
||||
|
||||
refineryID := beads.RefineryBeadID(rigName)
|
||||
refineryID := beads.RefineryBeadIDWithPrefix(prefix, rigName)
|
||||
if _, err := bd.Show(refineryID); err != nil {
|
||||
fields := &beads.AgentFields{
|
||||
RoleType: "refinery",
|
||||
@@ -247,7 +218,7 @@ func (c *AgentBeadsCheck) Fix(ctx *CheckContext) error {
|
||||
// Create crew worker agents if missing
|
||||
crewWorkers := listCrewWorkers(ctx.TownRoot, rigName)
|
||||
for _, workerName := range crewWorkers {
|
||||
crewID := beads.CrewBeadID(rigName, workerName)
|
||||
crewID := beads.CrewBeadIDWithPrefix(prefix, rigName, workerName)
|
||||
if _, err := bd.Show(crewID); err != nil {
|
||||
fields := &beads.AgentFields{
|
||||
RoleType: "crew",
|
||||
|
||||
@@ -417,13 +417,13 @@ func (m *Manager) initAgentBeads(rigPath, rigName, prefix string, isFirstRig boo
|
||||
// Always create rig-specific agents (using canonical naming: prefix-rig-role-name)
|
||||
agents = append(agents,
|
||||
agentDef{
|
||||
id: beads.WitnessBeadID(rigName),
|
||||
id: beads.WitnessBeadIDWithPrefix(prefix, rigName),
|
||||
roleType: "witness",
|
||||
rig: rigName,
|
||||
desc: fmt.Sprintf("Witness for %s - monitors polecat health and progress.", rigName),
|
||||
},
|
||||
agentDef{
|
||||
id: beads.RefineryBeadID(rigName),
|
||||
id: beads.RefineryBeadIDWithPrefix(prefix, rigName),
|
||||
roleType: "refinery",
|
||||
rig: rigName,
|
||||
desc: fmt.Sprintf("Refinery for %s - processes merge queue.", rigName),
|
||||
|
||||
Reference in New Issue
Block a user