用途
clean-ai-slop 是一个纠正性纪律技能,用于清理 AI 生成的代码。它在代码生成之后运行——无论代码来自 run-plan、手动会话还是其他来源。
核心问题在于:LLM 生成的代码虽然能运行,但带有鲜明的异味——过度注释、不必要的抽象、对不可能场景的防御性偏执、冗长命名。如果不加控制,这些会累积成比手写代码更难阅读和维护的代码库。
该技能系统性地逐类移除这些异味,且不改变代码行为。
硬性门槛
以下规则没有例外:
- 清理前先锁定行为。 运行现有测试。如果覆盖率不足,为即将改动的代码补充回归测试。没有测试覆盖,就不做清理。
- 每轮只处理一类异味。 不要把死代码移除和命名修复混在一起。完成一轮、验证,再开始下一轮。
- 每轮之后运行测试。 如果测试失败,回滚该轮并排查。不要继续下一类。
- 保持在范围内。 只触碰由 AI 生成或修改的文件。不要扩展到看起来可以改进的“附近”代码。
- 精确保留行为。 如果清理改变了可观察行为——即使你认为新行为“更好”——也要回滚。行为变更需要单独的任务。
何时使用
- run-plan 完成后,实现能工作但读起来像 AI 写的
- 任何大规模代码生成会话之后
- 审查 AI 生成的 PR 时
- 用户明确要求清理或 deslop 代码时
何时不使用
- 人类编写的代码(异味不同,处理方式不同)
- 测试不存在且无法快速补充时(先锁定行为)
- 实现进行中——先完成功能,再清理
异味类别
各轮按以下顺序执行。每一轮完全结束后才开始下一轮。
第 1 轮:死代码
移除没有用途的代码:未使用的导入、未使用的变量和参数、不可达分支、被注释掉的代码块、吞掉异常的空错误处理器。
检测方式:编译器警告、linter 输出、IDE 置灰的符号。信任工具。
第 2 轮:过度注释
移除只是复述代码内容的注释。目标包括:// Initialize the counter 位于 let counter = 0 之上;// Return the result 位于 return result 之上;重复函数签名而无额外洞见的 JSDoc;不增加信息的分节符(// --- Helper Functions ---);描述文件名已显而易见内容的文件头。
保留:解释“为什么”而非“是什么”的注释、关于非显而易见约束的注释、指向外部文档或 issue 的链接。
第 3 轮:不必要的抽象
移除没有用途的间接层。目标包括:只被调用一次的辅助函数(内联它们);把所有事情都委托给一个内部对象的包装类;为永远不会被配置的东西创建的配置对象;总是产出相同结果的工厂函数;只被单一实现使用且没有更多计划的接口/类型定义。
测试方法:如果移除抽象后代码更短且同样可读,那它就是不必要的。
第 4 轮:防御性偏执
移除针对不可能发生场景的错误处理。目标包括:对类型系统保证非空的值做空值检查;围绕不可能抛出的代码的 try-catch;内部函数参数的校验(只在系统边界校验);必填字段的兜底值;冗余的类型断言。
保留:系统边界(用户输入、外部 API、文件 I/O)的校验;运行时确实可能失败处的错误处理。
第 5 轮:冗长命名
缩短携带冗余信息的名称。目标包括:getUserDataFromDatabase → getUser(还能从哪来?);userAccountStatus → status(在 User 类内部使用时前缀冗余);handleButtonClickEvent → onClick;responseDataObject → response;tempVariableForCalculation → temp 或直接内联。
规则:名称应尽可能短,同时在其作用域内保持无歧义。作用域越长,名称越长;作用域越短,名称越短。
第 6 轮:LLM 填充物
移除 LLM 生成风格的痕迹。目标包括:代码、注释或提交信息中的 emoji(除非项目有意使用);注释中的对话式语气(“Let's”、“Now we need to”、“Great!”);为“调试”添加的过多 console.log / print 语句;推断已能处理处的冗余类型标注;遵循模板模式而非问题自然形态的过度结构化代码。
流程
- 确定范围(要清理哪些文件)
- 运行现有测试——开始前必须全部通过
- 如果覆盖不足,补充回归测试
- 执行第 1 轮 → 验证 → 提交
- 执行第 2 轮 → 验证 → 提交
- ……继续所有相关轮次
- 运行完整测试套件
- 报告变更摘要
并非每一轮都适用于每个代码库。跳过零发现的轮次。但必须按顺序执行——绝不跳步。
反模式
- “我要一次性清理所有东西”——测试失败时混合变更无法调试
- “这个抽象很糟,让我重新设计”——重新设计是单独任务,不是清理
- “测试通过了,我跳过每轮验证”——后续轮次可能与早先变更相互作用
- “附近这段代码看起来也很乱”——范围蔓延,只清理范围内的
- “行为本来就不对,我顺手修了”——行为变更需要自己的任务和测试
- “我不需要回归测试,代码很简单”——简单代码也会坏,先锁定行为
危险信号
如果发现自己有以下想法,停下来重新考虑:
- “这太耗时了,让我把剩下的轮次批量处理”
- “我顺便快速修一下另一个文件”
- “测试大概没问题,不用再跑一遍”
- “这个行为本来就该不一样”
- “我不需要测试——只是删注释而已”
完成标准
清理完成的条件:所有适用的轮次已按顺序执行;每轮之后测试都通过;最后完整测试套件通过;没有任何行为改变;变更仅限已确定的文件。
如果任一条未满足,清理就不算完成。
最小检查清单
清理期间对照此清单核验:
- 开始前已用测试锁定行为
- 当前轮次只针对一类异味
- 当前轮次后测试已通过
- 未触碰定义范围之外的文件
- 未改变任何行为
过渡
清理完成后:如果代码由 run-plan 生成 → 向用户报告结果;如果生成期间缺少实现纪律 → 考虑在未来的会话中应用 karpathy,从源头防止 slop。