Slopwatch: KI-Anti-Cheat für .NET
Wann du diese Fähigkeit nutzen solltest
Nutze diese Fähigkeit ständig. Jedes Mal, wenn ein KI-Modell (einschließlich Claude) Änderungen an folgenden Dateien vornimmt:
- C#-Quelldateien (.cs)
- Projektdateien (.csproj)
- Props-Dateien (Directory.Build.props, Directory.Packages.props)
- Testdateien
Führe Slopwatch aus, um zu überprüfen, ob die Änderungen keinen "Slop" enthalten.
Was ist Slop?
"Slop" bezeichnet Abkürzungen, die KI-Modelle nehmen, um Tests bestehen oder Builds erfolgreich abzuschließen, ohne das eigentliche Problem zu lösen. Dabei handelt es sich um Belohnungshacking-Verhalten – das KI-Modell optimiert auf scheinbaren Erfolg, statt auf echte Korrekturen.
Häufige Slop-Muster
| Muster | Beispiel | Warum es schlecht ist |
|---|---|---|
| Deaktivierte Tests | [Fact(Skip="flaky")] | Versteckt Fehler, statt sie zu beheben |
| Warnungsunterdrückung | #pragma warning disable CS8618 | Schaltet den Compiler stumm, ohne das Problem zu beheben |
| Leere Catch-Blöcke | catch (Exception) { } | Verschlingt Fehler, versteckt Bugs |
| Willkürliche Verzögerungen | await Task.Delay(1000); | Kaschiert Race Conditions, macht Tests langsam |
| Projektweite Unterdrückung | <NoWarn>CS1591</NoWarn> | Deaktiviert Warnungen projektweit |
| CPM-Umgehung | Version="1.0.0" inline | Untergräbt zentrales Paketmanagement |
Akzeptiere diese Muster niemals. Wenn ein KI-Modell Slop einführt, lehne die Änderung ab und fordere eine korrekte Lösung.
Installation
Als lokales Tool (empfohlen)
Füge zu .config/dotnet-tools.json hinzu:
{
"version": 1,
"isRoot": true,
"tools": {
"slopwatch.cmd": {
"version": "0.2.0",
"commands": ["slopwatch"],
"rollForward": false
}
}
}
Dann wiederherstellen:
dotnet tool restore
Als globales Tool
dotnet tool install --global Slopwatch.Cmd
Ersteinrichtung: Baseline erstellen
Bevor du Slopwatch auf einem bestehenden Projekt verwendest, erstelle eine Baseline der aktuellen Probleme:
# Baseline aus vorhandenem Code initialisieren
slopwatch init
# Erstellt .slopwatch/baseline.json
git add .slopwatch/baseline.json
git commit -m "Slopwatch-Baseline hinzugefügt"
Warum eine Baseline? Legacy-Code kann bereits bestehende Probleme enthalten. Die Baseline stellt sicher, dass Slopwatch nur neu eingeführten Slop erfasst, nicht bestehende technische Schulden.
Verwendung während KI-Sitzungen
Nach jeder Codeänderung
Führe Slopwatch nach jeder durch ein KI-Modell generierten Codeänderung aus:
# Analysiere auf neue Probleme (nutzt Baseline)
slopwatch analyze
# Verwende strikten Modus – scheitere auch bei Warnungen
slopwatch analyze --fail-on warning
Wenn Slopwatch ein Problem meldet
Ignoriere es nicht. Stattdessen:
- Verstehe, warum das KI-Modell die Abkürzung genommen hat
- Fordere eine korrekte Lösung – sei spezifisch, was falsch ist
- Überprüfe die Korrektur darauf, dass sie keinen anderen Slop einführt
# Beispiel: KI-Modell hat einen Test deaktiviert
❌ SW001 [Fehler]: Deaktivierter Test erkannt
Datei: tests/MyApp.Tests/OrderTests.cs:45
Muster: [Fact(Skip="Test is flaky")]
# Korrekte Antwort: Fordere echte Korrektur
"Dieser Test wurde deaktiviert statt behoben. Bitte untersuche,
warum er flaky ist, und behebe das zugrunde liegende
Timing-/Race-Condition-Problem."
Baseline aktualisieren (selten)
Aktualisiere die Baseline nur, wenn Slop wirklich gerechtfertigt und dokumentiert ist:
# Füge aktuelle Erkennungen zur Baseline hinzu (sparsam verwenden!)
slopwatch analyze --update-baseline
Beispiele für Rechtfertigungen:
- Eine Drittanbieter-Bibliothek erzwingt ein Muster (z. B. bestimmte Warnung muss unterdrückt werden)
- Absichtliche Verzögerung für Ratenbegrenzung (nicht Test-Flakiness)
- Generierter Code, der nicht geändert werden kann
Dokumentiere den Grund in einem Codekommentar, wenn du die Baseline aktualisierst.
Claude Code Hook-Integration
Füge Slopwatch als Hook hinzu, um jede Bearbeitung automatisch zu validieren. Erstelle oder aktualisiere .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "slopwatch analyze -d . --hook",
"timeout": 60000
}
]
}
]
}
}
Der --hook-Flag:
- Analysiert nur Git-Dirty-Dateien (schnell, auch bei großen Repos)
- Gibt Fehler im lesbaren Format nach stderr aus
- Blockiert die Bearbeitung bei Warnungen/Fehlern (Exit-Code 2)
- Claude sieht den Fehler und kann ihn sofort beheben
CI/CD-Integration
Füge Slopwatch als Qualitätstor in deine CI-Pipeline ein:
GitHub Actions
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: Slopwatch installieren
run: dotnet tool install --global Slopwatch.Cmd
- name: Slopwatch ausführen
run: slopwatch analyze -d . --fail-on warning
Azure Pipelines
- task: DotNetCoreCLI@2
displayName: 'Slopwatch installieren'
inputs:
command: 'custom'
custom: 'tool'
arguments: 'install --global Slopwatch.Cmd'
- script: slopwatch analyze -d . --fail-on warning
displayName: 'Slopwatch-Analyse'
Erkennungsregeln
| Regel | Schweregrad | Was wird erkannt |
|---|---|---|
| SW001 | Fehler | Deaktivierte Tests (Skip=, Ignore, #if false) |
| SW002 | Warnung | Warnungsunterdrückung (#pragma warning disable, SuppressMessage) |
| SW003 | Fehler | Leere Catch-Blöcke, die Ausnahmen verschlucken |
| SW004 | Warnung | Willkürliche Verzögerungen in Tests (Task.Delay, Thread.Sleep) |
| SW005 | Warnung | Projektdatei-Slop (NoWarn, TreatWarningsAsErrors=false) |
| SW006 | Warnung | CPM-Umgehung (VersionOverride, inline Version-Attribute) |
Konfiguration
Erstelle .slopwatch/slopwatch.json zur Anpassung:
{
"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/**"
]
}
Strenger Modus (empfohlen für KI-Sitzungen)
Für maximalen Schutz während KI-Codiersitzungen stufe alle Regeln auf Fehler hoch:
{
"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" }
}
}
Die Philosophie: Null Toleranz für neuen Slop
- Baseline erfasst Altes – Bestehende Probleme werden anerkannt, aber isoliert
- Neuer Slop wird blockiert – Jede neue Abkürzung lässt den Build/Edit fehlschlagen
- Ausnahmen erfordern Begründung – Wenn du die Baseline aktualisieren musst, dokumentiere warum
- KI-Modelle sind nicht besonders – Dieselben Regeln gelten für menschlichen und KI-generierten Code
Ziel ist es, die allmähliche Anhäufung technischer Schulden zu verhindern, die entsteht, wenn KI-Modelle für "den Test bestehen lassen" optimieren, statt für "das eigentliche Problem lösen".
Kurzreferenz
# Ersteinrichtung
slopwatch init
git add .slopwatch/baseline.json
# Nach jeder KI-Codeänderung
slopwatch analyze
# Strenger Modus (empfohlen)
slopwatch analyze --fail-on warning
# Mit Statistiken (Performance-Debugging)
slopwatch analyze --stats
# Baseline aktualisieren (selten, Grund dokumentieren)
slopwatch analyze --update-baseline
# JSON-Ausgabe für Tooling
slopwatch analyze --output json
Wann überschreiben (fast nie)
Die einzigen gültigen Gründe, die Baseline zu aktualisieren oder eine Regel zu deaktivieren:
| Szenario | Aktion | Erforderlich |
|---|---|---|
| Drittanbieter erzwingt Muster | Baseline aktualisieren | Codekommentar mit Erklärung |
| Generierter Code (nicht bearbeitbar) | Zu Ausschlussliste hinzufügen | In Konfiguration dokumentieren |
| Absichtliche Ratenbegrenzungsverzögerung | Baseline aktualisieren | Codekommentar, nicht im Test |
| Bereinigung von Legacy-Code | Einmalige Baseline-Aktualisierung | PR-Beschreibung |
Ungültige Gründe:
- "Der Test ist flaky" → Behebe die Flakiness
- "Die Warnung ist nervig" → Behebe den Code
- "Auf meinem Rechner funktioniert es" → Behebe die Race Condition
- "Wir reparieren es später" → Repariere es jetzt