# Review pull requests with owners policies

This agent reviews every pull request in your repository. It risk-tiers
the diff, requests the owning team or user as reviewers, and approves
what your policy allows. Ownership rules live in
`.agentic-owners/policy.yml` files committed at any depth of the repo.
The closest policy to a changed file wins, and policies are always read
from the PR's base ref, so a PR cannot exempt itself.

## Scaffold

```bash
agent-sdk init ./owners-agent --template agentic-owners
```

`init` writes the project, installs dependencies, and puts `agent-sdk`
on PATH.

## Log in and run

Set your repositories in `bot/lib/config.ts` (`repos: ["acme/api"]`),
then:

```bash
cd owners-agent
agent-sdk login
agent-sdk dev
```

PR events stream through your Cursor account. No webhook or GitHub App
setup. The agent reviews a PR when it is opened, reopened, pushed to,
marked ready for review, or retargeted to another base. Draft PRs wait
until they are ready. Open a PR, or replay a real one (this also works
with `repos` empty):

```bash
agent-sdk github replay https://github.com/acme/api/pull/123 --dir .
```

Deploy with `agent-sdk deploy`.

## Policies

With no policy files, every PR gets a default risk review: very-low and
low risk approve, medium and above hold with a comment. Route reviews by
committing policies:

```yaml
# .agentic-owners/policy.yml at any depth; the closest policy wins.
version: 1
policies:
  - paths: ["docs/**"]
    always_approve: true
  - paths: ["src/api/**"]
    team: platform # bare slug in the repo's org; or acme/platform, or user: alice
    prompt: api-review.md # optional extra rubric, same directory
  - paths: ["src/billing/**"]
    users: [alice, bob]
    mode: hard # the agent never approves; a person must
```

`paths` are globs relative to the directory that holds the
`.agentic-owners/` folder, so a root policy sees repo-relative paths and
`src/.agentic-owners/policy.yml` matches `api/**` against
`src/api/**`. Leading `../` segments reach a sibling tree. A path cannot
escape the repo.

| Key | Meaning |
| --- | --- |
| `paths` | Globs relative to the policy's directory. Required. |
| `team` / `teams` | Owner teams. A bare slug resolves in the repo's org. An `org/team` handle names a team directly. |
| `user` / `users` | Owner GitHub logins, without `@`. |
| `prompt` | Markdown filename in the same directory, added to the rubric for matching PRs. |
| `mode` | `advisory` (default): low risk approves. `hard`: a person must approve. `notify`: the rule never blocks and its owners are not requested. |
| `human_review_required` | `true` is the older spelling of `mode: hard`. |
| `self_review` | A listed `user:` owner's own PRs clear this rule. |
| `always_approve` | Satisfied at every risk tier. Cannot combine with owners, `prompt`, `mode`, `self_review`, or `human_review_required`. |

A rule without owners must set `always_approve: true`.
`global_exclusions` in the root policy opts paths out entirely. The
agent rejects `delegated_automations`: nothing in this template consumes
automation approvals.

## What one review does

One model turn per PR head assesses the host-fetched diff against the
base rubric plus any matched rule prompts, then records a risk tier of
`very_low`, `low`, `medium`, `medium_high`, or `high` with
`record_review`. The host recomputes the policy from trusted state and
applies the deterministic decision:

- **Approve** when every matched rule is `always_approve` or `notify`,
  or when the tier is very low or low and every matched `hard` rule is
  cleared by an owner-author with `self_review`. At medium and above,
  the agent approves only when the author's `self_review` covers every
  rule that can require review.
- **Request reviewers** otherwise: the policy owners (max 2, never the
  author), plus one status comment the agent keeps updated in place.

An approval binds to the head SHA, and a later hold dismisses the
agent's earlier approvals. The agent also holds when the PR edits
`.agentic-owners/` or `CODEOWNERS`, when the diff is empty or truncated,
or when GitHub capped the changed-file list. `self_review` never clears
a governance edit.

The model never writes to GitHub. A broken policy file fails closed with
a comment listing the validation issues. Team membership is not
resolved, because repo-scoped credentials cannot read org teams, so
`self_review` applies to `user:` owners only.

## Rubric

Edit `bot/lib/owners/prompts/base-review.md` for the risk tiers and
their boundaries. Per-area guidance belongs in policy `prompt:` files
next to the policy that names them. The next review reads both.

## Evals

Use the three smoke reviews as a local exercise:

```bash
agent-sdk eval
```

The cases are a docs-only change, an auth deletion, and a prompt
injection. Eval sessions skip GitHub writes.
