feat: Complete command set standardization (bd-au0)

Epic bd-au0: Command Set Standardization & Flag Consistency

Completed all 10 child issues:

P0 tasks:
- Standardize --dry-run flag across all commands (bd-au0.1)
- Add label operations to bd update (bd-au0.2)
- Fix --title vs --title-contains redundancy (bd-au0.3)
- Standardize priority flag parsing (bd-au0.4)

P1 tasks:
- Add date/priority filters to bd search (bd-au0.5)
- Add comprehensive filters to bd export (bd-au0.6)
- Audit and standardize JSON output (bd-au0.7)

P2 tasks:
- Improve clean vs cleanup documentation (bd-au0.8)
- Document rarely-used commands (bd-au0.9)

P3 tasks:
- Add global verbosity flags --verbose/-v and --quiet/-q (bd-au0.10)

Key changes:
- export.go: Added filters (assignee, type, labels, priority, dates)
- main.go: Added --verbose/-v and --quiet/-q global flags
- debug.go: Added SetVerbose/SetQuiet and PrintNormal helpers
- clean.go/cleanup.go: Improved documentation with cross-references
- detect_pollution.go: Added use cases and warnings
- migrate_hash_ids.go: Marked as legacy command
- rename_prefix.go: Added use cases documentation

All success criteria met: flags standardized, feature parity achieved,
naming clarified, JSON output consistent.

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

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-11-23 20:33:25 -08:00
parent b5fb06c17d
commit 273a4d1cfc
8 changed files with 218 additions and 30 deletions

View File

@@ -14,6 +14,8 @@ import (
"github.com/steveyegge/beads/internal/debug"
"github.com/steveyegge/beads/internal/storage/sqlite"
"github.com/steveyegge/beads/internal/types"
"github.com/steveyegge/beads/internal/util"
"github.com/steveyegge/beads/internal/validation"
)
// countIssuesInJSONL counts the number of issues in a JSONL file
@@ -114,13 +116,30 @@ var exportCmd = &cobra.Command{
Long: `Export all issues to JSON Lines format (one JSON object per line).
Issues are sorted by ID for consistent diffs.
Output to stdout by default, or use -o flag for file output.`,
Output to stdout by default, or use -o flag for file output.
Examples:
bd export --status open -o open-issues.jsonl
bd export --type bug --priority-max 1
bd export --created-after 2025-01-01 --assignee alice`,
Run: func(cmd *cobra.Command, args []string) {
format, _ := cmd.Flags().GetString("format")
output, _ := cmd.Flags().GetString("output")
statusFilter, _ := cmd.Flags().GetString("status")
force, _ := cmd.Flags().GetBool("force")
// Additional filter flags
assignee, _ := cmd.Flags().GetString("assignee")
issueType, _ := cmd.Flags().GetString("type")
labels, _ := cmd.Flags().GetStringSlice("label")
labelsAny, _ := cmd.Flags().GetStringSlice("label-any")
priorityMinStr, _ := cmd.Flags().GetString("priority-min")
priorityMaxStr, _ := cmd.Flags().GetString("priority-max")
createdAfter, _ := cmd.Flags().GetString("created-after")
createdBefore, _ := cmd.Flags().GetString("created-before")
updatedAfter, _ := cmd.Flags().GetString("updated-after")
updatedBefore, _ := cmd.Flags().GetString("updated-before")
debug.Logf("Debug: export flags - output=%q, force=%v\n", output, force)
if format != "jsonl" {
@@ -155,12 +174,81 @@ Output to stdout by default, or use -o flag for file output.`,
defer func() { _ = store.Close() }()
}
// Normalize labels: trim, dedupe, remove empty
labels = util.NormalizeLabels(labels)
labelsAny = util.NormalizeLabels(labelsAny)
// Build filter
filter := types.IssueFilter{}
if statusFilter != "" {
status := types.Status(statusFilter)
filter.Status = &status
}
if assignee != "" {
filter.Assignee = &assignee
}
if issueType != "" {
t := types.IssueType(issueType)
filter.IssueType = &t
}
if len(labels) > 0 {
filter.Labels = labels
}
if len(labelsAny) > 0 {
filter.LabelsAny = labelsAny
}
// Priority ranges
if cmd.Flags().Changed("priority-min") {
priorityMin, err := validation.ValidatePriority(priorityMinStr)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --priority-min: %v\n", err)
os.Exit(1)
}
filter.PriorityMin = &priorityMin
}
if cmd.Flags().Changed("priority-max") {
priorityMax, err := validation.ValidatePriority(priorityMaxStr)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --priority-max: %v\n", err)
os.Exit(1)
}
filter.PriorityMax = &priorityMax
}
// Date ranges
if createdAfter != "" {
t, err := parseTimeFlag(createdAfter)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --created-after: %v\n", err)
os.Exit(1)
}
filter.CreatedAfter = &t
}
if createdBefore != "" {
t, err := parseTimeFlag(createdBefore)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --created-before: %v\n", err)
os.Exit(1)
}
filter.CreatedBefore = &t
}
if updatedAfter != "" {
t, err := parseTimeFlag(updatedAfter)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --updated-after: %v\n", err)
os.Exit(1)
}
filter.UpdatedAfter = &t
}
if updatedBefore != "" {
t, err := parseTimeFlag(updatedBefore)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing --updated-before: %v\n", err)
os.Exit(1)
}
filter.UpdatedBefore = &t
}
// Get all issues
ctx := rootCtx
@@ -421,5 +509,22 @@ func init() {
exportCmd.Flags().StringP("status", "s", "", "Filter by status")
exportCmd.Flags().Bool("force", false, "Force export even if database is empty")
exportCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output export statistics in JSON format")
// Filter flags
exportCmd.Flags().StringP("assignee", "a", "", "Filter by assignee")
exportCmd.Flags().StringP("type", "t", "", "Filter by type (bug, feature, task, epic, chore)")
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)")
// Priority filters
exportCmd.Flags().String("priority-min", "", "Filter by minimum priority (inclusive, 0-4 or P0-P4)")
exportCmd.Flags().String("priority-max", "", "Filter by maximum priority (inclusive, 0-4 or P0-P4)")
// Date filters
exportCmd.Flags().String("created-after", "", "Filter issues created after date (YYYY-MM-DD or RFC3339)")
exportCmd.Flags().String("created-before", "", "Filter issues created before date (YYYY-MM-DD or RFC3339)")
exportCmd.Flags().String("updated-after", "", "Filter issues updated after date (YYYY-MM-DD or RFC3339)")
exportCmd.Flags().String("updated-before", "", "Filter issues updated before date (YYYY-MM-DD or RFC3339)")
rootCmd.AddCommand(exportCmd)
}