关于 slopwatch
slopwatch 是面向 .NET 开发的技能,用于检查代码改动中掩盖问题的捷径,尤其适用于 LLM 生成的改动。它介绍了结合基线、可配置规则、钩子和 CI 检查的命令行流程。
主要功能
- 01检测被禁用的测试和警告抑制
- 02标记空 catch 块和测试延时
- 03检查项目设置和包版本覆盖
- 04用基线隔离已有问题
- 05支持钩子和 CI 验证
适用场景
- 01审查 LLM 对 C# 和项目文件的修改
- 02在本地分析中阻止新增捷径
- 03在 CI 流水线运行 slop 检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ wshaddix/ dotnet-skills --skill slopwatch安装后在 Claude Code 中输入/slopwatch确认已加载。
详细介绍
Slopwatch:.NET 大模型反作弊工具
何时使用此技能
请始终使用此技能。 每当大模型(包括 Claude)修改以下内容时:
- C# 源文件(.cs)
- 项目文件(.csproj)
- 属性文件(Directory.Build.props、Directory.Packages.props)
- 测试文件
运行 slopwatch,验证这些修改不会引入“糟粕”。
什么是糟粕?
“糟粕”是指大模型为通过测试或成功构建而采取的捷径,却没有真正解决根本问题。这些行为属于奖励作弊——大模型追求表面上的成功,而不是实际修复问题。
常见的糟粕模式
| 模式 | 示例 | 不良之处 |
|---|---|---|
| 禁用测试 | [Fact(Skip="flaky")] | 掩盖失败,而不是修复问题 |
| 抑制警告 | #pragma warning disable CS8618 | 只是让编译器不再报错,并未解决问题 |
| 空 catch 块 | catch (Exception) { } | 吞掉错误,掩盖 bug |
| 随意延迟 | await Task.Delay(1000); | 掩盖竞态条件,并拖慢测试 |
| 项目级抑制 | <NoWarn>CS1591</NoWarn> | 在整个项目范围内禁用警告 |
| 绕过 CPM | 内联 Version="1.0.0" | 破坏集中式包管理 |
绝不接受这些模式。 如果大模型引入了糟粕,请拒绝此次修改,并要求进行妥善修复。
安装
作为本地工具(推荐)
添加到 .config/dotnet-tools.json:
{
"version": 1,
"isRoot": true,
"tools": {
"slopwatch.cmd": {
"version": "0.3.3",
"commands": ["slopwatch"],
"rollForward": false
}
}
}
然后还原:
dotnet tool restore
作为全局工具
dotnet tool install --global Slopwatch.Cmd
首次设置:建立基线
在现有项目中使用 slopwatch 之前,请先建立基线:
# Initialize baseline from existing code
slopwatch init
# This creates .slopwatch/baseline.json
git add .slopwatch/baseline.json
git commit -m "Add slopwatch baseline"
为什么要建立基线? 遗留代码中可能已有问题。基线可确保 slopwatch 只检测新引入的糟粕。
用法
基本分析
# Analyze current directory for slop
slopwatch analyze
# Analyze specific directory
slopwatch analyze -d ./src
# Strict mode -- fail on warnings too
slopwatch analyze --fail-on warning
# JSON output for tooling integration
slopwatch analyze --output json
# Show performance stats
slopwatch analyze --stats
更新基线(不常见)
只有在糟粕确有合理原因且已记录的情况下才更新:
slopwatch analyze --update-baseline
合理原因:第三方库强制采用某种模式、有意进行速率限制的延迟(而非测试不稳定)、无法修改的生成代码。请始终添加代码注释,说明合理原因。
配置
创建 .slopwatch/slopwatch.json 以自定义配置:
{
"minSeverity": "warning",
"rules": {
"SW001": { "enabled": true, "severity": "error" },
"SW002": { "enabled": true, "severity": "warning" },
"SW003": { "enabled": true, "severity": "error" },
"SW004": { "enabled": true, "severity": "warning" },
"SW005": { "enabled": true, "severity": "warning" },
"SW006": { "enabled": true, "severity": "warning" }
},
"exclude": [
"**/Generated/**",
"**/obj/**",
"**/bin/**"
]
}
严格模式(推荐用于大模型会话)
{
"minSeverity": "warning",
"rules": {
"SW001": { "enabled": true, "severity": "error" },
"SW002": { "enabled": true, "severity": "error" },
"SW003": { "enabled": true, "severity": "error" },
"SW004": { "enabled": true, "severity": "error" },
"SW005": { "enabled": true, "severity": "error" },
"SW006": { "enabled": true, "severity": "error" }
}
}
检测规则
| 规则 | 严重性 | 检测内容 |
|---|---|---|
| SW001 | 错误 | 禁用的测试(Skip=、Ignore、#if false) |
| SW002 | 警告 | 警告抑制(#pragma warning disable、SuppressMessage) |
| SW003 | 错误 | 会吞掉异常的空 catch 块 |
| SW004 | 警告 | 测试中的随意延迟(Task.Delay、Thread.Sleep) |
| SW005 | 警告 | 项目文件中的糟粕(NoWarn、TreatWarningsAsErrors=false) |
| SW006 | 警告 | 绕过 CPM(VersionOverride、内联 Version 属性) |
Slopwatch 标记问题时
❌ SW001 [Error]: Disabled test detected
File: tests/MyApp.Tests/OrderTests.cs:45
Pattern: [Fact(Skip="Test is flaky")]
- 了解原因:大模型为何采取了捷径
- 要求妥善修复:明确指出问题所在
- 验证修复:确保没有引入其他糟粕
绝不要为了让构建通过而禁用测试。 请修复根本问题。
Claude Code Hook 集成
将 slopwatch 添加为 hook,以便自动验证每次编辑。创建或更新 .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "slopwatch analyze -d . --hook",
"timeout": 60000
}
]
}
]
}
}
--hook 标志:
- 只分析 git 工作区中的脏文件(速度快,即使在大型仓库中也是如此)
- 以易读格式将错误输出到 stderr
- 遇到警告或错误时阻止编辑(退出代码为 2)
- Claude 会看到错误并立即修复
CI/CD 集成
GitHub Actions
jobs:
slopwatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '8.0.x'
- name: Install Slopwatch
run: dotnet tool install --global Slopwatch.Cmd
- name: Run Slopwatch
run: slopwatch analyze -d . --fail-on warning
Azure Pipelines
- task: DotNetCoreCLI@2
displayName: 'Install Slopwatch'
inputs:
command: 'custom'
custom: 'tool'
arguments: 'install --global Slopwatch.Cmd'
- script: slopwatch analyze -d . --fail-on warning
displayName: 'Slopwatch Analysis'
理念:对新糟粕零容忍
- 基线记录遗留问题——现有问题会被确认并隔离
- 阻止新糟粕——任何新捷径都会导致构建或编辑失败
- 例外情况必须说明理由——如果必须更新基线,请记录原因
- 大模型不享有特殊待遇——人类编写的代码和 AI 生成的代码适用相同规则
快速参考
# First time setup
slopwatch init
git add .slopwatch/baseline.json
# After every LLM code change
slopwatch analyze
# Strict mode (recommended)
slopwatch analyze --fail-on warning
# With stats (performance debugging)
slopwatch analyze --stats
# Update baseline (rare, document why)
slopwatch analyze --update-baseline
# JSON output for tooling
slopwatch analyze --output json
# Hook mode (for Claude Code integration)
slopwatch analyze -d . --hook
何时覆盖(几乎从不)
更新基线或禁用规则的唯一合理理由:
| 场景 | 操作 | 要求 |
|---|---|---|
| 第三方强制采用某种模式 | 更新基线 | 添加代码注释说明原因 |
| 生成的代码(无法编辑) | 添加到排除列表 | 在配置中记录 |
| 有意设置的限速延迟 | 更新基线 | 添加代码注释,而非测试注释 |
| 清理遗留代码 | 一次性更新基线 | PR 描述 |
无效理由:
- “测试不稳定” → 修复不稳定问题
- “警告很烦人” → 修复代码
- “在我的机器上能运行” → 修复竞态条件
- “以后再修” → 现在就修
Agent 注意事项
- 不要抑制 slopwatch 的检查结果。 如果 slopwatch 标记了问题,就修复代码。
- 每次更改代码后都要运行,不要只在最后运行。
- 在 Claude Code 钩子中使用
--hook标志,不要直接使用analyze。 - 基线不是垃圾桶。 添加条目必须有记录在案的理由。
- 优先使用本地工具,而非全局工具。 使用
.config/dotnet-tools.json。
参考资料
评论
支持 Markdown