Most engineers who have tried AI code review distrust it — and blocking merges on a model's opinion deserves that distrust. The placement that works is different: an advisory reviewer that comments on infra PRs with an ops-specific rubric (blast radius, security, cost) and never holds the merge button.
Tier: Core · Workflow area: CI/CD & release engineering
Humans stay the gate; the AI makes the human review better-informed. This playbook builds that bot.
Skip this if your PRs are tiny and reviewed within the hour — the bot adds noise, not signal.
pull_request and post comments (GitHub Actions/GitLab CI with an API token scoped to comments only).Write the rubric as a file in the repo (.ai-review/rubric.md) so it is versioned and reviewable itself:
Review this infrastructure diff ONLY against these criteria:
1. BLAST RADIUS — resources deleted/replaced/renamed; changes affecting
shared infra (VPC, IAM, DNS, security groups) vs single-service scope.
2. SECURITY — IAM wildcards, 0.0.0.0/0 ingress, unencrypted storage,
secrets in plaintext, public buckets, disabled logging.
3. COST — instance sizes, counts, storage classes, NAT/data-transfer
implications. Flag anything that plausibly adds >10% to service cost.
4. IRREVERSIBILITY — destroy/replace of stateful resources (databases,
volumes, queues with data).
Output: max 5 findings, each with severity (INFO/WARN/CRITICAL), the file
and line, and a one-sentence rationale. If the diff is clean, say exactly:
"No findings against the rubric." Do not comment on style. Do not invent
context not present in the diff.
Wire the CI job. Keep it advisory by construction — the job always exits 0:
ai-review:
if: github.event_name == 'pull_request'
runs-on: ubuntu-latest
permissions: { contents: read, pull-requests: write }
steps:
- uses: actions/checkout@<pinned-sha>
with: { fetch-depth: 0 }
- name: Review diff
run: |
git diff origin/${{ github.base_ref }}...HEAD -- '*.tf' '*.yaml' \
| python3 .ai-review/review.py --rubric .ai-review/rubric.md \
--post-comment "$PR_URL" || true # advisory: never fail the build
Feed the diff plus minimal context — the diff alone, plus terraform plan summary if available. Resist sending the whole repo; more context means more hallucinated "issues" about code that is not changing.
Calibrate on historical PRs before going live. Run the bot on 10–20 merged PRs where you know the ground truth (including a couple that caused incidents). Count true/false positives per rubric line. Cut or rewrite any rubric line with worse than ~50% precision.
Ship with a feedback loop. Add 👍/👎 reactions convention or a weekly 10-minute review of bot comments; prune what the team ignores. An ignored bot is worse than no bot — it trains people to skim past all review comments.
Advisory placement is not a compromise — it is the design. The bot's job is to make the human reviewer look at the three lines that matter; the human's job is unchanged.
/review): fastest to enable; you trade rubric control for zero maintenance. Layer your rubric as custom instructions where supported.exit 1 on a CRITICAL finding and you have built the thing your team rejected. Keep advisory in the job design, not just in policy..terraform.lock.hcl, vendored modules — findings there are pure noise.Client repos: the diff itself is client IP. Options, in order of preference:
review.py at it.Never route client diffs through a personal AI account.