Agents write plausible code fast, and some of it takes shortcuts a careful engineer would not: a test skipped to get green, an error swallowed, a stub left in, a type check silenced, a second way of doing what your codebase already does. The anti-slop check looks for these in every change and sends the change back to the developer agent before you see it.
It is one check in your quality policy, not a separate score. A change passes it when it introduces nothing that blocks.
What it looks for
Rules are grouped into families. Each rule either blocks, advises or records info.
- Tests — focused or skipped tests, deleted tests, removed or weakened assertions, tests that cannot fail.
- Suppressions — new lint disables, type ignores and
anycasts. - Build and CI — test steps removed or neutralised, thresholds lowered, "pass with no tests", GitHub Actions not pinned to a commit.
- Test evidence — cached results passed off as a run, zero tests executed, a partial run reported as complete.
- Production code — debug leftovers, placeholders, mock data, notes to humans, test code shipped.
- Error handling — swallowed errors, fallbacks that hide failures, fail-open permission checks.
- Dependencies — packages that do not exist or are reported as malicious, new packages named like a popular one, packages that run code when they are installed, manifests changed without their lockfile.
- Security — secrets in code, TLS checks turned off, removed authorization checks, downloaded scripts run straight from the network.
- Comments, Architecture, Change scope, Caching and the agent trail — the record of what the agent did, such as editing a test right after it failed.
Each rule in Anti-slop rules, opened from the Anti-slop row in Quality Control, shows what it matches, why it matters and what it does in the organization default or in a project.
Only what the change introduced blocks
Most repositories already contain some of these patterns. Anti-slop sorts every finding into one of three groups:
- Introduced — new in this change.
- Touched — already there, on a line or in a function the change edits.
- Existing — elsewhere in the repository.
Only an introduced finding of a blocking rule fails the check. Touched and existing findings are recorded so you can follow your debt in Factory, under Debt, and file a task to fix a rule's findings there, but they never hold up unrelated work. Moving code does not count as introducing it; copying it does.
Raised
- An advisory gate
The reviewer agent
- A connected scanner
Routed
Fixable
Back to the developer as rework
Everything else
Attached to the pull request
Resolved
Fixed
The change addresses it
Accepted
True, not worth acting on here. Say why.
Suppressed
A false positive or rule that does not apply. Say why.
Weekly debt cleanup
Existing debt does not block, but it does not have to stay. Open a project in Quality Control, expand Anti-slop and switch on Weekly debt cleanup. Once a week Coroid scans the project's default branch and files small cleanup tasks for the debt it finds, a few files each. It keeps at most as many cleanup tasks open as Open tasks at a time says (two by default), so cleanup never crowds out the work people asked for. Every change offers Undo.
The cleanup is set per project. Its schedule is listed in Factory and says Quality Control manages it; change it here, not there.
New Work used to offer a "Weekly tech-debt cleanup" template. A schedule you created from it keeps running and is named under the switch; pause it in Factory if the debt cleanup replaces it.
Turning it on
In Quality Control, choose the organization default or a project and switch on Anti-slop. It adds five expectations:
- Tests still prove the change.
- Nothing unfinished or test-only ships.
- No new structural debt.
- The change stays in scope and reads like this codebase.
- New dependencies are real and reputable.
The change applies at once: the next run of that project, or of every project that follows the default, includes the check. The row's settings choose the change discipline, which groups block and the judge rules, and switching it off keeps them for the next time you switch it on.
Choosing a change discipline
The discipline tells the developer agent how far a change may reach:
- Surgical — only what the specification needs; other problems are reported, not fixed.
- Balanced (default) — also fix small problems on lines the change touches anyway.
- Restorative — also clean up findings inside the functions the change edits.
The agent works to the same rules before it submits: it gets the discipline and your quarantined patterns up front, sees the fast rules after every edit, and gets one chance to fix blocking findings before QA.
Making it fit your codebase
- Rule overrides — open a rule in Anti-slop rules to make it block, advise, only report or stop, for the organization default or for one project.
- Rule packs — your own patterns, forbidden imports and dependencies, file size limits, or results from tools you already run (SARIF). Each save is a new version, and a check keeps the version it selected.
- Quarantine — patterns you do not want copied any more, each with the replacement to use instead. Agents are told not to spread them, and new copies are flagged.
- Excluded paths — in Quality Control → Anti-slop, the generated or vendored
files no anti-slop check reads, one pattern per line (
dist/**,vendor/**). Use them for committed build output: a changed file over the scanner's 512 KiB limit that a rule needs makes the checks unavailable. - Repository file —
.coroid/anti-slop.ymlin the repository can add rules and excludegenerated/,vendor/,node_modules/and__generated__/directories. It is read from the base of the change, so a change cannot loosen its own rules, and editing it needs approval. - Lockfiles and translation catalogues — anti-slop counts their changes but
does not read them. Catalogues are the files
.coroid/i18n.jsondeclares at the base of the change; the Globalization check reads those. A rule of your own that names them still reads them.
New dependencies
Models sometimes suggest a package that does not exist, often a plausible mix of two real names. Attackers register such names on npm and PyPI so that the next install runs their code, an attack called slopsquatting. The Cloud Security Alliance describes it: almost one in five of the 2.23 million code samples in the research it cites named at least one package that did not exist.
Anti-slop looks up each dependency a change adds to package.json, a
requirements file or pyproject.toml:
- Blocks — a package that is not in its public registry, or one that OSV reports as malicious. The change goes back to the developer agent before you see it.
- Advises — a package first published less than 30 days ago, one with very few downloads, one whose name is one or two letters away from a popular package, or an npm package that runs code when it is installed. A PyPI package with a release reported as malicious also advises, because Coroid does not know which release a requirement installs.
If a registry cannot be reached, the check says so in its result and decides on the packages it could look up. It does not hold the change.
Which names Coroid looks up
Looking up a name sends it to a public registry, so an owner or admin chooses which names may leave Coroid, in Quality Control → Anti-slop → Checking new dependencies. The choice applies to every project in the organization.
- Public npm and PyPI, unless the repository names another registry —
every new dependency is looked up, except where
.npmrc, a requirements file,pip.conf,uv.toml, aPipfileor Python tool settings, beside the manifest or in a folder above it, name another registry or index. Choosing it asks you to confirm that no private registry is set up outside your repositories, for example in user or CI settings, and records when it was confirmed and by whom. Scoped npm packages (@scope/name) are looked up only where.npmrcnames the public registry for their scope. - Only where the repository names the public registry — the default. A
package is looked up only when
.npmrcsetsregistry=https://registry.npmjs.org/, its requirements file has exactly one--index-url https://pypi.org/simpleline, or a Poetry dependency uses a source that points at pypi.org. Most repositories do neither, so most new dependencies are not checked. - Off — no names are looked up, and invented packages are not caught.
Only the names of new dependencies leave Coroid. They go to registry.npmjs.org
and pypi.org, to api.npmjs.org for npm download counts, and to api.osv.dev
(with the npm version) for malicious-package reports. Your code is never sent.
Results are kept for up to a day, so the same name is not looked up again for
every change.
Findings and acceptance
A task's findings appear in its Quality section in Factory. When the developer agent fixed blocking findings before the change reached review, the section opens with Caught by anti-slop before review, the rules it caught and, under Show where and when, each finding's file and line and the check that found it. Factory, under Debt, counts the shortcuts caught before review in the last 30 days, and shows owners and admins the projects that do not check for them yet, with Turn on anti-slop.
To accept a finding, give a reason and an expiry; the acceptance is recorded against that exact finding. Agents cannot accept their own findings. When an agent says a test was wrong and changes it, a reviewer must approve that change before the check passes.
Judge rules
Two rules ask a model, one line at a time: a defensive check for something the code shown makes impossible, and a comment that contradicts the code next to it. They only advise, never block. Enable judge rules is on for a new check, with a per-run limit of decisions; turn it off in the check's settings.
Your own agents
The same rules can guide agents you run yourself:
- Download AGENTS.md snippet, in the Anti-slop settings of a project in Quality Control, gives the project's change discipline, quarantine and top rules as a section to paste into your agents' instructions.
- Through the Coroid MCP server,
anti_slop_rulesdescribes your published policy andanti_slop_scanscans a branch of a synced project, read-only.