SuperMarioYL/slopaudit
GitHub: SuperMarioYL/slopaudit
SlopAudit 是一个零配置的静态 CLI 审计工具,用于评估 JavaScript/TypeScript 仓库中由 AI 编码助手生成的劣质代码债务,并输出确定性评分与可视化报告。
Stars: 1 | Forks: 0
你的 AI 编码 agent 写了一半代码。现在由你来维护。
SlopAudit 会告诉你情况有多糟——以及具体在哪里。
## 目录
- [什么是 SlopAudit?](#what-is-slopaudit)
- [架构](#architecture)
- [快速开始](#quick-start)
- [演示](#demo)
- [工作原理](#how-it-works)
- [Slop 分类](#the-slop-categories)
- [CLI 用法](#cli-usage)
- [GitHub Action](#github-action)
- [SlopScore 徽章(病毒式循环)](#the-slopscore-badge)
- [定价](#pricing)
- [路线图](#roadmap)
- [贡献](#contributing)
- [许可证](#license)
## 什么是 SlopAudit?
AI 编码 **agent** 发布代码的速度非常快——如今每个 JS/TS 仓库中越来越多的代码都是由 AI 生成的,它们只经过了一半审查,最终被并没有编写这些代码的人类所接手。Agent 的 **Skills**、prompt 配置以及复制粘贴的脚手架(参见 [`Shubhamsaboo/awesome-llm-apps`](https://github.com/Shubhamsaboo/awesome-llm-apps) 和 [`affaan-m/everything-claude-code`](https://github.com/affaan-m/everything-claude-code) 等生态系统)累积了一种 linter 从未标记的特定类型的技术债务:**slop(劣质代码)**。
SlopAudit 是一个 **零配置 CLI**,用于审计现有的 JS/TS 仓库中由 AI 生成的 slop 债务,并输出一个核心指标数字——**SlopScore (0–100)**——以及排名的文件热力图和可共享的报告。
它是 **100% 静态和基于启发式的**——没有 LLM 调用,没有网络请求,没有遥测。同一个仓库在每次运行中都会产生相同的分数。
| | |
|---|---|
| **较高的 SlopScore** | 较多的 AI-slop 债务 (`heavy`) |
| **较低的 SlopScore** | 更干净、有意图的代码 (`clean`) |
| **区间** | `clean` < 34 · `moderate` 34–66 · `heavy` > 66 |
##

架构
一条命令遍历仓库 (`scan/walk.ts`) 并将每个 JS/TS 文件解析为 AST (`scan/parse.ts`,使用 `errorRecovery` 确保现代语法永远不会让扫描崩溃)。五个**纯检测器**——`over_abstraction`、`generic_boilerplate`、`plausible_but_wrong`、`dead_parameter` 和 `copy_paste_clone`——将该 AST 转换为加权的 `SlopFinding`,然后由 `score/aggregate.ts` 将其标准化为一个确定性的 **SlopScore (0–100)**。`report/` 层以三种方式渲染相同的分数:基于 chalk 的终端热力图、独立的 HTML 报告,以及 shields 风格的 SVG 徽章。整个流水线是静态且离线运行的——没有 LLM,没有网络请求,同样的仓库 → 同样的分数。在 CI 中,同样的门控会作为一个打包好的 **GitHub Action** 发布,它将分数写入作业摘要,**并将逐行的 slop 标注直接添加到 PR diff 上**。
## 快速开始
无需安装。在任何 JS/TS 仓库中只需一条命令:
```
npx slopaudit .
```
你会得到一个终端摘要、一个独立的 `slopaudit-report.html` 热力图,以及一个 `slopaudit-badge.svg`——在两分钟内写入你的当前目录。
```
SlopScore: 71/100 (heavy)
124 files scanned · 18452 lines · 213 findings
Top offender files
1. src/services/AbstractFactoryProvider.ts ████████████████░░░░ 82%
2. src/utils/genericHandlerWrapper.ts ██████████████░░░░░░ 71%
3. src/managers/ConfigManagerManager.ts █████████████░░░░░░░ 64%
4. src/core/BasePassthroughService.ts ███████████░░░░░░░░░ 58%
5. src/handlers/maybeTryCatchHandler.ts ██████████░░░░░░░░░░ 51%
...
Wrote slopaudit-report.html, slopaudit-badge.svg
```
在任何浏览器中打开 `slopaudit-report.html`——它是完全独立的(内联 CSS、可排序的文件表、颜色编码的热力图、无需服务器、无外部资源),可以安全地发送给你的团队。
##

演示
↑ 终端录制(在 CI 中使用 vhs 从 docs/demo.tape 渲染,并在每个 tag 上重新生成)。
## 工作原理
```
npx slopaudit .
│
▼
scan/walk.ts fast-glob the repo for *.{js,jsx,ts,tsx},
skipping node_modules / dist / build / vendor / .git
│
▼
scan/parse.ts @babel/parser → AST per file
(typescript + jsx + decorators, errorRecovery so
modern syntax never crashes the scan)
│
▼
detectors/ five pure AST detectors → SlopFinding[]
├─ overAbstraction.ts
├─ genericBoilerplate.ts
├─ plausibleButWrong.ts
├─ deadParameter.ts
└─ copyPasteClone.ts
│
▼
score/aggregate.ts SlopFinding[] → SlopScore (weighted density,
normalized 0..100, banded, deterministic)
│
▼
report/ terminal.ts (chalk) · html.ts (heatmap) · badge.ts (SVG)
│
▼
action.yml composite GitHub Action → runs the --fail-on gate in CI,
writes band + worst files to $GITHUB_STEP_SUMMARY
```
每个检测器都是一个**纯函数** (`AST → SlopFinding[]`),并经过独立的单元测试。这个接口层是未来插入更多分类和语言的地方。每一个发现都包含人类可读的**证据**(例如 `"4-deep wrapper, single caller"`)——SlopAudit 是一个你可以验证的筛查工具,而不是一个黑盒判决。
## Slop 分类
SlopAudit 对一个**AI 特定的维度**进行评分——不是代码风格,不是正确性,而是 agent 过度生成的模式:
| 分类 | 捕捉内容 | 示例证据 |
|---|---|---|
| **`over_abstraction`** | 深层的单调用包装器链,不必要的 factory/provider/manager 层,单方法接口,传递函数 | `4-deep wrapper, single caller` |
| **`generic_boilerplate`** | 几乎重复的脚手架块,复制粘贴的 try/catch,大量的琐碎 getters/setters,TODO/占位符注释密度高 | `near-identical scaffold ×6` |
| **`plausible_but_wrong`** | 吞没错误的空 catch,大量使用 `any` 的签名,未 await 的 promise,死分支,矛盾的守卫 | `empty catch swallows error` |
| **`dead_parameter`** *(v0.3.0 新增)* | 命名的函数参数被连接到签名中,但在函数体中从未被读取——即 agent “以防万一”添加的 `context`/`options` | `parameter "ctx" is never used` |
| **`copy_paste_clone`** *(v0.4.0 新增)* | *几乎*重复的代码块——经过重新排序或轻微编辑的复制块,这是精确形状的 `generic_boilerplate` 检查会漏过的(基于结构、与名称/字面量无关) | `~90% shared structure with the block at line 42` |
这些都是 lint 检查不出的 slop:能通过 ESLint 并正常编译的代码,但却是人类现在必须去理清的债务。
## CLI 用法
```
slopaudit [path] # full audit (default path ".")
```
| 标志 | 效果 |
|---|---|
| *(无)* | 完整审计:终端报告 + 将 `slopaudit-report.html` 和 `slopaudit-badge.svg` 写入当前工作目录 |
| `--list` | **仅 m1 清单** —— 列出每个源文件及其行数,不进行评分 |
| `--json` | 将 `SlopScore` 作为 JSON 打印到 stdout(机器可读,非常适合 CI) |
| `--format github` | 为每个发现输出一条 GitHub Actions `::warning file=…,line=…::…` 命令——**内联的逐行 PR 标注**(打包好的 Action 会自动开启此功能) |
| `--fail-on
` | **CI 门控**——当 SlopScore 达到/超过 ``(区间 `clean`/`moderate`/`heavy`,或整数 `0–100`)时以非零状态退出 |
| `--no-html` | 跳过写入 `slopaudit-report.html` |
| `--no-badge` | 跳过写入 `slopaudit-badge.svg` |
| `-v, --version` | 打印版本 |
| `-h, --help` | 显示帮助 |
示例:
```
npx slopaudit ./packages/api # audit a sub-package
npx slopaudit . --json # SlopScore as JSON to stdout (files still written)
npx slopaudit . --json --no-html --no-badge # pure stdout, nothing written — CI friendly
npx slopaudit . --list # file inventory + line counts only
npx slopaudit . --fail-on moderate # exit 1 if the repo is moderate-or-heavy (CI gate)
npx slopaudit . --fail-on 50 # exit 1 if SlopScore >= 50
```
### 在 CI 中设置门控
`--fail-on` 将 SlopScore 转化为拉取请求门控——一步到位,无需服务,无需账号。当分数越过你的阈值时,CLI 会以状态码 `1` 退出,从而导致作业失败:
```
# .github/workflows/slop.yml
- name: SlopAudit gate
run: npx slopaudit . --fail-on moderate --no-html --no-badge
```
`--fail-on` 可与 `--json` 组合使用:JSON 报告仍会在门控决定退出代码之前写入 stdout,因此你可以在一次运行中同时发布分数并阻止 PR 合并。
## GitHub Action
*v0.3.0 新增。* 对于 GitHub 仓库,同样的门控作为一个**打包的、可复用的复合 Action** 发布——无需 `npx` 样板代码,并且 SlopScore 区间及最严重的违规项将被直接写入**作业摘要**。将其放入任何工作流中:
```
# .github/workflows/slop.yml
name: SlopAudit
on: [pull_request]
jobs:
slopaudit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: SuperMarioYL/slopaudit-action@v0.3.0
with:
path: "." # directory to audit (default ".")
fail-on: moderate # band clean|moderate|heavy, or an integer 0–100
```
| 输入 | 默认值 | 效果 |
|---|---|---|
| `path` | `.` | 相对于工作区要进行审计的目录 |
| `fail-on` | *(空)* | 导致作业失败的阈值(区间或 `0–100`)。留空则仅在摘要中报告分数,**而不会**导致构建失败 |
| `version` | `0.3.0` | Action 运行的 `slopaudit` 的 npm 版本/tag |
当 SlopScore 达到或超过 `fail-on` 时,作业将会**失败**。运行的**摘要**(Summary)选项卡会显示分数区间、文件计数以及一个排名的“最严重违规者”表,并且**每个发现也会作为内联标注直接添加到 PR diff 对应的行上** *(v0.4.0 新增)*——无需额外设置,源自与写入摘要相同的运行过程。该 Action 还将 `score` 和 `band` 作为步骤输出暴露出来:
```
- uses: SuperMarioYL/slopaudit-action@v0.3.0
id: slop
with:
fail-on: heavy
- run: echo "SlopScore is ${{ steps.slop.outputs.score }} (${{ steps.slop.outputs.band }})"
```
## SlopScore 徽章
每次运行都会写入 `slopaudit-badge.svg`——一个根据分数区间着色的 shields 风格扁平徽章(绿色 `clean` / 黄色 `moderate` / 红色 `heavy`)。**提交它并将其添加到你的 README 中:**
```

```
这个徽章就是循环本身:有人粘贴的每一个 `SlopScore: 23/100` 都是一个公开信号,表明他们的仓库已经被审计过——并且提供了一个回链。以低分为荣;把高分当作一个待办事项清单。
## 定价
**CLI 是免费、开源 (Apache-2.0) 的,并将永远为个人和 OSS 项目保持免费。** 你可以随时随地离线运行它,零账号要求。
对于需要*监控*分数而不是仅仅抽查分数的团队,**托管团队层级**已在路线图中:
| | **OSS CLI** | **团队(托管版)——即将推出** |
|---|---|---|
| `npx slopaudit .` 审计 | 无限 | 无限 |
| HTML 热力图 + SVG 徽章 | ✓ | ✓ |
| 离线 / 确定性 | ✓ | ✓ |
| 在 CI 中基于绝对阈值**设置 PR 门控** (`--fail-on` / 打包的 Action) | ✓ | ✓ |
| 所有组织仓库的 SlopScore **历史记录 / 趋势** | — | ✓ |
| 基于*上升*分数进行门控(对比 main 分支的增量,而不仅仅是绝对值) | — | ✓ |
| 可转发给管理层的仪表板 | — | ✓ |
| 定价 | **免费** | **~$15 / 活跃开发者 / 月** |
免费的 CLI 证明了这个分数是可信的——从 v0.3.0 开始,它可以通过一行 **GitHub Action** (`--fail-on`) 独立在绝对阈值上对 CI 进行门控。团队层级添加了单个 CLI 运行无法做到的事情:*历史记录*——跨组织仓库跟踪随时间变化的分数,并阻止那些相对于 main 分支*增加*了 slop 债务的 PR。欢迎通过 [Issues](https://github.com/SuperMarioYL/slopaudit/issues) 提交“我们可以使用托管历史记录层级吗?”的请求。
## 路线图
- [x] **m1 — 扫描与解析:** 遍历仓库,将每个 JS/TS 文件解析为 AST(支持 TSX、装饰器、现代语法)且不崩溃,输出 `--list` 清单。
- [x] **m2 — 评分与定位:** 三个 slop 检测器 → 加权的 `SlopFinding` → 确定性的 `SlopScore (0–100)` + 排名的逐文件热力图。
- [x] **m3 — 可共享报告:** chalk 终端摘要、独立的 HTML 热力图以及 SVG SlopScore 徽章。
- [x] **m4 — CI 失败门控:** `--fail-on ` 在 SlopScore 超过阈值时以非零状态退出,可以通过一个工作流步骤阻止 PR 合并。
- [x] **m5 — GitHub Action:** 打包的复合 Action 封装了 `--fail-on`,将分数区间和最严重的违规项写入作业摘要 (`uses: SuperMarioYL/slopaudit-action@v0.3.0`)。
- [x] **m6 — 第四个检测器:** 通过纯函数检测器接口实现 `dead_parameter`(未使用的函数参数)。
- [x] **m7 — 内联 PR 标注:** `--format github` 为每个发现输出一条 `::warning file=…,line=…::…` 命令,打包的 Action 会将逐行的 slop 标注添加到 PR diff 上。
- [x] **m8 — 第五个检测器:** 通过相同的纯函数接口实现 `copy_paste_clone`(几乎重复的代码块——重新排序或轻微编辑的副本)。
- [ ] **托管团队层级:** 跨组织仓库的 SlopScore *历史记录* + 基于对比 main 分支增量的门控 + 管理层仪表板。
- [ ] **更多语言:** 在相同的纯函数检测器接口下实现 Python / Go / Rust 检测器。
- [ ] **更多检测器:** 社区贡献的 slop 分类。
## 许可证
[Apache-2.0](./LICENSE)。 标签:MITM代理, SOC Prime, TypeScript, 云安全监控, 人工智能, 安全插件, 开发工具, 暗色界面, 用户模式Hook绕过, 自动化攻击, 静态分析