---
name: slop-cleaner
description: >
  自动化代码卫生扫描——识别大文件、死代码、测试与实现混合、架构坏味道等结构性问题，
  产出结构化清扫报告和终端摘要。偏自动化批量扫描，非深度 code review。
  当用户说"扫一下 slop"、"清理代码卫生"、"检查代码质量"、
  "找找死代码"、"哪些文件太大了"、"测试混在源码里"、"架构有没有问题"、"代码有没有坏味道"、
  "slop scan"、"clean up codebase"、"find dead code"、"large files"时立即触发。
  也适用于："帮我看看有没有技术债"、"代码库健康度怎么样"、"这个模块该不该拆"、
  "有没有未使用的代码"等代码卫生评估场景。
  只要用户想快速了解代码库的结构性卫生状况，就应使用此 skill。
---

# Slop Cleaner

自动化扫描代码库中的结构性问题——大文件、死代码、测试与实现混合、架构坏味道——
快速产出可行动的清扫报告。

与 code-review 的定位区别：code-review 偏人工辅助，深度分析具体代码逻辑；
slop-cleaner 偏自动化批量扫描，用 Glob/Grep/Bash 快速定位结构性问题，产出可行动的清扫清单。

---

## 核心原则

1. **速度优先**：用 Glob/Grep/Bash 批量扫描，避免逐文件 Read。只在需要深入分析时才 Read 具体文件。
2. **数据说话**：每个发现都要有具体的文件路径、行号、度量数据（行数、调用次数等），不凭感觉。
3. **可行动**：报告不只是问题清单，还要给出优先级排序和具体的修复建议。
4. **尊重项目规范**：扫描前先读取 CLAUDE.md / 项目文档，按项目已有的约定判断问题，不套用外部模板。
5. **增量感知**：对比历史扫描结果，区分新增问题和已知问题，让清扫有可量化的进展。

---

## 第一步：项目上下文 + 排除列表（快速）

并行读取，建立最小必要上下文：

```
Read("CLAUDE.md")                           # 项目规范、约定、已知待办
Glob("src/**/*.rs") 或 Glob("src/**/*.ts")  # 主要源文件列表
Bash("git log --oneline -10")              # 最近改动方向（可选）
Glob("spec/reviews/*.md")                  # 历史扫描报告（用于对比）
```

从上下文中提取：
- 项目语言和技术栈
- 模块/包的划分方式
- 项目已有的代码规范（如测试分离规则、文件大小上限等）
- **已知待办项**：CLAUDE.md 中已记录的问题（如「待迁移文件」表格），扫描时标注为 `已记录`，避免重复报告
- **排除目录**：内置默认排除 + 从 CLAUDE.md 提取的额外排除

**默认排除列表**（所有扫描命令统一过滤）：

```
target/ node_modules/ vendor/ .git/ dist/ build/
*.generated.rs *.min.js *.min.css
migrations/ __snapshots/ fixtures/
```

所有 `find` / `Glob` / `Grep` 命令都必须遵守排除列表。用 `Grep` 时通过 `glob` 参数排除，用 `find` 时通过 `-not -path` 排除。

---

## 第二步：渐进式扫描

不是所有维度都需要每次全量跑。根据仓库规模和用户意图选择策略：

### 策略 A：快速扫描（默认）

先跑维度 1（大文件）+ 维度 2（死代码），这两个维度最快、结果最确定。

- 如果大文件扫描发现仓库整体很小（最大文件 < 200 行），跳过架构维度
- 如果没有 Rust 项目，跳过测试分离维度（`#[cfg(test)]` 是 Rust 特有的）
- 用户指定了维度时，只跑指定维度

### 策略 B：全量扫描

用户明确要求"全面扫描"或仓库规模较大时，四个维度全部并行执行。

### 策略 C：定向扫描

用户指定了目录或文件（如"扫一下 src/mcp/"），只对该范围执行扫描。

---

## 四大维度

### 维度 1：大文件 / 上帝类

**目标**：找出职责过重、应拆分的文件和函数。

**扫描命令**（并行执行）：

```bash
# 按文件大小排序（最快，秒级完成，无需逐行读取）
Bash("find <src_dir> -name '*.rs' -not -path '*/target/*' | xargs ls -lhS | head -30")

# 命中文件再用行数精确确认
Bash("find <src_dir> -name '*.rs' -not -path '*/target/*' | xargs wc -l | sort -rn | head -30")

# 超长函数（仅对 top-10 大文件深入检查）
Grep("pub fn |pub async fn ", path="<top10_files>")  # 列出候选函数，Read 确认行数
```

**判定阈值**（按项目规范调整，默认值）：

| 类型 | 警告阈值 | 严重阈值 |
|------|---------|---------|
| 单文件大小 | 15 KB | 30 KB |
| 单文件行数 | 400 行 | 800 行 |
| 单函数行数 | 50 行 | 100 行 |

先用 `ls -lhS` 按文件大小秒级粗筛，命中文件再用 `wc -l` 精确确认行数。

**对每个命中文件**：Read 前 50 行 + 后 50 行，判断职责是否可拆分。

### 维度 2：死代码

**目标**：找出定义了但从未使用的函数、变量、类型、导入。

**扫描命令**（并行执行）：

```bash
# 编译器级检测（最权威）
Bash("cargo build 2>&1 | grep -i 'unused\\|dead_code\\|never used'")
Bash("cargo clippy 2>&1 | grep -i 'unused\\|dead_code'")  # clippy 覆盖更广

# TODO/FIXME/HACK 注释（判断是否为被遗忘的技术债）
Grep("TODO|FIXME|HACK|XXX|WORKAROUND")

# 注释掉的代码块（连续 3 行以上以 // 开头的代码行）
Bash("grep -rn '^\s*// *[a-zA-Z]' <src_dir> | ... ")  # 提取连续 3+ 行的文件
```

**验证方法**：编译器已报告的直接确认，无需二次验证。对注释掉的代码和 TODO，只报告数量，不做逐条验证。

### 维度 3：测试与实现混合

**目标**：找出违反测试分离规范的文件。

**扫描命令**：

```bash
# 源文件中内联的 #[cfg(test)] mod tests 块
Grep("#\\[cfg\\(test\\)\\]")  # 找出所有含内联测试的源文件
```

对每个命中文件，用 Bash 统计 `#[cfg(test)]` 到对应 `}` 的行数。

**判定规则**（参考 CLAUDE.md 中的测试规范）：
- 内联测试 < 30 行：可以接受
- 内联测试 30-100 行：应分离
- 内联测试 > 100 行：必须分离

**同时检查**：
- `tests/` 目录是否存在、是否有内容
- 测试文件命名是否符合项目规范（如 `foo_test.rs`）

### 维度 4：架构坏味道

**目标**：找出违反分层规则、循环依赖、职责混乱的模块。

**扫描命令**（并行执行）：

```bash
# 依赖方向检查（Rust：下层 crate 依赖上层）
# 读取 Cargo.toml 的 [dependencies] 段，对照 CLAUDE.md 中的依赖关系图
Glob("**/Cargo.toml")  # 然后读取每个 crate 的依赖

# 模块内聚度：一个 mod.rs 引入大量不相关的子模块
Glob("*/mod.rs")  # 然后读取每个 mod.rs 的 mod 声明

# pub 接口过多（API 面过大）
Grep("pub fn |pub struct |pub enum |pub trait ")  # 按文件统计 pub 声明数量
```

**判定方法**：
- 对照 CLAUDE.md 中描述的架构规则，检查实际依赖是否匹配
- 检查是否存在 `utils.rs`/`common.rs`/`helpers.rs` 等万能模块（什么都往里扔）
- 检查 `mod.rs` 的子模块数量是否过多（>15 个子模块 = 模块应拆分）

---

## 第三步：去重 + 历史对比

扫描完成后、写入报告前：

1. **去重**：对比 CLAUDE.md 中已记录的待办项，标注 `已记录` 或 `新增`
2. **历史对比**：如果 `spec/reviews/` 下有历史报告，对比问题数量的变化

---

## 第四步：汇总与输出

### 终端摘要

扫描完成后，立即在终端输出简洁摘要：

```
🧹 Slop Scan 完成 → spec/reviews/2026-05-12.md

发现问题：2 critical / 5 major / 12 minor（+3 新增 / -2 已修复）

Top 问题：
- [critical] src/handler.rs — 920 行，严重超限，建议拆分为 3-4 个子模块 [新增]
- [critical] src/db/mod.rs — 引入 23 个子模块，内聚度极低 [已记录]
- [major] src/auth.rs — 内联测试 145 行，应分离为 auth_test.rs [新增]
- [major] src/utils.rs — 17 个 pub fn，仅 5 个被引用，12 个疑似死代码 [新增]
```

### Markdown 报告

读取 `assets/report-template.md`（本 skill 目录下），按模板填充，然后：

1. 确定输出路径：默认写到 `spec/reviews/YYYY-MM-DD.md`
   - 若用户指定了路径，使用用户指定的路径
   - 若 `spec/reviews/` 目录不存在，先用 `folder_operations` 创建

2. 用 `Write` 写入文件

**报告格式**：与 `spec/issues/` 保持一致的风格——简洁、数据驱动、可直接转化为 issue 跟踪。

---

## 严重程度标签

| 标签 | 含义 | 典型场景 |
|------|------|---------|
| 🔴 **[critical]** | 严重的结构性问题，会持续拖累开发效率 | 800+ 行文件、反向依赖、万能 utils 模块 |
| 🟡 **[major]** | 明显的结构性问题，应尽快处理 | 400+ 行文件、100+ 行内联测试、大量死代码 |
| 🟢 **[minor]** | 轻微的结构性问题 | 30-50 行内联测试、少量未使用导入、个别 TODO |
| 💡 **[info]** | 信息性发现，供参考 | 文件行数接近阈值、pub 接口较多但合理 |

---

## 指定范围扫描

如果用户指定了目录或文件（如"扫一下 src/mcp/"），只对该范围执行扫描，跳过无关模块。

如果用户指定了维度（如"只找死代码"），只执行该维度的扫描。

---

## 参考文件

- `assets/report-template.md` — Slop 报告模板
