feat(beads): Add hq- prefix helpers for town-level beads (gt-y24km, gt-qgmyz)
Phase 1: Create agent_ids.go with town-level bead ID helpers - MayorBeadIDTown(), DeaconBeadIDTown(), DogBeadIDTown() - RoleBeadIDTown() and role-specific helpers (hq-*-role) - Add deprecation notices to old gt-* prefix functions Phase 2: Create town-level agent beads during gt install - initTownAgentBeads() creates hq-mayor, hq-deacon agent beads - Creates role beads: hq-mayor-role, hq-deacon-role, etc. - Update rig/manager.go to use rig beads for Witness/Refinery This aligns with the two-level beads architecture: - Town beads (~/gt/.beads/): hq-* prefix for Mayor, Deacon, roles - Rig beads (<rig>/.beads/): <prefix>-* for Witness, Refinery, Polecats 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/steveyegge/gastown/internal/beads"
|
||||
"github.com/steveyegge/gastown/internal/config"
|
||||
"github.com/steveyegge/gastown/internal/deps"
|
||||
"github.com/steveyegge/gastown/internal/session"
|
||||
@@ -197,10 +198,11 @@ func runInstall(cmd *cobra.Command, args []string) error {
|
||||
fmt.Printf(" ✓ Initialized .beads/ (town-level beads with hq- prefix)\n")
|
||||
}
|
||||
|
||||
// NOTE: Agent beads (gt-deacon, gt-mayor) are created by gt rig add,
|
||||
// not here. This is because the daemon looks up beads by prefix routing,
|
||||
// and no rig exists yet at install time. The first rig added will get
|
||||
// these global agent beads in its beads database.
|
||||
// Create town-level agent beads (Mayor, Deacon) and role beads.
|
||||
// These use hq- prefix and are stored in town beads for cross-rig coordination.
|
||||
if err := initTownAgentBeads(absPath); err != nil {
|
||||
fmt.Printf(" %s Could not create town-level agent beads: %v\n", style.Dim.Render("⚠"), err)
|
||||
}
|
||||
}
|
||||
|
||||
// Detect and save overseer identity
|
||||
@@ -322,3 +324,116 @@ func ensureRepoFingerprint(beadsPath string) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// initTownAgentBeads creates town-level agent and role beads using hq- prefix.
|
||||
// This creates:
|
||||
// - hq-mayor, hq-deacon (agent beads for town-level agents)
|
||||
// - hq-mayor-role, hq-deacon-role, hq-witness-role, hq-refinery-role,
|
||||
// hq-polecat-role, hq-crew-role (role definition beads)
|
||||
//
|
||||
// These beads are stored in town beads (~/gt/.beads/) and are shared across all rigs.
|
||||
// Rig-level agent beads (witness, refinery) are created by gt rig add in rig beads.
|
||||
func initTownAgentBeads(townPath string) error {
|
||||
bd := beads.New(townPath)
|
||||
|
||||
// Town-level agent beads
|
||||
agentDefs := []struct {
|
||||
id string
|
||||
roleType string
|
||||
title string
|
||||
}{
|
||||
{
|
||||
id: beads.MayorBeadIDTown(),
|
||||
roleType: "mayor",
|
||||
title: "Mayor - global coordinator, handles cross-rig communication and escalations.",
|
||||
},
|
||||
{
|
||||
id: beads.DeaconBeadIDTown(),
|
||||
roleType: "deacon",
|
||||
title: "Deacon (daemon beacon) - receives mechanical heartbeats, runs town plugins and monitoring.",
|
||||
},
|
||||
}
|
||||
|
||||
for _, agent := range agentDefs {
|
||||
// Check if already exists
|
||||
if _, err := bd.Show(agent.id); err == nil {
|
||||
continue // Already exists
|
||||
}
|
||||
|
||||
fields := &beads.AgentFields{
|
||||
RoleType: agent.roleType,
|
||||
Rig: "", // Town-level agents have no rig
|
||||
AgentState: "idle",
|
||||
HookBead: "",
|
||||
RoleBead: beads.RoleBeadIDTown(agent.roleType),
|
||||
}
|
||||
|
||||
if _, err := bd.CreateAgentBead(agent.id, agent.title, fields); err != nil {
|
||||
return fmt.Errorf("creating %s: %w", agent.id, err)
|
||||
}
|
||||
fmt.Printf(" ✓ Created agent bead: %s\n", agent.id)
|
||||
}
|
||||
|
||||
// Role beads (global templates)
|
||||
roleDefs := []struct {
|
||||
id string
|
||||
title string
|
||||
desc string
|
||||
}{
|
||||
{
|
||||
id: beads.MayorRoleBeadIDTown(),
|
||||
title: "Mayor Role",
|
||||
desc: "Role definition for Mayor agents. Global coordinator for cross-rig work.",
|
||||
},
|
||||
{
|
||||
id: beads.DeaconRoleBeadIDTown(),
|
||||
title: "Deacon Role",
|
||||
desc: "Role definition for Deacon agents. Daemon beacon for heartbeats and monitoring.",
|
||||
},
|
||||
{
|
||||
id: beads.WitnessRoleBeadIDTown(),
|
||||
title: "Witness Role",
|
||||
desc: "Role definition for Witness agents. Per-rig worker monitor with progressive nudging.",
|
||||
},
|
||||
{
|
||||
id: beads.RefineryRoleBeadIDTown(),
|
||||
title: "Refinery Role",
|
||||
desc: "Role definition for Refinery agents. Merge queue processor with verification gates.",
|
||||
},
|
||||
{
|
||||
id: beads.PolecatRoleBeadIDTown(),
|
||||
title: "Polecat Role",
|
||||
desc: "Role definition for Polecat agents. Ephemeral workers for batch work dispatch.",
|
||||
},
|
||||
{
|
||||
id: beads.CrewRoleBeadIDTown(),
|
||||
title: "Crew Role",
|
||||
desc: "Role definition for Crew agents. Persistent user-managed workspaces.",
|
||||
},
|
||||
}
|
||||
|
||||
for _, role := range roleDefs {
|
||||
// Check if already exists
|
||||
if _, err := bd.Show(role.id); err == nil {
|
||||
continue // Already exists
|
||||
}
|
||||
|
||||
// Create role bead using bd create --type=role
|
||||
cmd := exec.Command("bd", "create",
|
||||
"--type=role",
|
||||
"--id="+role.id,
|
||||
"--title="+role.title,
|
||||
"--description="+role.desc,
|
||||
)
|
||||
cmd.Dir = townPath
|
||||
if output, err := cmd.CombinedOutput(); err != nil {
|
||||
// Log but continue - role beads are optional
|
||||
fmt.Printf(" %s Could not create role bead %s: %s\n",
|
||||
style.Dim.Render("⚠"), role.id, strings.TrimSpace(string(output)))
|
||||
continue
|
||||
}
|
||||
fmt.Printf(" ✓ Created role bead: %s\n", role.id)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user