Skip to content

feat(miner-hands): parse Codex's JSONL stdout for its real error object in the CLI-subprocess driver (#5169) - #5262

Merged
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
joaovictor91123:feat/miner-codex-jsonl-error-5169
Jul 12, 2026
Merged

feat(miner-hands): parse Codex's JSONL stdout for its real error object in the CLI-subprocess driver (#5169)#5262
loopover-orb[bot] merged 1 commit into
JSONbored:mainfrom
joaovictor91123:feat/miner-codex-jsonl-error-5169

Conversation

@joaovictor91123

Copy link
Copy Markdown
Contributor

Summary

  • Codex's stderr is typically just an uninformative "Reading prompt from stdin..." startup banner, so the current ${command}_exit_${code}: ${stderr} error shape surfaces nothing useful when a codex-cli attempt fails. The real error object lives in Codex's JSONL stdout instead.
  • Ports a codexErrorFromStdout-style scanner from src/selfhost/ai.ts into packages/gittensory-engine/src/miner/cli-subprocess-driver.ts (redeclared, not imported -- this package stays standalone per the file's own header comment). Scans stdout lines in reverse for a structured error object (error/message/msg/error.message shapes) on a non-zero exit from codex -- no new process spawned, purely reading already-captured stdout.
  • Auth-failure special case (ported from the same file): when no structured detail is found in stdout AND stderr is exactly the "Reading prompt from stdin..." banner, that specific combination means auth.json was present at boot but is now missing or expired. The driver resolves this to a distinct codex_no_auth: ... run \codex auth` to authenticate` remediation instead of a useless exit-code string.
  • Any other case (no structured detail, and stderr isn't exactly that banner) falls back to today's raw stderr-based shape, completely unchanged.
  • The folded error passes through the same knownSecrets-aware redactSecrets call every other error path in this driver already uses.
  • No attempt/governor control-flow, retry logic, or state outside the error-message construction is touched.

Test plan

  • npx vitest run test/unit/cli-subprocess-driver.test.ts -- 25/25 passing, including the new describe("Codex JSONL stdout error diagnostics (#5169)", ...) block: real error object preferred over generic error, reverse-scan picks the last detail-bearing line while skipping malformed/non-JSON/blank lines, nested error.message shape, falsy (empty-string) error field falls through to the next field, the auth-failure remediation case, the regression fallback when nothing is parseable and stderr isn't the exact banner, non-codex command never scans stdout, and an invariant that a folded JSONL-detail error is never left unredacted.
  • npx vitest run test/contract/coding-agent-driver-parity.test.ts -- 18/18 passing (unaffected).
  • npx vitest run test/unit/coding-agent-miner.test.ts -- 57/57 passing (unaffected).
  • npm --workspace @jsonbored/gittensory-engine run build -- clean.
  • npm run typecheck -- clean.
  • Isolated coverage via COVERAGE_NO_THRESHOLDS=1 npx vitest run test/unit/cli-subprocess-driver.test.ts --coverage --coverage.include="packages/gittensory-engine/src/miner/cli-subprocess-driver.ts" -- 100% statements/branches/functions/lines.
  • npm run docs:drift-check -- clean.
  • Did not run the full unsharded npm run test:coverage locally (shared/resource-contended machine); relying on CI's Codecov patch-coverage gate plus the isolated-coverage check above.

Fixes #5169.

…ct in the CLI-subprocess driver (JSONbored#5169)

Ports src/selfhost/ai.ts's codexErrorFromStdout scanner (and its
adjacent auth-failure special case) into cli-subprocess-driver.ts
(redeclared, not imported, per this file's no-src-import convention).

Codex's stderr is typically just an uninformative "Reading prompt from
stdin..." startup banner; the real error lives in its JSONL stdout. On a
non-zero exit from codex, the driver now scans stdout in reverse for a
structured error object and prefers it over the generic exit-code/stderr
error when found. When no structured detail is found AND stderr is
exactly the stdin-reading banner, that specific combination means
auth.json was present at boot but is now missing or expired -- the
driver resolves this to a distinct, actionable "run `codex auth`"
remediation instead of a useless exit-code string. Any other case
(no detail, different stderr) falls back to today's raw stderr-based
shape unchanged. The folded error passes through the same
knownSecrets-aware redactSecrets call every other error path here uses.
@superagent-security

Copy link
Copy Markdown
Contributor

Superagent didn't find any vulnerabilities or security issues in this PR.

@codecov

codecov Bot commented Jul 12, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 94.36%. Comparing base (738c8ca) to head (ab083c3).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #5262   +/-   ##
=======================================
  Coverage   94.36%   94.36%           
=======================================
  Files         474      474           
  Lines       40096    40114   +18     
  Branches    14620    14627    +7     
=======================================
+ Hits        37836    37854   +18     
  Misses       1585     1585           
  Partials      675      675           
Flag Coverage Δ
shard-1 46.42% <100.00%> (+0.02%) ⬆️
shard-2 34.72% <0.00%> (-0.02%) ⬇️
shard-3 32.09% <0.00%> (-0.02%) ⬇️
shard-4 32.02% <0.00%> (-0.02%) ⬇️
shard-5 33.69% <0.00%> (-0.02%) ⬇️
shard-6 44.75% <0.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...ttensory-engine/src/miner/cli-subprocess-driver.ts 100.00% <100.00%> (ø)
🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@loopover-orb loopover-orb Bot added the gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier. label Jul 12, 2026
@loopover-orb

loopover-orb Bot commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Tip

🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩

✅ Gittensory review result - approve/merge recommended

Review updated: 2026-07-12 12:28:36 UTC

2 files · 2 AI reviewers · no blockers · readiness 100/100 · CI green · clean

✅ Suggested Action - Approve/Merge

  • safe to merge

Review summary
This ports codexErrorFromStdout from src/selfhost/ai.ts into the standalone gittensory-engine driver, scanning codex's JSONL stdout in reverse for a structured error and preferring it over the uninformative stderr banner, with a distinct auth-failure remediation when stdout has no detail and stderr is exactly the stdin-reading banner. The logic correctly gates on `options.command === "codex"` so it doesn't affect claude, falls through unchanged to the existing stderr-based error otherwise, and the JSONL detail is redacted at the call site consistent with every other error path in this file. Tests cover the reverse-scan priority, malformed-line skipping, falsy-field fallthrough, nested error.message, the auth remediation, the non-auth-banner regression case, command isolation, and secret redaction — all mapped to real, reachable branches in the diff.

Nits — 5 non-blocking
  • `codexErrorFromStdout` at cli-subprocess-driver.ts:111 is a near-verbatim duplicate of `src/selfhost/ai.ts`'s function; the file header already documents the standalone-package rationale for redeclaring rather than importing, so this is acceptable but worth a comment cross-check if the two ever drift.
  • The `"Reading prompt from stdin..."` literal is duplicated as a magic string between the error-check and the comment; consider hoisting it to a named constant (e.g. `CODEX_STDIN_BANNER`) shared by both.
  • cli-subprocess-driver.ts:203-232 — extract the `Reading prompt from stdin...` string into a module-level constant to avoid silent drift if codex's banner text changes.
  • nit: packages/gittensory-engine/src/miner/cli-subprocess-driver.ts:123 accepts any top-level `message` or `msg` field from the last JSONL line, so a future non-error Codex event with a human message after the actual error could produce a misleading diagnostic; either constrain this to known error event shapes or add a comment explaining why these fields are error-only on failed Codex exits.
  • nit: packages/gittensory-engine/src/miner/cli-subprocess-driver.ts:204 hard-codes the stdin banner string inline; extracting it to a named constant would make the exact-match auth heuristic easier to audit if Codex changes the banner text.
Signal Result Evidence
Code review ✅ No blockers 2 reviewers, synthesized
Linked issue ✅ Linked #5169
Related work ✅ No active overlap found No same-issue or scoped active PR overlap found.
Change scope ✅ 20/20 Low review scope from cached public metadata (1 linked issue).
Validation posture ✅ 25/25 PR body includes validation/test evidence.
Contributor workload ✅ 10/10 Author activity: 117 registered-repo PR(s), 68 merged, 11 issue(s).
Contributor context ✅ Confirmed Gittensor contributor joaovictor91123; Gittensor profile; 117 PR(s), 11 issue(s).
Gate result ✅ Passing No configured blocker found.
Improvement ✅ Minor risk: clean · value: minor — Code changes are accompanied by test evidence. LLM value judgment: moderate — The diff closes a concrete diagnostic gap (uninformative codex errors) with narrowly-scoped, well-tested logic that mirrors an already-validated pattern (#5168) in the same file.
Linked issue satisfaction

Addressed
The PR ports a codexErrorFromStdout-style scanner into cli-subprocess-driver.ts, wires it for options.command === 'codex' with the JSONL detail preferred over the generic stderr fallback, special-cases the stdin-banner-only scenario into a 'run codex auth' remediation, preserves the unchanged stderr fallback otherwise, and routes both paths through redactSecrets, matching all stated requirements.

Review context
  • Author: joaovictor91123
  • Role context: outside_contributor
  • Public audience mode: oss maintainer
  • Lane context: Repository is configured for direct PR review.
  • Public profile languages: not available
  • Official Gittensor activity: 117 PR(s), 11 issue(s).
  • PR-specific overlap: none found.
Contributor next steps
  • Keep the PR focused and include validation evidence before maintainer review.
Signal definitions
  • Related work = same linked issue, overlapping active PRs, or title/path similarity.
  • Change scope = cached public metadata such as size labels, draft state, and review-burden hints.
  • Validation posture = whether the PR provides enough public validation/test evidence for maintainer review.
  • Contributor workload = public contributor activity and cleanup pressure, not a repo-wide quality failure.
  • Contributor context = public GitHub/Gittensor identity context; non-Gittensor status is not a blocker.
[BETA] Chat with Gittensory

Ask Gittensory a question about this PR directly in a comment — grounded only in the same cached, public-safe facts shown above, never a new claim.

  • @gittensory ask &lt;question&gt; answers contribution-quality Q&A with source citations and freshness.
  • @gittensory chat &lt;question&gt; answers in natural prose from cached decision-pack facts via local inference (maintainer/collaborator; read-only).
  • A plain-language @gittensory mention with a real question is routed to the closest matching read-only command automatically -- no exact syntax required.

Full command reference: https://gittensory.aethereal.dev/docs/gittensory-commands

🟩 Safe / merged · 🟦 Advisory · 🟨 Held for review · 🟥 Blocked / closed


💰 Earn for open-source contributions like this. Gittensor lets GitHub contributors earn for the work they already do — register to start earning →.

Checked by Gittensory, a quiet PR intelligence layer for OSS maintainers.

  • Re-run Gittensory review

@loopover-orb loopover-orb Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gittensory approves — the gate is satisfied and CI is green.

@loopover-orb
loopover-orb Bot merged commit 183e655 into JSONbored:main Jul 12, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gittensor:feature Gittensor-scored feature linked to a feature issue — scores a 0.25x multiplier.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

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

1 participant