feat(types): add rig identity bead type (gt-zmznh)

- Add TypeRig constant to IssueType enum
- Update IsValid() method to include TypeRig
- Add UI color (orange) and style for rig type
- Update CLI flag descriptions in create and update commands
- Add Obsidian export tag for rig type
- Add comprehensive test cases for rig and other newer types

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
furiosa
2026-01-06 18:55:06 -08:00
committed by Steve Yegge
parent 94997bd619
commit bf378650f4
8 changed files with 22 additions and 4 deletions
+1 -1
View File
@@ -595,7 +595,7 @@ func init() {
createCmd.Flags().String("title", "", "Issue title (alternative to positional argument)") createCmd.Flags().String("title", "", "Issue title (alternative to positional argument)")
createCmd.Flags().Bool("silent", false, "Output only the issue ID (for scripting)") createCmd.Flags().Bool("silent", false, "Output only the issue ID (for scripting)")
registerPriorityFlag(createCmd, "2") 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) registerCommonIssueFlags(createCmd)
createCmd.Flags().StringSliceP("labels", "l", []string{}, "Labels (comma-separated)") createCmd.Flags().StringSliceP("labels", "l", []string{}, "Labels (comma-separated)")
createCmd.Flags().StringSlice("label", []string{}, "Alias for --labels") createCmd.Flags().StringSlice("label", []string{}, "Alias for --labels")
+1
View File
@@ -45,6 +45,7 @@ var obsidianTypeTag = map[types.IssueType]string{
types.TypeGate: "#Gate", types.TypeGate: "#Gate",
types.TypeAgent: "#Agent", types.TypeAgent: "#Agent",
types.TypeRole: "#Role", types.TypeRole: "#Role",
types.TypeRig: "#Rig",
types.TypeConvoy: "#Convoy", types.TypeConvoy: "#Convoy",
types.TypeEvent: "#Event", types.TypeEvent: "#Event",
} }
+2 -2
View File
@@ -105,7 +105,7 @@ create, update, show, or close operation).`,
issueType, _ := cmd.Flags().GetString("type") issueType, _ := cmd.Flags().GetString("type")
// Validate issue type // Validate issue type
if !types.IssueType(issueType).IsValid() { 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 updates["issue_type"] = issueType
} }
@@ -595,7 +595,7 @@ func init() {
updateCmd.Flags().StringP("status", "s", "", "New status") updateCmd.Flags().StringP("status", "s", "", "New status")
registerPriorityFlag(updateCmd, "") registerPriorityFlag(updateCmd, "")
updateCmd.Flags().String("title", "", "New title") 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) registerCommonIssueFlags(updateCmd)
updateCmd.Flags().String("acceptance-criteria", "", "DEPRECATED: use --acceptance") updateCmd.Flags().String("acceptance-criteria", "", "DEPRECATED: use --acceptance")
_ = updateCmd.Flags().MarkHidden("acceptance-criteria") // Only fails if flag missing (caught in tests) _ = updateCmd.Flags().MarkHidden("acceptance-criteria") // Only fails if flag missing (caught in tests)
+2 -1
View File
@@ -417,6 +417,7 @@ const (
TypeGate IssueType = "gate" // Async coordination gate TypeGate IssueType = "gate" // Async coordination gate
TypeAgent IssueType = "agent" // Agent identity bead TypeAgent IssueType = "agent" // Agent identity bead
TypeRole IssueType = "role" // Agent role definition TypeRole IssueType = "role" // Agent role definition
TypeRig IssueType = "rig" // Rig identity bead (project container)
TypeConvoy IssueType = "convoy" // Cross-project tracking with reactive completion TypeConvoy IssueType = "convoy" // Cross-project tracking with reactive completion
TypeEvent IssueType = "event" // Operational state change record TypeEvent IssueType = "event" // Operational state change record
TypeSlot IssueType = "slot" // Exclusive access slot (merge-slot gate) TypeSlot IssueType = "slot" // Exclusive access slot (merge-slot gate)
@@ -425,7 +426,7 @@ const (
// IsValid checks if the issue type value is valid // IsValid checks if the issue type value is valid
func (t IssueType) IsValid() bool { func (t IssueType) IsValid() bool {
switch t { 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 true
} }
return false return false
+7
View File
@@ -401,6 +401,12 @@ func TestIssueTypeIsValid(t *testing.T) {
{TypeTask, true}, {TypeTask, true},
{TypeEpic, true}, {TypeEpic, true},
{TypeChore, true}, {TypeChore, true},
{TypeAgent, true},
{TypeRole, true},
{TypeRig, true},
{TypeConvoy, true},
{TypeEvent, true},
{TypeSlot, true},
{IssueType("invalid"), false}, {IssueType("invalid"), false},
{IssueType(""), false}, {IssueType(""), false},
} }
@@ -430,6 +436,7 @@ func TestIssueTypeRequiredSections(t *testing.T) {
{TypeGate, 0, ""}, {TypeGate, 0, ""},
{TypeAgent, 0, ""}, {TypeAgent, 0, ""},
{TypeRole, 0, ""}, {TypeRole, 0, ""},
{TypeRig, 0, ""},
{TypeConvoy, 0, ""}, {TypeConvoy, 0, ""},
{TypeEvent, 0, ""}, {TypeEvent, 0, ""},
{TypeMergeRequest, 0, ""}, {TypeMergeRequest, 0, ""},
+7
View File
@@ -143,6 +143,10 @@ var (
Light: "#7fd962", // green - role definition Light: "#7fd962", // green - role definition
Dark: "#7fd962", Dark: "#7fd962",
} }
ColorTypeRig = lipgloss.AdaptiveColor{
Light: "#e6a756", // orange - rig identity (project container)
Dark: "#e6a756",
}
// === Issue ID Color === // === Issue ID Color ===
// IDs use standard text color - subtle, not attention-grabbing // IDs use standard text color - subtle, not attention-grabbing
@@ -192,6 +196,7 @@ var (
TypeChoreStyle = lipgloss.NewStyle().Foreground(ColorTypeChore) TypeChoreStyle = lipgloss.NewStyle().Foreground(ColorTypeChore)
TypeAgentStyle = lipgloss.NewStyle().Foreground(ColorTypeAgent) TypeAgentStyle = lipgloss.NewStyle().Foreground(ColorTypeAgent)
TypeRoleStyle = lipgloss.NewStyle().Foreground(ColorTypeRole) TypeRoleStyle = lipgloss.NewStyle().Foreground(ColorTypeRole)
TypeRigStyle = lipgloss.NewStyle().Foreground(ColorTypeRig)
) )
// CategoryStyle for section headers - bold with accent color // CategoryStyle for section headers - bold with accent color
@@ -343,6 +348,8 @@ func RenderType(issueType string) string {
return TypeAgentStyle.Render(issueType) return TypeAgentStyle.Render(issueType)
case "role": case "role":
return TypeRoleStyle.Render(issueType) return TypeRoleStyle.Render(issueType)
case "rig":
return TypeRigStyle.Render(issueType)
default: default:
return issueType return issueType
} }
+1
View File
@@ -94,6 +94,7 @@ func TestRenderTypeVariants(t *testing.T) {
{"chore", TypeChoreStyle.Render("chore")}, {"chore", TypeChoreStyle.Render("chore")},
{"agent", TypeAgentStyle.Render("agent")}, {"agent", TypeAgentStyle.Render("agent")},
{"role", TypeRoleStyle.Render("role")}, {"role", TypeRoleStyle.Render("role")},
{"rig", TypeRigStyle.Render("rig")},
{"custom", "custom"}, {"custom", "custom"},
} }
for _, tc := range cases { for _, tc := range cases {
+1
View File
@@ -128,6 +128,7 @@ func TestParseIssueType(t *testing.T) {
{"gate type", "gate", types.TypeGate, false, ""}, {"gate type", "gate", types.TypeGate, false, ""},
{"agent type", "agent", types.TypeAgent, false, ""}, {"agent type", "agent", types.TypeAgent, false, ""},
{"role type", "role", types.TypeRole, false, ""}, {"role type", "role", types.TypeRole, false, ""},
{"rig type", "rig", types.TypeRig, false, ""},
{"message type", "message", types.TypeMessage, false, ""}, {"message type", "message", types.TypeMessage, false, ""},
// Case sensitivity (function is case-sensitive) // Case sensitivity (function is case-sensitive)