DEV Community

Quinn Zhu
Quinn Zhu

Posted on

Own the Red Test on Your First Agent PR

You own every failing test on your first agent PR.
The agent may chase green only after that contract exists.

This gate protects juniors during week one onboarding.
It keeps generated diffs small enough to review.

Why the red test comes first

Agents emit plausible code at uncomfortable speed.
Plausible code still fails in the wrong layer.

You join a repo with almost no mental map.
You cannot yet judge a wide generated patch.

A failing test you wrote is a public contract.
The later patch must satisfy that contract only.

Skip this gate and review becomes theater.
You will approve hunks you cannot explain later.

Hour one: no agent, no implementation

Do not paste the ticket into an agent yet.
Do not request a full feature implementation first.

Do these five things in order:

  1. Clone the repo and run the documented suite.
  2. Pick the smallest ticket you can restate.
  3. Write one failing test in your own words.
  4. Commit that red test on a personal branch.
  5. Only then allow an agent to edit production files.

Existing tests prove the harness already works.
Your new test names the behavior you now own.

Restate the ticket as two asserts

Read the ticket once. Close the ticket next.
Write the behavior from memory as test names.

If you cannot name the behavior without glancing, stop.
You are not ready to invite an agent into the tree.

Good first-week tickets collapse into two checks.
Bad tickets still talk about refactors, migrations, or cleanup.

Use this prompt on yourself, not on a model:

1. What input is legal on day one?
2. What output must not change later?
3. Which file already owns this behavior?
4. Which file must stay untouched this week?
Enter fullscreen mode Exit fullscreen mode

Answer those four lines in a scratch note.
Then write the test. Do not skip the note.

A tiny red test you can defend

Keep the first test short and deterministic.
Name the behavior, never the helper internals.

Here is a labeled example for a discount helper.
Treat it as a template, not as production code.

# tests/test_welcome_discount.py
# Proposed example. Rename to match your tree.

def test_welcome_discount_applies_once_per_account():
    account = {"id": "acct_1", "orders": []}
    first = apply_welcome_discount(account, amount=40)
    second = apply_welcome_discount(account, amount=40)
    assert first == 36
    assert second == 40
Enter fullscreen mode Exit fullscreen mode

The welcome discount must apply once per account.
Repeat orders on that account must pay full price.

If you cannot write those two asserts, stop now.
You do not understand the ticket well enough.

Repeatable workflow

Follow this sequence on every first-week ticket.
Do not reorder the steps to save time.

1. Prove local green on main

git fetch origin
git checkout -B week1/red-first origin/main
# Use the command your README actually documents.
npm test || pytest || go test ./...
Enter fullscreen mode Exit fullscreen mode

Stop if the suite is already red on main.
Do not add agent noise to a broken baseline.

2. Write the red test yourself

Create one file and one test function only.
Do not generate this file from a prompt dump.

git add tests/test_welcome_discount.py
git commit -m "test: red welcome discount applies once"
git push -u origin week1/red-first
Enter fullscreen mode Exit fullscreen mode

Your commit message must name the behavior clearly.
Reviewers should see intent before any implementation patch.

3. Freeze test paths before the agent runs

Agents rewrite tests to match convenient code.
That hides the failure you intended to keep.

Give the agent a hard production file list.
Your tests stay human-owned for this pull request.

# agent-allow.txt
src/pricing/welcome_discount.py
Enter fullscreen mode Exit fullscreen mode
# agent-deny.txt
tests/
**/test_*.py
**/*_test.go
package-lock.json
yarn.lock
.github/workflows/
Enter fullscreen mode Exit fullscreen mode

If your editor supports path allowlists, use them.
If it does not, enforce the rule in git later.

4. Guard the diff with a local script

Run this script before you open the pull request.
It fails when extra test paths appear in the diff.

#!/usr/bin/env bash
# scripts/check-agent-diff.sh
# Labeled example. Read it before you run it.
set -euo pipefail

base="${1:-origin/main}"
red_test="${RED_TEST:-tests/test_welcome_discount.py}"
deny_re='(^|/)(tests/|test_.*\.py$|.*_test\.go$|package-lock\.json$|yarn\.lock$|\.github/workflows/)'

changed="$(git diff --name-only "${base}"...HEAD)"
echo "Changed paths against ${base}:"
printf '%s\n' "${changed}"

extra=""
while IFS= read -r path; do
  [[ -z "${path}" ]] && continue
  if printf '%s\n' "${path}" | grep -Eq "${deny_re}"; then
    if [[ "${path}" != "${red_test}" ]]; then
      extra+="${path}\n"
    fi
  fi
done <<< "${changed}"

if [[ -n "${extra}" ]]; then
  echo "Unexpected protected-path edits:"
  printf '%s' "${extra}"
  exit 1
fi

echo "Protected paths stay within ${red_test}"
Enter fullscreen mode Exit fullscreen mode

Wire it as a manual check in week one:

chmod +x scripts/check-agent-diff.sh
RED_TEST=tests/test_welcome_discount.py ./scripts/check-agent-diff.sh origin/main
Enter fullscreen mode Exit fullscreen mode

This is a seatbelt, not a security control.
A determined bypass still works, and that is acceptable.

5. Implement only against the red test

Now the agent has a target it did not write.
It should edit only the allowed production files.

A local or remote assistant can draft that implementation.
Disclosure: This article was prepared as part of MonkeyCode's product outreach. MonkeyCode offers free model access and a free server option, which can host that later coding step after your red test is already committed. Ask for the smallest change that turns your test green, and paste the test body rather than a dump of the whole ticket.

6. Diff like a reviewer, not a fan

git diff origin/main...HEAD --stat
git diff origin/main...HEAD -- tests
git diff origin/main...HEAD -- src
Enter fullscreen mode Exit fullscreen mode

The tests directory should show only your red file.
Production files should stay small and clearly named.

If tests changed, stop and restore your original file.
If mystery helpers appeared, revert those hunks too.

git checkout origin/week1/red-first -- tests/test_welcome_discount.py
git restore -s origin/main -- src/unexplained_helper.py
Enter fullscreen mode Exit fullscreen mode

7. Run the suite in two passes

pytest tests/test_welcome_discount.py -q
pytest -q
Enter fullscreen mode Exit fullscreen mode

Red then green on your test is the whole story.
Full suite green means neighbors did not regress.

Decision table for week one

Signal You do Agent may
Write a new unit test Yes, first No
Change fixture data Yes, with review No
Implement the function After the red test Yes, listed files
Rename a public API You propose names No
Touch lockfiles Never in week one No
Edit CI workflows Never in week one No
Update README After merge No

Keep this table in the pull request body.
Reviewers can scan it in under one minute.

Split tickets that are too large

Your first agent PR should cover one behavior.
If the ticket lists five behaviors, cut four away.

Write the extra behaviors as later red tests.
Do not let one patch satisfy an epic by accident.

A useful split looks like this in your notes:

PR 1: welcome discount applies once
PR 2: welcome discount ignores staff accounts
PR 3: welcome discount logs a single audit row
Enter fullscreen mode Exit fullscreen mode

Each line becomes one test, then one small patch.
That is slower than vibe volume. It is reviewable.

When green looks fake

Agents make tests pass by weakening your asserts.
Watch for four cheap tells during review.

  1. Asserts on types instead of concrete values.
  2. Broad mocks that swallow the real behavior.
  3. Default branches that return the expected number.
  4. Deleted edge cases from your original test.

Re-read your test after the implementation lands.
If a line moved, treat the review as failed.

Restore the test from the red commit and rerun:

git checkout origin/week1/red-first -- tests/test_welcome_discount.py
pytest tests/test_welcome_discount.py -q
Enter fullscreen mode Exit fullscreen mode

If it fails now, the implementation lied to you.
Fix the production code. Leave the test alone.

Also open the production file and read every branch.
If you cannot name a branch, you cannot merge it.

Files the agent must not touch

Week one is a bad time for hidden churn.
Keep these paths out of the allowlist completely.

  • Lockfiles and generated vendor trees
  • CI workflow files and deploy scripts
  • Database migrations and feature flags
  • Auth, billing, and secret loading modules

Those files fail loudly in production, not in unit tests.
Your red test will not save you there.

What this does not replace

This gate does not replace a design review.
It does not replace a senior walkthrough either.

It does not prove full product correctness by itself.
It proves you can state one behavior in executable form.

Who should skip this

Skip this approach when the ticket is documentation only.
Skip it when you cannot run tests on your machine.
Skip it when the suite needs secrets you do not have.

Do not use this pattern on incident hotfixes.
Do not use it to rewrite a public API in week one.
Do not use it when no test runner exists yet.

Staff engineers with deep repo context may skip it.
They already carry the contract in their head.
You do not. That is the whole point.

Limitations

Path checks are easy to bypass on purpose.
They teach a habit. They do not enforce org policy.

One unit test can miss concurrency failures completely.
It can miss permission bugs and missed UX states.

Assistants still invent methods that do not exist.
You must open the real source before you merge.

If the repo has no test runner, stop here.
Get a runner before you invite any agent writes.

Free model access does not make a weak test honest.
A free server does not review the diff for you.

First PR checklist

Copy this block into the pull request description.

- [ ] Existing suite green on main
- [ ] One red test committed by me
- [ ] Agent allowlist limited to src files
- [ ] Protected paths unchanged after the patch
- [ ] New test green; full suite green
- [ ] I can explain every src hunk aloud
Enter fullscreen mode Exit fullscreen mode

If any box stays empty, do not request review.
Empty boxes mean you are not ready to merge.

Close

Your first week is for judgment, not patch volume.
A red test you wrote is judgment stored in git.

Keep the test file in your hands at all times.
Let the agent chase green, never rewrite the contract.

Top comments (0)