feat(types): add "enhancement" as alias for "feature" type

Support --type enhancement as an alias for --type feature when creating
issues. The normalization happens before validation to ensure consistency
across all code paths.

Closes gt-hzanoe

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
gastown/crew/george
2026-01-16 15:44:33 -08:00
committed by Steve Yegge
parent 99d6592207
commit 9ecdc00664
6 changed files with 22 additions and 8 deletions

View File

@@ -197,7 +197,7 @@ var createCmd = &cobra.Command{
Notes: notes,
Status: types.StatusOpen,
Priority: priority,
IssueType: types.IssueType(issueType),
IssueType: types.IssueType(issueType).Normalize(),
Assignee: assignee,
ExternalRef: externalRefPtr,
Ephemeral: wisp,
@@ -520,7 +520,7 @@ var createCmd = &cobra.Command{
Notes: notes,
Status: types.StatusOpen,
Priority: priority,
IssueType: types.IssueType(issueType),
IssueType: types.IssueType(issueType).Normalize(),
Assignee: assignee,
ExternalRef: externalRefPtr,
EstimatedMinutes: estimatedMinutes,
@@ -729,7 +729,7 @@ func init() {
createCmd.Flags().Bool("silent", false, "Output only the issue ID (for scripting)")
createCmd.Flags().Bool("dry-run", false, "Preview what would be created without actually creating")
registerPriorityFlag(createCmd, "2")
createCmd.Flags().StringP("type", "t", "task", "Issue type (bug|feature|task|epic|chore|merge-request|molecule|gate|agent|role|rig|convoy|event)")
createCmd.Flags().StringP("type", "t", "task", "Issue type (bug|feature|task|epic|chore|merge-request|molecule|gate|agent|role|rig|convoy|event); enhancement is alias for feature")
registerCommonIssueFlags(createCmd)
createCmd.Flags().StringSliceP("labels", "l", []string{}, "Labels (comma-separated)")
createCmd.Flags().StringSlice("label", []string{}, "Alias for --labels")
@@ -854,7 +854,7 @@ func createInRig(cmd *cobra.Command, rigName, title, description, issueType stri
Notes: notes,
Status: types.StatusOpen,
Priority: priority,
IssueType: types.IssueType(issueType),
IssueType: types.IssueType(issueType).Normalize(),
Assignee: assignee,
ExternalRef: externalRefPtr,
Ephemeral: wisp,

View File

@@ -108,7 +108,7 @@ func CreateIssueFromFormValues(ctx context.Context, s storage.Storage, fv *creat
AcceptanceCriteria: fv.AcceptanceCriteria,
Status: types.StatusOpen,
Priority: fv.Priority,
IssueType: types.IssueType(fv.IssueType),
IssueType: types.IssueType(fv.IssueType).Normalize(),
Assignee: fv.Assignee,
ExternalRef: externalRefPtr,
CreatedBy: getActorWithGit(), // GH#748: track who created the issue

View File

@@ -66,7 +66,7 @@ Example:
Title: title,
Status: types.StatusOpen,
Priority: priority,
IssueType: types.IssueType(issueType),
IssueType: types.IssueType(issueType).Normalize(),
}
ctx := rootCtx

View File

@@ -40,7 +40,8 @@ func validateStatusWithCustom(value interface{}, customStatuses []string) error
// validateIssueType validates an issue type value
func validateIssueType(value interface{}) error {
if issueType, ok := value.(string); ok {
if !types.IssueType(issueType).IsValid() {
// Normalize first to support aliases like "enhancement" -> "feature"
if !types.IssueType(issueType).Normalize().IsValid() {
return fmt.Errorf("invalid issue type: %s", issueType)
}
}

View File

@@ -528,6 +528,17 @@ func (t IssueType) IsValidWithCustom(customTypes []string) bool {
return false
}
// Normalize maps issue type aliases to their canonical form.
// For example, "enhancement" -> "feature".
func (t IssueType) Normalize() IssueType {
switch t {
case "enhancement":
return TypeFeature
default:
return t
}
}
// RequiredSection describes a recommended section for an issue type.
// Used by bd lint and bd create --validate for template validation.
type RequiredSection struct {

View File

@@ -28,8 +28,10 @@ func ParsePriority(content string) int {
// ParseIssueType extracts and validates an issue type from content.
// Returns the validated type or error if invalid.
// Supports type aliases like "enhancement" -> "feature".
func ParseIssueType(content string) (types.IssueType, error) {
issueType := types.IssueType(strings.TrimSpace(content))
// Normalize to support aliases like "enhancement" -> "feature"
issueType := types.IssueType(strings.TrimSpace(content)).Normalize()
// Use the canonical IsValid() from types package
if !issueType.IsValid() {