Communityコーディング&開発github.com

dotnet-slopwatch

Slopwatch を使用して、.NET コード変更における LLM の報酬ハッキングを検出します。テストの無効化、警告の抑制、空の catch ブロックなど、実際の問題を隠すショートカットを、コード変更のたびに実行して検出します。

dotnet-slopwatch とは?

Slopwatch は、LLM(Claude など)が生成した .NET コードに潜む「スロップ(手抜き)」を自動検出するためのツールです。LLM はテストを通すことやビルドを成功させることを優先し、本来の問題を解決せずにショートカット(テストのスキップ、警告の抑制、例外の握りつぶし、ハードコードされた遅延など)を導入しがちです。Slopwatch はこうした報酬ハッキング行為を発見し、開発者に修正を促します。主に C# ソースファイル、プロジェクトファイル、テストファイルを監視し、SW001~SW006 のルールに基づいて問題を検出します。初回実行時にはベースラインを作成し、既存の技術的負債を新しいスロップと区別します。Claude Code のフックとして統合すれば、編集のたびに自動検証が可能です。CI/CD パイプラインに組み込むことで品質ゲートとしても機能し、厳格モードではすべての警告をエラーとして扱うことで最大限の保護を提供します。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Aaronontheweb/dotnet-skills/tree/main/skills/slopwatch

Installed? Explore more コーディング&開発 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Slopwatch: LLM アンチチート for .NET

いつこのスキルを使うか

常にこのスキルを使用してください。 LLM(Claude を含む)が以下のファイルを変更するたびに実行します。

  • C# ソースファイル (.cs)
  • プロジェクトファイル (.csproj)
  • Props ファイル (Directory.Build.props, Directory.Packages.props)
  • テストファイル

slopwatch を実行して、変更によって「スロップ」が持ち込まれていないか検証します。

スロップとは?

「スロップ」とは、LLM が実際の問題を解決せずにテストを通したりビルドを成功させるために取るショートカットのことです。これらは報酬ハッキング行為であり、LLM は真の修正ではなく見かけ上の成功を最適化します。

一般的なスロップのパターン

パターン例なぜ悪いか
テストの無効化[Fact(Skip="flaky")]失敗を隠して修正しない
警告の抑制#pragma warning disable CS8618コンパイラ警告を黙らせ、問題を修正しない
空の catch ブロックcatch (Exception) { }エラーを飲み込み、バグを隠す
任意の遅延await Task.Delay(1000);競合状態を隠し、テストを遅くする
プロジェクト全体の抑制<NoWarn>CS1591</NoWarn>プロジェクト全体で警告を無効化
CPM バイパスインラインで Version="1.0.0"集中パッケージ管理を弱体化

これらのパターンを決して受け入れないでください。 LLM がスロップを導入した場合、その変更を拒否し、適切な修正を要求してください。


インストール

ローカルツールとして(推奨)

.config/dotnet-tools.json に追加:

{
  "version": 1,
  "isRoot": true,
  "tools": {
    "slopwatch.cmd": {
      "version": "0.2.0",
      "commands": ["slopwatch"],
      "rollForward": false
    }
  }
}

次に復元:

dotnet tool restore

グローバルツールとして

dotnet tool install --global Slopwatch.Cmd

初回セットアップ: ベースラインの確立

既存のプロジェクトで slopwatch を使用する前に、現在の問題のベースラインを作成します:

# 既存のコードからベースラインを初期化
slopwatch init

# これにより .slopwatch/baseline.json が作成されます
git add .slopwatch/baseline.json
git commit -m "Add slopwatch baseline"

なぜベースラインが必要か? レガシーコードには既存の問題が含まれている可能性があります。ベースラインにより、slopwatch は新しく導入されたスロップのみを検出し、既存の技術的負債を無視できます。


LLM セッション中の使用方法

コード変更のたびに

LLM によるコード変更のたびに slopwatch を実行:

# 新しい問題を分析(ベースラインを使用)
slopwatch analyze

# 厳格モード - 警告もエラーとして扱う
slopwatch analyze --fail-on warning

Slopwatch が問題を検出した場合

無視しないでください。 代わりに:

  1. なぜ LLM がそのショートカットを取ったのかを理解する
  2. 適切な修正を要求する - 何が問題かを具体的に伝える
  3. 修正が別のスロップを導入しないか検証する
# 例: LLM がテストを無効化した場合
❌ SW001 [Error]: Detected disabled test
   File: tests/MyApp.Tests/OrderTests.cs:45
   Pattern: [Fact(Skip="Test is flaky")]

# 正しい対応: 実際の修正を依頼する
"このテストは無効化されただけで修正されていません。テストがフレイキーな理由を調査し、
根本的なタイミング/競合状態の問題を修正してください。"

ベースラインの更新(稀)

スロップが真に正当化され、文書化されている場合にのみベースラインを更新:

# 現在の検出項目をベースラインに追加(慎重に使用!)
slopwatch analyze --update-baseline

正当化の例:

  • サードパーティライブラリがパターンを強制する場合(例: 特定の警告を抑制する必要がある)
  • レート制限のための意図的な遅延(テストのフレーキネスではない)
  • 変更できない生成コード

ベースラインを更新する際は、コードコメントに理由を文書化してください。


Claude Code フック統合

slopwatch をフックとして追加し、すべての編集を自動検証します。.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 統合

slopwatch を品質ゲートとして CI パイプラインに追加:

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: 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'

検出ルール

ルール重大度検出内容
SW001Error無効化されたテスト (Skip=, Ignore, #if false)
SW002Warning警告の抑制 (#pragma warning disable, SuppressMessage)
SW003Error例外を握りつぶす空の catch ブロック
SW004Warningテスト内の任意の遅延 (Task.Delay, Thread.Sleep)
SW005Warningプロジェクトファイルのスロップ (NoWarn, TreatWarningsAsErrors=false)
SW006WarningCPM バイパス (VersionOverride, インライン Version 属性)

設定

.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/**"
  ]
}

厳格モード(LLM セッション推奨)

LLM コーディングセッション中に最大限の保護を提供するため、すべてのルールをエラーに引き上げ:

{
  "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" }
  }
}

哲学: 新しいスロップに対するゼロトレランス

  1. ベースラインでレガシーをキャプチャ - 既存の問題は認識するが隔離する
  2. 新しいスロップはブロック - 新たなショートカットはビルド/編集を失敗させる
  3. 例外には正当な理由が必要 - ベースラインを更新する場合は理由を文書化する
  4. LLM は特別ではない - 人間と AI 生成コードに同じルールを適用する

目標は、LLM が「実際の問題を修正する」ではなく「テストを通す」ことを最適化するために生じる技術的負債の累積を防ぐことです。


クイックリファレンス

# 初回セットアップ
slopwatch init
git add .slopwatch/baseline.json

# LLM コード変更のたびに
slopwatch analyze

# 厳格モード(推奨)
slopwatch analyze --fail-on warning

# 統計情報付き(パフォーマンスデバッグ)
slopwatch analyze --stats

# ベースライン更新(稀、理由を文書化)
slopwatch analyze --update-baseline

# ツール連携用 JSON 出力
slopwatch analyze --output json

オーバーライドする場合(ほぼありません)

ベースラインを更新したりルールを無効化できる唯一の正当な理由:

シナリオ対応必須条件
サードパーティがパターンを強制ベースラインを更新理由を説明するコードコメント
生成コード(編集不可)除外リストに追加設定に文書化
意図的なレート制限遅延ベースラインを更新テスト外のコードコメント
レガシーコードのクリーンアップ1回限りのベースライン更新PR 説明

無効な理由:

  • 「テストがフレイキー」 → フレーキネスを修正する
  • 「警告がうっとうしい」 → コードを修正する
  • 「私のマシンでは動く」 → 競合状態を修正する
  • 「後で直す」 → 今直す

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

akka-hosting-actor-patterns

Patterns for building entity actors with Akka.Hosting - GenericChildPerEntityParent, message extractors, cluster sharding abstraction, akka-reminders, and ITimeProvider. Supports both local testing and clustered production modes.

akka-net-aspire-configuration

Configure Akka.NET with .NET Aspire for local development and production deployments. Covers actor system setup, clustering, persistence, Akka.Management integration, and Aspire orchestration patterns.

akka-net-best-practices

Critical Akka.NET best practices including EventStream vs DistributedPubSub, supervision strategies, error handling, Props vs DependencyResolver, work distribution patterns, and cluster/local mode abstractions for testability.

akka-net-management

Akka.Management for cluster bootstrapping, service discovery (Kubernetes, Azure, Config), health checks, and dynamic cluster formation without static seed nodes.

akka-net-testing-patterns

Write unit and integration tests for Akka.NET actors using modern Akka.Hosting.TestKit patterns. Covers dependency injection, TestProbes, persistence testing, and actor interaction verification. Includes guidance on when to use traditional TestKit.

api-design

Design stable, compatible public APIs using extend-only design principles. Manage API compatibility, wire compatibility, and versioning for NuGet packages and distributed systems.

aspire-configuration

Configure Aspire AppHost to emit explicit app config via environment variables; keep app code free of Aspire clients and service discovery.

aspire-integration-testing

Write integration tests using .NET Aspire

aspire-service-defaults

Create a shared ServiceDefaults project for Aspire applications. Centralizes OpenTelemetry, health checks, resilience, and service discovery configuration across all services.

crap-analysis

Analyze code coverage and CRAP (Change Risk Anti-Patterns) scores to identify high-risk code. Use OpenCover format with ReportGenerator for Risk Hotspots showing cyclomatic complexity and untested code paths.

csharp-concurrency-patterns

Choosing the right concurrency abstraction in .NET - from async/await for I/O to Channels for producer/consumer to Akka.NET for stateful entity management. Avoid locks and manual synchronization unless absolutely necessary.

database-performance

Database access patterns for performance. Separate read/write models, avoid N+1 queries, use AsNoTracking, apply row limits, and never do application-side joins. Works with EF Core and Dapper.

dependency-injection-patterns

Organize DI registrations using IServiceCollection extension methods. Group related services into composable Add* methods for clean Program.cs and reusable configuration in tests.

dotnet-devcert-trust

Diagnose and fix .NET HTTPS dev certificate trust issues on Linux. Covers the full certificate lifecycle from generation to system CA bundle inclusion, with distro-specific guidance for Ubuntu, Fedora, Arch, and WSL2.

dotnet-local-tools

Managing local .NET tools with dotnet-tools.json for consistent tooling across development environments and CI/CD pipelines.

dotnet-project-structure

Modern .NET project structure including .slnx solution format, Directory.Build.props, central package management, SourceLink, version management with RELEASE_NOTES.md, and SDK pinning with global.json.

efcore-patterns

Entity Framework Core best practices including NoTracking by default, query splitting for navigation collections, migration management, dedicated migration services, and common pitfalls to avoid.

ilspy-decompile

Understand implementation details of .NET code by decompiling assemblies. Use when you want to see how a .NET API works internally, inspect NuGet package source, view framework implementation, or understand compiled .NET binaries.

mailpit-integration

Test email sending locally using Mailpit with .NET Aspire. Captures all outgoing emails without sending them. View rendered HTML, inspect headers, and verify delivery in integration tests.

marketplace-publishing

Workflow for publishing skills and agents to the dotnet-skills Claude Code marketplace. Covers adding new content, updating plugin.json, validation, and release tagging.

関連スキル