fix(cli): output contract, terminal-safe text, char-safe truncation, cache symlinks

From the full-repo Codex audit:
- Provider and KSEI text reached the terminal raw, so an escape sequence
  in a news title or insight could clear or rewrite the screen. Every
  table cell, insight line, and graph label now has control characters
  and bidirectional overrides replaced.
- Table rendering sliced strings by byte (a description at 200, a URL at
  72, an earnings period), panicking when a multi-byte character such as
  "’" or "é" fell on the cut. Truncate by character.
- In JSON mode, argument errors were clap's plain text and warnings were
  plain lines ahead of the JSON error. Argument errors are now the usual
  JSON error (INVALIDINPUT, exit 2) when JSON output is selected, and
  diagnostics are JSON lines; --help and --version are unchanged.
- `config` commands ignored the output format; they follow it like every
  other command (JSON when piped or with -o json, text on a terminal).
- Ownership argument mistakes (--limit 0, --format, missing or
  conflicting import sources, --family, an empty graph root) returned
  PARSEERROR / exit 1; they are INVALIDINPUT / exit 2 as documented.
- `cache clear` followed symlinked directories and deleted files outside
  the cache; it now removes links without following them.

Output change, intentional: goldens regenerated for the JSON argument
error and the five config commands, which run with stdout piped.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01V3syn2fN2LNo5pvTSqc6eh
This commit is contained in:
hermes 2026-10-17 04:43:09 +00:00
commit ec2e870c6a
17 changed files with 410 additions and 231 deletions

View file

@ -162,7 +162,12 @@ CLI flags > environment variables > config file > defaults
## Error Strategy
- `IdxError` enum (thiserror) with structured error codes
- Table mode: human-readable error on stderr
- JSON and JSONL modes: `{"error": true, "code": "...", "message": "..."}` on stderr, stdout empty
- JSON and JSONL modes: `{"error": true, "code": "...", "message": "..."}` on stderr, stdout empty.
This includes argument errors (`INVALIDINPUT`, exit 2) when `-o`/`--output`,
`IDX_OUTPUT`, or auto mode with stdout not a terminal selects JSON; `--help`
and `--version` print normally.
- Untrusted text (provider strings, KSEI names) has control characters and
bidirectional overrides replaced before it reaches a terminal table.
- Exit codes by class: `0` success, `2` `INVALIDINPUT`/`CONFIGERROR` and clap usage
errors, `3` `SYMBOLNOTFOUND`/`NOMARKETDATA`/`CACHEMISS`, `4` `HTTP`/`RATELIMITED`/
`PROVIDERUNAVAILABLE`/`OFFLINE`/`AUTHERROR`, `5` `UNSUPPORTED`, `1` everything else
@ -182,4 +187,6 @@ CLI flags > environment variables > config file > defaults
- `stocks quote` and `stocks compare` require at least one symbol.
- Offline reads warn on stderr when serving cache entries past their TTL,
including the cache fetch timestamp. `--quiet` suppresses these warnings.
In JSON mode warnings and info are JSON lines,
`{"level": "warning", "message": "..."}`, so stderr stays parseable.
Staleness is not yet represented by a versioned JSON result envelope.