no-slop-code · git:20260927.d224a3a · 2026-09-27 · sha256 6e645a0de05508aa
no-slop-code git:20260927.d224a3aA
Immutable. This exact content never changes and is served at /api/v1/blob/6e645a0de05508aa.
---
name: no-slop-code
description: Anti-slop convention for code, tests, docs and user-facing text - no comments that restate the code, no defensive checks out of place, no orphan or dead code, no speculative abstractions, no loose casts, no claims the code does not fulfil, no filler. Use it whenever you write or edit code, tests, templates or documentation, whenever you review generated code, and whenever the user mentions slop, redundant comments, unnecessary checks, clean code, over-engineering or "keep it lean".
---
# No slop code
## Code
| Slop | Do instead |
| --- | --- |
| A comment that repeats what the next line does | Delete it. Rename the variable or extract a function so the code says it. |
| A comment that explains *why*, when the project forbids comments | Put the reason in the name, in a test name or in an ADR. |
| A check for a case that cannot happen here (`if (!db) throw` right after creating `db`) | Delete it. Trust types and invariants. Validate only at boundaries: user input, files, network, environment. |
| A missing check at a real boundary (form body, query string, route params, env vars) | Add a schema or a parser at the boundary, with a test for bad input. |
| A function, dependency, export, template or table that nothing uses | Delete it, or add it in the same step as its first caller. |
| An abstraction for one caller "in case we need it later" | Inline it. Extract when the second caller appears. |
| `as SomeType` to silence the compiler | Narrow with a type guard, or fix the type at its source. |
| The same lookup copied into several handlers | Extract one helper when you add the second copy. |
| Catch-all error handling that hides the cause | Handle the errors you expect. Let the rest reach the error handler and the log. |
## Tests
- A test must fail when the behavior breaks. For each fix, check that the new test fails without the fix.
- Test helpers must behave like the real client. A helper that keeps a stale cookie or skips a step can make tests pass for the wrong reason.
- Do not assert on incidental details (a hard-coded id that depends on seed size) when you can compute them.
- Security controls need at least one test that plays the attacker, not only the expected path.
- Check untrusted values (headers, form fields) against an allow-list. A deny-list lets every unexpected value through: casing, repeated headers, unknown values.
## Text
- User-facing messages must be true. Do not write "the error has been logged" unless a logger is enabled and the error reaches it. Messages with a count must read well with 0, 1 and many ("1 jokes" is a bug). Use a singular and a plural form, or a label such as `Deleted: 1`.
- Keep docs in sync in the same commit: README, AGENTS.md, spec, plan, environment variable tables.
- A spec or a plan that is longer than the code it describes is suspect. Cut repeated tables, restated decisions and text that a reader can get from the code or another document.
## Before you commit
Read the diff once with these questions:
1. Can I delete a line and lose nothing? Delete it.
2. Does every new symbol have a caller in this commit?
3. Is every check at a boundary, and every boundary checked?
4. Does any text promise something the code does not do?