{
 "grupo": "codigo",
 "descricao": "Escrever e mudar código",
 "itens": [
  {
   "id": "cod-entender-repo",
   "nome": "Entender um repositório novo",
   "receita": "README, package.json/pyproject, pasta principal, 1 teste; rg dos pontos de entrada",
   "prova": "mapa de 5 linhas do projeto"
  },
  {
   "id": "cod-seguir-padrao",
   "nome": "Seguir o padrão da casa",
   "receita": "leia 2 arquivos vizinhos; copie nomes, estrutura, tratamento de erro",
   "prova": "diff parece escrito pelo mesmo autor"
  },
  {
   "id": "cod-funcao-pura",
   "nome": "Extrair função pura",
   "receita": "tire efeito colateral para fora; entrada e saída; teste com 3 casos",
   "prova": "teste da função passa"
  },
  {
   "id": "cod-validar-entrada",
   "nome": "Validar entrada de fora",
   "receita": "na borda: tipo, tamanho, faixa, formato (zod/pydantic); falha cedo com mensagem útil",
   "prova": "entrada ruim devolve erro claro"
  },
  {
   "id": "cod-erro-bom",
   "nome": "Tratar erro de verdade",
   "receita": "capture onde dá pra agir; mensagem com contexto; nunca catch vazio",
   "prova": "falha simulada mostra mensagem útil"
  },
  {
   "id": "cod-config",
   "nome": "Configuração sem hardcode",
   "receita": "valor por ambiente em variável; padrão seguro; falha clara se faltar",
   "prova": "rodar sem a variável dá erro explicando"
  },
  {
   "id": "cod-feature-flag",
   "nome": "Entregar mudança arriscada",
   "receita": "atrás de flag; padrão desligado; remova depois",
   "prova": "ligar e desligar funcionam"
  },
  {
   "id": "cod-migrar-api",
   "nome": "Trocar uma API por outra",
   "receita": "ache todos os usos (rg); adaptador fino; migre um por vez com teste",
   "prova": "rg do nome antigo vazio"
  },
  {
   "id": "cod-renomear",
   "nome": "Renomear com segurança",
   "receita": "rg do nome em código, testes, docs, config e strings; troque tudo junto",
   "prova": "rg vazio e teste verde"
  },
  {
   "id": "cod-remover-codigo-morto",
   "nome": "Apagar código morto",
   "receita": "confirme com rg que ninguém usa (inclusive dinâmico); apague; rode testes",
   "prova": "testes verdes e build ok"
  },
  {
   "id": "cod-cli",
   "nome": "Criar uma CLI",
   "receita": "argumentos claros, --help, código de saída, erro no stderr, exemplo no README",
   "prova": "--help e um caso de erro rodados"
  },
  {
   "id": "cod-idempotente",
   "nome": "Operação repetível",
   "receita": "rodar duas vezes dá o mesmo resultado; chave de idempotência ou \"se não existe\"",
   "prova": "segunda execução não muda nada"
  },
  {
   "id": "cod-paginar",
   "nome": "Paginar lista",
   "receita": "limite máximo, cursor ou offset estável, ordem determinística",
   "prova": "página 1, 2 e última conferidas"
  },
  {
   "id": "cod-cache",
   "nome": "Cache simples",
   "receita": "chave clara, TTL, invalidação ao escrever; mede o ganho",
   "prova": "taxa de acerto ou tempo medido"
  },
  {
   "id": "cod-retry",
   "nome": "Tentar de novo",
   "receita": "só erro transitório; backoff exponencial com jitter; limite de tentativas",
   "prova": "falha simulada recupera"
  },
  {
   "id": "cod-logs",
   "nome": "Logs úteis",
   "receita": "nível, contexto (id), sem segredo, uma linha por evento",
   "prova": "log legível sem dados sensíveis"
  },
  {
   "id": "cod-upload",
   "nome": "Receber arquivo",
   "receita": "limite de tamanho, tipo por conteúdo, nome gerado por você, fora da raiz pública",
   "prova": "arquivo grande e tipo errado rejeitados"
  },
  {
   "id": "cod-formulario",
   "nome": "Formulário completo",
   "receita": "rótulos, validação ao sair, erro por campo, estado enviando, foco no 1º erro",
   "prova": "envio válido e inválido testados"
  },
  {
   "id": "cod-tema-escuro",
   "nome": "Modo escuro",
   "receita": "tokens de cor em variáveis; prefers-color-scheme; teste contraste nos dois",
   "prova": "screenshot dos dois temas"
  },
  {
   "id": "cod-i18n",
   "nome": "Internacionalizar",
   "receita": "tire strings para arquivos por idioma; plural e data pela biblioteca",
   "prova": "troca de idioma funciona"
  },
  {
   "id": "cod-teste-primeiro",
   "nome": "Bug com teste primeiro",
   "receita": "escreva teste que falha pelo motivo certo; conserte; veja verde",
   "prova": "teste falhava e agora passa"
  },
  {
   "id": "codigo-ler-antes-de-mudar",
   "nome": "Ler antes de mudar",
   "receita": "abra o arquivo, quem o chama e os testes dele antes de editar",
   "prova": "a lista de chamadores e de testes citada na mudança"
  },
  {
   "id": "codigo-mudanca-minima-que-resolve",
   "nome": "Mudança mínima que resolve",
   "receita": "altere só o necessário; cada linha do diff se explica pelo pedido",
   "prova": "o diff não tem formatação nem refatoração alheia"
  },
  {
   "id": "codigo-nomes-que-explicam",
   "nome": "Nomes que explicam",
   "receita": "nome pelo papel (valorTotal, não x); verbos para funções, substantivos para dados",
   "prova": "um leitor novo entende sem comentário"
  },
  {
   "id": "codigo-funcao-pequena-com-um-motivo",
   "nome": "Função pequena com um motivo",
   "receita": "uma função faz uma coisa; extraia quando precisar de \"e\" para descrever",
   "prova": "a função se descreve em uma frase"
  },
  {
   "id": "codigo-retorno-cedo",
   "nome": "Retorno cedo",
   "receita": "trate os casos inválidos no começo com return/throw e deixe o caminho feliz sem aninhamento",
   "prova": "a função com no máximo 2 níveis de indentação"
  },
  {
   "id": "codigo-substituir-condicional-por-tabela",
   "nome": "Substituir condicional por tabela",
   "receita": "mapa de chave para função ou valor em vez de if/else longo",
   "prova": "adicionar um caso é uma linha"
  },
  {
   "id": "codigo-parametros-em-objeto",
   "nome": "Parâmetros em objeto",
   "receita": "acima de 3 parâmetros use um objeto nomeado, com padrões",
   "prova": "as chamadas se leem sem decorar a ordem"
  },
  {
   "id": "codigo-evitar-booleano-de-flag",
   "nome": "Evitar booleano de flag",
   "receita": "duas funções ou um enum em vez de um boolean que muda o comportamento",
   "prova": "a chamada se entende pelo nome"
  },
  {
   "id": "codigo-constantes-nomeadas",
   "nome": "Constantes nomeadas",
   "receita": "troque número e texto mágico por constante com nome e unidade",
   "prova": "a busca pela constante acha todos os usos"
  },
  {
   "id": "codigo-imutabilidade",
   "nome": "Imutabilidade",
   "receita": "não mude argumento; devolva novo valor e use const",
   "prova": "a entrada original permanece igual depois da chamada"
  },
  {
   "id": "codigo-tipos-como-documentacao",
   "nome": "Tipos como documentação",
   "receita": "declare tipos de entrada e saída e restrinja valores (união, enum)",
   "prova": "o compilador recusa o uso errado"
  },
  {
   "id": "codigo-valores-opcionais",
   "nome": "Valores opcionais",
   "receita": "represente ausência de forma explícita (null/undefined/Option) e trate na borda",
   "prova": "nenhum acesso a propriedade de nulo nos testes de borda"
  },
  {
   "id": "codigo-erros-como-parte-da-api",
   "nome": "Erros como parte da API",
   "receita": "defina erros tipados com código e contexto; não use string solta",
   "prova": "o chamador distingue erro por tipo"
  },
  {
   "id": "codigo-falhar-cedo-e-alto",
   "nome": "Falhar cedo e alto",
   "receita": "valide pré-condições e lance erro claro com o dado inválido",
   "prova": "a mensagem diz o que foi recebido e o que se esperava"
  },
  {
   "id": "codigo-nao-engolir-excecao",
   "nome": "Não engolir exceção",
   "receita": "capture só o que sabe tratar; senão deixe subir com contexto",
   "prova": "nenhum catch vazio (grep)"
  },
  {
   "id": "codigo-limpeza-garantida",
   "nome": "Limpeza garantida",
   "receita": "finally, using, defer ou with para fechar recursos",
   "prova": "o recurso fecha mesmo com erro"
  },
  {
   "id": "codigo-log-de-aplicacao-sem-dado-sensivel",
   "nome": "Log de aplicação sem dado sensível",
   "receita": "registre ids e resultados, nunca senha, token ou dado pessoal",
   "prova": "grep por chaves no log não acha nada"
  },
  {
   "id": "codigo-configuracao-tipada",
   "nome": "Configuração tipada",
   "receita": "leia a configuração uma vez na partida, valide e passe como parâmetro",
   "prova": "valor ausente interrompe a partida com mensagem"
  },
  {
   "id": "codigo-injecao-de-dependencia-simples",
   "nome": "Injeção de dependência simples",
   "receita": "passe as dependências como parâmetros e crie na borda do programa",
   "prova": "o teste troca a dependência sem mock global"
  },
  {
   "id": "codigo-separar-leitura-e-escrita",
   "nome": "Separar leitura e escrita",
   "receita": "funções que consultam não alteram estado; as que alteram não devolvem dados complexos",
   "prova": "duas chamadas de consulta dão o mesmo resultado"
  },
  {
   "id": "codigo-camada-de-dominio-sem-framework",
   "nome": "Camada de domínio sem framework",
   "receita": "regras de negócio em funções puras, sem importar banco ou HTTP",
   "prova": "o teste da regra roda sem rede nem banco"
  },
  {
   "id": "codigo-adaptador-para-servico-externo",
   "nome": "Adaptador para serviço externo",
   "receita": "envolva a biblioteca de terceiros em uma interface sua",
   "prova": "trocar o fornecedor muda um arquivo"
  },
  {
   "id": "codigo-evitar-abstracao-prematura",
   "nome": "Evitar abstração prematura",
   "receita": "espere a terceira repetição antes de extrair; duplicar é mais barato que a abstração errada",
   "prova": "a abstração criada tem 3 usos reais"
  },
  {
   "id": "codigo-remover-duplicacao-real",
   "nome": "Remover duplicação real",
   "receita": "extraia só o que muda junto pelo mesmo motivo",
   "prova": "um ajuste de regra edita um lugar só"
  },
  {
   "id": "codigo-composicao-em-vez-de-heranca",
   "nome": "Composição em vez de herança",
   "receita": "combine funções e objetos pequenos; herde só por um \"é um\" verdadeiro",
   "prova": "a mudança de comportamento sem tocar hierarquia"
  },
  {
   "id": "codigo-maquina-de-estados",
   "nome": "Máquina de estados",
   "receita": "liste estados e transições permitidas em uma tabela e recuse as demais",
   "prova": "uma transição inválida lança erro no teste"
  },
  {
   "id": "codigo-idempotencia",
   "nome": "Idempotência",
   "receita": "faça a operação segura para repetir (chave única, upsert, checagem)",
   "prova": "duas execuções dão o mesmo resultado"
  },
  {
   "id": "codigo-paginacao-correta",
   "nome": "Paginação correta",
   "receita": "cursor ou limite+offset com ordenação estável e total opcional",
   "prova": "a página 2 não repete itens da página 1"
  },
  {
   "id": "codigo-busca-com-filtros-combinaveis",
   "nome": "Busca com filtros combináveis",
   "receita": "construa a consulta por partes com parâmetros ligados, nunca concatenando",
   "prova": "filtros combinados retornam o conjunto certo"
  },
  {
   "id": "codigo-ordenacao-estavel",
   "nome": "Ordenação estável",
   "receita": "desempate por id para a ordem ser determinística",
   "prova": "duas chamadas devolvem a mesma ordem"
  },
  {
   "id": "codigo-datas-sem-dor",
   "nome": "Datas sem dor",
   "receita": "armazene UTC e instantes; formate na borda; use biblioteca de datas",
   "prova": "o teste cobre fuso e fim de mês"
  },
  {
   "id": "codigo-dinheiro-sem-erro",
   "nome": "Dinheiro sem erro",
   "receita": "inteiro em centavos e moeda explícita; arredonde uma vez",
   "prova": "somas de parcelas igual ao total"
  },
  {
   "id": "codigo-texto-e-unicode",
   "nome": "Texto e Unicode",
   "receita": "normalize (NFC), compare sem caixa e cuidado com emoji e tamanho em bytes",
   "prova": "o teste com acentos e emoji passa"
  },
  {
   "id": "codigo-slug-e-url",
   "nome": "Slug e URL",
   "receita": "normalize, remova acentos, troque separadores e garanta unicidade com sufixo",
   "prova": "dois títulos iguais geram slugs distintos"
  },
  {
   "id": "codigo-gerar-identificadores",
   "nome": "Gerar identificadores",
   "receita": "UUID/ULID para ids públicos; nunca sequencial exposto",
   "prova": "os ids não revelam a quantidade de registros"
  },
  {
   "id": "codigo-hash-e-comparacao-seguros",
   "nome": "Hash e comparação seguros",
   "receita": "compare segredos em tempo constante e use hash de senha com sal (argon2)",
   "prova": "o teste não vaza informação pelo tempo"
  },
  {
   "id": "codigo-limitar-entrada",
   "nome": "Limitar entrada",
   "receita": "limite tamanho, profundidade e quantidade de itens de tudo que vem de fora",
   "prova": "a entrada enorme é recusada rápido"
  },
  {
   "id": "codigo-sanitizar-saida",
   "nome": "Sanitizar saída",
   "receita": "escape conforme o destino (HTML, SQL, shell, URL) com a biblioteca",
   "prova": "o texto com <script> aparece como texto"
  },
  {
   "id": "codigo-parser-em-vez-de-regex",
   "nome": "Parser em vez de regex",
   "receita": "para JSON, HTML, CSV e datas use o parser dedicado",
   "prova": "dados com aspas e vírgulas internas são lidos certos"
  },
  {
   "id": "codigo-leitura-de-arquivo-grande",
   "nome": "Leitura de arquivo grande",
   "receita": "processe em stream por linha, sem carregar tudo",
   "prova": "a memória estável em arquivo de 1 GB"
  },
  {
   "id": "codigo-escrita-atomica-de-arquivo",
   "nome": "Escrita atômica de arquivo",
   "receita": "escreva em temporário e renomeie",
   "prova": "queda no meio não deixa arquivo pela metade"
  },
  {
   "id": "codigo-concorrencia-segura",
   "nome": "Concorrência segura",
   "receita": "evite estado compartilhado; use fila, mutex ou operação atômica",
   "prova": "o teste paralelo mantém o invariante"
  },
  {
   "id": "codigo-limite-de-concorrencia",
   "nome": "Limite de concorrência",
   "receita": "processe em lotes de N com p-limit ou semáforo",
   "prova": "o pico de requisições nunca passa de N"
  },
  {
   "id": "codigo-cancelamento",
   "nome": "Cancelamento",
   "receita": "propague AbortSignal/context até a E/S e limpe",
   "prova": "cancelar interrompe a requisição de verdade"
  },
  {
   "id": "codigo-timeout-em-tudo-que-e-externo",
   "nome": "Timeout em tudo que é externo",
   "receita": "defina tempo máximo em cada chamada de rede e banco",
   "prova": "a dependência lenta falha em tempo definido"
  },
  {
   "id": "codigo-retry-com-backoff",
   "nome": "Retry com backoff",
   "receita": "tente só em erro transitório, com espera crescente, jitter e limite",
   "prova": "a falha permanente não repete para sempre"
  },
  {
   "id": "codigo-circuit-breaker",
   "nome": "Circuit breaker",
   "receita": "abra o circuito após N falhas, responda rápido e teste meia-abertura",
   "prova": "a dependência fora do ar não trava as requisições"
  },
  {
   "id": "codigo-cache-com-chave-certa",
   "nome": "Cache com chave certa",
   "receita": "inclua tudo que muda o resultado na chave e defina expiração",
   "prova": "duas entradas distintas nunca compartilham a chave"
  },
  {
   "id": "codigo-memoizacao-cuidadosa",
   "nome": "Memoização cuidadosa",
   "receita": "memorize função pura com limite de tamanho",
   "prova": "a segunda chamada não recalcula e a memória não cresce"
  },
  {
   "id": "codigo-otimizar-com-medida",
   "nome": "Otimizar com medida",
   "receita": "perfil primeiro; mude o gargalo; meça de novo",
   "prova": "números antes e depois com a mesma carga"
  },
  {
   "id": "codigo-evitar-n-1-no-codigo",
   "nome": "Evitar N+1 no código",
   "receita": "busque em lote e monte um mapa por id",
   "prova": "o número de consultas não cresce com a lista"
  },
  {
   "id": "codigo-processamento-em-lote",
   "nome": "Processamento em lote",
   "receita": "agrupe escritas e leituras em blocos de tamanho medido",
   "prova": "o tempo cai sem aumentar o pico de memória"
  },
  {
   "id": "codigo-gerar-relatorio",
   "nome": "Gerar relatório",
   "receita": "consulta agregada no banco, formatação na borda, exportação em stream",
   "prova": "o total do relatório bate com a fonte"
  },
  {
   "id": "codigo-importar-csv",
   "nome": "Importar CSV",
   "receita": "valide linha a linha, reporte erros com número da linha e processe em transação ou em lotes",
   "prova": "o arquivo com linhas ruins relata só elas"
  },
  {
   "id": "codigo-exportar-dados",
   "nome": "Exportar dados",
   "receita": "colunas estáveis, cabeçalho, escape de aspas, UTF-8 com BOM para Excel",
   "prova": "o arquivo abre certo no Excel"
  },
  {
   "id": "codigo-webhook-handler",
   "nome": "Webhook handler",
   "receita": "valide assinatura, responda rápido, enfileire e processe idempotente",
   "prova": "o reenvio do mesmo evento não duplica efeito"
  },
  {
   "id": "codigo-cliente-de-api-com-sdk-proprio",
   "nome": "Cliente de API com SDK próprio",
   "receita": "função por endpoint, tipos de resposta, erros tipados e retry",
   "prova": "o cliente passa nos testes contra servidor falso"
  },
  {
   "id": "codigo-contrato-de-api",
   "nome": "Contrato de API",
   "receita": "defina o schema (OpenAPI/zod) e gere tipos e validação do mesmo lugar",
   "prova": "o teste de contrato recusa resposta fora do schema"
  },
  {
   "id": "codigo-feature-flag-no-codigo",
   "nome": "Feature flag no código",
   "receita": "flag lida em um ponto só, padrão seguro e data de remoção",
   "prova": "ligar e desligar muda o comportamento sem deploy"
  },
  {
   "id": "codigo-migrar-dados-no-codigo",
   "nome": "Migrar dados no código",
   "receita": "script idempotente com dry-run, lotes e log",
   "prova": "rodar duas vezes não altera o resultado"
  },
  {
   "id": "codigo-compatibilidade-para-tras",
   "nome": "Compatibilidade para trás",
   "receita": "adicione campo opcional em vez de mudar o existente e dê aviso de depreciação",
   "prova": "o cliente antigo continua funcionando"
  },
  {
   "id": "codigo-remover-recurso-depreciado",
   "nome": "Remover recurso depreciado",
   "receita": "registre uso, avise, espere o prazo e remova com teste",
   "prova": "o log de uso do recurso zerado antes da remoção"
  },
  {
   "id": "codigo-atualizar-dependencia",
   "nome": "Atualizar dependência",
   "receita": "leia o changelog, atualize uma por vez, rode a suíte e o build",
   "prova": "a suíte verde e o changelog citado no PR"
  },
  {
   "id": "codigo-trocar-biblioteca",
   "nome": "Trocar biblioteca",
   "receita": "escreva testes de caracterização, troque por trás de uma interface e compare",
   "prova": "o comportamento idêntico nos testes"
  },
  {
   "id": "codigo-reduzir-dependencias",
   "nome": "Reduzir dependências",
   "receita": "prefira a API nativa; adicione pacote só se evita muito código e é mantido",
   "prova": "a lista de dependências não cresce sem motivo"
  },
  {
   "id": "codigo-codigo-gerado",
   "nome": "Código gerado",
   "receita": "gere de uma fonte (schema), não edite à mão, e inclua o comando no README",
   "prova": "regenerar não produz diff"
  },
  {
   "id": "codigo-comentario-que-ajuda",
   "nome": "Comentário que ajuda",
   "receita": "comente o porquê e a armadilha, não o que o código já diz",
   "prova": "cada comentário responde \"por que assim?\""
  },
  {
   "id": "codigo-readme-de-projeto-que-um-colega-novo-roda",
   "nome": "README de projeto que um colega novo roda",
   "receita": "pré-requisitos, instalação, execução e testes com comandos copiáveis",
   "prova": "um colega novo roda o projeto em 10 minutos"
  },
  {
   "id": "codigo-exemplo-executavel",
   "nome": "Exemplo executável",
   "receita": "inclua um exemplo mínimo testado no CI",
   "prova": "o exemplo roda no pipeline"
  },
  {
   "id": "codigo-cli-com-boa-experiencia",
   "nome": "CLI com boa experiência",
   "receita": "--help claro, códigos de saída, erro em stderr, saída em JSON opcional",
   "prova": "os comandos funcionam em pipe"
  },
  {
   "id": "codigo-script-de-migracao-de-projeto",
   "nome": "Script de migração de projeto",
   "receita": "detecte o estado atual, aplique em passos e permita desfazer",
   "prova": "rodar em um projeto de teste dá o resultado esperado"
  },
  {
   "id": "codigo-estrutura-de-pastas",
   "nome": "Estrutura de pastas",
   "receita": "agrupe por funcionalidade, não por tipo de arquivo, e siga a convenção do framework",
   "prova": "achar o código de uma feature em um lugar"
  },
  {
   "id": "codigo-arquivo-grande-demais",
   "nome": "Arquivo grande demais",
   "receita": "divida por responsabilidade mantendo a API pública, passo a passo, com testes verdes",
   "prova": "cada arquivo abaixo de 300 linhas e a suíte verde"
  },
  {
   "id": "codigo-imports-limpos",
   "nome": "Imports limpos",
   "receita": "ordem consistente, sem import não usado, alias de caminho",
   "prova": "o lint sem avisos de import"
  },
  {
   "id": "codigo-formatacao-automatica",
   "nome": "Formatação automática",
   "receita": "configure formatter e lint no commit e no CI",
   "prova": "o diff não traz mais ruído de estilo"
  },
  {
   "id": "codigo-tipos-estritos",
   "nome": "Tipos estritos",
   "receita": "ative strict e corrija os erros por pasta",
   "prova": "tsc strict sem erros"
  },
  {
   "id": "codigo-verificacao-de-ponta-a-ponta",
   "nome": "Verificação de ponta a ponta",
   "receita": "depois de mexer, rode o fluxo real e leia a saída, não só os testes",
   "prova": "a saída do fluxo colada no relato"
  },
  {
   "id": "codigo-teste-primeiro-no-bug",
   "nome": "Teste primeiro no bug",
   "receita": "escreva o teste que reproduz, veja falhar, corrija, veja passar",
   "prova": "o teste vermelho antes e verde depois"
  },
  {
   "id": "codigo-teste-de-borda",
   "nome": "Teste de borda",
   "receita": "vazio, um item, máximo, negativo, texto longo, Unicode",
   "prova": "cada borda com um caso"
  },
  {
   "id": "codigo-depurar-com-assercoes",
   "nome": "Depurar com asserções",
   "receita": "afirme invariantes no código para falhar perto da causa",
   "prova": "a falha aponta a linha que quebrou a regra"
  },
  {
   "id": "codigo-revisar-o-proprio-diff",
   "nome": "Revisar o próprio diff",
   "receita": "leia git diff como revisor antes de pedir revisão",
   "prova": "a lista de achados corrigida"
  },
  {
   "id": "codigo-pr-pequeno-e-claro",
   "nome": "PR pequeno e claro",
   "receita": "uma mudança lógica, título que diz o efeito, descrição com o porquê e como testar",
   "prova": "o revisor entende em 5 minutos"
  },
  {
   "id": "codigo-responder-a-revisao",
   "nome": "Responder a revisão",
   "receita": "corrija ou explique cada comentário e não discuta gosto sem critério",
   "prova": "todos os comentários resolvidos"
  },
  {
   "id": "codigo-medir-complexidade",
   "nome": "Medir complexidade",
   "receita": "função com complexidade ciclomática acima de 10 é candidata a divisão",
   "prova": "o relatório de complexidade melhora"
  },
  {
   "id": "codigo-detectar-codigo-morto",
   "nome": "Detectar código morto",
   "receita": "ferramentas (knip, vulture) e busca por uso antes de apagar",
   "prova": "nada quebra após a remoção e a suíte passa"
  },
  {
   "id": "codigo-duplicatas-no-repositorio",
   "nome": "Duplicatas no repositório",
   "receita": "busque trechos repetidos (jscpd) e consolide os com mesmo motivo de mudança",
   "prova": "a duplicação diminui sem acoplar o que difere"
  },
  {
   "id": "codigo-acessibilidade-no-codigo",
   "nome": "Acessibilidade no código",
   "receita": "elementos semânticos, rótulos, foco e teclado",
   "prova": "navegar só pelo teclado funciona"
  },
  {
   "id": "codigo-estado-de-carregamento-e-erro",
   "nome": "Estado de carregamento e erro",
   "receita": "toda chamada assíncrona na tela tem carregando, erro e vazio",
   "prova": "cada estado visto no teste"
  },
  {
   "id": "codigo-formulario-com-validacao",
   "nome": "Formulário com validação",
   "receita": "valide no cliente para ajudar e no servidor para garantir",
   "prova": "o envio inválido mostra erro por campo"
  },
  {
   "id": "codigo-mensagens-de-erro-humanas",
   "nome": "Mensagens de erro humanas",
   "receita": "diga o que aconteceu e o que fazer, sem código interno",
   "prova": "a mensagem entendível por alguém não técnico"
  },
  {
   "id": "codigo-tema-e-tokens",
   "nome": "Tema e tokens",
   "receita": "cores e espaços em variáveis, nunca valor solto",
   "prova": "trocar o token muda todos os usos"
  },
  {
   "id": "codigo-internacionalizacao",
   "nome": "Internacionalização",
   "receita": "textos em chaves, formatos por localidade, plural certo",
   "prova": "a interface em dois idiomas sem texto fixo"
  },
  {
   "id": "codigo-seguranca-de-dependencias",
   "nome": "Segurança de dependências",
   "receita": "npm audit/pip-audit no CI e atualização das vulneráveis",
   "prova": "o relatório sem vulnerabilidade alta"
  },
  {
   "id": "codigo-variaveis-de-ambiente-no-front",
   "nome": "Variáveis de ambiente no front",
   "receita": "só valores públicos no bundle; segredo no servidor",
   "prova": "a busca no bundle por chave não encontra segredos"
  },
  {
   "id": "codigo-armazenamento-no-navegador",
   "nome": "Armazenamento no navegador",
   "receita": "localStorage só para preferência; token em cookie HttpOnly",
   "prova": "nenhum token legível por script"
  },
  {
   "id": "codigo-entrega-incremental",
   "nome": "Entrega incremental",
   "receita": "merge pequeno atrás de flag, em vez de uma branch longa",
   "prova": "a main sempre implantável"
  }
 ]
}
