fix(review): surface codex's human error, not the raw JSON blob
Commit

When codex fails, it wraps the upstream API error as a JSON string in
its envelope message, so a failed reviewer row showed the whole blob
(e.g. codex: {"type":"error","status":400,"error":{"message": "The 'gpt-5.6-sol' model requires a newer version of Codex..."}}) —
the actual reason buried inside. cleanCodexFailureMessage unwraps it to
the .error.message text so the row reads "codex: The 'gpt-5.6-sol'
model requires a newer version of Codex...". Plain (non-JSON) messages
and JSON without a message pass through unchanged; unwrapping is bounded
against multiple nesting. Found while diagnosing a live codex failure
(model/CLI-version mismatch) that the raw blob made hard to read.
Co-Authored-By: Claude Fable 5 noreply@anthropic.com Entire-Checkpoint: 01KXH8Z4S6VJF3PFYBW4V44WEN