fix(cli): keep stdout parseable in JSON mode - #76
Merged
Conversation
JSON is the default output for `query`, `goto` and `callers` -- `--humanize` is the opt-out -- but every failure path bypassed the formatter and printed a Rich line to stdout instead. `json.loads(subprocess.check_output(...))` worked while the symbol existed and raised JSONDecodeError the moment it did not. `_warn_if_ambiguous` broke it from the other side: its docstring says the note is "for JSON consumers", but it printed the note to stdout ahead of the document, wrapped mid-sentence by Rich. Diagnostics now go to a stderr console, empty results go through the formatter so stdout is still a document, and the ambiguity note is carried in the payload as `ambiguous` rather than only as a coloured line. Exit codes are unchanged: 0 and 1 still separate the cases.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
JSON is the default output for
query,gotoandcallers—--humanizeisthe opt-out — but every failure path bypassed the formatter and printed a Rich
line to stdout instead:
works while the symbol exists and raises
JSONDecodeErrorthe moment it doesnot.
_warn_if_ambiguousbreaks it from the other side — its docstring saysthe note is returned "for JSON consumers", but it also prints the note to
stdout, ahead of the document and wrapped mid-sentence by Rich:
Diagnostics now go to a stderr console, empty results go through the formatter
so stdout is still a document, and the ambiguity note is carried in the payload
as
ambiguousrather than only as a coloured line.Exit codes are unchanged — 0 and 1 still separate the cases.
Related Issue
Relates to #15 (
--format jsoneverywhere). That issue assumes the commandshave no JSON; three of them already default to it. This fixes the paths where
that default is broken. The remaining flag inconsistency —
refsandsymbol-impacttake--format table|jsonand default to table,statstakes
--json— is untouched here and worth its own PR.Type of Change
Checklist
ast-rag evaluate --all— needs live services; no query or scoring path touchedTesting
New
tests/test_json_output_is_parseable.pydrives the real Typer app throughCliRunnerwith the API mocked, so no Neo4j or Qdrant is needed, and assertsjson.loads(result.stdout)on every empty, not-found and ambiguous path.Without the fix, 6 of its 10 tests fail:
Two of the ten guard the other direction —
--humanizemust still produceRich text, and the human path must not go silent now that the "not found"
message moved off stdout.
Suite: 257 passed / 1 skipped / 1 xfailed before, 267 / 1 / 1 after (10 new).
Also checked outside
CliRunnerthaterr_consolereally writes to fd 2 in anormal process, since
CliRunnercaptures streams differently than a pipe.