fix(json): audit and standardize JSON output across commands (bd-au0.7)

Audit findings:
- All commands properly respect --json flag for success output
- Added outputJSONError() helper for consistent JSON error output
- Removed redundant local --json flag from stale.go (inherited from rootCmd)
- Fixed stale_test.go to check InheritedFlags() instead of local Flags()

JSON output patterns verified across:
- Query commands: ready, blocked, stale, count, stats, status
- Dep commands: dep add/remove/tree/cycles
- Label commands: label add/remove/list/list-all
- Comment commands: comments add/list
- Epic commands: epic status/close-eligible

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

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Steve Yegge
2025-12-23 20:42:57 -08:00
parent 70cfec1ecf
commit f2506088b6
3 changed files with 22 additions and 3 deletions

View File

@@ -33,6 +33,24 @@ func outputJSON(v interface{}) {
}
}
// outputJSONError outputs an error as JSON to stderr and exits with code 1.
// Use this when jsonOutput is true and an error occurs, to ensure consistent
// machine-readable error output. The error is formatted as:
//
// {"error": "error message", "code": "error_code"}
//
// The code parameter is optional (pass "" to omit).
func outputJSONError(err error, code string) {
errObj := map[string]string{"error": err.Error()}
if code != "" {
errObj["code"] = code
}
encoder := json.NewEncoder(os.Stderr)
encoder.SetIndent("", " ")
_ = encoder.Encode(errObj)
os.Exit(1)
}
// findJSONLPath finds the JSONL file path for the current database
// findJSONLPath discovers the JSONL file path for the current database and ensures
// the parent directory exists. Uses beads.FindJSONLPath() for discovery (checking

View File

@@ -110,6 +110,6 @@ func init() {
staleCmd.Flags().IntP("days", "d", 30, "Issues not updated in this many days")
staleCmd.Flags().StringP("status", "s", "", "Filter by status (open|in_progress|blocked|deferred)")
staleCmd.Flags().IntP("limit", "n", 50, "Maximum issues to show")
staleCmd.Flags().BoolVar(&jsonOutput, "json", false, "Output JSON format")
// Note: --json flag is defined as a persistent flag in main.go, not here
rootCmd.AddCommand(staleCmd)
}

View File

@@ -403,7 +403,8 @@ func TestStaleCommandInit(t *testing.T) {
if flags.Lookup("limit") == nil {
t.Error("staleCmd should have --limit flag")
}
if flags.Lookup("json") == nil {
t.Error("staleCmd should have --json flag")
// --json is inherited from rootCmd as a persistent flag
if staleCmd.InheritedFlags().Lookup("json") == nil {
t.Error("staleCmd should inherit --json flag from rootCmd")
}
}