dotnet-slopwatch
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseSlopwatch: LLM Anti-Cheat for .NET
Slopwatch:面向.NET的LLM反作弊工具
When to Use This Skill
何时使用该工具
Use this skill constantly. Every time an LLM (including Claude) makes changes to:
- C# source files (.cs)
- Project files (.csproj)
- Props files (Directory.Build.props, Directory.Packages.props)
- Test files
Run slopwatch to validate the changes don't introduce "slop."
**请持续使用该工具。**每当LLM(包括Claude)对以下文件进行变更时:
- C#源文件(.cs)
- 项目文件(.csproj)
- 属性文件(Directory.Build.props、Directory.Packages.props)
- 测试文件
运行slopwatch来验证变更是否引入了“slop”。
What is Slop?
什么是Slop?
"Slop" refers to shortcuts LLMs take that make tests pass or builds succeed without actually solving the underlying problem. These are reward hacking behaviors - the LLM optimizes for apparent success rather than real fixes.
“Slop”指的是LLM为了让测试通过或构建成功而采取的捷径,但并未真正解决潜在问题。这些属于奖励黑客行为——LLM为了表面上的成功而优化,而非真正修复问题。
Common Slop Patterns
常见的Slop模式
| Pattern | Example | Why It's Bad |
|---|---|---|
| Disabled tests | | Hides failures instead of fixing them |
| Warning suppression | | Silences compiler without fixing issue |
| Empty catch blocks | | Swallows errors, hides bugs |
| Arbitrary delays | | Masks race conditions, makes tests slow |
| Project-level suppression | | Disables warnings project-wide |
| CPM bypass | | Undermines central package management |
Never accept these patterns. If an LLM introduces slop, reject the change and require a proper fix.
| 模式 | 示例 | 危害 |
|---|---|---|
| 禁用测试 | | 掩盖失败而非修复问题 |
| 抑制警告 | | 屏蔽编译器警告但不解决问题 |
| 空catch块 | | 吞噬错误,隐藏bug |
| 任意延迟 | | 掩盖竞态条件,拖慢测试速度 |
| 项目级抑制 | | 全局禁用项目中的警告 |
| 绕过CPM | | 破坏中央包管理机制 |
**绝不要接受这些模式。**如果LLM引入了slop,请拒绝变更并要求提供正确的修复方案。
Installation
安装
As a Local Tool (Recommended)
作为本地工具(推荐)
Add to :
.config/dotnet-tools.jsonjson
{
"version": 1,
"isRoot": true,
"tools": {
"slopwatch.cmd": {
"version": "0.2.0",
"commands": ["slopwatch"],
"rollForward": false
}
}
}Then restore:
bash
dotnet tool restore将以下内容添加到:
.config/dotnet-tools.jsonjson
{
"version": 1,
"isRoot": true,
"tools": {
"slopwatch.cmd": {
"version": "0.2.0",
"commands": ["slopwatch"],
"rollForward": false
}
}
}然后执行恢复命令:
bash
dotnet tool restoreAs a Global Tool
作为全局工具
bash
dotnet tool install --global Slopwatch.Cmdbash
dotnet tool install --global Slopwatch.CmdFirst-Time Setup: Establish a Baseline
首次设置:建立基线
Before using slopwatch on an existing project, create a baseline of current issues:
bash
undefined在现有项目中使用slopwatch之前,请创建当前问题的基线:
bash
undefinedInitialize baseline from existing code
从现有代码初始化基线
slopwatch init
slopwatch init
This creates .slopwatch/baseline.json
此命令会创建.slopwatch/baseline.json
git add .slopwatch/baseline.json
git commit -m "Add slopwatch baseline"
**Why baseline?** Legacy code may have existing issues. The baseline ensures slopwatch only catches **new** slop being introduced, not pre-existing technical debt.
---git add .slopwatch/baseline.json
git commit -m "Add slopwatch baseline"
**为什么需要基线?**遗留代码可能存在现有问题。基线确保slopwatch仅捕获**新增的**slop,而非预先存在的技术债务。
---Usage During LLM Sessions
LLM会话期间的使用方法
After Every Code Change
每次代码变更后
Run slopwatch after any LLM-generated code modification:
bash
undefined在LLM生成任何代码修改后运行slopwatch:
bash
undefinedAnalyze for new issues (uses baseline)
分析新增问题(使用基线)
slopwatch analyze
slopwatch analyze
Use strict mode - fail on warnings too
使用严格模式——遇到警告也会失败
slopwatch analyze --fail-on warning
undefinedslopwatch analyze --fail-on warning
undefinedWhen Slopwatch Flags an Issue
当Slopwatch标记问题时
Do not ignore it. Instead:
- Understand why the LLM took the shortcut
- Request a proper fix - be specific about what's wrong
- Verify the fix doesn't introduce different slop
undefined**不要忽略它。**请执行以下步骤:
- 理解原因:LLM为什么采取了捷径
- 要求正确修复——明确指出问题所在
- 验证修复:确保修复没有引入其他slop
undefinedExample: LLM disabled a test
示例:LLM禁用了一个测试
❌ SW001 [Error]: Disabled test detected
File: tests/MyApp.Tests/OrderTests.cs:45
Pattern: [Fact(Skip="Test is flaky")]
❌ SW001 [Error]: 检测到禁用的测试
文件: tests/MyApp.Tests/OrderTests.cs:45
模式: [Fact(Skip="Test is flaky")]
Correct response: Ask for actual fix
正确回应:要求实际修复
"This test was disabled instead of fixed. Please investigate why
it's flaky and fix the underlying timing/race condition issue."
undefined"这个测试被禁用而非修复。请调查它不稳定的原因,并修复潜在的时序/竞态条件问题。"
undefinedUpdating the Baseline (Rare)
更新基线(极少情况)
Only update the baseline when slop is truly justified and documented:
bash
undefined只有当slop真正合理且有文档记录时,才更新基线:
bash
undefinedAdd current detections to baseline (use sparingly!)
将当前检测结果添加到基线(谨慎使用!)
slopwatch analyze --update-baseline
**Justification examples:**
- Third-party library forces a pattern (e.g., must suppress specific warning)
- Intentional delay for rate limiting (not test flakiness)
- Generated code that can't be modified
Document why in a code comment when updating baseline.
---slopwatch analyze --update-baseline
**合理场景示例:**
- 第三方库强制要求的模式(例如,必须抑制特定警告)
- 用于速率限制的有意延迟(非测试中的延迟)
- 无法修改的生成代码
更新基线时,请在代码注释中说明原因。
---Claude Code Hook Integration
Claude代码钩子集成
Add slopwatch as a hook to automatically validate every edit. Create or update :
.claude/settings.jsonjson
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "slopwatch analyze -d . --hook",
"timeout": 60000
}
]
}
]
}
}The flag:
--hook- Only analyzes git dirty files (fast, even on large repos)
- Outputs errors to stderr in readable format
- Blocks the edit on warnings/errors (exit code 2)
- Claude sees the error and can fix it immediately
添加slopwatch作为钩子,自动验证每次编辑。创建或更新:
.claude/settings.jsonjson
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "slopwatch analyze -d . --hook",
"timeout": 60000
}
]
}
]
}
}--hook- 仅分析git未提交的文件(速度快,即使在大型仓库中)
- 以可读格式将错误输出到stderr
- 遇到警告/错误时阻止编辑(退出码2)
- Claude会看到错误并可以立即修复
CI/CD Integration
CI/CD集成
Add slopwatch to your CI pipeline as a quality gate:
将slopwatch添加到CI流水线中作为质量门:
GitHub Actions
GitHub Actions
yaml
jobs:
slopwatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install Slopwatch
run: dotnet tool install --global Slopwatch.Cmd
- name: Run Slopwatch
run: slopwatch analyze -d . --fail-on warningyaml
jobs:
slopwatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Install Slopwatch
run: dotnet tool install --global Slopwatch.Cmd
- name: Run Slopwatch
run: slopwatch analyze -d . --fail-on warningAzure Pipelines
Azure Pipelines
yaml
- 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'yaml
- 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'Detection Rules
检测规则
| Rule | Severity | What It Catches |
|---|---|---|
| SW001 | Error | Disabled tests ( |
| SW002 | Warning | Warning suppression ( |
| SW003 | Error | Empty catch blocks that swallow exceptions |
| SW004 | Warning | Arbitrary delays in tests ( |
| SW005 | Warning | Project file slop ( |
| SW006 | Warning | CPM bypass ( |
| 规则 | 严重程度 | 检测内容 |
|---|---|---|
| SW001 | 错误 | 禁用的测试( |
| SW002 | 警告 | 警告抑制( |
| SW003 | 错误 | 吞噬异常的空catch块 |
| SW004 | 警告 | 测试中的任意延迟( |
| SW005 | 警告 | 项目文件中的slop( |
| SW006 | 警告 | 绕过CPM( |
Configuration
配置
Create to customize:
.slopwatch/slopwatch.jsonjson
{
"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/**"
]
}创建来自定义配置:
.slopwatch/slopwatch.jsonjson
{
"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/**"
]
}Strict Mode (Recommended for LLM Sessions)
严格模式(LLM会话推荐使用)
For maximum protection during LLM coding sessions, elevate all rules to errors:
json
{
"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" }
}
}在LLM编码会话中,为了获得最大保护,请将所有规则提升为错误级别:
json
{
"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" }
}
}The Philosophy: Zero Tolerance for New Slop
理念:零容忍新增Slop
- Baseline captures legacy - Existing issues are acknowledged but isolated
- New slop is blocked - Any new shortcut fails the build/edit
- Exceptions require justification - If you must update baseline, document why
- LLMs are not special - The same rules apply to human and AI-generated code
The goal is to prevent the gradual accumulation of technical debt that occurs when LLMs optimize for "make the test pass" rather than "fix the actual problem."
- 基线覆盖遗留问题——已存在的问题被确认但隔离
- 新增Slop被阻止——任何新的捷径都会导致构建/编辑失败
- 例外情况需要理由——如果必须更新基线,请记录原因
- LLM不享有特殊待遇——规则对人类和AI生成的代码同样适用
目标是防止LLM为了“让测试通过”而非“修复实际问题”而导致的技术债务逐渐累积。
Quick Reference
快速参考
bash
undefinedbash
undefinedFirst time setup
首次设置
slopwatch init
git add .slopwatch/baseline.json
slopwatch init
git add .slopwatch/baseline.json
After every LLM code change
每次LLM代码变更后
slopwatch analyze
slopwatch analyze
Strict mode (recommended)
严格模式(推荐)
slopwatch analyze --fail-on warning
slopwatch analyze --fail-on warning
With stats (performance debugging)
带统计信息(性能调试)
slopwatch analyze --stats
slopwatch analyze --stats
Update baseline (rare, document why)
更新基线(极少情况,记录原因)
slopwatch analyze --update-baseline
slopwatch analyze --update-baseline
JSON output for tooling
为工具输出JSON格式结果
slopwatch analyze --output json
---slopwatch analyze --output json
---When to Override (Almost Never)
何时可以覆盖规则(几乎从不)
The only valid reasons to update baseline or disable a rule:
| Scenario | Action | Required |
|---|---|---|
| Third-party forces pattern | Update baseline | Code comment explaining why |
| Generated code (not editable) | Add to exclude list | Document in config |
| Intentional rate limiting delay | Update baseline | Code comment, not in test |
| Legacy code cleanup | One-time baseline update | PR description |
Invalid reasons:
- "The test is flaky" → Fix the flakiness
- "The warning is annoying" → Fix the code
- "It works on my machine" → Fix the race condition
- "We'll fix it later" → Fix it now
更新基线或禁用规则的唯一有效理由:
| 场景 | 操作 | 要求 |
|---|---|---|
| 第三方库强制要求的模式 | 更新基线 | 代码注释说明原因 |
| 生成的代码(不可编辑) | 添加到排除列表 | 在配置中记录 |
| 有意的速率限制延迟 | 更新基线 | 代码注释,且不在测试中 |
| 遗留代码清理 | 一次性更新基线 | PR描述中说明 |
无效理由:
- “测试不稳定” → 修复不稳定问题
- “警告很烦” → 修复代码
- “在我机器上能运行” → 修复竞态条件
- “我们以后再修” → 现在就修