O que Desenvolvimento Orientado por Restrições faz?
Visão Geral
Outros skills neste pacote descrevem como é o bom. code-review-and-quality te dá cinco eixos. test-driven-development te dá um ciclo. security-and-hardening te dá uma lista de ameaças. Tudo isso vive em prosa que o agente lê e pode ou não seguir, e nada disso sobrevive ao fim da sessão.
Este skill produz algo diferente: um registro escrito da barra deste projeto, com números, que sobrevive à conversa e pode ser verificado mecanicamente.
O motivo importa. Quando você escrevia o código, lê-lo te dizia se era bom. Um agente escreve mais em uma tarde do que você lerá naquela semana, então o julgamento sai da sua cabeça e vai para verificações que rodam em loop. Essas verificações precisam existir, precisam de números que você realmente escolheu e precisam disparar perto o suficiente do trabalho para que o agente corrija sua própria saída.
O desenvolvimento orientado por especificações diz o que construir. O desenvolvimento orientado por testes prova que funciona. O desenvolvimento orientado por restrições define o que 'bom o suficiente para enviar' significa, antes que alguém discuta sobre isso em um pull request.
Quando Usar
Aplique este skill quando:
- Iniciando um projeto ou uma funcionalidade significativa e nenhuma barra de qualidade está escrita
- O usuário pedir para 'configurar restrições', 'adicionar portões de qualidade', 'definir nossos padrões' ou 'impedir o agente de enviar lixo'
- Um agente está produzindo volume que ninguém está lendo linha por linha
- O CI tem verificações, mas ninguém sabe quais bloqueiam um merge e quais são decoração
- Números de cobertura, desempenho ou acessibilidade são discutidos por PR em vez de decididos de uma vez
- Você está prestes a executar
/build autoou qualquer loop autônomo, e a única coisa entre ele e a main é um conjunto de testes que o agente também escreveu
Quando NÃO usar:
- O projeto já tem um
CONSTRAINTS.mde o usuário não o está alterando — leia-o e siga-o - Scripts descartáveis, spikes, protótipos temporários
- O usuário quer uma revisão de código agora (
code-review-and-quality) ou um pipeline de CI construído (ci-cd-and-automation) - Código pré-product-market-fit com expectativa de vida de duas semanas — o piso abaixo ainda vale a pena, o resto não
Carregando Restrições
A entrevista precisa de um usuário ativo. Não a execute em contextos não interativos (CI, /loop, execuções autônomas). Se as restrições estiverem faltando e você estiver em um desses, aplique o Piso abaixo, anote que o fez e sinalize o resto para um humano.
O Processo
Passo 1: Detecte antes de perguntar
Nunca pergunte o que você pode ler. Antes da primeira pergunta, colete:
| O quê | Onde procurar |
|---|---|
| Linguagem e stack | package.json, pyproject.toml, go.mod, Cargo.toml |
| Executor de testes | dependências de desenvolvimento, script test, arquivos de teste existentes |
| Linters existentes | eslint.config.*, biome.json, .ruff.toml |
| Cobertura atual | saída de coverage/, ou execute a suíte uma vez |
| CI | .github/workflows/, .gitlab-ci.yml |
| Infraestrutura do agente | .claude/, .codex/, AGENTS.md |
Relate o que encontrou em duas linhas, depois pergunte apenas o que sobrou.
Passo 2: Quatro perguntas, cada uma com um padrão
Siga a disciplina de uma pergunta por vez de interview-me, com uma mudança: cada pergunta aqui tem um padrão, então 'não sei' é uma resposta completa que ainda produz uma configuração funcional.
P1: Além do piso, quais destes você quer que sejam aplicados?
(a) Cobertura de testes no código novo
(b) Varredura de segurança
(c) Orçamentos de desempenho
(d) Acessibilidade
(e) Limites de arquitetura
PALPITE: (a) e (b) — você já tem um executor de testes e está lidando com entrada do usuário.
PADRÃO se não souber: (a) e (b).
Diga o que cada escolha custa: (c) e (d) precisam de uma URL em execução, (e) precisa de um arquivo de regras escrito.
P2: Quando uma verificação falha enquanto o agente está no meio de uma tarefa, ela deve bloquear ou avisar?
PALPITE: Bloquear. Você está executando agentes sem supervisão e um aviso que ninguém lê é um aviso.
PADRÃO se não souber: Bloquear no piso, avisar em todo o resto pelas primeiras duas semanas.
P3: Você tem números alvo em mente, ou devo medir onde você está hoje e manter essa linha?
PALPITE: Medir. A maioria das equipes não tem um número, e um inventado é ignorado.
PADRÃO se não souber: Medir e manter. Veja 'Catracas' abaixo.
P4: Qual é a verificação mais lenta que você tolerará antes do agente devolver o trabalho?
PALPITE: Cerca de 90 segundos. Mais que isso e você vai parar de executá-la.
PADRÃO se não souber: 90 segundos no final da tarefa, ilimitado no CI.
Pare em quatro. Uma coleta de doze perguntas produz uma configuração que ninguém entende e um usuário que se arrepende de ter começado.
Passo 3: Escreva CONSTRAINTS.md
Um arquivo na raiz do repositório. Qualquer agente em qualquer infraestrutura pode lê-lo, e uma alteração nele aparece na revisão onde pertence.
# Restrições
Última revisão: 2026-08-08 por @addy
## Piso (sempre aplicado, sem configuração necessária)
- Nenhum novo comentário de supressão: `@ts-ignore`, `eslint-disable`, `# noqa`, `# type: ignore`
- Nenhum stub não implementado: `throw new Error("Not implemented")`, `catch {}` vazio
- Nenhum teste ignorado ou excluído sem um motivo na mensagem de commit
- Nenhum segredo no código-fonte
- Este arquivo não deve ser enfraquecido para fazer uma alteração passar
## Aplicados com números
| Dimensão | Regra | Verificado por | Executa em |
|----------|-------|---------------|------------|
| Tipos | Zero erros de tipo | `tsc --noEmit` | a cada edição |
| Lint | Zero erros da nossa configuração | `biome check` | a cada edição |
| Segredos | Nenhum segredo no código-fonte | `gitleaks detect --redact` | a cada edição |
| Cobertura | Linhas alteradas ≥ 80% cobertas | `vitest run --coverage` + git diff | final da tarefa, CI |
| Segurança: código | Nenhum achado alto | `semgrep scan --config p/default` | CI |
| Segurança: dependências | Nada em alto ou acima | `osv-scanner scan source -r .` | CI |
| Acessibilidade | Zero crítico ou grave | `axe $PREVIEW_URL --tags wcag2a,wcag2aa,wcag21aa` | deploy de prévia |
| Desempenho | LCP ≤ 2500ms, CLS ≤ 0,1 | `lighthouse $PREVIEW_URL --output=json` | deploy de prévia |
Cada linha nomeia o comando que produz o veredito. Uma dimensão com um número e nenhum comando nesta coluna é uma aspiração, não uma restrição.
## Medidos, ainda não aplicados
| Métrica | Hoje | Direção |
|---------|------|---------|
| Cobertura do projeto | 62,4% | não deve cair |
| Tamanho do bundle (main) | 184 kB | não deve crescer |
## Exceções
| ID | Regra | Caminho | Motivo | Responsável | Expira em |
|----|-------|---------|--------|-------------|-----------|
| W1 | `no-explicit-any` | `src/legacy/**` | Reescrita rastreada em ENG-441 | @addy | 2026-11-01 |
Em seguida, adicione uma linha a AGENTS.md e CLAUDE.md: Leia CONSTRAINTS.md antes de escrever código. Não o enfraqueça para fazer uma alteração passar.
Passo 4: Instale o que cada dimensão precisa
Escolher uma dimensão significa instalar algo. Não deixe o usuário com um número e nenhum mecanismo, e não invente seu próprio verificador quando um de fato existe — essas ferramentas estão listadas porque seus formatos de regra e limites são o que todo o resto no ecossistema almeja, então a configuração existente da equipe continua funcionando.
| Dimensão | Ferramenta | Instalar | Executar | Bloquear em |
|---|---|---|---|---|
| Tipos (TS) | tsc | já existe | tsc --noEmit | qualquer erro |
| Tipos (Python) | mypy | pip install mypy | mypy . | qualquer erro |
| Lint | sua configuração existente | já existe | eslint . / biome check / ruff check | qualquer erro |
| Cobertura (JS) | seu executor de testes | já existe | vitest run --coverage (ou jest --coverage) | cobertura de linhas alteradas |
| Cobertura (Python) | pytest-cov | pip install pytest-cov | pytest --cov --cov-report=lcov | mesmo |
| Segurança: código | Semgrep | pipx install semgrep | semgrep scan --config p/default --config p/owasp-top-ten | qualquer achado alto |
| Segurança: segredos | gitleaks | brew install gitleaks | gitleaks detect --redact --no-banner | qualquer achado |
| Segurança: dependências | osv-scanner | brew install osv-scanner | osv-scanner scan source -r . | alto ou acima |
| Desempenho: página | Lighthouse | npm i -D lighthouse | lighthouse $URL --output=json --quiet | LCP, CLS, pontuação de desempenho |
| Desempenho: bundle | size-limit | npm i -D size-limit | size-limit --json | orçamento de bytes por entrada |
| Acessibilidade | axe-core | npm i -D @axe-core/cli | axe $URL --tags wcag2a,wcag2aa,wcag21aa | zero crítico ou grave |
| Arquitetura | dependency-cruiser | npm i -D dependency-cruiser | depcruise --validate src | qualquer violação |
| Qualidade de afirmação | Stryker | npm i -D @stryker-mutator/core | stryker run --mutate <arquivos alterados> | pontuação de mutação |
Cinco coisas que vão te morder se você pular:
--redactno gitleaks não é opcional. Sem ele, o segredo encontrado cai no transcript do agente, que é como uma chave vazada acaba em um log, um resumo ou uma mensagem de commit. Reporte a regra e a localização, nunca o valor.- Lighthouse e axe precisam de uma URL. Eles só funcionam contra um aplicativo em execução, então pertencem ao estágio de runtime contra um deploy de prévia ou um servidor local que você inicia primeiro. Se o projeto não tem URL para acessar — um CLI, uma biblioteca, um app desktop — diga isso e descarte a dimensão em vez de inventar uma verificação que não pode ser executada.
- Escopo das verificações caras para o diff.
stryker run --mutateem todo o repositório leva horas e acaba desligado; nos arquivos que uma alteração tocou, leva menos de um minuto. O mesmo para Semgrep, que aceita uma lista de caminhos. - Cobertura não precisa de uma segunda execução de testes. Leia o lcov que sua suíte já escreve e interseccione com
git diff. Executar a suíte duas vezes para obter um número é a maneira mais rápida de fazer as pessoas odiarem isso. - As regras do registro do Semgrep são gratuitas para executar; verifique a licença antes de redistribuí-las.
opengrepé um fork drop-in com o mesmo formato de regra e saída JSON se isso importar para seu departamento jurídico.
Adicione cada uma ao script do projeto para que seja reproduzível sem um agente:
{
"scripts": {
"check:fast": "tsc --noEmit && eslint . && gitleaks detect --redact --no-banner",
"check:task": "npm run check:fast && vitest run --coverage",
"check:full": "npm run check:task && semgrep scan --config p/default && osv-scanner scan source -r ."
}
}
Esse mapeamento importa mais que as ferramentas. check:fast é o que executa após uma edição, check:task quando o agente acha que terminou, check:full no CI.
Os comandos agora vivem em dois lugares — a coluna Verificado por em CONSTRAINTS.md e esses scripts. CONSTRAINTS.md é a fonte canônica: carrega o motivo junto com cada comando e aparece na revisão. Os scripts são wrappers de conveniência que devem espelhá-lo, não uma segunda fonte de verdade; se eles divergirem, o arquivo vence.
Passo 5: Conecte ao ciclo de vida
O maior erro único é executar tudo em todos os lugares. Uma verificação que trava o agente é desligada, e um portão que as pessoas desligaram é pior do que nenhum portão, porque a barra ainda parece existir.
| Fase | Comando | O que executa | Orçamento |
|---|---|---|---|
| BUILD | /build | Tipos, lint, segredos, o piso | abaixo de 5s, apenas arquivo alterado |
| VERIFY | /test | Testes relacionados, cobertura em linhas alteradas | abaixo de 90s |
| REVIEW | /review | Tudo, mais os guardiões abaixo | minutos |
| SHIP | /ship | Verificações de direção, sem regressões | CI |
Duas regras que mantêm isso tolerável:
- Escopo para o diff. Verifique as linhas que esta alteração tocou, não todo o repositório. Cobertura de linhas alteradas é um número que o agente pode mover; cobertura do projeto é um que ele herdou.
- O custo decide o posicionamento. Qualquer coisa acima de alguns segundos sai do loop de edição. Teste de mutação em todo o repositório leva horas; nos arquivos que uma alteração tocou, leva menos de um minuto, o que é a diferença entre uma verificação que as pessoas executam e uma que não executam.
Passo 6: Proteja a própria barra
Alguém vai apontar que, se o agente escreve o código e as verificações, as verificações não provam nada. Meio certo, e vale a pena projetar para isso.
Agentes não criam brechas engenhosas. Eles encontram uma verificação vermelha e pegam o caminho mais barato para o verde. Fique de olho nestes cinco movimentos no diff, na hora da revisão:
- O limite mudou. Um orçamento reduzido, uma gravidade diminuída, uma verificação removida do estágio rápido. Compare
CONSTRAINTS.mdcom seu estado no ponto de ramificação. - Um teste ficou mais fácil.
.skipadicionado, um arquivo de teste excluído, afirmações removidas de testes que permaneceram. - Um verificador foi silenciado. Novo
@ts-ignoreoueslint-disable. Quatro supressões merecem atenção especial porque desligam uma verificação na qual você está confiando:istanbul ignoreremove código da cobertura em vez de testá-lo,Stryker disableesconde um mutante sobrevivente,nosemgrepegitleaks:allowfazem isso para achados de segurança. - O trabalho está inacabado. Um stub que lança exceção, um
catchvazio transformando uma falha em silêncio, umTODOno lugar onde a implementação deveria estar. - Uma exceção apareceu. Uma nova linha na tabela de Exceções que ninguém discutiu.
Nada disso precisa de ferramentas além de git diff. Apertar a barra deve ser silencioso; afrouxá-la deve ser barulhento.
Ao contrário das dimensões numeradas, o piso não tem uma ferramenta de fato própria, então um agente solicitado a aplicá-lo tende a escrever um verificador do zero, e dois agentes escrevem dois diferentes. Uma implementação de referência dessas cinco verificações acompanha este skill em references/floor-guard.md (escopo no diff, saída 0/1/2, padrões adaptáveis por ecossistema). Adapte-a em vez de reinventá-la, pelo mesmo motivo que cada dimensão nomeia uma ferramenta de fato: para que o mecanismo seja o mesmo em todas as execuções e stacks.
Nem todas as verificações são igualmente circulares. Classifique-as por uma pergunta: o agente pode fazer esta verificação passar escrevendo código que não funciona?
- Externo — axe-core codifica WCAG,
osv-scannerlê um banco de dados de vulnerabilidades, Lighthouse mede um navegador real. O agente não pode argumentar contra estes. - Projeto — suas regras de lint, seus limites de camada. Um humano é dono do arquivo.
- Suíte — seus próprios testes. Mais útil, e o único genuinamente circular.
Uma barra …
… [truncado para tradução]