


Manter uma base de código grande e modular fácil de ler e de alterar sem quebrar
Use quando uma IA trabalha em uma base de código grande dividida em muitos componentes. Dá regras de estilo de código, tamanho de arquivos e de mudanças, revisão de código, testes, nomes da API e builds, para que as mudanças fiquem pequenas, legíveis e não quebrem outras partes.
Para usar estas regras de IA
## Evitar argumentos soltos como true/false para cada chamada se explicar sozinha
Priorize a clareza no local de chamada em vez de soluções engenhosas.
- Insira variáveis diretamente nos marcadores de formatação de string em vez de passá-las posicionalmente.
- Prefira referências a métodos em vez de closures triviais quando a linguagem permitir.
- Evite argumentos posicionais opacos — booleanos soltos, null/none ou literais numéricos — que obrigam quem lê a adivinhar o significado (por exemplo, `foo(false)`). Prefira enums, métodos nomeados, newtypes ou outras formas de API autoexplicativas.
- Quando uma forma autoexplicativa for impossível e um literal posicional precisar permanecer, anote-o com um comentário inline `/*param_name*/` que corresponda exatamente ao nome do parâmetro da função chamada. Deixe literais de string/char sem anotação, a menos que o comentário realmente agregue clareza.
- Torne as ramificações exaustivas (sem braços coringa que capturam tudo) para que novos casos adicionados apareçam em tempo de compilação.
- Adicione comentários de documentação às novas abstrações (traits/interfaces) explicando seu papel e como quem for implementá-las deve usá-las.
- Siga as convenções locais do arquivo. Não fique alternando o código entre formas equivalentes sem um ganho claro de legibilidade ou funcionalidade, e não adicione anotações de tipo apenas para satisfazer uma forma abreviada.
- Não crie pequenas funções auxiliares que são referenciadas apenas uma vez.
## Manter arquivos e mudanças pequenos em vez de inchar o componente central
Mantenha as unidades pequenas para que mudanças não relacionadas parem de colidir.
### Tamanho do módulo
- Prefira adicionar um novo módulo em vez de expandir um já existente. Busque manter os módulos com menos de aproximadamente 500 linhas de código que não seja de teste; quando um arquivo se aproximar de ~800 linhas, coloque a nova funcionalidade em um novo módulo, a menos que haja uma razão forte e documentada para não fazê-lo.
- Aplique isso com mais rigor aos arquivos centrais de orquestração de alto tráfego que já atraem edições não relacionadas; mantenha esses arquivos focados na orquestração em vez de acumular funções auxiliares independentes.
- Ao extrair código de um módulo grande, mova seus testes e a documentação de tipos/módulo junto com a nova implementação, para que os invariantes permaneçam próximos do código que os possui.
### Resista a inchar o maior componente
- O componente maior ou mais central é o caminho de menor resistência para código novo, e é exatamente por isso que ele continua crescendo. Resista a adicionar código a ele. Pergunte primeiro se um componente existente é um lugar melhor, ou se é hora de criar um novo — refatorando conforme necessário. Na revisão, questione mudanças que aumentariam o componente central sem necessidade.
### Tamanho da mudança
- A menos que a mudança seja mecânica, mantenha o total de linhas alteradas abaixo de ~800; para lógica complexa, abaixo de ~500.
- Se uma mudança for maior, divida-a em etapas revisáveis e integre primeiro a menor etapa coerente, baseando a divisão no diff real, nas dependências e nos pontos de chamada afetados.
## Na revisão de código, achar mudanças incompatíveis e contexto que cresce sem limite
Revise em busca dos riscos que são caros de detectar mais tarde.
### Mantenha a superfície pública pequena
Mantenha a API pública/exportada de cada componente a menor possível. Prefira internos privados com uma superfície pública explicitamente exportada, e evite a proliferação de auxiliares exclusivos para testes no código de produção.
### Proteja o contexto de modelo/inferência
Quando um sistema mantém um contexto que é enviado a um modelo a cada requisição de inferência, proteja-o:
- Construa o contexto de forma incremental; nunca reescreva o histórico.
- Evite mudanças frequentes no contexto que invalidem o cache.
- Tudo o que for injetado deve ter um tamanho limitado e um teto rígido — nenhum item sem limite, e nenhum item isolado além de um teto fixo de tokens.
- Sinalize qualquer novo item que possa, isoladamente, ultrapassar um limite de tamanho grande para revisão manual extra.
- Encaminhe todos os fragmentos injetados por meio de uma única abstração tipada, em vez de inserções ad hoc.
### Detecte mudanças que quebram compatibilidade
Procure ativamente por mudanças que quebrem compatibilidade nas superfícies de integração externas: APIs públicas, payloads de eventos (mesmo os experimentais), parâmetros de linha de comando, carregamento de configuração e a capacidade de retomar sessões existentes ou estado persistido.
## Verificar o comportamento real com testes de integração e de snapshot
Teste o comportamento, mantenha os testes honestos e fora do código de produção.
- Para mudanças no comportamento central, prefira testes de integração que exercitem uma instância real em vez de testes unitários restritos. Qualquer mudança nesse comportamento DEVE adicionar um teste de integração; enumere os comportamentos que precisam de cobertura.
- Coloque os testes unitários em um arquivo de teste irmão dedicado, em vez de embutidos no arquivo de implementação, e dê ao arquivo um nome descritivo. Não adicione funções exclusivas para testes em módulos de produção, e não reescreva módulos de teste inline existentes apenas para seguir esta convenção.
- Qualquer mudança na saída renderizada visível para o usuário deve incluir cobertura de snapshot — adicione ou atualize o snapshot e revise o diff como parte da mudança, para que o impacto na interface permaneça visível.
- Faça asserções sobre objetos inteiros com igualdade profunda em vez de comparar campos um a um, usando uma biblioteca de asserções que produza diffs claros.
- Não altere o estado global do processo (por exemplo, variáveis de ambiente) dentro dos testes; passe dependências e flags de fora para dentro.
- Não teste constantes definidas estaticamente, e não adicione testes negativos para lógica que foi removida.
- Verifique se já existem auxiliares de teste antes de escrever uma nova configuração, para que os testes permaneçam enxutos e legíveis.
## Usar os mesmos nomes e formatos de campos em toda a API
Ao evoluir uma API de rede ou multilinguagem, a consistência na fronteira de transmissão (wire) evita quebras silenciosas.
- Concentre o desenvolvimento ativo na versão atual da API; não adicione nova superfície a versões descontinuadas.
- Nomeie os payloads de forma consistente por função (um sufixo para parâmetros de requisição, um para respostas, um para notificações). Exponha os métodos como um nome de recurso seguido de um nome de ação, com uma convenção consistente de singular/plural para o recurso.
- Fixe uma única convenção de capitalização (casing) de transmissão para campos e valores de enum e aplique-a em todos os lugares, substituindo-a apenas por necessidades explícitas de compatibilidade. Mantenha as anotações do serializador e da geração de tipos alinhadas para que ambos os lados concordem; quando um usar uma renomeação explícita, o outro deve corresponder.
- Para uniões discriminadas, use marcação (tagging) explícita em todos os serializadores.
- Prefira IDs em string simples na fronteira e converta internamente. Use timestamps inteiros com nomenclatura consistente `*_at`.
- Para endpoints de listagem, implemente paginação por cursor como padrão (um cursor e um limite na entrada; um array de dados e o próximo cursor na saída).
- Proteja a superfície experimental atrás de um marcador explícito, e regenere documentação, exemplos e fixtures de schema sempre que as formas da API mudarem.
## Rodar primeiro o formatador e testes focados, sem mexer nas proteções de sandbox
Respeite o toolchain e as restrições que já existem.
### Proteções de ambiente e sandbox
- Nunca adicione ou modifique código que gerencia flags de sandbox ou de capacidade de ambiente sem intenção deliberada. Essas proteções existem porque o código e os testes foram escritos em torno de limites específicos de runtime — por exemplo, testes que encerram antecipadamente quando uma capacidade, como acesso à rede, está indisponível. Remover ou alterar uma proteção silenciosamente quebra essas premissas.
### Higiene de build e toolchain
- Execute o formatador automaticamente após concluir as mudanças no código; não peça aprovação para formatar.
- Execute primeiro os testes relevantes mais restritos, delimitados ao componente alterado. Só expanda para a suíte completa quando código compartilhado ou central tiver mudado, e confirme antes de iniciar execuções longas da suíte completa.
- Quando você alterar entradas que alimentam artefatos gerados — schemas, lockfiles, tipos gerados —, regenere-os na mesma mudança; o desvio (drift) é verificado no CI.
- Se a ferramenta de build precisar que os arquivos-fonte sejam declarados para acesso em tempo de compilação, atualize essa declaração sempre que você adicionar essas leituras.
- Seja paciente com comandos lentos de build e teste; a contenção de lock esperada pode deixá-los lentos. Não os encerre pelo ID do processo.
### Suporte a plataformas
- Testes e funcionalidades devem ter suporte em todos os sistemas operacionais oficialmente suportados, a menos que uma funcionalidade seja explicitamente específica de um SO. Nos casos em que o sistema permite que componentes rodem em diferentes sistemas operacionais, garanta que os novos testes exercitem essas configurações entre SOs.
