Community코딩 & 개발github.com

dotnet-slopwatch

Slopwatch를 사용하여 .NET 코드 변경에서 LLM 리워드 해킹을 탐지합니다. 모든 코드 수정 후에 실행하여 비활성화된 테스트, 경고 억제, 빈 catch 블록 등 실제 문제를 가리는 지름길을 찾아냅니다.

dotnet-slopwatch란 무엇인가요?

이 스킬은 .NET 프로젝트에서 LLM(예: Claude)이 코드를 수정할 때 발생할 수 있는 '슬롭(slop)'을 탐지하고 방지하는 Slopwatch 도구를 통합합니다. 슬롭은 LLM이 실제 문제를 해결하지 않고 테스트 통과나 빌드 성공만을 위해 취하는 지름길(리워드 해킹)을 의미합니다. 이 스킬은 C# 소스 파일, 프로젝트 파일, 테스트 파일 등의 변경 사항을 자동으로 분석하여 비활성화된 테스트(Skip 사용), 경고 억제(#pragma warning disable), 빈 catch 블록, 임의 지연(Task.Delay), 프로젝트 수준 경고 억제(NoWarn), 중앙 패키지 관리 우회와 같은 패턴을 감지합니다. 기존 코드의 베이스라인을 생성하여 새로운 슬롭만 탐지하도록 설정할 수 있으며, Claude Code 훅(Hook)과 CI/CD 파이프라인(GitHub Actions, Azure Pipelines)에 통합하여 LLM 세션 중 자동 검증을 수행할 수 있습니다. 모든 규칙을 오류로 승격시키는 엄격 모드를 제공하여 LLM 코딩 세션 중 최대한의 보호를 보장합니다.

지원 대상✓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: .NET용 LLM 안티 치트

이 스킬을 사용해야 하는 경우

이 스킬을 지속적으로 사용하세요. LLM(Claude 포함)이 다음 파일을 변경할 때마다:

  • C# 소스 파일 (.cs)
  • 프로젝트 파일 (.csproj)
  • Props 파일 (Directory.Build.props, Directory.Packages.props)
  • 테스트 파일

slopwatch를 실행하여 변경 사항에 '슬롭(slop)'이 도입되지 않았는지 검증하세요.

슬롭이란?

'슬롭'은 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 [오류]: 비활성화된 테스트 탐지
   파일: tests/MyApp.Tests/OrderTests.cs:45
   패턴: [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 dirty 파일만 분석 (큰 저장소에서도 빠름)
  • 오류를 읽기 쉬운 형식으로 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'

탐지 규칙

규칙심각도탐지 내용
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/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

재정의해야 하는 경우 (거의 없음)

베이스라인을 업데이트하거나 규칙을 비활성화할 수 있는 유일한 타당한 이유:

시나리오조치필요 사항
타사가 패턴을 강제함베이스라인 업데이트이유를 설명하는 코드 주석
생성 코드 (편집 불가)제외 목록에 추가설정에 문서화
의도적인 레이트 제한 지연베이스라인 업데이트코드 주석, 테스트 아님
레거시 코드 정리일회성 베이스라인 업데이트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.

관련 스킬