SuperMarioYL/slopaudit

GitHub: SuperMarioYL/slopaudit

SlopAudit 是一个零配置的静态 CLI 审计工具,用于评估 JavaScript/TypeScript 仓库中由 AI 编码助手生成的劣质代码债务,并输出确定性评分与可视化报告。

Stars: 1 | Forks: 0

SlopAudit

License: Apache-2.0 Node >= 22 npm version PRs welcome Built with TypeScript

你的 AI 编码 agent 写了一半代码。现在由你来维护。
SlopAudit 会告诉你情况有多糟——以及具体在哪里。

typing

## 目录 - [什么是 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 | ## 架构

SlopAudit data flow: the CLI walks and parses a JS/TS repo to ASTs, runs five pure AST detectors, aggregates findings into a deterministic SlopScore (0–100), then renders a terminal report, HTML heatmap and SVG badge — all offline.

一条命令遍历仓库 (`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、可排序的文件表、颜色编码的热力图、无需服务器、无外部资源),可以安全地发送给你的团队。 ## 演示

slopaudit audits a repo: SlopScore headline, ranked offender-file heatmap, then writes the HTML report and SVG badge

↑ 终端录制(在 CI 中使用 vhsdocs/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](https://raw.githubusercontent.com/SuperMarioYL/slopaudit/main/slopaudit-badge.svg) ``` 这个徽章就是循环本身:有人粘贴的每一个 `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绕过, 自动化攻击, 静态分析