Documentation

Anti-slop checks

Catch the shortcuts agents take — weakened tests, swallowed errors, unfinished code — before a change reaches you.

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 any casts.
  • 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 authorisation 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 organisation 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.

Fixable findings are handled inside the run. The rest reach the pull request, and every finding ends fixed, accepted or suppressed, with a reason for the last two.

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 organisation default or a project and switch on Anti-slop. It adds five expectations:

  1. Tests still prove the change.
  2. Nothing unfinished or test-only ships.
  3. No new structural debt.
  4. The change stays in scope and reads like this codebase.
  5. 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 organisation 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.yml in the repository can add rules and exclude generated/, 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.json declares at the base of the change; the Globalisation 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 organisation.

  • 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, a Pipfile or 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 .npmrc names the public registry for their scope.
  • Only where the repository names the public registry — the default. A package is looked up only when .npmrc sets registry=https://registry.npmjs.org/, its requirements file has exactly one --index-url https://pypi.org/simple line, 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_rules describes your published policy and anti_slop_scan scans a branch of a synced project, read-only.