Skip to content

Parse Claude Code's JSON error envelope into actionable diagnostics in the CLI-subprocess driver #5168

Description

@JSONbored

Context

Today, when createCliSubprocessCodingAgentDriver in packages/gittensory-engine/src/miner/cli-subprocess-driver.ts sees a non-zero exit from the claude CLI, the only error shape it produces is ${command}_exit_${code}: ${stderr.slice(0,500)}. It never inspects Claude Code's own structured JSON error envelope ({is_error, api_error_status}) that the CLI emits on some non-zero exits. src/selfhost/ai.ts already has a proven claudeErrorStatus-style parser for this exact envelope shape against the identical claude binary, so this is a port, not new design.

Dependencies

None — independently shippable. This is the Claude-side counterpart to the Codex JSONL-parsing issue in this same batch (C17); the two touch the same file but different options.command branches and can land in either order.

Requirements

  1. Port a claudeErrorStatus-style parser from src/selfhost/ai.ts into packages/gittensory-engine/src/miner/cli-subprocess-driver.ts.
  2. When options.command is claude, attempt to parse the captured stdout for the {is_error, api_error_status} JSON envelope on a non-zero exit.
  3. When the envelope is present and parseable, fold a precise status (e.g. claude_code_no_oauth_token) into the driver's returned error instead of the generic exit-code string.
  4. When the envelope is absent or fails to parse, fall back to today's ${command}_exit_${code}: ${stderr.slice(0,500)} behavior unchanged.
  5. Ensure the parsed/folded error value continues to pass through the existing redactSecrets call before being returned.
  6. Do not touch attempt/governor control-flow, retry logic, or any state outside the error-message construction itself — this issue changes only what the driver reports, not what happens next.

Deliverables / Acceptance Criteria

  • claudeErrorStatus-style parser added to cli-subprocess-driver.ts (ported from src/selfhost/ai.ts)
  • Driver wiring: envelope parsed only when options.command === 'claude', folded into the returned error when found
  • Fallback to the existing raw stderr-slice shape preserved when no envelope is found
  • Confirmed the folded error still passes through redactSecrets
  • No changes to attempt/governor control-flow files

Test Coverage Requirements

This PR must ship with full test coverage for every changed line and branch — the repo's Codecov patch gate requires 99%+ coverage and the house standard is to aim for 100%, including both sides of every conditional/nullish-coalescing branch introduced. Add: (1) unit tests covering the new parser's success path (valid {is_error, api_error_status} envelope folded into a precise status) and failure paths (envelope absent, envelope malformed/unparseable, non-claude command falls through untouched), (2) an invariant test asserting the driver never returns an error value containing an unredacted secret-shaped pattern regardless of which branch produced it, and (3) a regression test reproducing the current uninformative-error behavior to confirm it's specifically the claude_code_no_oauth_token-style case that improves, not a general behavior change.

Expected Outcome

An operator whose claude-cli-driven attempt fails will see a precise, actionable status (e.g. "no OAuth token") instead of a raw truncated stderr slice, letting them fix the actual problem without digging into logs.

Links & Resources

  • packages/gittensory-engine/src/miner/cli-subprocess-driver.ts
  • src/selfhost/ai.ts (source of the claudeErrorStatus-style parser to port)
  • See Make CLI error paths respect --json #4836 (a distinct, separate change to --json output formatting, not error-message content)
  • See C17 (the Codex-side counterpart in this same batch)
  • Theme: Claude/Codex self-host operational parity

Metadata

Metadata

Assignees

No one assigned

    Labels

    gittensor:featureGittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.help wantedExtra attention is needed

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions