Metadata-Version: 2.4
Name: slopmop
Version: 2.3.2
Summary: Quality gates for AI-assisted codebases — catch the slop LLMs leave behind.
Author: ScienceIsNeato
License: Apache-2.0
Project-URL: Homepage, https://github.com/ScienceIsNeato/slop-mop
Project-URL: Repository, https://github.com/ScienceIsNeato/slop-mop
Project-URL: Issues, https://github.com/ScienceIsNeato/slop-mop/issues
Project-URL: Changelog, https://github.com/ScienceIsNeato/slop-mop/releases
Keywords: quality-gate,linting,testing,ci-cd,code-quality,ai,llm,vibe-coding
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: Software Development :: Testing
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: NOTICE
Requires-Dist: tomli>=1.0.0; python_version < "3.11"
Requires-Dist: packaging>=21.0
Requires-Dist: PyYAML>=6.0
Provides-Extra: templates
Requires-Dist: jinja2>=3.0.0; extra == "templates"
Provides-Extra: lint
Requires-Dist: black>=26.3.1; extra == "lint"
Requires-Dist: isort>=5.12.0; extra == "lint"
Requires-Dist: autoflake>=2.0.0; extra == "lint"
Requires-Dist: flake8>=6.0.0; extra == "lint"
Requires-Dist: ruff>=0.1.0; extra == "lint"
Provides-Extra: typing
Requires-Dist: mypy>=1.17.0; extra == "typing"
Requires-Dist: pyright>=1.1.0; extra == "typing"
Requires-Dist: types-PyYAML>=6.0.12; extra == "typing"
Provides-Extra: analysis
Requires-Dist: vulture>=2.14; extra == "analysis"
Requires-Dist: radon>=5.1.0; extra == "analysis"
Provides-Extra: security
Requires-Dist: bandit>=1.7.0; extra == "security"
Requires-Dist: detect-secrets>=1.4.0; extra == "security"
Requires-Dist: cryptography>=46.0.7; extra == "security"
Requires-Dist: pyasn1>=0.6.3; extra == "security"
Requires-Dist: requests>=2.33.0; extra == "security"
Requires-Dist: python-multipart>=0.0.27; extra == "security"
Requires-Dist: pyjwt>=2.13.0; extra == "security"
Requires-Dist: starlette>=1.0.1; extra == "security"
Requires-Dist: semgrep>=1.140.0; extra == "security"
Requires-Dist: pip-audit>=2.0.0; extra == "security"
Provides-Extra: testing
Requires-Dist: pytest>=9.0.3; extra == "testing"
Requires-Dist: pytest-cov>=4.0.0; extra == "testing"
Requires-Dist: pytest-testmon>=2.0.0; extra == "testing"
Requires-Dist: diff-cover>=7.0.0; extra == "testing"
Requires-Dist: jsonschema>=4.0.0; extra == "testing"
Provides-Extra: tools
Requires-Dist: slopmop[lint]; extra == "tools"
Requires-Dist: slopmop[typing]; extra == "tools"
Requires-Dist: slopmop[analysis]; extra == "tools"
Requires-Dist: slopmop[security]; extra == "tools"
Requires-Dist: slopmop[testing]; extra == "tools"
Requires-Dist: slopmop[templates]; extra == "tools"
Provides-Extra: all
Requires-Dist: slopmop[tools]; extra == "all"
Provides-Extra: dev
Requires-Dist: slopmop[all]; extra == "dev"
Dynamic: license-file

# 🪣 Slop-Mop

<p>
  <a href="https://github.com/ScienceIsNeato/slop-mop/actions/workflows/slopmop-sarif.yml"><img src="https://github.com/ScienceIsNeato/slop-mop/actions/workflows/slopmop-sarif.yml/badge.svg" alt="Primary code scanning gate"/></a>
  <a href="https://codecov.io/gh/ScienceIsNeato/slop-mop"><img src="https://codecov.io/gh/ScienceIsNeato/slop-mop/branch/main/graph/badge.svg" alt="Coverage"/></a>
  <a href="https://pypi.org/project/slopmop/"><img src="https://img.shields.io/pypi/v/slopmop.svg" alt="PyPI version"/></a>
  <a href="https://pypi.org/project/slopmop/"><img src="https://img.shields.io/pypi/pyversions/slopmop.svg" alt="Python versions"/></a>
  <a href="https://pypistats.org/packages/slopmop"><img src="https://img.shields.io/pypi/dm/slopmop.svg" alt="PyPI downloads/month"/></a>
  <a href="https://github.com/ScienceIsNeato/slop-mop/releases"><img src="https://img.shields.io/github/v/release/ScienceIsNeato/slop-mop?display_name=tag&amp;sort=semver" alt="Latest GitHub release"/></a>
  <a href="https://github.com/ScienceIsNeato/slop-mop/blob/main/LICENSE"><img src="https://img.shields.io/badge/license-Slop--Mop%20Attribution%20v1.0-blue.svg" alt="License"/></a>
  <a href="https://github.com/ScienceIsNeato/slop-mop#use-with-claude"><img src="https://img.shields.io/badge/Claude-skill%20%2B%20plugin-7a5bff?logo=anthropic&amp;logoColor=white" alt="Claude skill + plugin"/></a>
</p>

Slop-mop reshapes the agent’s terrain so the most maintainable move feels like the easiest one downhill.

<img src="https://raw.githubusercontent.com/ScienceIsNeato/slop-mop/main/assets/heraldic_splash.png" alt="Slop-Mop heraldic" width="300" align="right"/>

It does not try to turn agents into what they aren't. Slop-mop reshapes the workflow
landscape around them: refit carves the initial terrain, swab/scour/buff keep the
gradient pointed at maintainable code, and wake-angry-drunk-captain blocks fake
progress when only a human decision can break the tie.

Don't make sloppy choices. Keep moving forward and address debt relentlessly.
Resist the urge to side-step the check. Just fix what it flags and keep moving: that is the whole idea.

It is purposefully opinionated, as structure begets adherence to best practices.

## Project Status

slop-mop is at version 2.3.2. The current public policy surface for release and
stability expectations lives here:

- [DOCS/COMPATIBILITY.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/COMPATIBILITY.md)
- [DOCS/MIGRATIONS.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/MIGRATIONS.md)
- [DOCS/RELEASING.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/RELEASING.md)
- [SECURITY.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/SECURITY.md)

## Quick Start

Install it:

```bash
pipx install slopmop[all]
```

Set up a repo:

```bash
sm init
```

Choose a starting point.

For an existing repo, start with refit. It walks the project through a
structured cleanup before you enter the day-to-day maintenance loop:

```bash
sm refit --start
sm refit --iterate
sm refit --finish
```

If you cannot do the full refit right now, generate a baseline as a temporary
escape hatch. That keeps new failures loud while you come back to the cleanup:

```bash
sm status --generate-baseline-snapshot
sm swab --ignore-baseline-failures
```

Run the normal loop:

```bash
sm swab
```

If it fails, fix what it reported and run `sm swab` again. When it passes,
commit. Before opening or updating a PR, run the deeper pass:

```bash
sm scour
```

After CI or review feedback lands:

```bash
sm buff
```

If you are not sure what comes next, use the auto-advance command:

```bash
sm sail
```

It reads the current workflow state and runs the next obvious slop-mop verb.

## Use with Claude

Slop-mop ships as a Claude plugin: a skill that auto-triggers on remediation
prompts, plus eight slash commands (`/sm-init`, `/sm-refit`, `/sm-sail`,
`/sm-swab`, `/sm-scour`, `/sm-buff`, `/sm-barnacle`,
`/sm-wake-angry-drunk-captain`). Install once and `sm` is available in every
repo — no per-repo `sm agent install` required.

<p align="center">
  <img src="https://raw.githubusercontent.com/ScienceIsNeato/slop-mop/main/assets/claude-skill-demo.gif" alt="Demo: sm scour flagging a bogus test, an uncovered function, and a silenced gate in one run" width="780"/>
</p>

In Claude Code or Cowork:

```
/plugin marketplace add ScienceIsNeato/slop-mop
/plugin install slopmop
```

Then ask Claude things like *"refit this repo"*, *"sail this repo"*, *"swab my
changes before I commit"*, *"buff PR 142"*, or *"file a barnacle for this sm
friction"*. The skill activates on remediation language and runs the right verb.

The CLI itself is still a prerequisite — install it once with
`pipx install slopmop[all]` and the plugin will call into it.

When `sm` itself gives invalid guidance or blocks valid work, use
`/sm-barnacle` or `sm barnacle file`. That is the preferred internal friction
reporting path; do not file ad hoc `gh issue create` reports for slop-mop
tooling defects.

Distribution notes, promotion TODOs, and adoption-tracking signals live in
[DOCS/PENETRATION_EFFORTS.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/PENETRATION_EFFORTS.md).

## The Loop

Slop-mop has five verbs you will actually use:

| Verb | What it is for | When to run it |
| --- | --- | --- |
| `sm status` | Workflow state and baseline snapshots | When you need current state or a temporary baseline |
| `sm swab` | Code-centric local feedback | After meaningful code changes |
| `sm scour` | Code-centric pre-PR sweep | Before opening or updating a PR |
| `sm buff` | Process-centric CI and review follow-up | After CI completes or review feedback lands |
| `sm sail` | Process-centric next-step selection | When you are not sure what to do next |

The boring version:

```text
write code -> sm swab -> commit -> sm scour -> push/open PR -> sm buff watch -> sm buff
```

Not sure where you are in that loop? `sm sail` figures it out for you.
Full state machine: [DOCS/WORKFLOW.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/WORKFLOW.md).

<figure>
  <img src="https://raw.githubusercontent.com/ScienceIsNeato/slop-mop/main/assets/sm-swab-human-readable.png" alt="Human-readable sm swab output showing grouped quality gates and a no slop detected summary" />
  <figcaption>
    The default <code>sm swab</code> view is built for humans: grouped gates,
    progress, timings, and a clear final verdict. Agent loops can use
    <code>--porcelain</code> when they need terse output instead.
  </figcaption>
</figure>

## What It Checks

Slop-mop groups gates around four common agent failure modes.

**Overconfidence**  
The code compiles. Tests pass. That's not the same as being tested or covered.
This catches missing tests, coverage gaps, and type-blindness that slips through
because the code *runs*.

**Deceptiveness**  
Tests pass, but do they actually prove anything? Bogus assertions, tests that
exist to make the coverage report happy, leftover debug traces that signal the
code was never properly cleaned up before shipping. Slop-mop sees through it.

**Laziness**  
Working code rots. Complexity creep, dead code, formatting drift, repeated
logic - these compound quietly until the codebase becomes unnavigable.
Catch them while they're small.

**Myopia**  
Your change looks fine. The repo-wide picture might not be. Duplication,
security gaps, dependency risk - things that only show up when you zoom out
past the file you're in.

The full gate reasoning lives in [DOCS/GATE_REASONING.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/GATE_REASONING.md).

## Refit vs Maintenance

New repo or inherited mess? Start with refit. It builds a remediation plan
and walks you through gate-by-gate until the codebase is clean enough to
enter the maintenance loop:

```bash
sm refit --start
sm refit --iterate
sm refit --finish
```

Once you're in decent shape, maintenance is just the loop:

```bash
sm swab
sm scour
sm buff
```

Don't skip refit to go straight to maintenance on a dirty repo. You'll spend
more time fighting the gates than fixing the code. Do the work upfront.

## Minimal Install

If you only want the framework without optional gate dependencies:

```bash
pipx install slopmop
```

Minimal install gives you the framework. Gates that need tools like `black`,
`pyright`, `bandit`, or `pytest` will tell you what is missing.

Developer setup details live in [DOCS/DEVELOPING.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/DEVELOPING.md).

## Configuration

`sm init` writes `.sb_config.json` after looking at the repo. It enables gates
that appear relevant and leaves non-applicable gates alone.

Useful commands:

```bash
sm config --show
sm config --enable myopia:vulnerability-blindness.py
sm config --disable laziness:complexity-creep.py
```

Disabling a gate should be temporary. If a gate is wrong, tune it or file the
bug. Don't just silence it and move on - that's how slop accumulates.

Migration behavior is documented in [DOCS/MIGRATIONS.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/MIGRATIONS.md).

## Baselines

Inherited a mess and can't stop to fix it all right now? Snapshot the current
failures. New failures stay loud, old ones get paid down over time:

```bash
sm status --generate-baseline-snapshot
sm swab --ignore-baseline-failures
sm scour --ignore-baseline-failures
```

This isn't a way to hide problems. It's a way to stop old debt from blocking
every unrelated change while you work back to a clean state. Don't live in
baseline mode - it's a temporary unblocker, not a permanent config.

## CI

Run slop-mop in CI the same way you run it locally: install it and run the gate
command.

See [DOCS/CI.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/CI.md) for a GitHub Actions template.

## Agent Setup

Slop-mop can install repo-local agent instructions for common coding agents:

```bash
sm agent install
```

You can target one agent if you prefer:

```bash
sm agent install --target copilot
sm agent install --target cursor
sm agent install --target claude
```

Generated agent files are local workspace configuration. They should stay out
of source control; the reusable source templates live in this repository under
`slopmop/agent_install/templates/`.

The short version for agents: ride the rail, fix what it reports, do not bypass
the gate.

## PR Review and Bot Integration

Slop-mop closes the loop on PR feedback too, not just local code quality. Once
a PR is open, review comments accumulate from humans, and bots alike. Left 
unaddressed, they block the merge and erode reviewer trust. `sm buff`
handles this:

```bash
sm buff inspect <PR>      # triage CI results + fetch all unresolved threads
sm buff resolve <PR> <ID> --scenario fixed_in_code --message "<evidence>"
                          # post a reply and resolve the thread
sm buff verify <PR>       # confirm nothing is still open
sm buff watch <PR>        # poll CI until it finishes
```

The `myopia:ignored-feedback` gate checks this during `sm scour`. By default it
warns if unresolved review threads exist; set `fail_on_unresolved: true` if you
want `sm scour` to block on them. `sm buff` runs the same check in blocking
mode, so the post-PR rail won't report a PR as clean while comments remain open.

### Review Bots

Copilot code review, Cursor's bugbot and the like catch things slop-mop deliberately
doesn't try to own: logic errors in your specific domain, API misuse, smelly design
patterns and logical errors. They're trained on human review patterns;
slop-mop is optimized for the failure modes unique to agent-generated code.

Run them in parallel, not as alternatives. The combination covers more ground:

- slop-mop: duplication, complexity creep, coverage gaps, unaddressed feedback
- Copilot / bugbot / human reviewers: logic correctness, style conformance, domain-specific hazards

When a bot leaves a comment, treat it like a human reviewer left it. Use
`sm buff resolve` to reply and close the thread - the same workflow applies
regardless of who opened it.

## Custom Gates

Slop-mop's CI framework is well adapted to existing checks that are not covered
by built-in gates. Add your own check as a custom gate and manage it like any
other slop-mop quality gate.

Start with [DOCS/NEW_GATE_PROTOCOL.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/NEW_GATE_PROTOCOL.md).

## When To Push Back On The Tool

Sometimes slop-mop is wrong.

That's useful information. Don't route around it with ad-hoc commands and
pretend the rail is fine. Fix the gate, tune the config, file the bug. The
point isn't obedience - it's making the correct path the path of least
resistance.

For slop-mop tooling friction, file a barnacle issue upstream:

```bash
sm barnacle file \
  --title "short summary of the slop-mop friction" \
  --command "sm <verb> [flags]" \
  --expected "what should have happened" \
  --actual "what happened instead" \
  --repro-step "how to reproduce it" \
  --tried "what you already tried" \
  --workflow swab \
  --blocker-type blocking \
  --json
```

Barnacles are for defects in slop-mop itself: invalid guidance, false gate
results, broken rails, confusing output, or install/upgrade/refit friction. They
create structured GitHub issues tagged for maintainer triage. They are not a
local queue and not a replacement for fixing real target-repo failures.
The generated Markdown body is also written to `.slopmop/last_barnacle_issue.md`
so failed filings are retryable without reconstructing context.

## Contributing

For repo conventions, see [DOCS/CONVENTIONS.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/CONVENTIONS.md).

For contribution guidance, see [DOCS/CONTRIBUTING.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/CONTRIBUTING.md).

For local development, see [DOCS/DEVELOPING.md](https://github.com/ScienceIsNeato/slop-mop/blob/main/DOCS/DEVELOPING.md).

## License

Slop-mop is licensed under the [Apache License 2.0](https://github.com/ScienceIsNeato/slop-mop/blob/main/LICENSE).

Attribution is appreciated — see the [NOTICE](https://github.com/ScienceIsNeato/slop-mop/blob/main/NOTICE) file.
