{"slug": "dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating", "title": "Dotnet-slopwatch – detect when AI coding agents \"fix\" problems by cheating", "summary": "A new .NET tool called Slopwatch detects when AI coding assistants cheat by disabling tests, suppressing warnings, or swallowing exceptions instead of properly fixing code issues. The tool runs as a Claude Code hook or in CI/CD pipelines, using a baseline approach to catch only newly introduced \"slop\" patterns without flagging legacy code. Slopwatch aims to prevent AI agents from taking shortcuts that make tests pass without solving the underlying problem.", "body_md": "**// LLM anti-cheat**\n\nA .NET tool that detects LLM \"reward hacking\" behaviors in code changes.\n\nRuns as a Claude Code hook or in CI/CD pipelines to catch when AI coding assistants take shortcuts instead of properly fixing issues.\n\nWhen LLMs generate code, they sometimes take shortcuts that make tests pass or builds succeed without actually solving the underlying problem. These patterns include:\n\n**Disabling tests** instead of fixing them (`[Fact(Skip=\"flaky\")]`\n\n)**Suppressing warnings** instead of addressing them (`#pragma warning disable`\n\n)**Swallowing exceptions** with empty catch blocks**Adding arbitrary delays** to mask timing issues (`Task.Delay(1000)`\n\n)**Project-level warning suppression**(`<NoWarn>`\n\n,`<TreatWarningsAsErrors>false</TreatWarningsAsErrors>`\n\n)**Bypassing Central Package Management** with`VersionOverride`\n\nor inline`Version`\n\nattributes- And more...\n\nSlopwatch catches these patterns before they make it into your codebase.\n\n```\n# Install as a global tool\ndotnet tool install --global Slopwatch.Cmd\n\n# Or install locally\ndotnet new tool-manifest\ndotnet tool install --local Slopwatch.Cmd\n# 1. Install slopwatch\ndotnet tool install --global Slopwatch.Cmd\n\n# 2. Initialize in your project (creates baseline from existing code)\ncd your-project\nslopwatch init\n\n# 3. Commit the baseline to your repository\ngit add .slopwatch/baseline.json\ngit commit -m \"Add slopwatch baseline\"\n\n# 4. From now on, only NEW slop is detected\nslopwatch analyze\n```\n\nThe baseline approach ensures slopwatch catches **new** slop being introduced without flagging legacy code. Your CI/CD pipeline will fail if someone introduces new slop patterns.\n\n```\n# Create baseline from existing code\nslopwatch init\n\n# Force overwrite existing baseline\nslopwatch init --force\n```\n\nThis creates `.slopwatch/baseline.json`\n\ncontaining all existing detections. Commit this file to your repository.\n\n```\n# Analyze current directory (requires baseline by default)\nslopwatch analyze\n\n# Analyze specific directory\nslopwatch analyze -d src/\n\n# Skip baseline and report ALL issues (not recommended for CI)\nslopwatch analyze --no-baseline\n```\n\nWhen you intentionally add code that triggers slopwatch (with proper justification):\n\n```\n# Add new detections to existing baseline\nslopwatch analyze --update-baseline\n# Human-readable console output (default)\nslopwatch analyze\n\n# JSON for programmatic use\nslopwatch analyze --output json\n# Fail if errors found (default)\nslopwatch analyze --fail-on error\n\n# Fail on warnings too\nslopwatch analyze --fail-on warning\n```\n\nIf you're concerned about performance on large projects, use `--stats`\n\nto see how many files are being analyzed and how long it takes:\n\n```\nslopwatch analyze --stats\n# Output: Stats: 44 files analyzed in 1.64s\n```\n\n| Rule | Severity | Description |\n|---|---|---|\n| SW001 | Error | Disabled tests via Skip, Ignore, or #if false |\n| SW002 | Warning | Warning suppression via pragma or SuppressMessage |\n| SW003 | Error | Empty catch blocks that swallow exceptions |\n| SW004 | Warning | Arbitrary delays in test code (Task.Delay, Thread.Sleep) |\n| SW005 | Warning | Project file slop (NoWarn, TreatWarningsAsErrors=false) |\n| SW006 | Error | CPM bypass via VersionOverride or inline Version attributes |\n\nAdd slopwatch as a hook to catch slop patterns during AI-assisted coding. Add the following to your project's `.claude/settings.json`\n\n:\n\n```\n{\n  \"hooks\": {\n    \"PostToolUse\": [\n      {\n        \"matcher\": \"Write|Edit|MultiEdit\",\n        \"hooks\": [\n          {\n            \"type\": \"command\",\n            \"command\": \"slopwatch analyze -d . --hook\",\n            \"timeout\": 60000\n          }\n        ]\n      }\n    ]\n  }\n}\n```\n\nThe `--hook`\n\nflag enables Claude Code integration mode which:\n\n**Uses**- makes hooks near-instant even on large repos`git status`\n\nto only analyze dirty files- Outputs errors to stderr in a readable format\n- Suppresses all other output\n- Blocks on warnings and errors\n- Exits with code 2 on failure (blocking the edit)\n\nClaude will see the formatted error message and can then fix the issue properly.\n\nNote:Hook mode requires git. If git is unavailable, it falls back to full analysis.\n\n```\n- name: Install Slopwatch\n  run: dotnet tool install --global Slopwatch.Cmd\n\n- name: Run Slopwatch\n  run: slopwatch analyze -d . --output json --fail-on error\n```\n\n**Note:** The baseline file (`.slopwatch/baseline.json`\n\n) should be committed to your repository. Run `slopwatch init`\n\nlocally first.\n\n```\n- task: DotNetCoreCLI@2\n  displayName: 'Install Slopwatch'\n  inputs:\n    command: 'custom'\n    custom: 'tool'\n    arguments: 'install --global Slopwatch.Cmd'\n\n- script: slopwatch analyze -d . --fail-on error\n  displayName: 'Run Slopwatch'\n```\n\nCreate a `.slopwatch/config.json`\n\nfile to define suppressions:\n\n```\n{\n  \"suppressions\": [\n    {\n      \"ruleId\": \"SW002\",\n      \"pattern\": \"**/Generated/**\",\n      \"justification\": \"Generated code from tooling cannot be manually changed\"\n    },\n    {\n      \"ruleId\": \"SW006\",\n      \"pattern\": \"src/Legacy/**\",\n      \"justification\": \"Legacy CPM migration in progress; tracked in issue #123\"\n    }\n  ],\n  \"globalSuppressions\": []\n}\n```\n\nUse the `-c`\n\nor `--config`\n\noption to specify a custom suppression config file location:\n\n```\nslopwatch analyze -d . --config path/to/config.json\n```\n\nTo exclude files or directories from analysis entirely, use `--exclude`\n\n:\n\n```\nslopwatch analyze -d . --exclude \"**/Generated/**,**/obj/**,**/bin/**\"\ndotnet build\ndotnet test\ndotnet pack\n```\n\n- Fork and create a feature branch\n- Make changes and add tests\n- Submit a pull request\n\nNote: This project uses slopwatch on itself - your PR will be analyzed for slop patterns!\n\nApache 2.0 - see [LICENSE](/Aaronontheweb/dotnet-slopwatch/blob/dev/LICENSE) for details.\n\n[Slopometry](https://github.com/TensorTemplar/slopometry)- Python equivalent for Claude Code[Incrementalist](https://github.com/petabridge/Incrementalist)- Git diff analysis patterns", "url": "https://wpnews.pro/news/dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating", "canonical_source": "https://github.com/Aaronontheweb/dotnet-slopwatch", "published_at": "2026-06-03 14:35:37+00:00", "updated_at": "2026-06-03 14:49:39.355718+00:00", "lang": "en", "topics": ["ai-tools", "ai-agents", "ai-safety", "large-language-models", "ai-ethics"], "entities": ["Slopwatch", "Claude Code", "LLM", "AI coding agents"], "alternates": {"html": "https://wpnews.pro/news/dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating", "markdown": "https://wpnews.pro/news/dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating.md", "text": "https://wpnews.pro/news/dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating.txt", "jsonld": "https://wpnews.pro/news/dotnet-slopwatch-detect-when-ai-coding-agents-fix-problems-by-cheating.jsonld"}}