What comes back
Prose by default: a review is read more often than it is parsed — by the
person who wrote it and by the agent it is for, which reads prose as readily
as anything else and pays fewer tokens for it. --format json prints the
same review as structure, for the program that parses it:
{
"decision": "request_changes",
"summary": "The rename parser is the only part I'd hold up.",
"vcs": "jj",
"revset": "trunk()..@",
"repo_root": "/home/you/projects/slop-review",
"comments": [
{
"id": "c1",
"commits": [
{
"id": "rlrmnkssuyyv",
"short_id": "6b2964ad",
"subject": "Read commits without binding to a VCS"
}
],
"location": {
"path": "crates/core/src/vcs.rs",
"lines": {
"side": "new",
"start": 287,
"end": 291,
"quoted": " match (spec.find('{'), spec.find('}')) {"
}
},
"body": "This assumes the brace form. jj also emits a bare `a => b`."
},
{
"id": "c2",
"commits": [{ "id": "kwpoztqyzznm", "short_id": "9c1f0b32", "subject": "Add .envrc" }],
"location": null,
"body": "Fix this up into the commit that added the file."
}
]
}
Every field is there so the agent can act without going back to the VCS: a
commit carries its subject, not just an ID, and quoted echoes the reviewed
source so the annotation can be found without re-reading a diff it never
received. side matters — new line numbers are valid in the file as of the
last commit in commits, old ones belong to before the first, so quoted
is the only reliable anchor for those.
commits has more than one entry when the reviewer was looking at an
accumulated range; the comment is then about the combined change, and line
numbers are relative to the parent of the first commit.
The two nullable anchors say how wide the remark is. location is null for
one about the commits themselves; location.lines is null for one about a
whole file. summary is null rather than "" when the reviewer left it
blank.
The prose that --format md prints — the default — carries the same
content, and is cheaper to read and harder to machine-handle. Pick per
agent.