DEV Community

Taylor Zhu
Taylor Zhu

Posted on

Prove AI Code Before You Merge: 9 Gates, One Script

Every week there is a new thread about AI coding tools and a new story about an AI-generated patch that broke something in production. The pattern is almost always the same: the problem wasn't the model. It was the pipeline around it. Someone merged code because it looked plausible, not because the evidence said it worked.

Recent DEV discussions keep returning to the same spot: AI turned every developer into a reviewer, and nobody audited the reviewer. The fix isn't a better prompt. It's a gate — a set of checks that default to blocked until the evidence exists.

Here is a fail-closed pipeline you can copy: nine gates, each with the question it answers, the evidence it requires, and the rule that blocks the merge when evidence is missing.

What fail-closed actually means

A fail-closed gate starts from denial. No evidence, no merge. That's the opposite of how most AI-assisted PRs get reviewed today, which is looks good to me.

Fail-open treats checks as optional. Fail-closed treats them as the contract. When in doubt, the patch stops moving forward.

The nine gates

# Gate Question it answers Evidence required Fail-closed rule
1 Provenance Where did this code come from? Marker like ai-gen:<session-id> in commit metadata No marker -> blocked
2 Build & lint Does it compile without new warnings? Clean lint.log and build.log Any new warning -> blocked
3 Unit tests Does existing behavior still hold? Test log with pass counts Any failure -> blocked
4 New-code tests Is the new logic actually covered? Test diff touching new lines No new tests for new logic -> blocked
5 Dependency audit Did the patch add or change packages? audit-deps report New unapproved dependency -> blocked
6 Secret scan Did the patch leak credentials? SAST or secrets output Any high or critical finding -> blocked
7 Performance evidence Does the hot path stay fast? Before/after benchmark JSON Hot-path change without benchmark -> blocked
8 Rollback path Can this be turned off without a deploy? Flag name in PR metadata No rollback plan -> blocked
9 Evidence review Did a human inspect the evidence, not just the diff? Reviewer sign-off referencing the evidence files Review without evidence -> merge refused

Gates 1 through 6 are mechanical. You can automate them today. Gates 7 through 9 require judgment, but you can still automate the blocked-until-done part.

The script: a fail-closed gate you can copy

The script below implements gates 1, 2, 3, 5 and 6 in about forty lines. Drop it into your repo, wire it to CI as a required check, and it blocks anything that doesn't produce evidence.

#!/usr/bin/env bash
# gate.sh - fail-closed gate for AI-generated patches
# Usage: GENERATED_MARKER=ai-gen:<session-id> BASE_SHA=HEAD~1 ./gate.sh
set -euo pipefail

EVIDENCE_DIR=".gate-evidence/$(git rev-parse --short HEAD 2>/dev/null || echo local)"
mkdir -p "$EVIDENCE_DIR"

die() { echo "BLOCKED: $1" >&2; exit 1; }

# Gate 1 - provenance. No marker, no merge.
: "${GENERATED_MARKER:?Gate 1: set GENERATED_MARKER to identify the AI session that produced this code}"
echo "$GENERATED_MARKER" > "$EVIDENCE_DIR/provenance.txt"

# Gate 2 - build and lint. Treat warnings as failures.
make lint > "$EVIDENCE_DIR/lint.log" 2>&1 || die "lint failed; see $EVIDENCE_DIR/lint.log"
make build > "$EVIDENCE_DIR/build.log" 2>&1 || die "build failed; see $EVIDENCE_DIR/build.log"

# Gate 3 - the whole test suite must pass.
make test > "$EVIDENCE_DIR/test.log" 2>&1 || die "tests failed; see $EVIDENCE_DIR/test.log"

# Gate 5 - dependency changes need an audit trail.
if git diff --name-only "${BASE_SHA:-HEAD~1}" | grep -E '(package-lock.json|go.sum|poetry.lock|requirements.*\.txt)$'; then
  ./scripts/audit-deps > "$EVIDENCE_DIR/deps.txt" 2>&1 || die "dependency audit failed"
fi

# Gate 6 - secrets and critical findings block the merge.
./scripts/scan-secrets > "$EVIDENCE_DIR/secrets.txt" 2>&1 || die "secret scan failed"

echo "PASS: evidence collected in $EVIDENCE_DIR"
Enter fullscreen mode Exit fullscreen mode

The script is deliberately boring. It doesn't judge quality, it collects receipts. When a merge is later blamed for an outage, the evidence directory tells you which session produced the patch, which warnings were on the table, and who approved it.

Where the free tier fits: a $0 version of the loop

The generation step isn't the expensive part of this workflow. The expensive part is the server that runs the assistant and the gate. If you're evaluating AI-assisted development, you shouldn't have to pay for infrastructure before you have evidence it works in your codebase.

MonkeyCode is an open-source AI coding assistant whose current offering includes free model access and a free server option, which is enough to run both halves of the loop at no cost: the assistant generates the patch, and the free server executes the gate script. Disclosure: This article was prepared as part of MonkeyCode's product outreach. As of this writing the advertised free tier includes a 10-million-token allowance and a free server; token limits and server specs change, so verify the current numbers in the project docs before you architect around them.

To be clear, the gate script itself is plain bash. It works with or without MonkeyCode, with whatever model service your team already uses. The free tier just removes the last excuse for not having this pipeline in place.

A worked example: adding a cache layer

You ask the assistant to add Redis caching to fetchUser. The patch looks great. Then you run the gate.

Gate 1 blocks you immediately: the commit has no provenance marker. You rerun with GENERATED_MARKER=ai-gen:cache-1 and move on. Gate 2 passes. Gate 3 fails: the existing mock doesn't expect a TTL argument. You send the failure log back to the assistant, it updates the mocks, and the suite turns green.

Gate 5 stops the patch again, because go.mod changed and the audit script requires a human review of the new Redis client. You approve the dependency. Gate 7 isn't in the script, but your process rule is: fetchUser is a hot path, so the PR needs a before/after benchmark. Without it, the merge stays blocked.

That sequence takes about twenty minutes and catches two real issues before they reach production. That's the point of the gate. It converts this looks fine into a list of things you can prove.

When this checklist will bite you

The gates are honest about their limits:

  • A gate is only as good as your test suite. If you have no tests, the gate blocks every patch with the same error, and you'll be tempted to delete it. Fix the suite first.
  • Free tiers are subject to change. Anything this article says about the 10-million-token allowance is what the project currently advertises, not a contract.
  • Automated gates don't replace human judgment. For regulated work, you still need a named human to sign off, and gates 7-9 exist to make that sign-off meaningful.
  • This pipeline is wrong for teams that don't care about evidence yet. If merge speed is the only metric, fail-closed gates will annoy everyone. That's a process problem, not a script problem.

Who should use it: teams with an existing CI and at least a basic test suite who are introducing AI-assisted coding and want to see failures early. Who should not: teams hoping tooling alone will fix a broken engineering process.

The gate is the product

Model quality is a moving target. Your test suite and review habits are things you actually control. The next time someone proposes an AI coding workflow, don't ask which model it uses. Ask which gate will block it when the model is confidently wrong.

If you want to run this experiment cheaply, the fastest path is to point the script at your next AI-assisted PR and watch it block something. When it does, you'll know your process just got more honest. The MonkeyCode project docs walk through setting up the free-tier assistant and server if you want the whole loop at zero cost.

Top comments (0)