Generative AI

AI slop in code: what it looks like and how to stop it landing in your repo

AI slop in code is not broken code, which is what makes it dangerous. Broken code fails a test and gets fixed. Slop compiles, runs, passes a quick review, and degrades the codebase gradually: a helper that duplicates one three folders away because the agent never saw it, an interface with a single implementation added out of habit, a validation pattern that differs from every other file because the model reached for a different plausible convention, a test that exercises a method and asserts almost nothing. Each item looks defensible in isolation. The damage is cumulative, and it accelerates with generation volume, since an agent can produce more of it in an afternoon than a reviewer can carefully read in a day. This explains what the common failure shapes are and, more usefully, which mechanical checks actually catch them.

What slop actually looks like

The patterns repeat across teams, and naming them makes them easier to spot:

  • Near-duplicate implementations. The agent needs a date parser, a retry wrapper, or a mapping helper, does not know the codebase already has one, and writes another. Both are fine; having both is not, and this is the single most common form.
  • Unnecessary abstraction. Interfaces with one implementation, factories that construct one type, layers that forward calls unchanged. It looks like good engineering and is complexity with no payoff.
  • Pattern drift. The same concern handled three different ways in three files, because each generation independently chose a plausible approach. The codebase loses the property that knowing one part helps you read another.
  • Hollow tests. Tests that call a method and assert something trivially true, or assert on mocks rather than behavior. Coverage rises, confidence should not.
  • Ceremonial comments. Comments restating what the line does rather than why it does it, adding volume and no information.

The unifying property is that none of these fail a build. They pass CI, they read acceptably in a pull request, and they accumulate. That is precisely why review alone does not hold the line: a human reviewer evaluating a 900-line diff can assess correctness locally but cannot reliably notice that a helper duplicates something elsewhere in the repository, or that this file's validation approach differs from the established one.

Why this is a measurement problem

The instinct is to solve slop with better prompts or more careful review. Both help and neither scales, because the properties that distinguish slop from good code are global rather than local: duplication is a relationship between two files, drift is a relationship across many, and hollow tests are only obvious when you look at what a test asserts relative to what it covers. Humans are poor at holding global properties in mind while reading a large diff, and they get worse as volume rises.

Machines are good at exactly that. A formatter eliminates style variance entirely, so the diff shows semantic change instead of cosmetic noise. Analyzers detect anti-patterns and questionable constructs by rule rather than by attention. Complexity thresholds flag the over-abstraction that reads as sophistication. And test-quality analysis distinguishes tests that verify behavior from tests that merely execute it. These checks do not get tired at line 700 of a diff, which is the entire argument for putting them in the path rather than relying on review. It is the same verification principle behind why AI-generated apps fail security review, and the same reason AI code review works best as one layer among several rather than the only gate.

The metric that targets AI code specifically

One measure deserves particular attention because it maps almost exactly onto how AI-generated code fails: the CRAP score, for Change Risk Anti-Patterns. It combines cyclomatic complexity with test coverage, so a method scores badly when it is complex and under-tested, and well when it is either simple or thoroughly covered. Simple code needs little testing; complex code needs a lot; complex and untested is where change risk concentrates.

That is a good description of the slop zone. AI-generated code trends toward more complexity than necessary (extra branches, defensive paths, layers) and toward tests that raise coverage without verifying behavior, so it lands precisely in the high-complexity, weak-coverage quadrant that CRAP is built to surface. Tracking it turns a subjective worry ("this feels over-engineered") into a threshold you can enforce in CI. Paired with the test-quality analysis that flags assertions verifying nothing, test smells, and coverage gaps, you get both halves of the problem: code that is riskier than it looks, and tests that are weaker than they claim.

The mechanical baseline

Concretely, the checks worth having in the path before AI-generated code merges:

  • A formatter, so style is not a review topic and diffs show real change.
  • Analyzers with a configured ruleset, so anti-patterns are caught by rule, not by whoever is reviewing that day.
  • Complexity thresholds, so over-abstraction and deep branching get flagged rather than admired.
  • CRAP scoring, so complex, under-tested code is visible as change risk rather than hidden behind a coverage percentage.
  • Test-quality analysis, so hollow tests and test smells are caught rather than counted as coverage.
  • A shared editorconfig, so the conventions are declared once and applied by every tool and every agent.
  • All of it enforced in CI, blocking rather than advisory, because a warning nobody must act on is a warning nobody acts on.

If you work in .NET, this set is exactly what our quality bundle installs as one command, ten skills covering the formatter, analyzers, complexity checks, CRAP analysis, editorconfig guidance, and CI quality checks. It is part of the open-source dotnet-skills catalog, and the wider .NET quality collection covers the individual pieces if you would rather install them selectively:

dotnet tool install --global dotnet-skills

dotnet skills install bundle quality

Installing it gives the agent the guidance to configure and respect those checks, which matters because an agent that knows the ruleset writes to it rather than against it. That is the second-order benefit: the same mechanical baseline that catches slop after generation also reduces how much slop gets generated, since the agent is working with the conventions rather than guessing at them, the reason a well-defined instruction layer belongs in an agent harness.

The takeaway

AI slop in code is output that compiles and passes casual review while degrading the codebase: near-duplicate helpers, unnecessary abstraction, pattern drift across files, hollow tests, and ceremonial comments. It resists review because the properties that identify it are global rather than local, and human reviewers cannot reliably hold a whole repository in mind across a large diff. Deterministic checks can: formatters remove noise, analyzers catch anti-patterns by rule, complexity thresholds flag over-abstraction, CRAP scoring surfaces the complex-and-under-tested code where AI output concentrates risk, and test-quality analysis exposes tests that assert nothing. Put them in the path as blocking CI checks, and give the agent the same conventions so it writes to them. Slop is a measurement problem, and the fix is mechanical.

If you want AI-generated code that ships through a verification layer instead of into your technical debt, that is where our AI Dev Team work starts.

FAQ

What is AI slop in code? Code generated by an AI that compiles and passes a quick review but degrades the codebase: near-duplicate implementations of things that already exist, unnecessary abstraction, inconsistent patterns across files, tests that run green while asserting almost nothing, and comments that restate the code.

Why is AI slop hard to catch in code review? Because the properties that identify it are global rather than local. Each piece looks defensible on its own; the problem is its relationship to the rest of the repository (a duplicate helper elsewhere, a different convention in neighboring files). Reviewers assess a diff locally and cannot hold the whole codebase in mind, especially at volume.

What is a CRAP score? Change Risk Anti-Patterns, a metric combining cyclomatic complexity with test coverage. Code scores badly when it is both complex and under-tested, which is where change risk concentrates. It is useful against AI-generated code because that code tends toward extra complexity and coverage-raising tests that verify little.

What checks stop AI slop from landing? A formatter, analyzers with a configured ruleset, complexity thresholds, CRAP scoring, test-quality analysis, and a shared editorconfig, all enforced as blocking CI checks rather than advisory warnings. These measure global properties that human review cannot reliably assess across a large diff.

Can better prompting prevent AI slop? It helps and it does not scale. Prompting improves individual generations, but slop accumulates through relationships between generations (duplication, drift) that no single prompt controls. Giving the agent the project's actual conventions and enforcing them mechanically is what holds up as volume rises.

“You can’t monetize pain. You can only monetize value. The moment users feel cared for, they’ll see paying as an investment in themselves — not a cost.”

You know what you want to build. Let's go ship it.

Book a 15-min call
Book a 15-min call
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.