DEV Community

Quinn Zhu
Quinn Zhu

Posted on

Score the Agent Diff Before You Request Review

You do not earn a first PR with fluent agent code. You earn it by scoring the diff yourself. Reviewers read your judgment instead of model confidence.

Put this gate in your first hour. Use it on the first agent patch. Use it again before anyone else reviews.

The core rule

Never request review for an unscored agent diff. A score is written evidence, not a vibe. Keep SCORE.md next to the patch always.

What this gate is not

This is not a path freeze map. This is not a first rollback drill. This is not a red-test ownership note.

Those other gates still matter on this team. This gate asks a narrower question today. Can you explain the change without the chat?

Build the score sheet

Copy this template into every agent worktree. Fill every section in your own words. Do not let the agent draft it first.

# SCORE.md

## Intent
- (three bullets you typed)

## Bound
- allowed paths:
- forbidden paths:

## Diff census
- added:
- edited:
- deleted:

## Risk
- auth or secrets: yes/no — why
- data loss: yes/no — why
- concurrency: yes/no — why
- public API: yes/no — why

## Proof I ran
Enter fullscreen mode Exit fullscreen mode

(commands and exit codes)


## Lines I cannot explain
- path:line — question I will ask

## Rollback
- exact git command
Enter fullscreen mode Exit fullscreen mode

An empty section means you are not ready. Treat empty sections as a hard stop.

Numbered workflow

1. Isolate the session

Create a worktree before the agent starts. Keep main clean while the patch exists. Stay on a throwaway branch the whole time.

git fetch origin
git worktree add ../repo-first-pr origin/main
cd ../repo-first-pr
git switch -c first-pr/score-gate
cp ../SCORE.template.md ./SCORE.md
Enter fullscreen mode Exit fullscreen mode

You now own a disposable git sandbox. The agent may edit code inside it. You still own SCORE.md without any debate.

2. Capture a baseline

Run the smallest honest test command first. Record the exit code before any patch. A red baseline is not an agent ticket.

# proposal: swap in your repo's real runner
{
  echo "=== baseline $(date -u +%FT%TZ) ==="
  python -m pytest -q --maxfail=1
  echo "exit:$?"
} | tee /tmp/baseline.txt
Enter fullscreen mode Exit fullscreen mode

If baseline fails, you stop the session. You cannot score a patch on sand.

3. Bound the ticket

Write three intent bullets by hand. List allowed paths with boring exact detail. List forbidden paths on the same screen.

Keep the bound to one feature slice. Refuse drive-by refactors on day one.

allowed:
  src/billing/quote.py
  tests/billing/test_quote.py
forbidden:
  .github/**
  src/auth/**
  migrations/**
Enter fullscreen mode Exit fullscreen mode

Paste that bound into SCORE.md now. Paste the same bound into the agent prompt. The prompt follows your bound, never the reverse.

4. Patch only inside the bound

You may use an agent after the bound. You may type the patch yourself instead. Either path still requires a written score.

Take a census after the agent stops. Do not trust the chat file list.

git diff --stat origin/main
git diff --name-status origin/main
git diff origin/main -- '*.py' | head -n 200
Enter fullscreen mode Exit fullscreen mode

A forbidden path is not a discussion. Restore that file from origin/main right now.

git restore --source=origin/main -- .github src/auth migrations
Enter fullscreen mode Exit fullscreen mode

5. Walk every hunk out loud

Open a wide diff and read minus lines first. State the behavior change in one sentence. Then read the plus lines against a test name.

git diff origin/main -U5 -- src/billing/quote.py
Enter fullscreen mode Exit fullscreen mode

No matching test means you add one. Or you revert that hunk today. Silence is not a walkthrough.

Close the agent window before you write. Name each risk in plain short sentences. Paste the commands you actually ran locally.

{
  echo "=== proof $(date -u +%FT%TZ) ==="
  python -m pytest tests/billing/test_quote.py -q
  echo "exit:$?"
} | tee -a SCORE.md
Enter fullscreen mode Exit fullscreen mode

Read every hunk before you claim none. List every line you still cannot explain. Unexplained lines become questions, not merge fuel.

6. Optional hostile critique

You may ask a model to attack SCORE.md. You may not ask it to write SCORE.md.

Disclosure: This article was prepared as part of MonkeyCode's product outreach.

MonkeyCode offers free model access and a free server option. Use them to interrogate your score sheet. Do not use them to invent the score.

Do not paste secrets into that prompt. Do not paste any production logs either. Do not paste customer records or tokens.

Keep the payload limited to SCORE.md plus diffstat. Label the next prompt as an unexecuted proposal.

System: You are a hostile reviewer for a junior PR.
User: SCORE.md and git diff --stat follow.
Ask 8 questions I must answer before review.
Refuse to rewrite SCORE.md.
Refuse to generate a new patch.
Refuse to guess hidden files.
Enter fullscreen mode Exit fullscreen mode

Treat model questions as homework, not answers. Update SCORE.md in your own typing. If the model rewrites a section, delete it.

7. Gate the PR command

Do not open GitHub until the gate passes. The script checks structure, not your honesty. You still have to supply the brains.

#!/usr/bin/env bash
# save as scripts/score-gate.sh — proposal, run locally
set -euo pipefail
FILE="${1:-SCORE.md}"
fail() { echo "gate fail: $1" >&2; exit 1; }
[[ -f "$FILE" ]] || fail "missing $FILE"

heads=(
  "## Intent"
  "## Bound"
  "## Diff census"
  "## Risk"
  "## Proof I ran"
  "## Lines I cannot explain"
  "## Rollback"
)
for h in "${heads[@]}"; do
  grep -qxF "$h" "$FILE" || fail "missing $h"
done

python3 - "$FILE" <<'PY'
from pathlib import Path
import re, sys
text = Path(sys.argv[1]).read_text()
parts = re.split(r"(?m)^## ", text)
for part in parts[1:]:
    title, _, body = part.partition("\n")
    body = body.strip()
    if not body:
        raise SystemExit(f"empty section: {title.strip()}")
    if title.strip() == "Intent" and body.count("-") < 3:
        raise SystemExit("Intent needs three bullets")
print("score-gate: structure ok")
PY
Enter fullscreen mode Exit fullscreen mode
chmod +x scripts/score-gate.sh
./scripts/score-gate.sh SCORE.md
Enter fullscreen mode Exit fullscreen mode

A failed gate means you keep working. A passed gate means you may request review. Write the PR body yourself after it passes.

## What changed
(your words, not the chat summary)

## How I scored it
- bound:
- tests:
- leftover questions:

## How to roll back
`git switch main && git branch -D first-pr/score-gate`
Enter fullscreen mode Exit fullscreen mode

Example sheet (fake ticket, unexecuted)

Use this only as a shape check. It is not a production report. It is not a measured benchmark.

# SCORE.md

## Intent
- Recalculate quote tax for one locale.
- Keep the public function signature stable.
- Add one unit test that now passes.

## Bound
- allowed paths: src/billing/quote.py, tests/billing/test_quote.py
- forbidden paths: .github/**, src/auth/**, migrations/**

## Diff census
- added: tests/billing/test_quote.py
- edited: src/billing/quote.py
- deleted: none

## Risk
- auth or secrets: no — no credential paths
- data loss: no — pure calculation
- concurrency: no — no shared cache
- public API: no — signature unchanged

## Proof I ran
python -m pytest tests/billing/test_quote.py -q
exit:0

## Lines I cannot explain
- none after reading quote.py:88-101

## Rollback
git restore --source=origin/main -- src/billing/quote.py tests/billing/test_quote.py
Enter fullscreen mode Exit fullscreen mode

Decision table

Use this table when you feel stuck. Do not improvise some clever third option.

Symptom Action
SCORE.md missing a heading Stop. Fill it by hand.
Forbidden path in git diff git restore that path.
Baseline tests already red Stop. No agent patch yet.
Hunk with no matching test Add a test or revert hunk.
Agent rewrote SCORE.md Delete rewrite. Type it again.
Prompt wants .env or logs Abort the whole session.
Auth or migration files appear Get a human before continuing.
Gate script fails Keep working. Do not ping.

Common first-week failures

The agent also cleaned imports in six files. You restore five files. You keep the one file you bound.

git diff --name-only origin/main
# restore every path you did not list
Enter fullscreen mode Exit fullscreen mode

The agent rewrote comments into marketing. Drop comment-only hunks. Keep behavior hunks you can score.

git diff origin/main -U3 | less
Enter fullscreen mode Exit fullscreen mode

The agent added a retry loop you cannot explain. You cannot name the backoff. Revert that hunk before review.

git restore -p src/billing/quote.py
Enter fullscreen mode Exit fullscreen mode

Limitations

This workflow does not prove any production safety. Structure checks cannot detect a wrong idea. Free model access can vanish or change.

This article does not claim quotas, models, or uptime. Hostile model questions can still stay shallow. A mentor review still beats a SCORE.md file.

The gate script cannot smell copied answers. It cannot see a secret you pasted. It cannot replace your team's real CI.

Who should not use this

Skip this if you lack git worktrees. Skip this during an active production incident. Skip this if the patch must touch auth.

Get a human before any auth diff. Staff engineers may already have tighter gates. Do not replace those gates with this sheet.

Skip this when the ticket is a one-line typo. Scoring theater wastes review time there. Use judgment, then ship the typo fix.

Close

Your first PR is a judgment sample. Score the diff before you ping reviewers. If you already have free model access, point it at SCORE.md only.

Top comments (0)