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:
- Clone the repo and run the documented suite.
- Pick the smallest ticket you can restate.
- Write one failing test in your own words.
- Commit that red test on a personal branch.
- 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?
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
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 ./...
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
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
# agent-deny.txt
tests/
**/test_*.py
**/*_test.go
package-lock.json
yarn.lock
.github/workflows/
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}"
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
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
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
7. Run the suite in two passes
pytest tests/test_welcome_discount.py -q
pytest -q
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
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.
- Asserts on types instead of concrete values.
- Broad mocks that swallow the real behavior.
- Default branches that return the expected number.
- 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
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
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)