diff --git a/cmd/bd/create.go b/cmd/bd/create.go index a2af514a..2f3cf59e 100644 --- a/cmd/bd/create.go +++ b/cmd/bd/create.go @@ -595,7 +595,7 @@ func init() { createCmd.Flags().String("title", "", "Issue title (alternative to positional argument)") createCmd.Flags().Bool("silent", false, "Output only the issue ID (for scripting)") registerPriorityFlag(createCmd, "2") - createCmd.Flags().StringP("type", "t", "task", "Issue type (bug|feature|task|epic|chore|merge-request|molecule|gate|agent|role|convoy|event)") + createCmd.Flags().StringP("type", "t", "task", "Issue type (bug|feature|task|epic|chore|merge-request|molecule|gate|agent|role|rig|convoy|event)") registerCommonIssueFlags(createCmd) createCmd.Flags().StringSliceP("labels", "l", []string{}, "Labels (comma-separated)") createCmd.Flags().StringSlice("label", []string{}, "Alias for --labels") diff --git a/cmd/bd/export_obsidian.go b/cmd/bd/export_obsidian.go index 182f2f0e..82812ea6 100644 --- a/cmd/bd/export_obsidian.go +++ b/cmd/bd/export_obsidian.go @@ -45,6 +45,7 @@ var obsidianTypeTag = map[types.IssueType]string{ types.TypeGate: "#Gate", types.TypeAgent: "#Agent", types.TypeRole: "#Role", + types.TypeRig: "#Rig", types.TypeConvoy: "#Convoy", types.TypeEvent: "#Event", } diff --git a/cmd/bd/update.go b/cmd/bd/update.go index f8a1b536..0e8d9a2f 100644 --- a/cmd/bd/update.go +++ b/cmd/bd/update.go @@ -105,7 +105,7 @@ create, update, show, or close operation).`, issueType, _ := cmd.Flags().GetString("type") // Validate issue type if !types.IssueType(issueType).IsValid() { - FatalErrorRespectJSON("invalid issue type %q. Valid types: bug, feature, task, epic, chore, merge-request, molecule, gate", issueType) + FatalErrorRespectJSON("invalid issue type %q. Valid types: bug, feature, task, epic, chore, merge-request, molecule, gate, agent, role, rig, convoy, event, slot", issueType) } updates["issue_type"] = issueType } @@ -595,7 +595,7 @@ func init() { updateCmd.Flags().StringP("status", "s", "", "New status") registerPriorityFlag(updateCmd, "") updateCmd.Flags().String("title", "", "New title") - updateCmd.Flags().StringP("type", "t", "", "New type (bug|feature|task|epic|chore|merge-request|molecule|gate)") + updateCmd.Flags().StringP("type", "t", "", "New type (bug|feature|task|epic|chore|merge-request|molecule|gate|agent|role|rig|convoy|event|slot)") registerCommonIssueFlags(updateCmd) updateCmd.Flags().String("acceptance-criteria", "", "DEPRECATED: use --acceptance") _ = updateCmd.Flags().MarkHidden("acceptance-criteria") // Only fails if flag missing (caught in tests) diff --git a/internal/types/types.go b/internal/types/types.go index 9e28a124..b6fa493b 100644 --- a/internal/types/types.go +++ b/internal/types/types.go @@ -417,6 +417,7 @@ const ( TypeGate IssueType = "gate" // Async coordination gate TypeAgent IssueType = "agent" // Agent identity bead TypeRole IssueType = "role" // Agent role definition + TypeRig IssueType = "rig" // Rig identity bead (project container) TypeConvoy IssueType = "convoy" // Cross-project tracking with reactive completion TypeEvent IssueType = "event" // Operational state change record TypeSlot IssueType = "slot" // Exclusive access slot (merge-slot gate) @@ -425,7 +426,7 @@ const ( // IsValid checks if the issue type value is valid func (t IssueType) IsValid() bool { switch t { - case TypeBug, TypeFeature, TypeTask, TypeEpic, TypeChore, TypeMessage, TypeMergeRequest, TypeMolecule, TypeGate, TypeAgent, TypeRole, TypeConvoy, TypeEvent, TypeSlot: + case TypeBug, TypeFeature, TypeTask, TypeEpic, TypeChore, TypeMessage, TypeMergeRequest, TypeMolecule, TypeGate, TypeAgent, TypeRole, TypeRig, TypeConvoy, TypeEvent, TypeSlot: return true } return false diff --git a/internal/types/types_test.go b/internal/types/types_test.go index 1f3895bb..3c6644a2 100644 --- a/internal/types/types_test.go +++ b/internal/types/types_test.go @@ -401,6 +401,12 @@ func TestIssueTypeIsValid(t *testing.T) { {TypeTask, true}, {TypeEpic, true}, {TypeChore, true}, + {TypeAgent, true}, + {TypeRole, true}, + {TypeRig, true}, + {TypeConvoy, true}, + {TypeEvent, true}, + {TypeSlot, true}, {IssueType("invalid"), false}, {IssueType(""), false}, } @@ -430,6 +436,7 @@ func TestIssueTypeRequiredSections(t *testing.T) { {TypeGate, 0, ""}, {TypeAgent, 0, ""}, {TypeRole, 0, ""}, + {TypeRig, 0, ""}, {TypeConvoy, 0, ""}, {TypeEvent, 0, ""}, {TypeMergeRequest, 0, ""}, diff --git a/internal/ui/styles.go b/internal/ui/styles.go index d697453a..23e14dc4 100644 --- a/internal/ui/styles.go +++ b/internal/ui/styles.go @@ -143,6 +143,10 @@ var ( Light: "#7fd962", // green - role definition Dark: "#7fd962", } + ColorTypeRig = lipgloss.AdaptiveColor{ + Light: "#e6a756", // orange - rig identity (project container) + Dark: "#e6a756", + } // === Issue ID Color === // IDs use standard text color - subtle, not attention-grabbing @@ -192,6 +196,7 @@ var ( TypeChoreStyle = lipgloss.NewStyle().Foreground(ColorTypeChore) TypeAgentStyle = lipgloss.NewStyle().Foreground(ColorTypeAgent) TypeRoleStyle = lipgloss.NewStyle().Foreground(ColorTypeRole) + TypeRigStyle = lipgloss.NewStyle().Foreground(ColorTypeRig) ) // CategoryStyle for section headers - bold with accent color @@ -343,6 +348,8 @@ func RenderType(issueType string) string { return TypeAgentStyle.Render(issueType) case "role": return TypeRoleStyle.Render(issueType) + case "rig": + return TypeRigStyle.Render(issueType) default: return issueType } diff --git a/internal/ui/styles_test.go b/internal/ui/styles_test.go index 23dcf00c..4091328d 100644 --- a/internal/ui/styles_test.go +++ b/internal/ui/styles_test.go @@ -94,6 +94,7 @@ func TestRenderTypeVariants(t *testing.T) { {"chore", TypeChoreStyle.Render("chore")}, {"agent", TypeAgentStyle.Render("agent")}, {"role", TypeRoleStyle.Render("role")}, + {"rig", TypeRigStyle.Render("rig")}, {"custom", "custom"}, } for _, tc := range cases { diff --git a/internal/validation/bead_test.go b/internal/validation/bead_test.go index d5e1e366..eaf96694 100644 --- a/internal/validation/bead_test.go +++ b/internal/validation/bead_test.go @@ -128,6 +128,7 @@ func TestParseIssueType(t *testing.T) { {"gate type", "gate", types.TypeGate, false, ""}, {"agent type", "agent", types.TypeAgent, false, ""}, {"role type", "role", types.TypeRole, false, ""}, + {"rig type", "rig", types.TypeRig, false, ""}, {"message type", "message", types.TypeMessage, false, ""}, // Case sensitivity (function is case-sensitive)