You asked your AI assistant to add a caching layer. It generated 200 lines of clean code. You skimmed it, committed, pushed. The PR got merged.
Three days later: a production bug. The generated code cached error responses.
A review gate would have caught this in seconds.
The Pattern
A review gate is an automated check that runs between "AI generates code" and "code enters your branch." Think of it as a linter specifically designed for AI-generated output.
AI generates code → Review Gate → Your branch
↓
Pass: commit
Fail: fix or regenerate
Gate 1: The Diff Size Check
AI-generated code tends to be verbose. If you asked for a 20-line change and got 200 lines, something went wrong.
#!/bin/bash
# gate-diff-size.sh — Reject oversized AI changes
MAX_LINES="${1:-100}"
DIFF_LINES=$(git diff --cached --stat | tail -1 | grep -oP '\d+ insertion' | grep -oP '\d+')
if [ "${DIFF_LINES:-0}" -gt "$MAX_LINES" ]; then
echo "❌ GATE FAIL: $DIFF_LINES insertions exceeds limit of $MAX_LINES"
echo " AI may have over-generated. Review before committing."
exit 1
fi
echo "✅ Diff size OK: $DIFF_LINES insertions"
Install as a pre-commit hook:
cp gate-diff-size.sh .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
Gate 2: The Import Scanner
AI models love importing things you don't use — or don't have installed.
#!/bin/bash
# gate-imports.sh — Check for phantom imports in staged files
STAGED=$(git diff --cached --name-only --diff-filter=AM | grep -E '\.(ts|js|tsx|jsx)$')
FAIL=false
for file in $STAGED; do
# Check for imports of packages not in package.json
IMPORTS=$(grep -oP "from ['\"]([^./][^'\"]*)" "$file" | sed "s/from ['\"]//")
for pkg in $IMPORTS; do
BASE_PKG=$(echo "$pkg" | cut -d'/' -f1-2 | sed 's/@//' | sed 's/^/@/')
if ! grep -q "\"$BASE_PKG\"" package.json 2>/dev/null; then
echo "❌ Unknown import: '$pkg' in $file"
FAIL=true
fi
done
done
if $FAIL; then
echo " Run 'npm install' or remove unused imports"
exit 1
fi
echo "✅ All imports verified"
Gate 3: The TODO/FIXME Detector
AI models leave breadcrumbs. Catch them before they become permanent.
#!/bin/bash
# gate-todos.sh — Block commits with AI placeholder markers
STAGED=$(git diff --cached --name-only --diff-filter=AM)
MARKERS="TODO|FIXME|HACK|XXX|PLACEHOLDER|IMPLEMENT ME|YOUR_.*_HERE"
FAIL=false
for file in $STAGED; do
HITS=$(grep -nE "$MARKERS" "$file" 2>/dev/null)
if [ -n "$HITS" ]; then
echo "❌ Placeholder found in $file:"
echo "$HITS" | head -5
FAIL=true
fi
done
if $FAIL; then
echo " AI left placeholders. Resolve before committing."
exit 1
fi
echo "✅ No placeholders found"
Gate 4: The Type Check Gate
If you're using TypeScript, this is free — but most people don't run tsc before committing AI code.
#!/bin/bash
# gate-typecheck.sh — Type-check staged files
STAGED_TS=$(git diff --cached --name-only --diff-filter=AM | grep -E '\.tsx?$')
if [ -n "$STAGED_TS" ]; then
npx tsc --noEmit 2>/tmp/tsc-errors.txt
if [ $? -ne 0 ]; then
echo "❌ TypeScript errors in AI-generated code:"
cat /tmp/tsc-errors.txt | head -20
exit 1
fi
fi
echo "✅ Type check passed"
Combining Gates
Chain them in a single pre-commit hook:
#!/bin/bash
# .git/hooks/pre-commit
set -e
echo "🔍 Running AI review gates..."
./gates/gate-diff-size.sh 150
./gates/gate-imports.sh
./gates/gate-todos.sh
./gates/gate-typecheck.sh
echo ""
echo "✅ All gates passed — safe to commit"
When Gates Fail
A gate failure isn't a disaster — it's the system working. When a gate fails:
- Read the error. It tells you exactly what's wrong.
- Fix or regenerate. Sometimes a one-line fix is enough. Sometimes you need to re-prompt with better constraints.
- Update the gate. If you keep hitting false positives, adjust the threshold. If you keep missing bugs, add a new gate.
The Numbers
Since adding review gates to my workflow:
- Placeholder TODOs shipped to main: 0 (was ~2/week)
- Phantom import errors in CI: 0 (was ~1/week)
- Oversized AI commits: caught and split 4 times in the first month
- Time cost: ~3 seconds per commit
Four bash scripts. Three seconds per commit. Zero AI-generated placeholders in production.
Your AI assistant doesn't review its own work. That's your job — but there's no reason to do it manually.
Top comments (0)