agent-orchestrator/backend/internal/service/review
neversettle 0e5891df91
fix(review): notify worker on changes_requested instead of relying on SCM poll (#337) (#340)
* fix(review): message worker on changes_requested instead of relying on SCM poll (#337)

review.Engine.Submit previously only persisted the verdict/body and left the
worker to learn about requested changes via the SCM poll loop, which is gated on
GitHub's reviewDecision and never reaches CHANGES_REQUESTED for self-reviews or
COMMENT-state reviews. Submit now nudges the worker's live pane directly via
ports.AgentMessenger (the same mechanism lifecycle uses) whenever the verdict is
changes_requested.

Extended flow: the reviewer reads back the GitHub review id it posted and passes
it through `ao review submit --review-id`; the id is stored on the review_run row
(new column + migration 0016) and included in the worker message so the worker
knows exactly which review to address and reply to.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): mark worker nudge as AO internal review, ask to reply + resolve

Distinguish the AO internal review nudge from the external GitHub-reviewer
feedback the lifecycle SCM loop relays. For an AO review the worker is now asked,
once it has pushed its fix, to reply on the review referencing its id with what
it changed and resolve the inline review comment threads it addressed (the
reviewer posts inline comments, so the per-finding threads are resolvable via
resolveReviewThread; the top-level review object is not, hence the reply).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): generalise the changes-requested worker nudge wording

Drop the "not an external GitHub PR reviewer" aside and the assumption that the
worker pushes a fix — it may resolve the feedback without code changes. The nudge
now reads "Review the feedback below and address it" and asks the worker to reply
with how it addressed the review and resolve the threads it addressed.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): harden the review-id read-back against array order and empty results

The reviewer read the just-posted review id with `--jq '.[-1].id'`, which trusts
the REST API to return reviews in ascending submission order and errors when no
review exists. Review ids are monotonic, so select the highest id instead and
emit nothing when the list is empty: `--jq 'map(.id) | max // empty'`. Update the
matching `--review-id` flag help.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): post the review via gh api and capture its id from that response

The reviewer must use `gh api --method POST .../reviews` to attach inline
comments anyway (`gh pr review` cannot), and that response already contains the
created review's id. Capture `.id` from that single call instead of a second
read-back, dropping the array-ordering/pagination heuristics entirely — the id is
the exact review just created.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): send the review as a JSON body so inline comments are a real array

gh api -f/-F cannot build an array of objects: comments[][path] is sent as a
literal key, so the inline comments are dropped — defeating the reason for using
gh api over gh pr review. Post the review via --input JSON instead, keeping the
.id capture and the approve/COMMENT fallback.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: format with prettier [skip ci]

* chore(review): drop accidentally committed reviewer scratch, write review out of tree

review.md was the reviewer agent's own writeup, swept onto the worker branch by a
stray `git add -A` in 5df20c9. Remove it, gitignore `/review.md` as a backstop,
and change the reviewer prompt to write its review to a temp file outside the
checkout instead of into the worktree (where it could be committed onto the
worker's branch).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): message the worker before marking the run complete

If messenger.Send failed after UpdateReviewRunResult had already flipped the run
to complete, a retried `ao review submit` tripped the status='running' guard and
could never record the result. Send first; only mark the run complete once the
worker has been notified, so a failed send leaves the run retryable. A landed
message followed by a failed DB write degrades to one extra nudge on retry — the
same trade lifecycle's sendOnce makes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(review): accept the review body on stdin so the reviewer writes no file

`ao review submit --body -` now reads the review from stdin, and the reviewer
prompt pipes its writeup via a heredoc instead of writing a file. Previously the
reviewer wrote review.md into its checkout to pass as --body, which could be
committed onto the worker's branch (as it just was). A file path is still
accepted for backward compatibility.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): always post approvals as COMMENT, drop the APPROVE attempt

The reviewer posts from the PR author's own GitHub account, so event=APPROVE
always 422s. Drop it: request changes with REQUEST_CHANGES, approve with a
COMMENT-event review whose body states it is an approval.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(review): post every review as event=COMMENT (author can't APPROVE or REQUEST_CHANGES own PR)

The reviewer posts from the PR author's own account, where GitHub rejects both
APPROVE and REQUEST_CHANGES. Always post a COMMENT-event review and state the
verdict in the body; the machine-readable verdict still reaches AO via
`ao review submit --verdict`.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(cli): accept underscore flag names on `ao review submit`

Reviewer agents routinely invoke the submit command with --review_id
instead of --review-id, which cobra rejected as an unknown flag and
dropped the GitHub review id from the worker notification. Normalize
underscores to hyphens on the command's flags so both spellings resolve
to the same flag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix: sanitize review id in worker notifications

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Vaibhaav <user@example.com>
2026-06-21 19:52:46 +05:30
..
review.go fix(review): notify worker on changes_requested instead of relying on SCM poll (#337) (#340) 2026-06-21 19:52:46 +05:30