Skip to content

Parse Codex's JSONL stdout for its real error object in the CLI-subprocess driver #5169

Description

@JSONbored

Context

Codex's stderr is typically just an uninformative startup banner, so the current ${command}_exit_${code}: ${stderr} error shape in packages/gittensory-engine/src/miner/cli-subprocess-driver.ts surfaces nothing useful when a codex-cli attempt fails. The real error object lives in Codex's JSONL stdout instead. src/selfhost/ai.ts already has a proven codexErrorFromStdout-style scanner for exactly this shape against the identical codex binary, so this is a port, not new design.

Dependencies

None — independently shippable. This is the Codex-side counterpart to the Claude JSON-envelope issue in this same batch (C16); the two touch the same file but different options.command branches (different CLI, different output stream) and can land in either order.

Requirements

  1. Port a codexErrorFromStdout-style scanner from src/selfhost/ai.ts into packages/gittensory-engine/src/miner/cli-subprocess-driver.ts.
  2. When options.command is codex, scan the already-captured stdout (JSONL lines) for the real error object on a non-zero exit — do not spawn any new process or re-invoke the CLI to get this data.
  3. Special-case the auth-failure scenario: when the scanned error indicates missing/invalid auth, resolve it to a clear "run codex auth" remediation string.
  4. Prefer the parsed stdout-derived error over the generic ${command}_exit_${code}: ${stderr} fallback whenever a real error object is found.
  5. Fall back to today's stderr-based shape unchanged when no parseable error object is found in stdout.
  6. Ensure the parsed/folded error value continues to pass through the existing redactSecrets call before being returned.
  7. Do not touch attempt/governor control-flow, retry logic, or any state outside the error-message construction itself.

Deliverables / Acceptance Criteria

  • codexErrorFromStdout-style scanner added to cli-subprocess-driver.ts (ported from src/selfhost/ai.ts)
  • Driver wiring: stdout scanned only when options.command === 'codex', real error object preferred over stderr fallback when found
  • Auth-failure case resolves to a "run codex auth" remediation string
  • Fallback to the existing raw stderr-based shape preserved when no parseable error object exists in stdout
  • Confirmed the folded error still passes through redactSecrets

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 scanner's success path (a real error object found in JSONL stdout, including the specific auth-failure sub-case) and failure paths (no error object present in stdout, malformed JSONL lines, non-codex 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 confirming the generic stderr-banner fallback still applies when stdout has nothing parseable.

Expected Outcome

An operator whose codex-cli-driven attempt fails will see the actual error Codex reported (including a precise "run codex auth" remediation for auth failures) instead of a useless stderr startup banner.

Links & Resources

  • packages/gittensory-engine/src/miner/cli-subprocess-driver.ts
  • src/selfhost/ai.ts (source of the codexErrorFromStdout-style scanner to port)
  • See C16 (the Claude-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

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions