Summary
Add configurable AO code review so a worker's PR can be reviewed by a configured reviewer agent after the PR is raised. The reviewer runs one-shot over the worker's own worktree, the result is posted to GitHub, and the worker picks the feedback up through AO's existing SCM observer → review-nudge path.
Source of truth: this body folds in the V1 design comment (2026-06-11), which supersedes the original HLD. Superseded items are listed under Out of V1 / later.
V1 behavior
- A single per-project config names the reviewer agent(s) by
harness (Greptile CLI, Codex, Claude, or any adapter). There is no enabled on/off switch — review is always manual and runs only when triggered for a specific session. If no reviewer is configured, AO uses a default reviewer harness (claude-code).
- The reviewer is a one-shot run over the worker's own worktree: it reads what the worker already has checked out, reviews it, and reports a result. V1 assumes the worker adds no commits during a pass (no SHA-pinned copy, no separate reviewer worktree, no
target_sha).
- A review happens only when triggered — no loop, no "until PR is ready" terminal condition. The worker fixes things and the user triggers another pass if and when they want one.
- The reviewer is not modeled as a child session. It is tracked by a separate
review table (one row per worker) plus a per-pass review_run.
- The review result is posted to GitHub (PR review/comment); the worker receives it through AO's existing SCM observer → review-nudge path (no bespoke delivery message).
Backend shape
Domain & config
projects config gains a reviewers list (part of the existing per-project config JSON):
{
"reviewers": [
{ "harness": "codex" }
]
}
- No
enabled field.
- Empty/unset
reviewers resolves to a default of one reviewer with harness claude-code.
Storage
review — one per worker:
| Column |
Purpose |
id |
identity |
session_id (UNIQUE) |
worker session under review; one review per worker in V1. A repeat trigger reuses this row. |
project_id |
owning project (for CDC) |
harness |
which reviewer agent reviews this PR |
pr_url |
the PR under review (recorded, not part of the key yet) |
created_at, updated_at |
when set up / last touched |
review_run — per pass:
id, review_id, session_id (worker), harness, pr_url
status (pending | complete | failed)
verdict ('' | approved | changes_requested)
iteration
created_at, updated_at
The review body is not persisted in V1 — it flows from ao review submit to GitHub.
Service layer
A ReviewService responsible for:
- loading reviewer config (with default resolution);
- creating/updating the
review row and per-pass review_run;
- resolving the reviewer harness and running it one-shot over the worker's worktree;
- receiving submitted review results;
- posting the result to GitHub via a minimal SCM post capability.
CLI & HTTP
POST /sessions/{workerId}/reviews/trigger
GET /sessions/{workerId}/reviews
POST /sessions/{workerId}/reviews/submit
ao review trigger <worker-session-id>
ao review submit --verdict changes_requested --body review.md
ao review list <worker-session-id>
CLI and HTTP stay thin; the daemon service owns behavior.
Out of V1 / later
These items from the original HLD are intentionally deferred:
sessions.parent_session_id, sessions.kind = reviewer (reviewer is not a session).
- Disposable pinned reviewer worktree and
target_sha (reviewer reuses the worker worktree).
enabled config flag.
- Auto-trigger on PR head SHA advance.
- Derived
in_review status.
- Greptile no-workspace / reviewer-only adapter; reviewer read-only permission mode.
- Relaxing the
review key to one-per-(session_id, pr_url).
Summary
Add configurable AO code review so a worker's PR can be reviewed by a configured reviewer agent after the PR is raised. The reviewer runs one-shot over the worker's own worktree, the result is posted to GitHub, and the worker picks the feedback up through AO's existing SCM observer → review-nudge path.
V1 behavior
harness(Greptile CLI, Codex, Claude, or any adapter). There is noenabledon/off switch — review is always manual and runs only when triggered for a specific session. If no reviewer is configured, AO uses a default reviewer harness (claude-code).target_sha).reviewtable (one row per worker) plus a per-passreview_run.Backend shape
Domain & config
projectsconfig gains areviewerslist (part of the existing per-project config JSON):{ "reviewers": [ { "harness": "codex" } ] }enabledfield.reviewersresolves to a default of one reviewer with harnessclaude-code.Storage
review— one per worker:idsession_id(UNIQUE)project_idharnesspr_urlcreated_at,updated_atreview_run— per pass:id,review_id,session_id(worker),harness,pr_urlstatus(pending|complete|failed)verdict(''|approved|changes_requested)iterationcreated_at,updated_atThe review body is not persisted in V1 — it flows from
ao review submitto GitHub.Service layer
A
ReviewServiceresponsible for:reviewrow and per-passreview_run;CLI & HTTP
CLI and HTTP stay thin; the daemon service owns behavior.
Out of V1 / later
These items from the original HLD are intentionally deferred:
sessions.parent_session_id,sessions.kind = reviewer(reviewer is not a session).target_sha(reviewer reuses the worker worktree).enabledconfig flag.in_reviewstatus.reviewkey to one-per-(session_id, pr_url).