The Mistake That Made This Necessary

Today, an AI agent working on the .pip repository committed directly to main and pushed to GitHub—violating one of our most fundamental rules: NEVER work directly on main.

The rule was clearly documented in WARP.md:

IMPORTANT: All changes MUST be made on feature branches. NEVER commit directly to main, even for small documentation updates.

Yet when the agent created the ROADMAP.md file, it worked directly on main instead of creating a feature branch. The violation was caught immediately by the user, but the damage was done—the commit was already on GitHub.

The Problem

Documentation alone isn’t enough. Even with clear rules and prominent warnings, mistakes happen:

The solution? Make the wrong thing hard to do.

The Solution: Defense in Depth

We implemented a two-layer protection system:

Layer 1: Local Git Hooks

A pre-commit hook that runs before any commit:

#!/usr/bin/env bash
branch="$(git rev-parse --abbrev-ref HEAD)"

if [ "$branch" = "main" ]; then
  echo ""
  echo "❌ ERROR: Direct commits to 'main' branch are not allowed!"
  echo ""
  echo "Please use a feature branch instead:"
  echo "  git checkout -b feat/your-feature"
  echo ""
  exit 1
fi

Benefits:

Layer 2: GitHub Branch Protection

Configured via GitHub API with these rules:

Benefits:

Installation

For all contributors (takes 10 seconds):

cd /path/to/pip
./hooks/install-hooks.sh

Output:

Installing git hooks...
✅ Installed pre-commit hook (blocks commits to main)

These hooks will:
  - Block direct commits to main branch
  - Check for secrets (if git-secrets is installed)

For repository administrators, GitHub protection is configured via API and documented in docs/github-branch-protection.md.

How It Works in Practice

Before (wrong way):

git checkout main
# make changes
git commit -m "quick fix"  # ❌ Used to work (BAD!)

After (enforced workflow):

git checkout main
# make changes
git commit -m "quick fix"

# Output:
# ❌ ERROR: Direct commits to 'main' branch are not allowed!
#
# Please use a feature branch instead:
#   git checkout -b feat/your-feature

Correct workflow (what you should do):

git checkout -b fix/quick-fix
# make changes
git commit -m "fix: quick fix"
git push origin fix/quick-fix
gh pr create
gh pr merge --squash

Why This Matters

Branch protection isn’t just process bureaucracy—it serves real purposes:

1. Code Review Quality

Pull requests force a moment of reflection:

Even solo developers benefit from the pause.

2. History Clarity

Squash merging via PRs creates clean, semantic git history:

6107df6 Add git hooks and branch protection (#10)
0ac2e70 Add roadmap for agentic system transformation
dce0da0 Add .cursorrules.example template (#9)

Instead of:

abc1234 WIP
def5678 fix typo
ghi9012 actually fix typo
jkl3456 merge

3. CI/CD Integration

PRs are the perfect place to run:

Committing directly to main bypasses all of this.

4. Rollback Safety

If a PR causes issues, you can:

With direct commits, rollback is messier and riskier.

The Learning

This implementation came directly from an AI agent’s mistake. Instead of just scolding the agent, we asked: “How can we make this mistake impossible?”

The answer:

  1. ✅ Local hooks catch mistakes early
  2. ✅ GitHub protection catches bypasses
  3. ✅ Clear error messages guide correct behavior
  4. ✅ Documentation explains the “why”

Now, even if an agent (or human) tries to commit to main, the system gently but firmly redirects them to the correct workflow.

For Solo Developers

“But I’m the only person working on this repo—why do I need branch protection?”

Valid question. Here’s the configuration we landed on for solo repos:

Strict protection (what we tried first):

Solo-friendly protection (what we use):

This gives you:

Emergency Override

In rare emergencies where direct push is absolutely necessary:

# Bypass local hook
git commit --no-verify

# Then temporarily disable GitHub protection
# (documented in docs/github-branch-protection.md)

⚠️ WARNING: This should be extremely rare—perhaps once or twice per year at most. If you’re doing this regularly, something else is wrong.

Resources

What’s Next

With branch protection in place, we can confidently move forward with:

All with the confidence that mistakes will be caught before they cause problems.


Key Takeaway: The best process enforcement is the kind you don’t have to think about—it just prevents mistakes automatically while guiding you to the right path.

Previous: Interactive Bootstrap
Next: Agentic System Transformation Plan