{"slug": "a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by", "title": "A battle-tested AGENTS.md for higher quality code output. Helps avoid \"AI slop creep\" by keeping your codebase lean and clean.", "summary": "A developer shared a battle-tested AGENTS.md document designed to produce higher quality code output by preventing 'AI slop creep'. The document enforces principles such as defaulting to modular design, type-owned dispatch, and placing functionality where it generalizes to keep codebases lean and clean.", "body_md": "This document exists to keep the codebase * minimal, elegant, and proper*.\n\n**Default to modular.** When you design anything with more than one variant — or\nthat will plausibly grow one — the first question is \"what's the unit, and how\ndoes the rest of the code stay ignorant of which one it's looking at?\" That\nmindset applies at every scale: from a small enum where one method per variant\nbeats a branch at the call site, up to full subsystems with interfaces,\nregistries, and per-variant files. The cost of designing modularly up front is\nalmost always small; the cost of retrofitting after centralized branching has\nspread across the codebase is large. Hand-written dispatch should feel like an\nexception that needs justifying, not the default shape.\n\nThis is a stronger claim than the Engineering Principle's \"build a proper system\nfor it\" — that one says *don't hack*; this one says *the proper system is almost\nalways one where new variants slot in without consumers being edited*.\n\nModule-specific code lives in the module. Module-generic infrastructure — registries, dispatchers, shared state, caches — is generic by name and by shape, never named after any single module that happens to use it today.\n\nWhen adding a new item to a modular system (a new filter, tool, handler, etc.):\n\n**DO:** Create a single unit (file/module) in the appropriate directory that contains everything about that variant — type, implementation, registration, constants, helpers.**DO NOT:** Add branches to a central dispatcher. Add entries to a hand-written list. Touch any file outside the module directory except whatever central manifest the build genuinely requires.\n\nPrefer a mechanism where new variants are *discovered* (by a build step, a\nregistry, reflection, or convention) rather than *enumerated* by hand. Generic\ninfrastructure (the interface, the registration record, the registry) is named\nafter the kind, not after the first variant that happened to exist.\n\nThe \"default to modular\" stance leads directly to the type-owned dispatch rule below: once a system is modular, the consumer must not re-introduce centralized branching by asking variants what they are.\n\n**Type-owned dispatch:** Anything a type knows about itself — behavior,\nproperties, capabilities, identity — lives on the type, behind a uniform\ninterface. Consumers call methods; they never introspect, classify, or branch on\nwhich variant they got. The diagnostic question: *would adding a new variant, or\nchanging what an existing one knows about itself, force me to edit this code?* If\nyes, the knowledge is misplaced. The violation has one recurring shape — a\n`switch`\n\n/`match`\n\non a type tag, `if kind == X`\n\n, an `is_foo(type)`\n\npredicate, or\nany consumer-side helper that routes by type — code outside a type's own module\nasking questions the type should be answering itself. Replace it with a method,\ndefaulted to the common case and overridden per variant, so new variants are\npurely additive.\n\nDon't Repeat Yourself — and interpret this broadly. If two pieces of code aren't identical but follow a similar enough pattern that they could be generalized, they should be. This applies across modules, layers, and systems.\n\n**Place functionality where it generalizes.** Before writing logic, ask: \"where\ndoes this belong so that it works for all cases, not just this one?\" If a\nbehavior applies to any item of a kind, it belongs in that kind's generic hooks —\nnot inside one specific item. If a behavior applies to any async operation, it\nbelongs in the shared completion pipeline — not special-cased at one call site.\nPutting the right logic in the right architectural layer eliminates the need to\nrepeat it, and prevents future features from having to rediscover where to plug\nin. A good signal you've placed something wrong: it only works for one workflow,\nor a second caller would have to copy-paste the same pattern.\n\n**Stop-sign phrases.** If you find yourself writing \"mirrors X\", \"bit-exact copy\nof X\", \"keep in sync with X\", or \"identical to X\" in a comment, you are\nduplicating code. Pause and consider why you're doing it. If it's not easily\nfactorable into a shared feature, stop executing and raise the issue to the user.\n\nState belongs to the thing it describes — not to a parent that manages it on its behalf. Don't let language or tooling constraints dictate the data model. If splitting state out of a structure makes some local concern easier but scatters a logical concept across multiple locations, find a different way to satisfy the constraint (helper methods, restructured access, narrower borrows/scopes) and keep the data model clean.\n\nBefore deciding on an approach, research how established projects in the same space handle it. Read the actual source — never rely on web searches, docs, blog posts, or LLM training data for architectural claims. If a reference project isn't available locally, clone it. Never claim \"Project X does Y\" without pointing to a specific file and function. When delegating research to a subagent, instruct it to clone and cite specific files and line numbers — reject any claim not backed by source.\n\nWe do not blindly copy prior art; we use it to inform our own decisions. Our implementation will differ in specifics, but core algorithms and architectural decisions should be informed by prior art, not invented from scratch.\n\nWhen an idea, algorithm, snippet, or implementation comes from an external source — open source code, papers, blog posts, video tutorials, etc. — credit the source and author at the top of the file (or inline next to the borrowed fragment, if it's smaller than file-scope). Include the author's name or handle and a link to the original.\n\n**Every feature must have a test.** Verify the feature works. The test exists; it\npasses. That's it.\n\n**Every bug must have a regression test — one that defends against that\nspecific bug being reintroduced.** \"Regression\" means \"the bug we just fixed must\nnot come back\"; a test for a new feature is not a regression test, even if it\nfollows the same pattern. Write it FIRST, confirm it FAILS against the unfixed\ncode, then fix the bug and confirm it passes; if it doesn't fail without the fix,\nit doesn't count.\n\nEvery system must be implemented properly. No hacks, no hardcoding, no shortcuts. If we implement one of something, we build a proper system for it. It's okay to take a step back from the current task to do things right.\n\n**Every bug is a signal that something nearby is awkward or overcomplicated.**\nBefore patching, ask: \"is this an elegant solution?\" If the answer is no, the bug\nis telling you the code wants to be restructured — propose a refactor instead of\nlayering a fix on top. The cleanest fix is often the one that makes the bug\nimpossible to express, not the one that handles it.\n\n**Keep user-facing documentation in sync with the codebase.** When you ship,\nremove, or rename a user-visible feature, update the corresponding docs\n(README, changelog, feature checklist) in the same change.\n\n**Speculative deletion.** If code looks dead, delete it and see what happens. The\ncompiler, type checker, and tests are the authoritative check, and version\ncontrol restores it cheaply if you're wrong. Every file read is an opportunity to\nscan nearby code for vestigial slop. If you're not sure whether to keep an old\nsnippet, err on the side of deleting, and let the user know what was deleted.\n\nRun the project's formatter, linter, type checker, build, and test suite at commit time only — not during iterative debugging. Use the cheapest build/check command for mid-iteration sanity. All checks must pass before a change is considered done.\n\nNever run `git commit`\n\n— make the changes and leave staging and committing to the\nuser.", "url": "https://wpnews.pro/news/a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by", "canonical_source": "https://gist.github.com/typicaleoxx/b43b115942cd6c3e44fef12b781559fc", "published_at": "2026-07-09 16:27:32+00:00", "updated_at": "2026-07-09 16:35:15.612543+00:00", "lang": "en", "topics": ["developer-tools"], "entities": [], "alternates": {"html": "https://wpnews.pro/news/a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by", "markdown": "https://wpnews.pro/news/a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by.md", "text": "https://wpnews.pro/news/a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by.txt", "jsonld": "https://wpnews.pro/news/a-battle-tested-agents-md-for-higher-quality-code-output-helps-avoid-ai-slop-by.jsonld"}}