✨ feat(kebab-cli): emit error.v1 ndjson on stderr in --json mode (fb-27)

Wraps the existing `Err(e)` arm with a `cli.json` branch:
- `--json`: stderr ndjson `error.v1` via wire_error_v1
- non-`--json`: legacy `error: <msg>` text path (unchanged)

exit_code() unchanged — RefusalSignal/NoHitSignal/DoctorUnhealthy
still drive 1/1/3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
th-kim0823
2026-05-07 12:28:41 +09:00
parent 4eb13c63ae
commit 912c7aa07d

View File

@@ -281,10 +281,18 @@ fn main() -> ExitCode {
// Refusals at exit code 1 print to stdout (already done by the // Refusals at exit code 1 print to stdout (already done by the
// caller); errors go to stderr. // caller); errors go to stderr.
if code != 1 { if code != 1 {
eprintln!("error: {e}"); if cli.json {
if cli.verbose { let v1 = error_classify::classify(&e, cli.verbose);
for cause in e.chain().skip(1) { let v = wire::wire_error_v1(&v1);
eprintln!(" caused by: {cause}"); eprintln!("{}", serde_json::to_string(&v).unwrap_or_else(|_| {
"{\"schema_version\":\"error.v1\",\"code\":\"generic\",\"message\":\"serialize failed\"}".to_string()
}));
} else {
eprintln!("error: {e}");
if cli.verbose {
for cause in e.chain().skip(1) {
eprintln!(" caused by: {cause}");
}
} }
} }
} }