Slopwatch: Anti-Trapaça para LLM no .NET
Quando Usar Esta Habilidade
Use esta habilidade constantemente. Sempre que um LLM (incluindo Claude) fizer alterações em:
- Arquivos de código C# (.cs)
- Arquivos de projeto (.csproj)
- Arquivos de propriedades (Directory.Build.props, Directory.Packages.props)
- Arquivos de teste
Execute o slopwatch para validar que as alterações não introduziram "slop".
O que é Slop?
"Slop" se refere a atalhos que LLMs tomam para fazer testes passarem ou builds serem bem-sucedidos sem realmente resolver o problema subjacente. São comportamentos de trapaça de recompensa — o LLM otimiza para sucesso aparente em vez de correções reais.
Padrões Comuns de Slop
| Padrão | Exemplo | Por que é Ruim |
|---|---|---|
| Testes desabilitados | [Fact(Skip="instável")] | Esconde falhas em vez de corrigi-las |
| Supressão de avisos | #pragma warning disable CS8618 | Silencia o compilador sem corrigir o problema |
| Blocos catch vazios | catch (Exception) { } | Engole erros, esconde bugs |
| Atrasos arbitrários | await Task.Delay(1000); | Mascara condições de corrida, torna testes lentos |
| Supressão em nível de projeto | <NoWarn>CS1591</NoWarn> | Desabilita avisos para todo o projeto |
| Bypass de CPM | Version="1.0.0" inline | Enfraquece o gerenciamento central de pacotes |
Nunca aceite esses padrões. Se um LLM introduzir slop, rejeite a alteração e exija uma correção adequada.
Instalação
Como Ferramenta Local (Recomendado)
Adicione em .config/dotnet-tools.json:
{
"version": 1,
"isRoot": true,
"tools": {
"slopwatch.cmd": {
"version": "0.2.0",
"commands": ["slopwatch"],
"rollForward": false
}
}
}
Depois restaure:
dotnet tool restore
Como Ferramenta Global
dotnet tool install --global Slopwatch.Cmd
Configuração Inicial: Estabelecer uma Linha de Base
Antes de usar o slopwatch em um projeto existente, crie uma linha de base dos problemas atuais:
# Inicializar linha de base a partir do código existente
slopwatch init
# Isso cria .slopwatch/baseline.json
git add .slopwatch/baseline.json
git commit -m "Adicionar linha de base do slopwatch"
Por que linha de base? Código legado pode ter problemas existentes. A linha de base garante que o slopwatch capture apenas novo slop sendo introduzido, não dívida técnica pré-existente.
Uso Durante Sessões com LLM
Após Cada Alteração de Código
Execute slopwatch após qualquer modificação de código gerada por LLM:
# Analisar novos problemas (usa linha de base)
slopwatch analyze
# Usar modo estrito - falhar também em avisos
slopwatch analyze --fail-on warning
Quando o Slopwatch Sinalizar um Problema
Não o ignore. Em vez disso:
- Entenda por que o LLM tomou o atalho
- Solicite uma correção adequada - seja específico sobre o que está errado
- Verifique se a correção não introduz outro slop
# Exemplo: LLM desabilitou um teste
❌ SW001 [Erro]: Teste desabilitado detectado
Arquivo: tests/MyApp.Tests/OrderTests.cs:45
Padrão: [Fact(Skip="Teste está instável")]
# Resposta correta: Peça a correção real
"Este teste foi desabilitado em vez de corrigido. Por favor,
investigue por que ele está instável e corrija o problema
subjacente de temporização/condição de corrida."
Atualizando a Linha de Base (Raramente)
Atualize a linha de base apenas quando o slop for verdadeiramente justificado e documentado:
# Adicionar detecções atuais à linha de base (usar com moderação!)
slopwatch analyze --update-baseline
Exemplos de justificativa:
- Biblioteca de terceiros força um padrão (ex.: deve suprimir aviso específico)
- Atraso intencional para limitação de taxa (não instabilidade de teste)
- Código gerado que não pode ser modificado
Documente o motivo em um comentário de código ao atualizar a linha de base.
Integração com Gancho do Claude Code
Adicione o slopwatch como um gancho para validar automaticamente cada edição. Crie ou atualize .claude/settings.json:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Write|Edit|MultiEdit",
"hooks": [
{
"type": "command",
"command": "slopwatch analyze -d . --hook",
"timeout": 60000
}
]
}
]
}
}
A flag --hook:
- Analisa apenas arquivos sujos do git (rápido, mesmo em repositórios grandes)
- Saída de erros no stderr em formato legível
- Bloqueia a edição em avisos/erros (código de saída 2)
- Claude vê o erro e pode corrigi-lo imediatamente
Integração com CI/CD
Adicione o slopwatch ao seu pipeline de CI como um portão de qualidade:
GitHub Actions
jobs:
slopwatch:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configurar .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: '9.0.x'
- name: Instalar Slopwatch
run: dotnet tool install --global Slopwatch.Cmd
- name: Executar Slopwatch
run: slopwatch analyze -d . --fail-on warning
Azure Pipelines
- task: DotNetCoreCLI@2
displayName: 'Instalar Slopwatch'
inputs:
command: 'custom'
custom: 'tool'
arguments: 'install --global Slopwatch.Cmd'
- script: slopwatch analyze -d . --fail-on warning
displayName: 'Análise Slopwatch'
Regras de Detecção
| Regra | Gravidade | O que Captura |
|---|---|---|
| SW001 | Erro | Testes desabilitados (Skip=, Ignore, #if false) |
| SW002 | Aviso | Supressão de avisos (#pragma warning disable, SuppressMessage) |
| SW003 | Erro | Blocos catch vazios que engolem exceções |
| SW004 | Aviso | Atrasos arbitrários em testes (Task.Delay, Thread.Sleep) |
| SW005 | Aviso | Slop em arquivos de projeto (NoWarn, TreatWarningsAsErrors=false) |
| SW006 | Aviso | Bypass de CPM (VersionOverride, atributos Version inline) |
Configuração
Crie .slopwatch/slopwatch.json para personalizar:
{
"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/**"
]
}
Modo Estrito (Recomendado para Sessões com LLM)
Para proteção máxima durante sessões de codificação com LLM, eleve todas as regras para erros:
{
"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" }
}
}
A Filosofia: Tolerância Zero para Novo Slop
- Linha de base captura legado - Problemas existentes são reconhecidos, mas isolados
- Novo slop é bloqueado - Qualquer novo atalho falha o build/edição
- Exceções exigem justificativa - Se precisar atualizar a linha de base, documente por quê
- LLMs não são especiais - As mesmas regras se aplicam a código humano e gerado por IA
O objetivo é evitar o acúmulo gradual de dívida técnica que ocorre quando LLMs otimizam para "fazer o teste passar" em vez de "corrigir o problema real".
Referência Rápida
# Configuração inicial
slopwatch init
git add .slopwatch/baseline.json
# Após cada alteração de código do LLM
slopwatch analyze
# Modo estrito (recomendado)
slopwatch analyze --fail-on warning
# Com estatísticas (depuração de desempenho)
slopwatch analyze --stats
# Atualizar linha de base (raro, documente por quê)
slopwatch analyze --update-baseline
# Saída JSON para ferramentas
slopwatch analyze --output json
Quando Substituir (Quase Nunca)
As únicas razões válidas para atualizar a linha de base ou desabilitar uma regra:
| Cenário | Ação | Obrigatório |
|---|---|---|
| Biblioteca de terceiros força padrão | Atualizar linha de base | Comentário no código explicando por quê |
| Código gerado (não editável) | Adicionar à lista de exclusão | Documentar na configuração |
| Atraso intencional para limitação de taxa | Atualizar linha de base | Comentário no código, não em teste |
| Limpeza de código legado | Atualização única da linha de base | Descrição no PR |
Motivos inválidos:
- "O teste está instável" → Corrija a instabilidade
- "O aviso é irritante" → Corrija o código
- "Funciona na minha máquina" → Corrija a condição de corrida
- "Vamos corrigir depois" → Corrija agora