feat: --json structured output for task and review - #593
Conversation
task --wait --json, review --json, and adversarial-review --json now print
exactly one structured JSON object ({ kind, status, cwd, model, effort,
jobId, threadId, finalMessage, findings, touchedFiles, error }) derived
from the same execution result as the rendered markdown view. Default
(no --json) output is byte-for-byte unchanged.
- buildStructuredRunResult/extractReviewFindings live in lib/render.mjs
next to the markdown renderers; adversarial findings pass through the
review-output schema shape untouched
- errors under --json emit the same failed-shape JSON on stdout while
preserving the nonzero exit and stderr message
- task --background --json now reuses buildSingleJobSnapshot so job
references match the status/result --json shape
- task accepts --wait as the explicit foreground flag (conflicts with
--background)
- stop-review-gate-hook reads finalMessage (with rawOutput fallback)
- runtime tests cover task/review/adversarial --json happy and failure
paths; existing background --json tests updated to the snapshot shape
Co-Authored-By: Claude Fable 5 <[email protected]>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2e469c57eb
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| exitStatus: result.status, | ||
| threadId: result.threadId, | ||
| finalMessage: parsed.rawOutput, | ||
| findings: extractReviewFindings(parsed.parsed), | ||
| failureMessage: result.error?.message ?? result.stderr |
There was a problem hiding this comment.
Mark malformed adversarial JSON as failed
When adversarial-review --json gets a final message that is invalid JSON or is missing required review fields while the Codex turn itself exits 0, this structured result still reports status: "completed" and simply omits findings/error. The rendered path already treats the same parsed.parseError or validation failure as an unexpected review result, so JSON callers can currently misinterpret a malformed review as a clean completed review instead of retrying or surfacing the parse failure.
Useful? React with 👍 / 👎.
Adds
--jsontotask,review, andadversarial-review(status/result/cancel already support it). Emits one JSON object — kind, status, cwd, model, effort, jobId/threadId, finalMessage, findings (adversarial-review, passing through the shipped review-output schema), touchedFiles, error — derived from the same execution result as the rendered view, so orchestrators no longer parse prose. Default (no --json) output is byte-for-byte unchanged; backgroundtask --jsonreuses the status/result job-snapshot shape;taskgains an explicit--waitflag. 5 new runtime tests; suite 96/96.