Skip to content

AI slop PR firewall for open source — detect and block low-quality AI-generated pull requests with a single GitHub Action.

License

Notifications You must be signed in to change notification settings

A386official/slopgate

Repository files navigation

     _____ _             _____       _
    / ____| |           / ____|     | |
   | (___ | | ___  _ __| |  __  __ _| |_ ___
    \___ \| |/ _ \| '_ \ | |_ |/ _` | __/ _ \
    ____) | | (_) | |_) | |__| | (_| | ||  __/
   |_____/|_|\___/| .__/ \_____|\__,_|\__\___|
                  | |
                  |_|

SlopGate

CI License: MIT Node.js

The AI slop firewall for open source maintainers.


The Problem

Open source is drowning in low-quality pull requests generated by AI tools and submitted without review. The Godot engine maintainers were overwhelmed by mass AI-generated PRs that wasted hundreds of hours of reviewer time. curl shut down its bug bounty program after a flood of AI-generated reports that were worse than useless. GitHub itself has discussed implementing a kill switch for AI-generated contributions. SlopGate gives you that kill switch today -- a configurable, automated defense against the wave of low-effort AI-generated pull requests flooding open source.

Quick Start

Add this workflow to your repository at .github/workflows/slopgate.yml:

name: SlopGate

on:
  pull_request:
    types: [opened, synchronize, reopened]

permissions:
  pull-requests: write
  issues: write

jobs:
  slopgate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: A386official/slopgate@v1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

That's it. Every PR will be analyzed and scored automatically.

How It Works

SlopGate runs 12 independent detectors across three categories, produces a weighted score from 0-100, and responds accordingly:

Score Range Verdict Action
0-29 Pass Green label added. No comment.
30-59 Warn Yellow label + comment with findings.
60-79 Flag Red label + changes requested with detailed analysis.
80-100 Block Block label + full report. Optionally auto-closes the PR.

Detection Methods

SlopGate analyzes three signal categories:

Behavioral Checks

Check What It Detects Default Weight
PR Velocity >3 PRs to the same repo in 24 hours 80
Abandonment Rate High percentage of closed-without-merge PRs 60
Shotgun Pattern Identical PRs submitted across multiple repositories 90
New Account Account <30 days old submitting first PR to the repo 20

Content Checks

Check What It Detects Default Weight
Placeholder Code Empty functions, bare pass statements, TODO stubs, placeholder variable names 70
Hallucinated Imports Import statements referencing packages not in the project's dependencies 90
Docstring Inflation Comment-to-code ratio above 60%, padding thin contributions with verbose docs 40
Internal Duplication Large blocks of identical code copy-pasted within the diff 60

Pattern Checks

Check What It Detects Default Weight
Generic Description Vague titles like "fix bug" or "update code" with no meaningful body 50
Oversized Diff 500+ line changes with a one-sentence description 60
Unrelated Changes Files spanning 5+ unrelated directories in a single PR 40
Formatting Only Whitespace-only changes that claim to fix bugs or add features 30

Scoring System

Each check produces a raw score from 0-100. The final score is computed as a weighted average:

finalScore = sum(check.score * check.weight) / sum(check.weight)

Checks with weight 0 are skipped entirely. The verdict is determined by comparing the final score against configurable thresholds.

Configuration

Create a .slopgate.yml file in your repository root to customize behavior:

# Score thresholds for each response tier
thresholds:
  warn: 30     # 30-59: review label + comment
  flag: 60     # 60-79: flagged label + request changes
  block: 80    # 80+: blocked label + optional auto-close

# Auto-close PRs that score above the block threshold
# WARNING: Use with caution. Defaults to false.
auto_close: false

# Check weights (0-100, set to 0 to disable a check)
weights:
  velocity: 80
  abandonment: 60
  shotgun: 90
  new_account: 20
  placeholder: 70
  hallucinated_import: 90
  docstring_inflation: 40
  copy_paste: 60
  generic_description: 50
  oversized_diff: 60
  unrelated_changes: 40
  formatting_only: 30

# Allowlist -- PRs from these users/bots skip all checks
allowlist:
  users: []
  bots:
    - dependabot[bot]
    - renovate[bot]
    - github-actions[bot]

Configuration Reference

Field Type Default Description
thresholds.warn number 30 Minimum score to trigger a warning
thresholds.flag number 60 Minimum score to flag and request changes
thresholds.block number 80 Minimum score to block (and optionally close)
auto_close boolean false Automatically close PRs above block threshold
weights.<check> number varies Weight for each check (0 disables it)
allowlist.users string[] [] Usernames that bypass all checks
allowlist.bots string[] [dependabot, renovate, github-actions] Bot accounts that bypass all checks

Action Inputs and Outputs

Inputs

Input Required Default Description
github-token Yes ${{ github.token }} GitHub token with pull-requests: write and issues: write permissions

Outputs

Output Description
score Final SlopGate score (0-100)
verdict Verdict: pass, warn, flag, or block
allowlisted Whether the PR author was allowlisted
summary Human-readable summary of findings

Use outputs in subsequent workflow steps:

- uses: A386official/slopgate@v1
  id: slopgate
  with:
    github-token: ${{ secrets.GITHUB_TOKEN }}

- name: Block merge if flagged
  if: steps.slopgate.outputs.verdict == 'block'
  run: exit 1

Architecture

pull_request event
       |
       v
  +-----------+
  |  index.ts  |  Entry point: load config, fetch PR data
  +-----------+
       |
       v
  +-------------------+
  | checks/behavioral |  velocity, abandonment, shotgun, new_account
  | checks/content    |  placeholder, hallucinated_import, docstring_inflation, copy_paste
  | checks/patterns   |  generic_description, oversized_diff, unrelated_changes, formatting_only
  +-------------------+
       |
       v
  +-------------+
  | scoring.ts  |  Weighted average -> verdict
  +-------------+
       |
       v
  +-------------+
  | respond.ts  |  Labels, comments, review requests, auto-close
  +-------------+

Without SlopGate vs. With SlopGate

Scenario Without With SlopGate
Bot opens 20 identical PRs across repos You review and close each one manually Detected by velocity + shotgun checks, auto-labeled or auto-closed
New account submits 800-line PR titled "fix bug" Lands in your review queue with no context Flagged: generic description + oversized diff + new account signals
PR adds 50 empty functions with TODO stubs Looks like progress at a glance Caught by placeholder check, detailed findings posted
PR imports packages that don't exist in your project Breaks CI, wastes reviewer time investigating Hallucinated import check identifies unknown dependencies immediately
PR is 90% comment padding with 3 lines of actual code Inflates the diff to look substantial Docstring inflation check exposes the real code-to-comment ratio

Development

# Install dependencies
npm install

# Run tests
npm test

# Type check
npx tsc --noEmit

# Build
npm run build

Contributing

See CONTRIBUTING.md for guidelines.

License

MIT -- A386official

About

AI slop PR firewall for open source — detect and block low-quality AI-generated pull requests with a single GitHub Action.

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors