Desenhando as garantias de segurança para uma limpeza orquestrada por IA, não só automatizando o trabalho braçal
Desenhei e construí uma skill de Claude Code que orquestra com segurança agentes paralelos para remover feature flags expiradas em um frontend compartilhado e dois serviços de backend, fechando um épico de limpeza de 36 subtarefas (24 feature flags mais 3 tours de produto expirados e uma página legada, ~3.100 linhas removidas em um único commit), com batching por conjuntos de arquivos disjuntos para que agentes não possam colidir, validação por diff contra baseline em vez de aprovação/reprovação absoluta, e uma ordem de deploy entre dois repositórios reforçada para que mudanças de infraestrutura nunca possam preceder o código do qual dependem.
impactoFechei um épico de limpeza de 35 tarefas abrangendo um frontend compartilhado e dois serviços de backend, removendo mais de 25 feature flags expiradas e infraestrutura obsoleta de tours de produto. Um único commit removeu sozinho cerca de 3.100 linhas de código morto.Produzi uma ferramenta reutilizável, não um script pontual: a mesma skill se aplica ao próximo épico de limpeza de flags em qualquer um dos três repositórios, codificando convenções que antes só existiam na memória.Removi os modos de falha que tornam esse tipo de limpeza perigoso à mão, ou seja, classificar mal uma flag, agentes colidindo em um arquivo compartilhado, ou inverter a ordem de deploy entre dois repositórios, desenhando-os para fora da ferramenta em vez de depender de quem a executa lembrar dos três sob pressão de tempo.Qualitativo: uma base de código mais simples e legível como resultado direto da remoção de código morto; nenhuma métrica isolada de antes/depois de tempo de build foi capturada só para esta mudança.
01
Contexto
Esta é minha evidência mais clara de tratar agentes de IA como uma força de trabalho que precisa de pensamento real de design de sistemas, não só uma forma mais rápida de digitar código. A engenharia interessante aqui não é "usei IA para remover algumas flags". É reconhecer que rodar vários agentes simultaneamente em uma base de código compartilhada é um problema de concorrência (agentes podem colidir no mesmo arquivo), que a saída de ferramentas genéricas é ruidosa em uma base de código grande e imperfeita (um typecheck bruto ou relatório de código morto afoga o sinal real), e que uma decisão específica nesse fluxo pode silenciosamente mudar o que vai para produção e portanto precisa continuar sendo uma decisão humana. Codificar as três coisas em uma ferramenta reutilizável, em vez de fazer a tarefa uma vez à mão e seguir em frente, é o tipo de alavancagem que escala além de qualquer limpeza única.
02
Problema
Feature flags e tours de produto antigos tinham se acumulado em um frontend compartilhado e dois serviços de backend, rastreados como 35 tarefas individuais de remoção em um épico. Os três serviços não compartilhavam uma convenção para onde o valor de uma flag realmente vive ou como o código a lê: o frontend mantém valores em arquivos de ambiente com vários padrões de código para lê-los (acesso direto, um helper tipado, e indireções de re-exportação local que tinham que ser rastreadas); um backend lê um serviço de ambiente tipado protegido por um decorator; o outro mantém seus valores de flag em um repositório de infraestrutura totalmente separado, implantado de forma independente do código de serviço que os lê.
Esse último ponto é a aresta mais afiada: remover o valor de uma flag do repositório de infraestrutura antes que a mudança de código correspondente tenha sido implantada pode silenciosamente desativar uma funcionalidade que ainda está ao vivo em produção, sem nenhum erro para pegar isso.
03Restrições
+
—Nenhuma regra mecânica única cobria os três repositórios. Cada um tinha uma convenção de armazenamento diferente e padrões de código diferentes para ler uma flag, então uma ferramenta que funcionasse para o formato de um repositório silenciosamente perderia casos em outro.
—O valor real de produção da flag decide o que é seguro automatizar. Uma flag que é `true` em produção significa que o caminho de código antigo está genuinamente morto e é seguro deletar automaticamente. Uma flag que é `false` pode significar uma funcionalidade que o time ainda pretende lançar, e colapsar essa distinção automaticamente arrisca deletar código que ninguém tinha abandonado.
—Paralelizar a remoção introduz um novo modo de falha. Vários agentes editando uma base de código grande e compartilhada ao mesmo tempo podem colidir no mesmo arquivo e corromper o trabalho um do outro se nada coordenar quem toca em quê.
—As checagens de segurança padrão são ruidosas nessa escala. Um monorepo com erros de typecheck pré-existentes e falsos positivos de código morto torna uma leitura absoluta de aprovação/reprovação inútil: ou esconde uma regressão real no ruído ou sinaliza fantasmas.
—O caso de dois repositórios tem um invariante de ordenação fácil de inverter sob pressão de tempo, e inverter isso tem uma consequência de produção, não só um build falho.
04
Decisão
Tratei os agentes paralelos como uma força de trabalho que precisava do mesmo design de segurança que qualquer sistema concorrente, e tratei a única decisão que afeta produção como algo que a ferramenta deveria expor, não resolver sozinha.
—Codifiquei explicitamente as convenções reais de armazenamento e leitura de cada repositório, para que a classificação fosse determinística por repositório em vez de re-derivada à mão a cada vez.
—Fiz o valor real de produção da flag conduzir a decisão. `true` em produção embute como `true` e deleta o caminho morto automaticamente; `false` em produção para e pergunta, recomendando o padrão seguro (manter o comportamento de produção) em vez de adivinhar silenciosamente, porque esse ramo específico pode mudar o que vai para produção.
—Agrupei agentes por conjuntos de arquivos disjuntos, computados a partir da sobreposição entre os arquivos que cada flag toca, para que agentes designados ao mesmo lote nunca escrevam no mesmo arquivo; flags que compartilhavam um arquivo foram serializadas em vez de paralelizadas.
—Validei fazendo diff contra uma baseline pré-mudança, ou seja, contagens de erro de typecheck e um relatório de código morto rodados uma vez no código não modificado e uma vez depois, em vez de ler a saída bruta de qualquer ferramenta, então só regressões que a remoção de fato introduziu aparecem.
—Tornei a ordem de deploy entre os dois repositórios uma etapa explícita e reforçada, não uma nota em uma página de wiki: a própria mudança do serviço vai para produção e é implantada primeiro; a mudança de infraestrutura que remove a variável agora não utilizada é marcada como dependente desse deploy e nunca autorizada a precedê-lo.
—Exigi um gate de confirmação explícito antes de fazer commit ou abrir um PR, com um checklist de telas ou endpoints afetados derivado dos arquivos de fato tocados, para uma pessoa verificar manualmente antes do merge.
05Trade-offs
+
—Batching por conjuntos de arquivos disjuntos em vez de paralelizar por padrão. Computar sobreposição de arquivos antes de designar trabalho custa uma etapa de planejamento, mas deixar agentes compartilharem um arquivo sem isso arrisca um merge silenciosamente quebrado, o que vale a etapa extra quando dezenas de tarefas rodam simultaneamente.
—Diff contra uma baseline em vez de confiar na saída bruta de uma ferramenta. Rodar cada checagem de segurança duas vezes custa tempo, mas uma leitura absoluta em uma base de código grande e imperfeita ou esconde uma regressão real no ruído pré-existente ou reporta fantasmas, e nenhuma das duas é utilizável.
—Perguntar antes de embutir uma flag que é `false` em produção, em vez de sempre deletar o caminho que nunca foi lançado. Uma etapa mais lenta e confirmada por humano aqui é o custo certo, porque automatizar isso errado significa matar silenciosamente uma funcionalidade que o time não tinha abandonado.
—Reforçar a ordem de deploy na ferramenta em vez de documentá-la e confiar nos revisores. Uma regra que só vive na memória de uma pessoa não sobrevive a turnover ou a um release apressado; codificá-la significa que não pode ser pulada por acidente.
06
Impacto
—Fechei um épico de limpeza de 35 tarefas abrangendo um frontend compartilhado e dois serviços de backend, removendo mais de 25 feature flags expiradas e infraestrutura obsoleta de tours de produto. Um único commit removeu sozinho cerca de 3.100 linhas de código morto.
—Produzi uma ferramenta reutilizável, não um script pontual: a mesma skill se aplica ao próximo épico de limpeza de flags em qualquer um dos três repositórios, codificando convenções que antes só existiam na memória.
—Removi os modos de falha que tornam esse tipo de limpeza perigoso à mão, ou seja, classificar mal uma flag, agentes colidindo em um arquivo compartilhado, ou inverter a ordem de deploy entre dois repositórios, desenhando-os para fora da ferramenta em vez de depender de quem a executa lembrar dos três sob pressão de tempo.
—Qualitativo: uma base de código mais simples e legível como resultado direto da remoção de código morto; nenhuma métrica isolada de antes/depois de tempo de build foi capturada só para esta mudança.
07Lições Aprendidas
+
Conhecimento de engenharia reutilizável que levo adiante disso:
—Agentes de IA paralelos precisam do mesmo design de segurança que qualquer outro worker concorrente. Isole o trabalho deles por ownership de arquivos disjuntos, ou eles vão corromper as mudanças uns dos outros exatamente como qualquer outra race condition.
—Valide contra uma baseline, não uma leitura absoluta, em qualquer base de código velha o suficiente para ter ruído pré-existente. Do contrário, o sinal que realmente importa fica enterrado ou afogado por falsos positivos.
—Codifique um invariante na ferramenta; não só o documente. Uma regra que depende de uma pessoa se lembrar dela sob pressão eventualmente será pulada; uma ferramenta que a reforça não pode ser.
—Automatize tudo exceto a única decisão que pode mudar silenciosamente o comportamento de produção. Esse único ramo merece uma pessoa, mesmo dentro de um pipeline por outro lado totalmente automatizado.
08Evidência
+
—Verificado contra o tracker: uma story carregando 36 subtarefas (27 delas atribuídas a mim) sob um épico de sanitização, abrangendo um frontend compartilhado e dois serviços de backend. Composição: 24 feature flags, 3 tours de produto expirados, e a remoção de uma página de dashboard legada, todas fechadas 2026-07-17 a 2026-07-23, incluindo um commit que removeu cerca de 3.100 linhas de código morto.
—Construí uma skill reutilizável de Claude Code codificando as regras de classificação, segurança paralela e validação para as convenções dos três repositórios.
—Parte de uma prática mais ampla e sustentada de construir ferramentas confiáveis sobre agentes de codificação com IA: um servidor MCP construído do zero expondo a API do SonarCloud para revisão de quality-gate dentro do mesmo fluxo, e outras ferramentas automatizando investigação de bug até correção entregue (com arqueologia de git/Jira e criação de PR), triagem de erros de produção escopada por time, e análise de latência pós-incidente.
—Fonte (privada): tracker de engenharia da Dynamox (épico e subtarefas do Jira) e repositório pessoal de ferramentas.