67 lines
4.2 KiB
Go
67 lines
4.2 KiB
Go
package review
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// reviewTexts returns the user-facing prompt and the system prompt to deliver to
|
|
// a reviewer, authored in one place — the reviewer analogue of
|
|
// session_manager.buildSpawnTexts. The standing reviewer role lives in the
|
|
// system prompt; the per-pass task (which PR/commit, and the exact submit
|
|
// command carrying the ids) lives in the prompt, so it is also what AO injects
|
|
// into an already-running reviewer to review a new commit.
|
|
//
|
|
// The texts are self-contained — they carry the ids the reviewer needs to
|
|
// submit — so no environment variables are required.
|
|
func reviewTexts(spec LaunchSpec) (prompt, systemPrompt string) {
|
|
systemPrompt = `## Code reviewer role
|
|
|
|
You are an AO code reviewer. You review the requested pull request changes in the current checkout — do not start unrelated work. Inspect what each PR changed by diffing the checkout against the PR's base branch, and review for correctness bugs, missing error handling, security issues, test coverage, and clear deviations from the surrounding code's conventions. Prefer a few high-confidence findings over nitpicks.
|
|
|
|
Post your review as a comment on the pull request, stating clearly whether it needs changes or is ready, with inline comments for specific findings. Do not push commits, edit files, or modify the branch — review only.`
|
|
|
|
queueText := reviewQueueText(spec)
|
|
prompt = fmt.Sprintf(`Review the requested pull request(s) for worker session %s.
|
|
%s
|
|
|
|
Complete every review task in the queue autonomously. Do not ask the user whether to continue to the next PR, and do not stop after the first PR unless the provider or checkout is genuinely unusable for every queued task.
|
|
|
|
Do these steps in order:
|
|
1. For each PR below, post a separate review on that pull request and capture its id in one call. Post with `+"`gh api`"+` rather than `+"`gh pr review`"+`: it is the only way to attach inline comments, and its response carries the created review's id, so AO can tell the worker exactly which review to address. Send the review as a JSON body so the inline comments form a proper array of objects:
|
|
|
|
gh api --method POST repos/{owner}/{repo}/pulls/{number}/reviews --input - --jq '.id' <<'JSON'
|
|
{ "event": "COMMENT", "body": "<summary>",
|
|
"comments": [ { "path": "<file>", "line": <n>, "body": "<finding>" } ] }
|
|
JSON
|
|
|
|
- Substitute the PR's owner/repo/number. Add one object to "comments" per inline finding; omit the field for a review with no inline comments.
|
|
- Always use "event": "COMMENT": reviews are posted from the PR author's own account, and GitHub rejects both APPROVE and REQUEST_CHANGES on your own PR. State in the body whether you are requesting changes or approving; the machine-readable verdict goes to AO in step 2.
|
|
- The printed number is the review id. If the call fails on the provider, leave the id empty.
|
|
2. After every PR has its own GitHub review from step 1, record AO's bookkeeping for those already-posted reviews using one command. Pass JSON on stdin so nothing is ever written into the worktree (a file there could be committed onto the worker's branch). Include one object per PR/run from the queue:
|
|
|
|
ao review submit --session %s --reviews - <<'JSON'
|
|
{
|
|
"reviews": [
|
|
{ "runId": "<run-id>", "verdict": "<approved|changes_requested>", "githubReviewId": "<id-from-step-1-or-empty>", "body": "<your full review markdown>" }
|
|
]
|
|
}
|
|
JSON
|
|
|
|
Only if step 1 genuinely fails on the provider for a PR, still include that run in step 2 with an empty githubReviewId so the result is recorded.`,
|
|
spec.WorkerID, queueText, spec.WorkerID)
|
|
return prompt, systemPrompt
|
|
}
|
|
|
|
func reviewQueueText(spec LaunchSpec) string {
|
|
if len(spec.ReviewQueue) <= 1 {
|
|
return fmt.Sprintf("\nReview task queue:\n* 1. %s (head commit %s, run %s)\n", spec.PRURL, spec.TargetSHA, spec.RunID)
|
|
}
|
|
var b strings.Builder
|
|
fmt.Fprintf(&b, "\nAO created %d review tasks for this worker session. Review every queued PR, then submit all results together.\n\nReview task queue:\n", len(spec.ReviewQueue))
|
|
for i, task := range spec.ReviewQueue {
|
|
fmt.Fprintf(&b, "* %d. %s (head commit %s, run %s)\n", i+1, task.PRURL, task.TargetSHA, task.RunID)
|
|
}
|
|
return b.String()
|
|
}
|