feat: add structured labels for agent beads (bd-g7eq)

Add role_type and rig labels to agent beads for filtering queries.

Changes:
- Add RoleType/Rig to CreateArgs and UpdateArgs in RPC protocol
- Auto-add role_type:<value> and rig:<value> labels when creating/updating agents
- Add --role-type and --agent-rig flags to bd create (requires --type=agent)
- Add bd agent backfill-labels command to update existing agent beads

This enables queries like:
  bd list --type=agent --label=role_type:witness
  bd list --type=agent --label=rig:gastown

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-29 21:15:46 -08:00
parent 22fb3ff56b
commit a8748936e4
4 changed files with 318 additions and 0 deletions

View File

@@ -121,6 +121,15 @@ var createCmd = &cobra.Command{
}
}
// Agent-specific flags
roleType, _ := cmd.Flags().GetString("role-type")
agentRig, _ := cmd.Flags().GetString("agent-rig")
// Validate agent-specific flags require --type=agent
if (roleType != "" || agentRig != "") && issueType != "agent" {
FatalError("--role-type and --agent-rig flags require --type=agent")
}
// Handle --rig or --prefix flag: create issue in a different rig
// Both flags use the same forgiving lookup (accepts rig names or prefixes)
targetRig := rigOverride
@@ -258,6 +267,8 @@ var createCmd = &cobra.Command{
Ephemeral: wisp,
CreatedBy: getActorWithGit(),
MolType: string(molType),
RoleType: roleType,
Rig: agentRig,
}
resp, err := daemonClient.Create(createArgs)
@@ -305,6 +316,8 @@ var createCmd = &cobra.Command{
Ephemeral: wisp,
CreatedBy: getActorWithGit(),
MolType: molType,
RoleType: roleType,
Rig: agentRig,
}
ctx := rootCtx
@@ -367,6 +380,22 @@ var createCmd = &cobra.Command{
}
}
// Auto-add role_type/rig labels for agent beads (enables filtering queries)
if issue.IssueType == types.TypeAgent {
if issue.RoleType != "" {
agentLabel := "role_type:" + issue.RoleType
if err := store.AddLabel(ctx, issue.ID, agentLabel, actor); err != nil {
WarnError("failed to add role_type label: %v", err)
}
}
if issue.Rig != "" {
rigLabel := "rig:" + issue.Rig
if err := store.AddLabel(ctx, issue.ID, rigLabel, actor); err != nil {
WarnError("failed to add rig label: %v", err)
}
}
}
// Add dependencies if specified (format: type:id or just id for default "blocks" type)
for _, depSpec := range deps {
// Skip empty specs (e.g., from trailing commas)
@@ -487,6 +516,9 @@ func init() {
createCmd.Flags().IntP("estimate", "e", 0, "Time estimate in minutes (e.g., 60 for 1 hour)")
createCmd.Flags().Bool("ephemeral", false, "Create as ephemeral (ephemeral, not exported to JSONL)")
createCmd.Flags().String("mol-type", "", "Molecule type: swarm (multi-polecat), patrol (recurring ops), work (default)")
// Agent-specific flags (only valid when --type=agent)
createCmd.Flags().String("role-type", "", "Agent role type: polecat|crew|witness|refinery|mayor|deacon (requires --type=agent)")
createCmd.Flags().String("agent-rig", "", "Agent's rig name (requires --type=agent)")
// Note: --json flag is defined as a persistent flag in main.go, not here
rootCmd.AddCommand(createCmd)
}