DEV Community

Alex Zhu
Alex Zhu

Posted on

The AI PR Handoff Protocol: Roles, Escalations, and a One-Page Runbook for Your Wiki

The AI PR Handoff Protocol: Roles, Escalations, and a One-Page Runbook for Your Wiki

Last quarter, a teammate merged an AI-assisted refactor that silently deleted a database migration, and the staging database lost its rollback path. We spent a day rebuilding the changeset, and the postmortem kept circling the same phrase: nobody owned the handoff between the AI-generated diff and the human review. That moment convinced me that teams need an explicit protocol, not another checklist, to safely absorb AI-written code.

This article is a playbook for turning that chaos into a repeatable protocol. You will get two artifacts: a Python script that pre-screens pull requests using a free model, and a one-page runbook you can paste directly into your wiki. The script requires only a Git repository and a model endpoint, and it can be hosted on a free server option if you do not have CI infrastructure.

For the pre-screening step, I used MonkeyCode's free model access and its free server option to host the queue. Disclosure: This article was prepared as part of MonkeyCode's product outreach.

The Three Roles That Make AI Review Safe

A robust review process needs three distinct responsibilities, and they must not be combined in one person.

  • The Requestor is the human who submits the AI-generated change. This person owns the final diff, even if the model wrote the code, and must be able to explain every line.
  • The Sentinel is the automated script that runs on every PR. It summarizes the diff, flags high-risk patterns, and posts the report where the team can see it. The Sentinel never merges.
  • The Decider is a senior engineer who reads the Sentinel report, inspects the actual diff, and makes the merge decision. This role requires context about the codebase and the business logic.

Here is the handoff sequence you should encode in your team documentation:

  1. The Requestor opens a PR with an #ai label and a short description of what the model changed.
  2. The Sentinel runs within five minutes and leaves a structured comment on the PR.
  3. The Decider reviews the Sentinel report, then looks at the changed files.
  4. If no findings are present, the Decider approves. If findings exist, the Decider requests changes with a specific, actionable reason.
  5. The Requestor resolves every finding and re-runs the Sentinel before requesting a second review.

This sequence forces each role to do one activation only, which prevents the classic failure mode where everyone assumes someone else has already reviewed the diff.

Artifact 1: The Sentinel Script (Python + Git)

The Sentinel script below scans the changed files between your base branch and a given commit, detects a handful of risky patterns, and asks a free model for a concise risk summary. You can run it locally or wire it to a cron job.

#!/usr/bin/env python3
"""Sentinel: pre-screen AI-generated PRs for high-risk changes."""
import argparse, json, os, re, subprocess, sys, urllib.request

def git_stdout(args):
    return subprocess.run(["git"]+args, capture_output=True, text=True).stdout

def changed_files(base):
    files = git_stdout(["diff", "--name-only", base]).splitlines()
    return [f for f in files if not f.startswith("docs/")]

def flag_file(path):
    with open(path, encoding="utf-8", errors="ignore") as f:
        text = f.read()
    problems = []
    if path.endswith("migration") or ("migration" in path and path.endswith(".py")):
        if "downgrade" not in text:
            problems.append("migration lacks a downgrade function")
    if path.endswith(".py") and re.search(r"^\s*#\s*type:\s*ignore", text, re.M):
        problems.append("contains type: ignore comments")
    if path.endswith(".test.ts"):
        if re.search(r"\.skip\(", text):
            problems.append("contains .skip() tests")
    return problems

def call_model(prompt, endpoint):
    # Endpoint should point to your free model provider (e.g. MonkeyCode).
    body = json.dumps({"messages":[{"role":"user","content":prompt}], "max_tokens": 400}).encode()
    req = urllib.request.Request(endpoint, data=body, headers={"Content-Type":"application/json"})
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read())["choices"][0]["message"]["content"]

def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--base", default="main")
    ap.add_argument("--endpoint", default=os.environ.get("MODEL_ENDPOINT"))
    args = ap.parse_args()
    files = changed_files(args.base)
    if not files:
        print("No changed files.")
        return
    findings = []
    for f in files:
        problems = flag_file(f)
        if problems:
            findings.append(f"{f}: {', '.join(problems)}")
    diff = git_stdout(["diff", "--stat", args.base])
    prompt = ("Given this PR stat and flag list, write a two-sentence risk summary:\n"
              + diff + "\n" + "\n".join(findings))
    summary = call_model(prompt, args.endpoint) if args.endpoint else "No endpoint configured; flags below are local."
    print("## Sentinel Report")
    print(summary)
    if findings:
        print("\n### Flags")
        print("\n".join("- " + x for x in findings))
        sys.exit(1)

if __name__ == "__main__":
    main()
Enter fullscreen mode Exit fullscreen mode

To use the Sentinel, set the MODEL_ENDPOINT environment variable to the API endpoint your free model tier exposes, then run:

git checkout main && git pull
python sentinel.py --base main...HEAD
Enter fullscreen mode Exit fullscreen mode

The script exits with a non-zero status when it finds blocking flags, so you can call it from a CI pipeline or an hourly cron job. On MonkeyCode's free server option, you can host a lightweight clone of the repository and schedule the script with a simple cron entry.

Artifact 2: The One-Page Runbook (Wiki Template)

The next piece is the runbook that your team will actually read. Copy this Markdown block into your wiki, then adjust the file patterns to match your stack.

# AI PR Review Runbook

## Roles
- **Requestor**: opens the PR, owns the change.
- **Sentinel**: automated script that flags risks and summarizes diff.
- **Decider**: senior reviewer who makes the merge call.

## Handoff Sequence
1. Requestor opens PR with `#ai` label.
2. Sentinel runs within 5 minutes and comments.
3. Decider reviews sentinel report and diffs.
4. If no flags → approve. If flags → request changes with specific reason.
5. Requestor resolves all flags and re-runs Sentinel.

## Escalation Criteria
- Migrations missing downgrade: block merge.
- Deleted test files: block merge.
- `.skip()` added: block merge unless linked to an issue.
- Sentinel endpoint down: manual review required.

## Exit Criteria
- No blocking flags.
- Decider explicitly documents a decision.
Enter fullscreen mode Exit fullscreen mode

Put this runbook next to your pull request template. When the Sentinel posts a report, copy the runbook link into that report so the Decider can always find the process.

Limitations, and Who Should Not Use This

The Sentinel is a heuristic tool, not a proof reader. It will miss logic errors, security issues, and business-rule violations, and the free model summary can be confidently wrong, so the Decider must always read the actual diff. If your team lacks a senior engineer who can make judgment calls, this protocol will not fix a broken review culture, and you should fix that first. If your repository has no test suite or no migrations, you will need to extend the flag patterns before the script becomes useful.

You should also remember that free-tier capacity can change without warning, which is why the runbook treats an endpoint outage as an escalation, not a pause. This approach works best for small-to-mid-sized teams that merge a few AI PRs per day. For organizations with strict compliance requirements or huge monorepos, you would want deeper integration with your code review APIs and a more formal approval audit trail.

If you want to try the Sentinel with a zero-cost starting point, the free model and server tiers from MonkeyCode are reasonable choices, and you can find the link on my profile. Start with one small repository, document the handoffs, and you will catch the next migration delete before your staging database does.

Top comments (0)