feat: extract Gas Town types from beads core (bd-i54l)

Remove Gas Town-specific issue types (agent, role, rig, convoy, slot)
from beads core. These types are now identified by labels instead:
- gt:agent, gt:role, gt:rig, gt:convoy, gt:slot

Changes:
- internal/types/types.go: Remove TypeAgent, TypeRole, TypeRig, TypeConvoy, TypeSlot constants
- cmd/bd/agent.go: Create agents with TypeTask + gt:agent label
- cmd/bd/merge_slot.go: Create slots with TypeTask + gt:slot label
- internal/storage/sqlite/queries.go, transaction.go: Query convoys by gt:convoy label
- internal/rpc/server_issues_epics.go: Check gt:agent label for role_type/rig label auto-add
- cmd/bd/create.go: Check gt:agent label for role_type/rig label auto-add
- internal/ui/styles.go: Remove agent/role/rig type colors
- cmd/bd/export_obsidian.go: Remove agent/role/rig/convoy type tag mappings
- Update all affected tests

This enables beads to be a generic issue tracker while Gas Town
uses labels for its specific type semantics.

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

Executed-By: beads/crew/dave
Rig: beads
Role: crew
This commit is contained in:
dave
2026-01-06 22:18:37 -08:00
committed by Steve Yegge
parent b7358f17bf
commit a70c3a8cbe
14 changed files with 139 additions and 93 deletions

View File

@@ -14,6 +14,16 @@ import (
"github.com/steveyegge/beads/internal/utils"
)
// containsLabel checks if a label exists in the list
func containsLabel(labels []string, label string) bool {
for _, l := range labels {
if l == label {
return true
}
}
return false
}
// parseTimeRPC parses time strings in multiple formats (RFC3339, YYYY-MM-DD, etc.)
// Matches the parseTimeFlag behavior in cmd/bd/list.go for CLI parity
func parseTimeRPC(s string) (time.Time, error) {
@@ -346,7 +356,8 @@ func (s *Server) handleCreate(req *Request) Response {
}
// Auto-add role_type/rig labels for agent beads (enables filtering queries)
if issue.IssueType == types.TypeAgent {
// Check for gt:agent label to identify agent beads (Gas Town separation)
if containsLabel(createArgs.Labels, "gt:agent") {
if issue.RoleType != "" {
label := "role_type:" + issue.RoleType
if err := store.AddLabel(ctx, issue.ID, label, s.reqActor(req)); err != nil {
@@ -590,13 +601,14 @@ func (s *Server) handleUpdate(req *Request) Response {
}
// Auto-add role_type/rig labels for agent beads when these fields are set
// This enables filtering queries like: bd list --type=agent --label=role_type:witness
// This enables filtering queries like: bd list --label=gt:agent --label=role_type:witness
// Note: We remove old role_type/rig labels first to prevent accumulation
if issue.IssueType == types.TypeAgent {
// Check for gt:agent label to identify agent beads (Gas Town separation)
issueLabels, _ := store.GetLabels(ctx, updateArgs.ID)
if containsLabel(issueLabels, "gt:agent") {
if updateArgs.RoleType != nil && *updateArgs.RoleType != "" {
// Remove any existing role_type:* labels first
existingLabels, _ := store.GetLabels(ctx, updateArgs.ID)
for _, l := range existingLabels {
for _, l := range issueLabels {
if strings.HasPrefix(l, "role_type:") {
_ = store.RemoveLabel(ctx, updateArgs.ID, l, actor)
}
@@ -612,8 +624,7 @@ func (s *Server) handleUpdate(req *Request) Response {
}
if updateArgs.Rig != nil && *updateArgs.Rig != "" {
// Remove any existing rig:* labels first
existingLabels, _ := store.GetLabels(ctx, updateArgs.ID)
for _, l := range existingLabels {
for _, l := range issueLabels {
if strings.HasPrefix(l, "rig:") {
_ = store.RemoveLabel(ctx, updateArgs.ID, l, actor)
}