fix(bundle): send command errors to stderr so --json stdout stays parseable (#3235)

The bundle command group's _fail() helper is documented as printing 'to stderr', and the module contract is 'human logs go to stderr/console' while --json 'emits machine-readable data on stdout'. But it called console.print(), and the shared console writes to STDOUT, so every bundle error (every command routes through _fail) landed on stdout -- corrupting the JSON stream that --json consumers parse.

Add a stderr-bound err_console to _console.py (its documented role as the single Console source) and use it in _fail. stdout now carries only the JSON payload.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Ali jawwad
2026-06-30 01:46:56 +05:00
committed by GitHub
parent 5a7d84311b
commit c5fb3dc86f
3 changed files with 23 additions and 2 deletions

View File

@@ -34,6 +34,10 @@ TAGLINE = "GitHub Spec Kit - Spec-Driven Development Toolkit"
console = Console(highlight=False)
# Stderr-bound console for error/diagnostic output, so human-facing messages
# never contaminate stdout (which carries machine-readable ``--json`` payloads).
err_console = Console(stderr=True, highlight=False)
class StepTracker:
"""Track and render hierarchical steps without emojis, similar to Claude Code tree output.
Supports live auto-refresh via an attached refresh callback.

View File

@@ -13,7 +13,7 @@ from pathlib import Path
import typer
from ..._console import console
from ..._console import console, err_console
from ...bundler import BundlerError
from ...bundler.lib.project import (
active_integration,
@@ -41,7 +41,9 @@ bundle_app.add_typer(bundle_catalog_app, name="catalog")
def _fail(message: str) -> None:
"""Print an actionable error to stderr and exit non-zero."""
console.print(f"[red]Error:[/red] {message}", style=None)
# Use the stderr console so the error never lands on stdout, which under
# ``--json`` carries the machine-readable payload and must stay parseable.
err_console.print(f"[red]Error:[/red] {message}", style=None)
raise typer.Exit(code=1)