feat(list): Add type aliases for --type flag (gt-pvhsv)
Add convenience aliases for common type names: - mr → merge-request - feat → feature - mol → molecule Applied to bd list, bd ready, and bd export commands. Case-insensitive matching (MR, Mr, mr all work). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
1794
.beads/issues.jsonl
1794
.beads/issues.jsonl
File diff suppressed because one or more lines are too long
@@ -140,6 +140,7 @@ Examples:
|
|||||||
// Additional filter flags
|
// Additional filter flags
|
||||||
assignee, _ := cmd.Flags().GetString("assignee")
|
assignee, _ := cmd.Flags().GetString("assignee")
|
||||||
issueType, _ := cmd.Flags().GetString("type")
|
issueType, _ := cmd.Flags().GetString("type")
|
||||||
|
issueType = util.NormalizeIssueType(issueType) // Expand aliases (mr→merge-request, etc.)
|
||||||
labels, _ := cmd.Flags().GetStringSlice("label")
|
labels, _ := cmd.Flags().GetStringSlice("label")
|
||||||
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
|
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
|
||||||
priorityMinStr, _ := cmd.Flags().GetString("priority-min")
|
priorityMinStr, _ := cmd.Flags().GetString("priority-min")
|
||||||
@@ -582,7 +583,7 @@ func init() {
|
|||||||
// Filter flags
|
// Filter flags
|
||||||
registerPriorityFlag(exportCmd, "")
|
registerPriorityFlag(exportCmd, "")
|
||||||
exportCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
|
exportCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
|
||||||
exportCmd.Flags().StringP("type", "t", "", "Filter by type (bug, feature, task, epic, chore, merge-request, molecule, gate)")
|
exportCmd.Flags().StringP("type", "t", "", "Filter by type (bug, feature, task, epic, chore, merge-request, molecule, gate). Aliases: mr→merge-request, feat→feature, mol→molecule")
|
||||||
exportCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL)")
|
exportCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL)")
|
||||||
exportCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE)")
|
exportCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE)")
|
||||||
|
|
||||||
|
|||||||
@@ -375,6 +375,7 @@ var listCmd = &cobra.Command{
|
|||||||
status, _ := cmd.Flags().GetString("status")
|
status, _ := cmd.Flags().GetString("status")
|
||||||
assignee, _ := cmd.Flags().GetString("assignee")
|
assignee, _ := cmd.Flags().GetString("assignee")
|
||||||
issueType, _ := cmd.Flags().GetString("type")
|
issueType, _ := cmd.Flags().GetString("type")
|
||||||
|
issueType = util.NormalizeIssueType(issueType) // Expand aliases (mr→merge-request, etc.)
|
||||||
limit, _ := cmd.Flags().GetInt("limit")
|
limit, _ := cmd.Flags().GetInt("limit")
|
||||||
allFlag, _ := cmd.Flags().GetBool("all")
|
allFlag, _ := cmd.Flags().GetBool("all")
|
||||||
formatStr, _ := cmd.Flags().GetString("format")
|
formatStr, _ := cmd.Flags().GetString("format")
|
||||||
@@ -936,7 +937,7 @@ func init() {
|
|||||||
listCmd.Flags().StringP("status", "s", "", "Filter by status (open, in_progress, blocked, deferred, closed)")
|
listCmd.Flags().StringP("status", "s", "", "Filter by status (open, in_progress, blocked, deferred, closed)")
|
||||||
registerPriorityFlag(listCmd, "")
|
registerPriorityFlag(listCmd, "")
|
||||||
listCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
|
listCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
|
||||||
listCmd.Flags().StringP("type", "t", "", "Filter by type (bug, feature, task, epic, chore, merge-request, molecule, gate, convoy)")
|
listCmd.Flags().StringP("type", "t", "", "Filter by type (bug, feature, task, epic, chore, merge-request, molecule, gate, convoy). Aliases: mr→merge-request, feat→feature, mol→molecule")
|
||||||
listCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL). Can combine with --label-any")
|
listCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL). Can combine with --label-any")
|
||||||
listCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE). Can combine with --label")
|
listCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE). Can combine with --label")
|
||||||
listCmd.Flags().String("title", "", "Filter by title text (case-insensitive substring match)")
|
listCmd.Flags().String("title", "", "Filter by title text (case-insensitive substring match)")
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ This is useful for agents executing molecules to see which steps can run next.`,
|
|||||||
labels, _ := cmd.Flags().GetStringSlice("label")
|
labels, _ := cmd.Flags().GetStringSlice("label")
|
||||||
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
|
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
|
||||||
issueType, _ := cmd.Flags().GetString("type")
|
issueType, _ := cmd.Flags().GetString("type")
|
||||||
|
issueType = util.NormalizeIssueType(issueType) // Expand aliases (mr→merge-request, etc.)
|
||||||
parentID, _ := cmd.Flags().GetString("parent")
|
parentID, _ := cmd.Flags().GetString("parent")
|
||||||
molTypeStr, _ := cmd.Flags().GetString("mol-type")
|
molTypeStr, _ := cmd.Flags().GetString("mol-type")
|
||||||
prettyFormat, _ := cmd.Flags().GetBool("pretty")
|
prettyFormat, _ := cmd.Flags().GetBool("pretty")
|
||||||
@@ -441,7 +442,7 @@ func init() {
|
|||||||
readyCmd.Flags().StringP("sort", "s", "hybrid", "Sort policy: hybrid (default), priority, oldest")
|
readyCmd.Flags().StringP("sort", "s", "hybrid", "Sort policy: hybrid (default), priority, oldest")
|
||||||
readyCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL). Can combine with --label-any")
|
readyCmd.Flags().StringSliceP("label", "l", []string{}, "Filter by labels (AND: must have ALL). Can combine with --label-any")
|
||||||
readyCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE). Can combine with --label")
|
readyCmd.Flags().StringSlice("label-any", []string{}, "Filter by labels (OR: must have AT LEAST ONE). Can combine with --label")
|
||||||
readyCmd.Flags().StringP("type", "t", "", "Filter by issue type (task, bug, feature, epic, merge-request)")
|
readyCmd.Flags().StringP("type", "t", "", "Filter by issue type (task, bug, feature, epic, merge-request). Aliases: mr→merge-request, feat→feature, mol→molecule")
|
||||||
readyCmd.Flags().String("mol", "", "Filter to steps within a specific molecule")
|
readyCmd.Flags().String("mol", "", "Filter to steps within a specific molecule")
|
||||||
readyCmd.Flags().String("parent", "", "Filter to descendants of this bead/epic")
|
readyCmd.Flags().String("parent", "", "Filter to descendants of this bead/epic")
|
||||||
readyCmd.Flags().String("mol-type", "", "Filter by molecule type: swarm, patrol, or work")
|
readyCmd.Flags().String("mol-type", "", "Filter by molecule type: swarm, patrol, or work")
|
||||||
|
|||||||
@@ -2,6 +2,23 @@ package util
|
|||||||
|
|
||||||
import "strings"
|
import "strings"
|
||||||
|
|
||||||
|
// issueTypeAliases maps shorthand type names to canonical types
|
||||||
|
var issueTypeAliases = map[string]string{
|
||||||
|
"mr": "merge-request",
|
||||||
|
"feat": "feature",
|
||||||
|
"mol": "molecule",
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalizeIssueType expands type aliases to their canonical forms.
|
||||||
|
// For example: "mr" -> "merge-request", "feat" -> "feature", "mol" -> "molecule"
|
||||||
|
// Returns the input unchanged if it's not an alias.
|
||||||
|
func NormalizeIssueType(t string) string {
|
||||||
|
if canonical, ok := issueTypeAliases[strings.ToLower(t)]; ok {
|
||||||
|
return canonical
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
// NormalizeLabels trims whitespace, removes empty strings, and deduplicates labels
|
// NormalizeLabels trims whitespace, removes empty strings, and deduplicates labels
|
||||||
// while preserving order.
|
// while preserving order.
|
||||||
func NormalizeLabels(ss []string) []string {
|
func NormalizeLabels(ss []string) []string {
|
||||||
|
|||||||
@@ -96,9 +96,82 @@ func TestNormalizeLabels(t *testing.T) {
|
|||||||
func TestNormalizeLabels_PreservesCapacity(t *testing.T) {
|
func TestNormalizeLabels_PreservesCapacity(t *testing.T) {
|
||||||
input := []string{"bug", "critical", "frontend"}
|
input := []string{"bug", "critical", "frontend"}
|
||||||
result := NormalizeLabels(input)
|
result := NormalizeLabels(input)
|
||||||
|
|
||||||
// Result should have reasonable capacity (not excessive allocation)
|
// Result should have reasonable capacity (not excessive allocation)
|
||||||
if cap(result) > len(input)*2 {
|
if cap(result) > len(input)*2 {
|
||||||
t.Errorf("NormalizeLabels capacity too large: got %d, input len %d", cap(result), len(input))
|
t.Errorf("NormalizeLabels capacity too large: got %d, input len %d", cap(result), len(input))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNormalizeIssueType(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
input string
|
||||||
|
expected string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "mr alias",
|
||||||
|
input: "mr",
|
||||||
|
expected: "merge-request",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "MR uppercase",
|
||||||
|
input: "MR",
|
||||||
|
expected: "merge-request",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "feat alias",
|
||||||
|
input: "feat",
|
||||||
|
expected: "feature",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "FEAT uppercase",
|
||||||
|
input: "FEAT",
|
||||||
|
expected: "feature",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "mol alias",
|
||||||
|
input: "mol",
|
||||||
|
expected: "molecule",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Mol mixed case",
|
||||||
|
input: "Mol",
|
||||||
|
expected: "molecule",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "non-alias unchanged",
|
||||||
|
input: "bug",
|
||||||
|
expected: "bug",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "full name unchanged",
|
||||||
|
input: "merge-request",
|
||||||
|
expected: "merge-request",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "empty string",
|
||||||
|
input: "",
|
||||||
|
expected: "",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "feature unchanged",
|
||||||
|
input: "feature",
|
||||||
|
expected: "feature",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "task unchanged",
|
||||||
|
input: "task",
|
||||||
|
expected: "task",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
result := NormalizeIssueType(tt.input)
|
||||||
|
if result != tt.expected {
|
||||||
|
t.Errorf("NormalizeIssueType(%q) = %q, want %q", tt.input, result, tt.expected)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user