Surface codex error envelopes instead of bare 'exit status 1' · Entire

Surface codex error envelopes instead of bare 'exit status 1'

When a codex review fails, codex writes the reason as a stdout JSON envelope (type error/turn.failed) and exits non-zero with empty stderr. The parser dropped these, leaving only 'exit status 1'. Capture the message (flat 'message' or nested 'error.message') and emit it as a RunError when the turn never completes, so the real cause shows in the dump and TUI detail.

Sessions

Changes

112 unmodified lines

// Codex reports failures as a stdout envelope carrying a message
// (type "error"/"turn.failed"/…) and exits non-zero with empty
// stderr. Capture the message so the reason surfaces instead of a
// bare "exit status 1". Only emitted below if the turn never
// completes, so a stray message on a successful run is ignored.
if msg := strings.TrimSpace(firstNonEmptyString(env.Error.Message, env.Message)); msg != "" {
    failureMsg = msg
}
type codexEnvelope struct {
    Type  string     `json:"type"`
    Item  codexItem  `json:"item"`
    Usage codexUsage `json:"usage"`
    Message string   `json:"message"`
    Error   codexErrorField `json:"error"`
}

type codexErrorField struct {
    Message string `json:"message"`
}