{"manifest":{"name":"Anti-AI Code Slop","version":"1.0.0","description":"Identify and eliminate the 10 most common AI over-engineering patterns that inflate code complexity without adding value.","tags":["coding","quality","refactoring","ai","best-practices"],"standard":"agentskills.io","standard_version":"1.0","content_checksum":"14cc630bb10131bfdc467fa607bfac267742cc5f1bf0d9ac57df0e94b6b3bcbc","bundle_checksum":null,"metadata":{},"files":[]},"files":{"SKILL.md":"# Anti-AI Code Slop\n\nIdentify and eliminate the 10 most common AI over-engineering patterns that inflate code complexity without adding value.\n\n## Overview\n\nAI coding assistants produce characteristic over-engineering patterns: defensive code for impossible scenarios, unnecessary abstractions, self-evident comments, and premature generalization. This skill trains you to recognize and eliminate AI code slop before it ships.\n\n**Inspired by community research on AI-generated code anti-patterns.**\n\n## The 10 AI Code Slop Patterns\n\n### Pattern 1: Self-Evident Comments\n\nComments that describe exactly what the code already says.\n\n```typescript\n// Bad — AI slop\nconst userId = user.id  // Get the user's ID\nconst total = price * quantity  // Calculate total by multiplying price by quantity\nusers.push(newUser)  // Add the new user to the users array\n\n// Good — no comment needed, or comment explains WHY not WHAT\nconst userId = user.id\n```\n\n**Rule:** Only comment when the code cannot be made self-explanatory, or when you need to explain *why* a non-obvious choice was made.\n\n### Pattern 2: Defensive Error Handling for Impossible Scenarios\n\nCatching errors that cannot occur given the system's invariants.\n\n```typescript\n// Bad — AI slop\nfunction getUser(users: User[], id: string): User {\n  const user = users.find(u => u.id === id)\n  if (!user) {\n    throw new Error(`User not found: ${id}`)  // caller guarantees id is valid\n  }\n  return user\n}\n\n// Good — trust internal invariants\nfunction getUser(users: User[], id: string): User {\n  return users.find(u => u.id === id)!\n}\n```\n\n**Rule:** Validate at system boundaries (user input, external APIs). Trust internal code and framework guarantees. Don't add error handling for scenarios that can't happen.\n\n### Pattern 3: One-Time Abstractions\n\nA helper function or wrapper that is called exactly once and wraps a single operation that was already simple.\n\n```typescript\n// Bad — AI slop\nfunction formatUserDisplayName(user: User): string {\n  return `${user.firstName} ${user.lastName}`\n}\n// ...called once, 3 lines away from the definition\n\n// Good — just inline it\nconst displayName = `${user.firstName} ${user.lastName}`\n```\n\n**Rule:** Three similar calls justify an abstraction. One call does not. A helper wrapping a single stdlib call adds indirection without removing repetition.\n\n### Pattern 4: Backwards-Compatibility Shims for Unshipped Code\n\nType aliases, re-exports, or renamed variables kept for \"compatibility\" when the original was never in production.\n\n```typescript\n// Bad — AI slop (this code was never shipped anywhere)\nexport type UserRecord = User  // backwards compat alias\nexport { getUserById as fetchUser }  // old name kept for migration\nconst _unusedConfig = config  // _prefix instead of deletion\n\n// Good — delete unused code\n```\n\n**Rule:** If the code was never in production and has no external callers, there is nothing to be backward-compatible with. Delete it.\n\n### Pattern 5: Feature Flags for Internal Decisions\n\nUsing boolean flags or configuration variables for decisions that are purely internal and will never vary at runtime.\n\n```typescript\n// Bad — AI slop\nconst USE_NEW_VALIDATION = true  // feature flag that has been true since day one\n\nfunction validate(data: unknown) {\n  if (USE_NEW_VALIDATION) {\n    return newValidate(data)\n  }\n  return oldValidate(data)  // never reached\n}\n\n// Good\nfunction validate(data: unknown) {\n  return newValidate(data)\n}\n```\n\n**Rule:** Feature flags are for rollout management. Internal code paths that will never be toggled in production should just be the code.\n\n### Pattern 6: Premature Options-Object Generalization\n\nConverting a function with 2 specific parameters to an options object \"for future flexibility\" before any second usage exists.\n\n```typescript\n// Bad — AI slop\ninterface CreateUserOptions {\n  name: string\n  email: string\n  role?: string       // added \"just in case\"\n  sendEmail?: boolean // not used yet\n}\n\nfunction createUser(options: CreateUserOptions) { ... }\n\n// Good — simple parameters for simple calls\nfunction createUser(name: string, email: string) { ... }\n```\n\n**Rule:** Generalize when you have 3+ callers with varying needs. Two parameters does not need an options object.\n\n### Pattern 7: Redundant JSDoc on Self-Evident Functions\n\nDocumentation comments that restate what the function signature already communicates.\n\n```typescript\n// Bad — AI slop\n/**\n * Gets the user by ID.\n * @param id - The user's ID\n * @returns The user object\n */\nfunction getUserById(id: string): User { ... }\n\n// Good — no docs needed; the name and types explain it\nfunction getUserById(id: string): User { ... }\n```\n\n**Rule:** Document *why* something non-obvious is done, or the *contract* when it's not obvious from types. Don't document \"this function does what its name says.\"\n\n### Pattern 8: Over-Typed Single-Use Structures\n\nDefining an interface or type alias for a value that is created once and used once in the same function.\n\n```typescript\n// Bad — AI slop\ninterface ValidationResult {\n  isValid: boolean\n  errors: string[]\n}\n\nfunction validate(input: string): ValidationResult {\n  const result: ValidationResult = { isValid: true, errors: [] }\n  // ...\n  return result\n}\n\n// Good — inline type is fine here, or just return the object\nfunction validate(input: string): { isValid: boolean; errors: string[] } {\n  return { isValid: true, errors: [] }\n}\n```\n\n**Rule:** Named types earn their place when used in 3+ places, in public APIs, or when naming the concept aids readability. Single-use internal structures don't need names.\n\n### Pattern 9: Unnecessary Async Wrapping\n\nWrapping synchronous operations in async/await or Promise.resolve() with no actual async work.\n\n```typescript\n// Bad — AI slop\nasync function getConfig(): Promise<Config> {\n  const config = JSON.parse(fs.readFileSync('config.json', 'utf-8'))  // sync!\n  return config\n}\n\n// Or worse:\nasync function add(a: number, b: number): Promise<number> {\n  return a + b\n}\n\n// Good\nfunction getConfig(): Config {\n  return JSON.parse(fs.readFileSync('config.json', 'utf-8'))\n}\n```\n\n**Rule:** Use async only when the function actually awaits something. Don't future-proof synchronous functions with async wrappers \"just in case.\"\n\n### Pattern 10: Significance-Inflating Variable Names\n\nNaming variables with grandeur that inflates the importance of routine operations.\n\n```typescript\n// Bad — AI slop\nconst comprehensiveUserDataFetchResult = await getUser(id)\nconst criticalAuthenticationToken = generateToken(user)\nconst transformedAndNormalizedInputData = input.trim()\n\n// Good\nconst user = await getUser(id)\nconst token = generateToken(user)\nconst trimmed = input.trim()\n```\n\n**Rule:** Variable names describe what they hold, not how important it is. \"result,\" \"user,\" \"token\" are fine names.\n\n## Review Checklist\n\nRun before every code review or self-review:\n\n```\n[ ] Every comment explains WHY, not WHAT\n[ ] No error handling for scenarios that cannot occur\n[ ] No function called exactly once that wraps a single line\n[ ] No type aliases or re-exports for code that was never shipped\n[ ] No feature flags that are always one value\n[ ] No options objects for functions with 1-2 natural parameters\n[ ] No JSDoc on self-evident function signatures\n[ ] No named interfaces used in only one place\n[ ] No async functions without actual await calls\n[ ] Variable names describe content, not importance\n```\n\n## Application Scope\n\nApply to: code you are writing or reviewing for production use.\n\nDo not apply to:\n- Public APIs where backwards compatibility is a real concern\n- Libraries where the options object pattern is conventional\n- Code that genuinely needs future extensibility (well-established extension points)\n- Existing code bases where consistency with surrounding patterns matters more than purity\n"}}