top of page

Migração do Runtime do GitHub Copilot para Rust: Agentes Tornaram a Reescrita Viável

há 6 dias
15 min de leitura

O GitHub concluiu uma migração do runtime do GitHub Copilot para Rust que abrangeu cerca de 830.000 linhas de produção — uma reescrita que, segundo a empresa, os agentes tornaram economicamente viável. O projeto substituiu a implementação em TypeScript do runtime enquanto o próprio Copilot ajudava a gerar, revisar, testar e corrigir o novo código.

Não se tratava de uma demonstração construída em torno de uma biblioteca isolada. O runtime coordena modelos, ferramentas, sessões, extensões e aplicações hospedeiras em um produto de programação em produção. O GitHub continuou lançando versões públicas da CLI enquanto os engenheiros alteravam a infraestrutura que a sustenta.

O conflito mais relevante não é Rust versus TypeScript. É a velocidade do código gerado por agentes versus o trabalho de verificação humana necessário para manter uma grande migração comportamentalmente correta. Os resultados do GitHub sugerem que agentes podem comprimir o tempo de implementação, mas não eliminam a responsabilidade de engenharia.

O projeto ocorreu de 12 de maio a 21 de agosto, segundo o relato detalhado do GitHub sobre a migração do runtime. Nesse período, a equipe integrou 128 pull requests de portabilidade e lançou 135 versões públicas da CLI.

Essa sequência importa porque desafia uma suposição comum sobre reescritas. Grandes reescritas normalmente exigem um longo congelamento de funcionalidades, uma substituição separada ou anos de migração incremental. O GitHub, em vez disso, alterou a implementação enquanto mantinha o produto em movimento.

O resultado oferece a líderes de engenharia um raro teste em escala de produção do desenvolvimento de software assistido por IA. Também traz um alerta: a geração de código foi apenas uma parte do trabalho e, com frequência, não a mais difícil.

O Que a Migração do Runtime do GitHub Copilot para Rust Mudou

O GitHub substituiu um runtime em produção sem tratar a reescrita como um projeto separado e oculto, que só apareceria após sua conclusão.

A arquitetura anterior colocava uma fronteira de processo entre os kits de desenvolvimento de software e a CLI do Copilot. Uma fronteira de processo exige que componentes se comuniquem entre processos distintos do sistema operacional, normalmente por meio de mensagens serializadas e gerenciamento de ciclo de vida.

O novo design oferece suporte à hospedagem dentro e fora do processo. A hospedagem dentro do processo coloca o runtime na aplicação chamadora, evitando parte dos custos de inicialização, comunicação e memória associados a um processo separado.

Essa mudança arquitetural ampliou o escopo do projeto para além da tradução de sintaxe. A equipe precisou preservar o comportamento observável do runtime enquanto alterava propriedade, concorrência, tratamento de erros, gerenciamento de estado e fronteiras de integração.

O histórico final de código do GitHub mostrou aproximadamente 830.000 linhas de Rust em produção e 469.000 linhas de testes unitários em Rust. A implementação em TypeScript caiu a zero ao fim do projeto.

Esses números exigem contexto. Linhas de código não medem qualidade, dificuldade ou produtividade de desenvolvedores de forma consistente. Código gerado pode ser verboso, e testes podem incluir fixtures, auxiliares ou casos expandidos mecanicamente.

Ainda assim, os números estabelecem a escala da migração. Não foi uma conversão de fim de semana de um utilitário de linha de comando. Envolveu um runtime com múltiplos hosts, comportamento de extensões, orquestração de modelos, sessões persistentes, integrações específicas de plataforma e bibliotecas externas.

O GitHub usou uma camada temporária de interoperabilidade durante a transição. A interoperabilidade permite que código escrito em linguagens diferentes se comunique por uma interface definida enquanto as duas implementações permanecem ativas.

O projeto expôs funções Rust por meio do N-API, a interface estável usada por módulos nativos em aplicações Node.js. Assim, chamadores em TypeScript podiam invocar componentes recém-portados para Rust antes que toda a cadeia de dependências tivesse migrado.

A superfície temporária cresceu à medida que os engenheiros introduziam implementações Rust sob os chamadores TypeScript existentes. Mais tarde, ela encolheu quando esses chamadores migraram para Rust e deixaram de precisar da ponte.

Essa ascensão e queda é importante. A interoperabilidade permanente pode se tornar uma arquitetura própria, com custos de serialização, tipos duplicados e regras complexas de propriedade. O GitHub tratou a ponte como andaime, e não como destino.

A portabilidade também avançou de fundações menores para componentes maiores de orquestração e sessões. Essa ordem deu aos agentes e engenheiros interfaces Rust estabelecidas antes de lidarem com código de alcance comportamental mais amplo.

Enquanto isso, a equipe lançou 135 versões públicas da CLI durante a janela de migração. Esse número superou os 128 pull requests de portabilidade, mostrando que a entrega normal do produto continuou ao lado da reescrita.

O resultado muda a aparência de uma reescrita viável. Em vez de financiar uma equipe paralela para uma substituição prolongada, uma organização pode usar agentes para acelerar unidades delimitadas de migração.

Ainda assim, essa possibilidade depende de testes, interfaces estáveis e revisores que entendam o comportamento original. Sem esses controles, uma tradução rápida pode simplesmente produzir software incorreto mais depressa.

Por Que os Agentes Tornaram uma Reescrita de 800.000 Linhas Viável

A mudança econômica veio da implementação paralela e do contexto persistente, não de um agente decidindo de forma independente como o runtime deveria funcionar.

Reescritas tradicionais enfrentam uma curva de custo severa. Engenheiros precisam ler o código existente, reconstruir contratos não documentados, projetar interfaces substitutas, implementá-las e comparar o resultado com o comportamento em produção.

Cada etapa compete com o desenvolvimento de funcionalidades e a resposta a incidentes. Quanto mais a reescrita dura, mais o produto original muda, criando um alvo móvel para a equipe de substituição.

Agentes de programação reduzem parte dessa carga de leitura e implementação. Eles podem rastrear referências, elaborar módulos equivalentes, gerar testes, executar comandos de compilação e revisar código após falhas.

O trabalho do GitHub mostra como essa assistência vai além do preenchimento automático. Os agentes operaram em sessões de longa duração e delegaram subtarefas a agentes filhos, criando fluxos de trabalho paralelos em torno de um objetivo compartilhado de migração.

Uma sessão que portou session.ts durou 25 horas. Ela utilizou cinco subagentes e criou 15 sessões filhas em sete ondas de trabalho.

Outra sessão concentrou-se na orquestração de modelos por 42 horas e envolveu 126 subagentes. A linha do tempo do GitHub indica que a maior parte do código apareceu nas primeiras 12 horas, seguida de validação e revisão extensivas.

Esse padrão revela um mecanismo central. Agentes podem produzir uma primeira implementação rapidamente, mas a confiança se acumula muito mais lentamente por meio de compilação, testes, comparação e inspeção humana.

Uma portabilidade separada do runtime de extensões durou 88 horas. Leitura, escrita, compilação e revisão permaneceram intercaladas durante grande parte dessa sessão, em vez de formar fases sequenciais bem definidas.

A diferença importa porque nem todo componente comporta o mesmo fluxo de trabalho. Um módulo relativamente autocontido pode passar da geração à validação. Um runtime com muitas fronteiras exige ciclos repetidos à medida que novas interações se tornam visíveis.

O cache de prompts também moldou a economia. Entre as sessões de portabilidade, 96,22% da entrada de prompts veio de leituras em cache. Escritas em cache representaram 3,07%, enquanto entrada nova representou 0,71%.

Um cache de prompts reutiliza contexto de modelo já processado, reduzindo a necessidade de recalcular instruções repetidas e materiais do repositório. Ele pode tornar sessões longas mais baratas e rápidas quando grande parte do contexto permanece estável.

Essas porcentagens não estabelecem o custo financeiro total do projeto. O GitHub não publicou uma comparação convencional de trabalho entre uma portabilidade assistida por agentes e uma reescrita totalmente manual.

Elas mostram que o fluxo de trabalho dependia da reutilização de contexto. Alimentar repetidamente um grande repositório, instruções de design e descobertas acumuladas como entrada nova criaria um perfil de custo diferente.

É aqui que a migração do runtime do GitHub Copilot para Rust se torna mais do que uma história sobre linguagens. O projeto testou se agentes conseguem continuar trabalhando em um grafo de dependências sem perder as decisões estabelecidas por tarefas anteriores.

Essa exigência se assemelha à gestão de conhecimento em qualquer grande organização de engenharia. Restrições importantes estão distribuídas entre código, testes, discussões de issues, notas de arquitetura e feedback de revisores.

Equipes que tentam projetos semelhantes precisam de uma base de conhecimento de engenharia confiável. Agentes não podem aplicar um contrato que não conseguem recuperar, e pressupostos não documentados continuam perigosos independentemente da qualidade do modelo.

A migração, portanto, altera a equação de viabilidade sem tornar reescritas baratas por padrão. Agentes reduzem o custo marginal de leitura e elaboração, enquanto as organizações ainda financiam validação, coordenação e risco operacional.

A Verdadeira Disputa É entre Velocidade de Geração e Capacidade de Revisão

Os próprios dados de interação do GitHub mostram que a atenção humana passou a se concentrar em verificar, questionar e concluir o trabalho dos agentes.

O GitHub analisou 2.639 mensagens escritas por humanos durante a migração. Dessas mensagens, 31% tratavam de revisão, testes ou integração contínua.

Outros 17,4% questionavam decisões técnicas ou de design. Mais 15% direcionavam o agente para a completude, frequentemente identificando trabalho que uma primeira passagem havia deixado de fora.

Juntas, essas categorias descrevem uma mudança de papel. Engenheiros gastaram menos tempo digitando cada linha de implementação e mais tempo especificando padrões, inspecionando resultados e orientando a recuperação.

Isso não significa que a contribuição humana tenha se tornado menor. O trabalho de revisão pode exigir concentração mais profunda do que escrever um módulo conhecido, porque revisores precisam detectar diferenças comportamentais sutis em código gerado e pouco familiar.

As cinco categorias de regressão identificadas pelo GitHub ilustram essa carga. Elas incluíram migração incompleta, erros de estado e tempo de vida, incompatibilidades de contratos comportamentais, problemas nas fronteiras de hosts e oráculos de teste incorretos.

Migração incompleta ocorre quando a nova implementação omite um caminho, opção ou efeito colateral presente na original. Um agente pode produzir código que compila enquanto deixa para trás um comportamento raramente utilizado.

Falhas de estado e tempo de vida são especialmente relevantes em Rust. Rust codifica regras de propriedade e empréstimo em tempo de compilação, mas um programa ainda pode modelar incorretamente o estado da aplicação.

Um compilador pode rejeitar acesso inseguro à memória sem saber que uma sessão deve permanecer disponível após um evento específico. Segurança de tipos e correção do produto se sobrepõem, mas não são idênticas.

Incompatibilidades de contratos comportamentais surgem quando duas implementações aceitam as mesmas entradas, mas diferem em tempo, ordem, texto de erro, tentativas ou limpeza. Software downstream pode depender desses detalhes mesmo quando nenhuma especificação formal os registra.

As fronteiras de hosts acrescentam outra camada. O runtime precisa se comportar corretamente quando incorporado a aplicações diferentes ou executado como um processo separado. Manipulação de ambiente, cancelamento, acesso a arquivos e encerramento de processos podem variar entre hosts.

Oráculos de teste incorretos criam a falha mais enganosa. Um oráculo de teste define o resultado esperado usado para julgar uma implementação. Se um agente gerar tanto o código quanto uma expectativa equivocada, todos os testes podem passar enquanto preservam o comportamento errado.

É por isso que testes gerados a partir da mesma interpretação não conseguem oferecer confirmação independente. As equipes precisam de rastros de produção, fixtures existentes, invariantes especificadas manualmente e comparações com a implementação anterior.

O código Rust do GitHub continha 158 blocos unsafe. Em Rust, unsafe permite operações específicas que o compilador não consegue verificar completamente, como chamar funções externas ou desreferenciar ponteiros brutos.

O GitHub afirma que todos os 158 blocos surgiram em limites externos. Eles incluíam interfaces C, APIs do Windows, chamadas a POSIX e libc, SQLite, carregamento de bibliotecas dinâmicas e alteração do ambiente de processos.

Essa concentração condiz com o modelo de segurança pretendido pelo Rust. A linguagem incentiva desenvolvedores a isolar operações não verificáveis por trás de interfaces pequenas, mantendo o programa maior sob regras verificadas pelo compilador.

A orientação relevante sobre unsafe Rust também faz uma distinção crucial. unsafe flexibiliza determinadas verificações do compilador, mas não suspende a responsabilidade do programador de cumprir requisitos de segurança.

Para revisores, isso significa que código inseguro merece inspeção concentrada. Agentes podem gerar bindings e wrappers, mas um wrapper plausível ainda pode usar o tempo de vida, o tamanho de buffer, a convenção de chamada ou a regra de sincronização errados.

O gargalo de revisão também afeta o planejamento organizacional. Adicionar mais agentes aumenta rapidamente a capacidade de produção de código. Isso não cria automaticamente mais engenheiros que entendam o runtime o bastante para aprovar mudanças.

Esse desequilíbrio pode inundar uma equipe com trabalho aparentemente concluído. Pull requests esperam mais tempo, revisores alternam contextos com maior frequência e inconsistências sutis se acumulam entre branches paralelas.

O GitHub parece ter administrado essa pressão com componentes delimitados, builds repetidos, especialização de subagentes e integração contínua. As mensagens humanas mostram intervenção ativa, não aceitação passiva.

O principal adversário, portanto, não é outro assistente de programação. É a velha suposição de que o throughput de implementação determina a velocidade do projeto.

Em migrações conduzidas por agentes, a capacidade de revisão confiável se torna o recurso limitante. Equipes que ignorarem essa mudança correm o risco de medir o código gerado enquanto deixam de perceber a produção mais lenta de confiança justificada.

Ganhos de Desempenho Não Resolvem a Questão da Correção

O novo runtime tornou-se dramaticamente mais rápido nos testes do GitHub, mas desempenho não pode provar equivalência comportamental nem generalizar o fluxo de trabalho para todas as bases de código.

De 12 de maio a 21 de agosto, o ciclo de vida medido de cliente e sessão mudou substancialmente. Criar um cliente, iniciar uma sessão, concluir um turno e encerrar tudo caiu de 5,25 segundos para 55,3 milissegundos no processo.

Essa comparação representa uma redução de quase 95 vezes na duração medida. O throughput aumentou de 7,55 para 120 sessões por segundo, ou quase 16 vezes a taxa anterior.

A mudança arquitetural explica parte da diferença. Um runtime no processo evita iniciar e coordenar um processo CLI separado para cada interação.

Rust também oferece aos desenvolvedores controle sobre alocação, layout de dados e concorrência sem um runtime com coleta de lixo. No entanto, as medições publicadas combinam mudanças de linguagem, arquitetura, implementação e otimizações acumuladas.

Portanto, seria enganoso afirmar que substituir TypeScript por Rust, por si só, produziu todo o ganho. Remover uma fronteira de processo pode transformar a latência independentemente da linguagem de implementação.

O benchmark também reflete a carga de trabalho e o ambiente escolhidos pelo GitHub. Leitores não devem converter diretamente essas proporções em melhorias esperadas para aplicações não relacionadas.

Ainda assim, a magnitude traz implicações práticas. Menor latência de inicialização de sessão pode fazer recursos de agentes incorporados parecerem responsivos em editores, terminais e automações em segundo plano.

Maior throughput de sessões pode suportar mais tarefas simultâneas por host. Também pode reduzir a infraestrutura necessária para cargas de trabalho que criam e destroem repetidamente sessões de curta duração.

Esses benefícios explicam por que a reescrita teve valor estratégico além da manutenção de código. O GitHub não estava apenas mudando uma preferência de linguagem. Estava alterando a facilidade com que o runtime poderia viver dentro de outros produtos.

O ceticismo começa pela independência das evidências. Os dados de migração, a taxonomia de regressões, a análise de interações e os benchmarks vêm todos do relato do próprio GitHub.

O GitHub forneceu medições incomumente detalhadas, mas pesquisadores externos não reproduziram a migração completa. O contexto do repositório, os testes internos, a experiência da equipe, o acesso a modelos e as ferramentas operacionais moldaram o resultado.

O projeto também envolveu a equipe responsável tanto pelo runtime original quanto por sua substituição. Isso dá aos revisores conhecimento valioso, mas torna o exercício diferente de uma equipe externa modernizando um sistema legado desconhecido.

Um runtime maduro pode ter cobertura de testes mais forte e limites de módulos mais claros do que muitas aplicações corporativas. Por outro lado, seus hosts multiplataforma e o comportamento dos agentes podem torná-lo mais complicado de outras formas.

As 469.000 linhas de testes unitários são, portanto, encorajadoras, mas inconclusivas. A quantidade de testes não pode demonstrar se comportamentos importantes de produção continuam sem teste.

As cinco classes conhecidas de regressões demonstram que o sucesso do compilador não foi suficiente. Nem mesmo as garantias de memória do Rust puderam identificar comportamentos ausentes, expectativas equivocadas ou contratos de produto incorretos.

Os modelos de agentes também mudam rapidamente. O GitHub usou uma combinação de modelos em sessões principais e subagentes, incluindo sistemas diferentes de alta capacidade e menor latência.

Essa diversidade torna o fluxo de trabalho resiliente às limitações de um único modelo, mas complica a replicação. Uma equipe futura pode receber resultados diferentes mesmo com prompts e estado do repositório semelhantes.

A segurança merece cautela equivalente. Código gerado pode reproduzir padrões vulneráveis do código ao redor ou introduzir suposições inseguras em pontos de integração.

Rust reduz diversos riscos de segurança de memória, mas não consegue validar lógica de autorização, tratamento de segredos, construção de comandos ou a confiabilidade de entradas externas. Revisores precisam examinar essas propriedades diretamente.

Agentes de longa duração criam outra preocupação operacional. Uma sessão que dura 25, 42 ou 88 horas precisa de limites de recursos, logs observáveis, checkpoints recuperáveis e fronteiras claras de autoridade.

Sem esses controles, um agente pode consumir computação substancial, repetir abordagens fracassadas ou ampliar uma tarefa além de seu escopo pretendido. Subagentes paralelos multiplicam tanto o trabalho útil quanto o risco de coordenação.

O resultado do GitHub sustenta uma conclusão cautelosa. Grandes reescritas assistidas por agentes passaram de demonstrações especulativas para engenharia de produção crível.

Ele não sustenta a afirmação de que qualquer organização pode entregar um sistema legado a um agente e receber uma substituição Rust confiável. O ingrediente ausente não é outro prompt. É um sistema de evidências para validar o comportamento.

O Que a Reescrita em Rust do GitHub Copilot Coloca Sob Pressão

A migração pressiona equipes de software a redesenhar o desenvolvimento em torno de evidências de revisão, em vez de tratar agentes como programadores individuais mais rápidos.

A primeira pressão recai sobre gestores de engenharia que planejam trabalhos de modernização. Projetos antes rejeitados como caros demais agora merecem uma nova estimativa, especialmente quando podem ser divididos em componentes verificáveis.

Isso não significa que toda reescrita deva avançar. A manutenção incremental pode continuar mais segura quando o comportamento é pouco compreendido, as dependências são instáveis ou a substituição não oferece ganho operacional mensurável.

A diferença é que o custo de implementação já não domina a estimativa da mesma forma. Gestores precisam modelar qualidade dos testes, disponibilidade de revisores, limites da migração, opções de rollback e comparação em produção.

A segunda pressão recai sobre fornecedores de assistentes de programação. Gerar uma função ou explicar um arquivo já não é o benchmark mais exigente.

Clientes de produção perguntarão cada vez mais se os agentes conseguem manter contexto ao longo de semanas, coordenar tarefas paralelas, preservar contratos e fornecer evidências para cada mudança.

Também esperarão que os agentes se recuperem de falhas. Um agente de migração útil precisa ler a saída de builds, isolar regressões, revisar sua abordagem e saber quando é necessária uma decisão humana.

A terceira pressão recai sobre equipes de linguagens e plataformas. Rust ganhou uma referência de produção de destaque, mas a lição mais profunda diz respeito às ferramentas de migração.

Interfaces estáveis de função externa, bindings automatizados, modelos de dados compatíveis e pontes temporárias permitem que equipes avancem por fatias de dependência. Sem esses mecanismos, os agentes enfrentam mudanças maiores e de tudo ou nada.

A especificação oficial da N-API ilustra por que uma fronteira nativa estável importa. Ela separa módulos nativos de muitas mudanças internas no mecanismo JavaScript.

Para o GitHub, essa fronteira permitiu que componentes Rust atendessem chamadores TypeScript durante a transição. A abordagem reduziu a necessidade de portar todos os chamadores e dependências simultaneamente.

A quarta pressão recai sobre organizações que contam produção em vez de resultados. Linhas geradas, prompts enviados ou horas de agentes consumidas dizem pouco sobre valor em produção.

Os indicadores mais fortes do GitHub foram comportamentais e operacionais. O runtime chegou a zero TypeScript, continuou sendo lançado publicamente, reduziu a latência medida, aumentou o throughput e revelou padrões conhecidos de regressão.

Relatórios futuros devem ir além. Devem incluir defeitos que chegaram à produção, frequência de rollbacks, horas de revisão, taxas de incidentes e consumo total de computação.

Três sinais determinarão se este projeto se torna um modelo repetível.

O primeiro é a confiabilidade em produção após a migração. Lançamentos estáveis, baixas taxas de regressão e menos incidentes de runtime fortaleceriam o argumento de que portas rápidas conduzidas por agentes podem preservar comportamento maduro.

Um padrão de correções emergenciais enfraqueceria esse argumento, mesmo que Rust melhorasse o desempenho. A questão crítica não é se os testes passaram antes do merge, mas se os usuários vivenciam comportamento equivalente ou melhor.

O segundo sinal é a replicação por equipes fora do GitHub. Organizações independentes precisam documentar migrações de escala, cronogramas, métodos de verificação e resultados operacionais comparáveis.

Histórias de sucesso menores ajudarão, mas uma comparação convincente exige sistemas de produção complexos. Idealmente, esses sistemas terão arquiteturas diferentes e acesso menos direto aos autores originais.

O terceiro sinal é a própria transformação do fluxo de trabalho em produto pelo GitHub. Orquestração reutilizável, planejamento de migração, gates de revisão e resumos de evidências mostrariam que o método se estende além de um projeto interno.

O GitHub já oferece fluxos de trabalho do Copilot coding agent para desenvolvimento delegado. O próximo passo é provar que a coordenação em escala de repositório pode se tornar confiável para equipes de engenharia comuns.

Esses sinais deveriam importar mais aos desenvolvedores do que alegações sobre programação autônoma. Os dados de mensagens humanas da migração mostram que a especialização permaneceu central, mas sua aplicação mudou.

Engenheiros precisam cada vez mais definir invariantes, inspecionar fronteiras, comparar comportamentos e organizar contexto técnico durável. A velocidade de digitação importa menos quando agentes conseguem redigir milhares de linhas.

Compradores empresariais devem fazer perguntas igualmente concretas. Quais ações exigem aprovação? Como o sistema preserva o contexto? Revisores podem rastrear mudanças geradas até testes e requisitos declarados?

Também devem perguntar como o fluxo de trabalho lida com trabalho inacabado. Um runtime parcialmente migrado pode criar implementações duplicadas, pontes temporárias e propriedade confusa, a menos que o sistema acompanhe cuidadosamente as dependências.

Para os trabalhadores do conhecimento, o padrão mais amplo vai além do software. Os agentes tornam a produção inicial mais barata, enquanto a verificação e o contexto se tornam mais valiosos.

Uma equipe pode usar um sistema pessoal de conhecimento para preservar decisões e evidências ao longo de projetos extensos. Esse registro se torna essencial quando as máquinas produzem trabalho mais rapidamente do que as pessoas conseguem reconsiderar suas premissas.

A migração do runtime do GitHub Copilot para Rust é convincente porque expõe as duas metades dessa transição. Os agentes mudaram a escala da implementação acessível, enquanto os humanos assumiram o ônus do julgamento.

Acompanhe a confiabilidade das próximas versões do Copilot, migrações independentes e as ferramentas de fluxo de trabalho do GitHub. Se os três fatores se mantiverem, este projeto parecerá um modelo de engenharia, e não um caso interno excepcional.

A pergunta para as equipes agora é prática: qual reescrita adiada tem testes suficientes, valor mensurável e capacidade de revisão para justificar um teste controlado com assistência de agentes?

 
 

Comece grátis

Um assistente de IA local-first com gestão de conhecimento pessoal

Para oferecer uma experiência de IA melhor,

atualmente, o remio é compatível apenas com Windows 10+ (x64) e M-Chip Macs.

Seu parceiro de IA no trabalho
Faça mais com o remio

Planeje. Crie. Entregue.
Tudo em um só lugar.

bottom of page