AI Slop After the Em Dash
We banned the em dash and the model stopped using it. The slop moved into sentence shapes, then section headers, then last week into the titles of a slide deck whose paragraphs passed every rule I had.
Two years ago you could spot AI writing by the em dash. Three per paragraph, one in every heading, a rhythm crutch no human editor would let through. I put "no em dashes" in my rules file, the dashes disappeared, and for a while the text read like a person wrote it.
The colon came next. "The detail that makes it work: a separate agent grades it." Same job the dash was doing, one character over. After that came "It's not X. It's Y.", then headings called "Why this matters" over two paragraphs, then three-pillar frameworks nobody asked for. Each time I banned a form, the form vanished and something with the same function appeared one level up.
Word
Sentence
Structure
Medium
[ Four walls, seven accounts ] · chart legends, commit messages, alt text
Last week it reached a place I had not thought to look. I asked my agent to build a slide deck about an AI test runner from my notes. The paragraphs passed every rule I had. The slide titles were "One harness, four swappable sides", "Four walls, seven accounts", "Five calls to make this month", headlines in the slot where a title belongs. Every rule I had was written for prose, and the agent had, reasonably, treated a slide title as layout.
Training corpus and preference tuning
For a year I treated slop as a list of habits. The model uses "delve", you ban "delve", it stops using "delve", and the sentence that needed a filler word finds another one, because the model is producing text that resembles a finished, thorough, confident answer and that is what it was rewarded for.
Most text about work on the internet is marketing copy, consulting decks, listicles, LinkedIn posts, and documentation written to a template. In that corpus a title is a headline, a section has a "Why this matters", an argument has three parts, and a conclusion restates the opening. When a model reaches for the most probable shape of a slide title, it reaches for "Four walls, seven accounts".
Preference tuning then rewards the look of completeness. When people rate two answers, the one with headers, bullets, a summary and a confident closing line tends to win, because it looks like more work was done. So the model learns structure as a proxy for quality. A paragraph of reasoning scores lower than the same reasoning wrapped as "the three-layer model", so the wrapper appears even when the source material contains no layers, and answers end with "the bottom line" because answers that end that way rate as more finished than answers that stop when the information stops.
And words cost the model nothing. A human writer runs out of energy; the sentences that survive are the ones you cared enough to type. A model fills every slot the template offers, so two paragraphs get a header, a single point gets a bulleted list, and a table gets a "So what" column.
Under those conditions a ban moves the behaviour to the nearest unbanned surface: from a word to a sentence shape, from a sentence shape to section structure, from prose structure to whatever medium has no rule yet.
There is data on this now. A Reddit user pulled 89,239 posts from 47 subreddits about spotting AI writing, filtered to 7,984 on topic, and hand-audited 600 of them for what readers actually cite as the tell. The em dash leads at 7.1 percent of audited posts. Second is uniform sentence rhythm at 4.0 percent, third "not just X, it's Y" at 2.8, then the five-paragraph essay shape and sycophancy, both at 2.5. The words everyone bans, "delve" and its cousins, sit at 1.3 percent. The keyword scanner in the same study ranked "however", "thus" and "hence" as the top match, at 6.3 percent of posts, and readers cited them as a tell zero times. Rhythm and emptiness, the tells readers cite most after the dash, cannot be keyword-matched at all.
One commenter on that thread had run the same experiment I had, with Claude. He banned constructions one at a time and watched the model comply with each ban while keeping the underlying behaviour: ban the em dash and it switched to ", and" and semicolons. After two dozen bans he found the driver was over-explanation and restatement, and a single instruction, "be airy, don't over-explain", did more than the whole list. The study's repository is public and MIT licensed.
Slide titles
My rules file says headings identify subject matter, never rhetorical function. It lists banned heading shapes. The agent had it in context and still wrote "One harness, four swappable sides" into the slide-title slot. When I asked why, the answer was that the paragraphs had been written in a writing step, where the rules fired, and the slide titles had been written in a layout step, as strings that look like slide titles look, where the rules did not fire because that step was not, in the agent's own accounting, writing.
bullets
speaker notes
tile and card labels
table headers, row keys
diagram node labels
chart titles, legends
button copy, alt text
commit messages
memory-file descriptions
Every medium I had not explicitly named was sitting on that unchecked side: diagram node labels, table headers, chart legends, Slack drafts, commit messages, the one-line descriptions on memory files.
Information gain as the test
The test that has survived every surface change so far is marginal information gain: after each unit of output, ask what the reader now knows that they did not know before it, and delete the unit if the answer is nothing.
The same question removes "delve" (a shorter word carries the same information), "It's not X. It's Y." (X was never on the table), "Why this matters" as a heading (it names the prose's job and says nothing about the subject), and a three-pillar framework whose pillars were not in the source. It works at the medium level too. A reader glancing at the slide index learns nothing from "Four walls, seven accounts" and learns exactly when to jump from "Common challenges across customers". Here is the full set from that deck, before and after, with the check applied to each title:
| Was | Now |
|---|---|
| What runs today | Current AI Test Runner workflow |
| Who uses the runner, and the wall each one hits | Customers using the AI Test Runner and their use cases |
| Four walls, seven accounts | Common challenges across customers |
| What stands between the runner and production use | Current challenges |
| One harness, four swappable sides | New runner architecture |
| Why hard apps are the niche | AUT knowledge base: how it is built with a customer |
| Where the same engine can live | Two paths: local file-based vs online integrated |
| One harness, two shells, and a bridge | Recommendation: ship the local path first, keep True as the system of record |
| Five calls to make this month | Decisions needed |
| Where the facts come from | Sources |
The right column is duller, and "Sources" tells a reader scanning the index what is on the slide without opening it.
The same check catches what the bans miss inside the content. The deck had a slide body that said "the walls are the pattern" and a tile that said "hard apps are hard for everyone; we are the ones with a slot for the answer". Neither adds a fact the surrounding text lacks, and both sit where a conclusion would go. A ban list names repeated patterns and cannot see a one-off empty sentence.
The test also settles the argument about single words. My first draft of the new rule tried to protect words like "robust" by giving an example where the word was needed: "a robust retry on OTP fetch". My reviewer asked why the retry needed "robust". It did not, and "a retry that survives a mail-slot timeout" tells the reader what it does, where "robust" tells them the author wanted the sentence to sound engineered. The same applies to "clean", "plain", "simple", "elegant". Remove the adjective, and if the reader would do nothing differently, it was decoration. The exception is a term of art, "robust statistics", where the word is the name of the thing.
Word counts across my own archive
Once I stopped trusting the ban list I counted. The twenty-five posts published here before this one, all of them drafted with an agent and edited by me, about 2,158 sentences.
My first pass used grep -o and reported "ship or shipped: 124 uses". That was wrong, and wrong in a way worth keeping: grep -o counts substrings, so it had been scoring "relationship", "shipping" and "ships" as instances of my tic. The tool I ended up writing counts on word boundaries and reports a per-file rate, which is the number that matters. The real figure is 51 across 25 posts, about two a post.
The shapes were the louder finding.
Behind "The" in the heading census sit "What" at 22 and "Why" at 7. The narrative heading I borrowed from a writer I admire, "Then the build lied to me", appears seven times across two posts, and the agent has since treated it as the house pattern.
This is specific to working with one agent over time. Besides the median of the internet, the model samples the median of me, from the posts and rules and memory files it has in context, and it regresses toward my most frequent choices because those are the highest-probability tokens in my corpus. "Ship" was a word I used for software releases. In the agent's hands it became the verb for publishing a post, saving a file, sending a Slack message and deploying a service. "Honest" was a word I used once when I meant it, and it came back as "the honest part:" at the top of paragraphs where nothing dishonest was on offer.
The census is now part of my pre-publish scan. It prints only what sits above the per-file rate, and I decide whether each one is my voice or my mode.
Specimens
The patterns are easier to refuse next to their repair. Every line on the left came out of a draft of mine, most of them out of drafts of this post.
Current setup
My rules file now opens with the target: optimize for information gain over apparent completeness, and compose as finding, evidence, reasoning, decision rather than principle, framework, exposition, takeaway. The ban list is still there, as examples of the target being missed.
After the deck the agent saved a rule that lists the places the quality bar applies: slide titles, kickers, tile and card labels, table headers and row keys, diagram node and edge labels, chart titles and legends, button copy, subtitles, Slack, email, Jira, PR bodies, commit messages, code comments, memory files, and the content under all of them.
The banned shapes carry verbatim examples from my own outputs. "One harness, four swappable sides" is in the memory file as the example of number pairing, "The wedge" as metaphor in place of the noun, "Why hard apps are the niche" as question-as-title, "The fix was one line." as the verdict sentence. A rule that quotes the exact string the agent produced last Tuesday is harder to route around than an abstract one.
Rules in a file are advisory, and the deck showed what advisory gets you, so the last step was a scanner that runs whether or not anyone remembers it. Before the agent writes a file, publishes a page, or sends a Slack or Confluence message, the script reads the outgoing text and refuses the call if it contains a hard tell, returning the hit list so the rewrite is targeted. The same script runs on the agent's chat replies. Hard tells refuse on one hit: the em dash, honesty framing, "not X, it's Y" and its trailing cousin "X, not Y", headings that name their own rhetorical job, "That is the point" closers, sycophantic openers like "great question". Filler adjectives are counted and refused at three in one piece, because three is where use turns into decoration. Text inside quotes or code formatting is skipped, so a post like this one, which quotes the tells as exhibits, can still be written.
Both halves are now skills in COG, the public version of my agent setup, so they work without my vault:
- slop-gate is the scanner.
python3 scan.py DRAFT.mdprints the tells and exits non-zero, so it runs as a CLI, a CI step, or a Claude Code hook with--hook. The pattern list, the quoted-span exemption and theslop-okescape hatch are in the skill. - voice-baseline is the census. Point it at a directory of your own writing and it reports the per-file rate of every word you over-use, plus the shapes: verdict endings, kicker closers, heading first words.
--check DRAFT.mdprints only what sits above your own baseline. Every number in the section above came out of it, including the correction to my grep.
The no-ai-slop skill they sit beside picked up the reader-cited ranking, the list of media, and the voice-mode caps in the same release.
The hook fired on its own author within the hour. My agent's reply describing the hook listed the banned words in a sentence, and the gate refused the reply until the list was moved into quotes. A few messages later I caught it writing "reads as a test, not a permission", the trailing contrast form, which the first version of the script did not cover, and the pattern went in.
A model from a different family reviews what the lead agent writes. Same-family reviewers share the author's training distribution and therefore the author's sense of what a finished answer looks like. On this post, the reviewer found 57 problems in a draft I thought was finished, 6 of them the exact verdict sentence the post complains about.
Each catch becomes a memory file the agent reads at the start of the next session. The deck produced three of them: titles name the subject, the bar applies to every medium, the bar applies to content as well as labels.
Alt text, issue descriptions, memory summaries
The drive to resemble a finished answer is what preference tuning selects for, and every lab is doing preference tuning, so the forms will keep moving to whatever surface I have not written a rule for yet. My guess for the next one is somewhere I do not read carefully: alt text on images, the descriptions on GitHub issues, the one-line summaries my agents write for their own memory files. The hook will not catch those until someone names the shape, so the first one through will be a human reader, probably my tech lead, who reads the deck I send him and tells me which slide he could not find.