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
- Port a
codexErrorFromStdout-style scanner from src/selfhost/ai.ts into packages/gittensory-engine/src/miner/cli-subprocess-driver.ts.
- 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.
- Special-case the auth-failure scenario: when the scanned error indicates missing/invalid auth, resolve it to a clear "run
codex auth" remediation string.
- Prefer the parsed stdout-derived error over the generic
${command}_exit_${code}: ${stderr} fallback whenever a real error object is found.
- Fall back to today's stderr-based shape unchanged when no parseable error object is found in stdout.
- Ensure the parsed/folded error value continues to pass through the existing
redactSecrets call before being returned.
- Do not touch attempt/governor control-flow, retry logic, or any state outside the error-message construction itself.
Deliverables / Acceptance Criteria
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
Context
Codex's stderr is typically just an uninformative startup banner, so the current
${command}_exit_${code}: ${stderr}error shape inpackages/gittensory-engine/src/miner/cli-subprocess-driver.tssurfaces nothing useful when acodex-cliattempt fails. The real error object lives in Codex's JSONL stdout instead.src/selfhost/ai.tsalready has a provencodexErrorFromStdout-style scanner for exactly this shape against the identicalcodexbinary, 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.commandbranches (different CLI, different output stream) and can land in either order.Requirements
codexErrorFromStdout-style scanner fromsrc/selfhost/ai.tsintopackages/gittensory-engine/src/miner/cli-subprocess-driver.ts.options.commandiscodex, 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.codex auth" remediation string.${command}_exit_${code}: ${stderr}fallback whenever a real error object is found.redactSecretscall before being returned.Deliverables / Acceptance Criteria
codexErrorFromStdout-style scanner added tocli-subprocess-driver.ts(ported fromsrc/selfhost/ai.ts)options.command === 'codex', real error object preferred over stderr fallback when foundcodex auth" remediation stringredactSecretsTest 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-
codexcommand 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 "runcodex auth" remediation for auth failures) instead of a useless stderr startup banner.Links & Resources
packages/gittensory-engine/src/miner/cli-subprocess-driver.tssrc/selfhost/ai.ts(source of thecodexErrorFromStdout-style scanner to port)