对抗 AI Slop:介绍 aislop,一款针对 AI 生成代码异味的 CLI 工具
AI 编程智能体(如 Claude Code、Cursor 等)的兴起从根本上改变了我们编写软件的方式。虽然这些工具可以生成通过测试和 linting 的功能性代码,但它们经常会引入一种被称为“AI slop”的特定技术债务。这类代码虽然可以运行,但其编写模式是任何经验丰富的工程师都不会选择的:叙述性的注释(只是在重复显而易见的事实)、吞掉异常,以及模糊实际逻辑的冗余保护措施。
为了应对这一问题,aislop 应运而生。它是一款确定性的 CLI 工具,旨在这些“代码异味”腐蚀你的代码库之前将其捕获。与许多由 AI 驱动的工具不同,aislop 在其运行时路径中不依赖 LLM,从而确保相同的代码始终产生相同的评分。
什么是“AI Slop”?
AI slop 并非指 Bug;它关乎质量和可维护性。它表现为几种截然不同的模式:
- 叙述性过度注释:注释描述的是代码在做什么(这本应从代码本身显而易见),而不是为什么要这样做。
- 适应不良的容错机制:一种“将异常扫到地毯下”的倾向,即通过捕获错误并记录警告,而不是在应该失败时允许系统发出响亮的错误提示。
- 冗余的保护措施:过度依赖空值合并运算符和防御性回退,将每个值都视为可选,这往往模糊了“正常路径”与“异常路径”之间的界限。
- 机械性浪费:幻觉导入、重复的辅助函数,以及在 TypeScript 中绕过类型系统的
as any转换。
aislop 的工作原理
aislop 并不依赖另一个 LLM 来审查代码(这既耗费 token 又不具确定性),而是结合使用了 Regex、抽象语法树 (AST) 以及现有的行业标准工具。它并行运行六个确定性引擎:
| 引擎 | 关注点 | 使用的工具 |
|---|---|---|
| Formatting | 样式一致性 | Biome, ruff, gofmt, cargo fmt, 等 |
| Linting | 特定语言的问题 | oxlint, ruff, golangci-lint, clippy, 等 |
| Sloppiness | AI 特有的模式 | 针对叙述性注释、TODO 存根等的自定义规则 |
| Code Quality | 复杂度与死代码 | Knip, 函数/文件大小限制, 深层嵌套 |
| Security | 漏洞 | 依赖项审计, eval/innerHTML 检查 |
| Architecture | 结构化规则 | 自定义导入禁令与分层规则 |
集成到开发工作流中
aislop 最强大的功能之一是其能够直接集成到开发者与 AI 智能体之间的反馈循环中。
1. 质量门禁 (The Quality Gate)
通过在 .aislop/config.yml 文件中实现 failBelow 阈值,团队可以将 AI slop 视为 CI 失败。如果智能体的 PR 将代码库评分降至某个阈值以下(例如 80/100),构建就会失败,从而迫使智能体(或人类)清理 slop。
2. 智能体交接 (Agent Handoff)
当 aislop 识别出它无法通过机械方式修复的问题(例如设计拙劣的重试机制)时,它会提供直接的交接。诸如 npx aislop fix --claude 或 npx aislop fix --cursor 之类的命令会将诊断信息传回给智能体,有效地告诉 AI:“你在这里留下了 slop;现在去修复它。”
3. 实时钩子 (Real-time Hooks)
对于使用 Claude Code 等智能体的人来说,aislop 可以安装在每次编辑后运行的钩子。这创建了一个即时的反馈循环,使智能体能够实时获知其产生的 sloppiness,从而防止技术债务的积累。
社区观点与挑战
虽然该工具因其速度和确定性而受到称赞,但社区也指出了检测 AI slop 的几项挑战:
- 误报 (False Positives):一些用户报告称,特定的库方法(例如 SQLModel 的
exec)可能被误认为危险的内置函数(如 Python 的exec())。 - “人类 Slop”悖论:一些开发者指出,该工具偶尔会将人类编写的代码标记为 AI slop,而一些真正懒惰的 AI 代码却能溜过去,这表明人类和 AI 的“sloppiness”往往是重叠的。
- 逻辑的细微差别:正如一位用户所指出的,AI 经常在“正常路径”与“异常路径”之间难以区分,从而生成过于“安全”而导致无法使用的代码。这种模式比叙述性注释更难用确定性 linter 捕获。
总结
随着我们迈向智能体驱动的软件工程时代,瓶颈不再是代码生成的速度,而是代码审查的速度。像 aislop 这样的工具将审查的负担从人类转移到了确定性的门禁,确保 AI 生成的效率不会以牺牲长期可维护性为代价。