You shouldn't be writing comments. And if you do, it should have a reason.
Should your agent be writing comments at all? Some teams say always, for documentation. Some say never. Most do not look. Here is what we landed on after catching our own pair agent leaking 70 narrative comments into the aislop source tree, and why the rule wrote itself.
Should your agent be writing comments at all? Honestly, it depends on who you ask. Some teams treat every function as a documentation surface and want a JSDoc block above it. Some teams delete everything that is not a directive. Most teams just do not look. Here is what we landed on after our own pair agent got caught leaking 70 narrative comments into the aislop source during the 0.5 rehaul.
Two commits before the tag, we ran aislop scan against our own source. The source the agent had been writing into all day. The score moved in the wrong direction. The diff was clean by every other measure. Tests passed. Self-scan should have been 100. It was not.
We pulled the report. The damage was almost entirely comments. Decorative separators. Phase headers. Cross-reference paragraphs naming functions in adjacent files. Multi-paragraph JSDoc blocks narrating what the body already said in TypeScript. None of it intentional. All of it the agent being "helpful" in the way pre-2020 style guides told it to be helpful.
One aislop fix pass took the // count from 319 to 256. Sixty-three lines deleted. JSDoc blocks went 58 to 39. Net 82 comments removed in a single command, parse-checked on every file before write. The tool builder got caught by the tool. We tagged on the next commit.
The five patterns we kept seeing
Every one of these was lifted from real diffs the agent wrote into the aislop source. None invented.
Decorative separators
A banner inside a file is the file confessing it is too big. The cure is splitting the file, not decorating it.
Phase headers
If something is a phase, it is a function. The header is pretending the phases are already separated when they are not.
Narrative JSDoc
The function name says it. The signature says it. The body says it. The block is restatement. It is the first thing that goes stale on rename.
Cross-references by name
Rots the moment anyone renames buildFixRender. Nobody updates it. The next agent reads the lie and bakes it into its next answer.
Section-header-with-text
Decoration plus a doc string. Twice the rot. The fix is the same. Split the file. Name the function.
The rule
ai-slop/narrative-comment shipped in 0.5. It flags decorative separators, phase headers, multi-paragraph JSDoc preambles, cross-reference commentary, and section-header-with-text. The rule wrote itself during the rehaul. The agent kept leaking these patterns into commits we had not yet tagged.
Companion rule ai-slop/trivial-comment handles the smaller stuff. // increment counter above i++. // return result above a return statement. Same pattern at a smaller scale. Same deletion logic.
Removal goes through the in-house AST engine, not a regex. Each delete proves the file still parses before write. That is the only reason we run it unattended.
What we kept
The rule is not "delete every comment." A working scan keeps everything that earns its place.
| Category | What it looks like |
|---|---|
| License / SPDX | License headers and SPDX tags at the top of the file. |
| Toolchain JSDoc tags | @deprecated, @see, @example, @param with real type narrowing, @internal. |
| Suppression directives | With a reason attached: biome-ignore, eslint-disable-next-line, ts-expect-error. |
| Non-obvious constraints | Things the type system cannot express. "This array must stay sorted; downstream binary search depends on it." |
| Library-quirk workarounds | Paired with a link. "Safari 16 returns undefined, see bug ID." |
Everything else is restatement. Restatement rots. Delete it. Rename the function. Put it in the commit message.
Why agent comments rot faster than human ones
Human-written comments aged badly because the human wrote them once, moved on, and never came back to maintain them. Agent-written comments are worse on two axes. The agent has no stake in whether the comment stays accurate. It will not be back in six months to fix the lie. And the volume is an order of magnitude larger. If an agent produces ten times the code a human does and three percent of it gets commented, you now have thirty times the stale narration.
Then there is the training-data feedback loop. The next agent reads the lying comment, treats it as ground truth about the function it sits above, and shapes its next answer around it. Every stale comment becomes a future bug shaped by a ghost.
The rule that catches you too
Honest version. We wrote ai-slop/narrative-comment for ourselves first. We were the team shipping a tool to police AI-written slop, and our own pair was producing the cleanest case of it we had ever seen. The rule pinged us for 70 comments in our own engine source. We accepted the patches. Score back to 100. Tagged 0.5. If the tool builder needs the rule, you probably do too.
If your agent has to explain what it just did in a comment, you need a better agent or a better guardrail. Probably both. Explanation belongs in the PR description and the commit message. Things humans read once, in context, with the diff in front of them. Not above a function that will outlive five refactors.
Run it on your repo
Point it at your source. See how many narrative comments the agent left behind. Star the repo if you want the next release in your feed.