Quality gates for AI-assisted codebases โ catch the slop LLMs leave behind.
Project description
๐ชฃ Slop-Mop
Quality gates for AI-assisted codebases. Not a silver bullet โ just a mop.
LLMs optimize for task completion, not codebase health. Left unchecked, they cargo-cult patterns, duplicate code they can't see, and accumulate technical debt in predictable, repeatable ways. Slop-Mop is a set of quality gates you bolt onto a project to catch that stuff automatically โ duplication, coverage gaps, complexity creep, security blind spots, bogus tests โ so you can focus on the decisions only a human can make.
Phase 1: Remediation. Bolt it on, run it, fix what it finds. Phase 2: Maintenance. Keep the gates passing on every commit.
Quick Start
# Install once per machine
pipx install slopmop # recommended โ isolated, no dep conflicts
# or: pip install slopmop
# Per-project setup (run in your repo root)
sm init # auto-detects project type, writes .sb_config.json
sm validate commit # run quality gates
Auto-detects your project type and enables relevant gates. See sm init for details and sm config for customization.
How It Works
Run a profile, fix what fails, repeat:
sm validate commit
When a gate fails, the output tells you exactly what to do next:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ค AI AGENT ITERATION GUIDANCE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Profile: commit โ
โ Failed Gate: python-coverage โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ NEXT STEPS: โ
โ โ
โ 1. Fix the issue described above โ
โ 2. Validate: sm validate python-coverage --verbose โ
โ 3. Resume: sm validate commit โ
โ โ
โ Keep iterating until all the slop is mopped. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Iterate until all gates pass, then commit. Use sm status for a full report card.
Available Gates
Python
| Gate | Description |
|---|---|
python:lint-format |
๐จ Code formatting (black, isort, flake8) |
python:static-analysis |
๐ Type checking with strict typing (mypy) |
python:tests |
๐งช Test execution (pytest) |
python:coverage |
๐ Whole repo coverage analysis (80% threshold default) |
python:diff-coverage |
๐ Coverage on changed lines only (diff-cover) |
JavaScript
| Gate | Description |
|---|---|
javascript:lint-format |
๐จ Linting/formatting (ESLint, Prettier) |
javascript:tests |
๐งช Test execution (Jest) |
javascript:coverage |
๐ Coverage analysis |
javascript:types |
๐ TypeScript type checking (tsc) |
Quality
| Gate | Description |
|---|---|
quality:complexity |
๐ Cyclomatic complexity (radon) |
quality:dead-code |
๐ Dead code detection (vulture) |
quality:loc-lock |
๐ File and function length limits |
quality:source-duplication |
๐ Code duplication detection (jscpd) |
quality:string-duplication |
๐ค Duplicate string literal detection |
quality:bogus-tests |
๐ง Bogus test detection (AST analysis) |
general:templates |
๐ Template syntax validation |
Security
| Gate | Description |
|---|---|
security:local |
๐ Code security scan (bandit + semgrep + detect-secrets) |
security:full |
๐ Security audit (code scan + dependency vulnerabilities via pip-audit) |
Profiles
| Profile | Description | Gates Included |
|---|---|---|
commit |
Commit validation | lint, static-analysis, tests, coverage, complexity, dead-code, loc-lock, duplication (source + string), bogus-tests, security-local, JS gates |
pr |
Full PR validation | All commit gates + PR comments, diff-coverage, security-full |
quick |
Ultra-fast lint check | lint, security-local |
JS gates auto-skip when no JavaScript is detected.
Setup: sm init
sm init # Interactive setup
sm init --non-interactive # Auto-detect, use defaults
Scans your repo, detects languages and test frameworks, writes .sb_config.json. Re-run to start fresh (backs up existing config first).
Start with what passes, disable the rest, ramp up over time:
sm config --disable python:coverage # Not ready yet
sm validate commit # Get everything else green first
sm config --enable python:coverage # Enable later
Configuration: sm config
sm config --show # Show all gates and their status
sm config --enable <gate> # Enable a disabled gate
sm config --disable <gate> # Disable a gate
sm config --json <file> # Update config from a JSON file
Include / Exclude Directories
sm config --exclude-dir quality:generated # Skip generated code
sm config --include-dir python:src # Only check src/
include_dirs: whitelist โ only these dirs are scannedexclude_dirs: blacklist โ always skipped, takes precedence
Edit .sb_config.json directly for per-gate configuration:
{
"version": "1.0",
"default_profile": "commit",
"python": {
"gates": {
"coverage": { "threshold": 80 },
"tests": { "test_dirs": ["tests"] }
}
},
"quality": {
"exclude_dirs": ["generated", "vendor"]
}
}
Git Hooks: sm commit-hooks
sm commit-hooks install commit # Install pre-commit hook
sm commit-hooks status # Show installed hooks
sm commit-hooks uninstall # Remove slop-mop hooks
Once installed, gates run automatically before every git commit. Failed gates block the commit.
CI Integration: sm ci
Example GitHub Actions workflow:
name: slop-mop
on:
pull_request:
branches: [main]
push:
branches: [main]
jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-python@v5
with:
python-version: '3.11'
- run: pip install slopmop
- run: sm validate commit
- if: github.event_name == 'pull_request'
env:
GH_TOKEN: ${{ github.token }}
run: sm validate pr:comments
Check CI status locally:
sm ci # Current PR
sm ci 42 # Specific PR
sm ci --watch # Poll until CI completes
The pr:comments gate checks for unresolved PR review threads. Use sm validate pr locally to see what's outstanding, fix or resolve each thread, then re-run until clear.
Architecture
Slop-mop installs as a normal package (pipx install slopmop or pip install slopmop) and is configured per-project via .sb_config.json. The sm command is on your PATH once and works in any repo.
Tool resolution order: When sm runs a check, it looks for the required tool in this order:
<project_root>/venv/bin/<tool>or.venv/bin/<tool>โ project-local venv (highest priority)$VIRTUAL_ENV/bin/<tool>โ currently activated venv- System PATH โ where sm's own bundled tools live when installed via pipx
This means if your project has its own pytest (with project-specific plugins like pytest-django), sm will use it. If it doesn't, sm falls back to its own.
Version pinning: If you need strict version pinning, the git submodule approach still works. Add slop-mop as a submodule and invoke python -m slopmop.sm from it directly. The submodule model is supported but no longer recommended for most projects.
Development
# Working on slop-mop itself
pip install -e .
sm validate --self
pytest
See CONTRIBUTING.md for adding new gates.
Further Reading
๐ A Hand for Daenerys: Why Tyrion Is Missing from Your Vibe-Coding Council
License
Slop-Mop Attribution License v1.0 โ free to use, modify, and redistribute with attribution.
P.S. Other than this line in the readme and a few scattered lines here and there, nothing in this project was written by a human. It is, for better or worse, the result of living under the slop-mop regime.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file slopmop-0.1.0.tar.gz.
File metadata
- Download URL: slopmop-0.1.0.tar.gz
- Upload date:
- Size: 127.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
27bee983dcceb4a5b724a2e3cba4973067aa425d5319ccac3859b90b1665edf3
|
|
| MD5 |
1a2e88fda16b9247d2e8585f1362d82a
|
|
| BLAKE2b-256 |
4c8e2a3db3e14820713a2366456de5f29037d7a3a2c22e0906bec009e083cddd
|
Provenance
The following attestation bundles were made for slopmop-0.1.0.tar.gz:
Publisher:
release.yml on ScienceIsNeato/slop-mop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
slopmop-0.1.0.tar.gz -
Subject digest:
27bee983dcceb4a5b724a2e3cba4973067aa425d5319ccac3859b90b1665edf3 - Sigstore transparency entry: 976242417
- Sigstore integration time:
-
Permalink:
ScienceIsNeato/slop-mop@9b182a0dd409049a3ad6adf1c964569ef62b15ee -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ScienceIsNeato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9b182a0dd409049a3ad6adf1c964569ef62b15ee -
Trigger Event:
push
-
Statement type:
File details
Details for the file slopmop-0.1.0-py3-none-any.whl.
File metadata
- Download URL: slopmop-0.1.0-py3-none-any.whl
- Upload date:
- Size: 158.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
959c504560eb437fe9472c093cc9a67f92c359b0157aced3dd813e487e8f7705
|
|
| MD5 |
78f409248ed8fc3dee3a7a9cf8d6a88c
|
|
| BLAKE2b-256 |
a45542bf576494977d4566ac2bf0b23c3b850b37108d01540fbbcc332e2ddbd5
|
Provenance
The following attestation bundles were made for slopmop-0.1.0-py3-none-any.whl:
Publisher:
release.yml on ScienceIsNeato/slop-mop
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
slopmop-0.1.0-py3-none-any.whl -
Subject digest:
959c504560eb437fe9472c093cc9a67f92c359b0157aced3dd813e487e8f7705 - Sigstore transparency entry: 976242418
- Sigstore integration time:
-
Permalink:
ScienceIsNeato/slop-mop@9b182a0dd409049a3ad6adf1c964569ef62b15ee -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/ScienceIsNeato
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@9b182a0dd409049a3ad6adf1c964569ef62b15ee -
Trigger Event:
push
-
Statement type: