stamatios
← Voltar ao feed
Cerca feita de chaves de código mantendo fileiras de pequenos robôs em suas faixas, metáfora do linter ArchSpec
Dev & Engenharia · Agentes

ArchSpec vira linter de arquitetura para código escrito por agentes

resumo de ~3 min

Carmine Paolino lançou o ArchSpec 1.0, um linter de arquitetura para Ruby e Rails. A premissa é que cada vez mais código é escrito por modelos: os testes dizem se ele funciona, o RuboCop diz se está organizado, mas nada diz se ele ainda segue a arquitetura. No ArchSpec, componentes e fronteiras são declarados em um único arquivo na raiz do projeto, e toda mudança é checada, escrita por pessoa ou por agente.

Análise estática, não IA

Apesar de o autor também ser autor do RubyLLM, o ArchSpec não usa IA. O Prism faz o parse do Ruby; a ferramenta extrai fatos, referências, herança, mixins, chamadas e definições, e avalia as regras contra eles. É determinístico, offline e, segundo o autor, rápido o bastante para ficar ligado: o Discourse, com 1.899 arquivos, foi checado em 2,5 segundos sem inicializar a aplicação. A única dependência de runtime é o Prism, sem Rails nem ActiveSupport, o que permite usá-lo em qualquer base Ruby. A ferramenta não tenta inferir o "verdadeiro" padrão de projeto do código: você descreve a arquitetura desejada e ela diz se o código corresponde. A IA fica do outro lado do ciclo, escrevendo o código que será verificado.

Regras, presets e diagnóstico

Regras declaradas podem proibir que models usem controllers, que código de domínio toque adaptadores ou que query objects chamem save!. Quem prefere não escrever regras parte de presets: architecture :vanilla_rails reproduz o playbook da 37signals - modelos ricos, sem service objects, form objects ou policy objects - e faz o build falhar se algo aparecer em app/services. Há presets para Rails, camadas, hexagonal, clean architecture, monólito modular, CQRS e orientado a eventos. Quando uma regra é quebrada, a saída mostra a localização exata, o trecho ofensor sublinhado, a evidência como nota e o id da regra entre colchetes, para supressão estreita - homenagem deliberada ao clang e ao Herb. Um humano entende de relance; um agente recebe arquivo, linha, regra e motivo para corrigir o erro sem perguntar.

O que pegou no RubyLLM

Os checks rodam no RubyLLM havia dois meses, em CI e como hook de pre-commit, e o autor os considera instrumentais na separação entre Protocol e Provider prevista para a versão 2.0. Protocolo é um formato de wire - Chat Completions, Responses, a API Messages da Anthropic, Gemini, Bedrock Converse; provider é uma conta com que se conversa, como OpenAI, Azure, DeepSeek ou Ollama. O DeepSeek fala Chat Completions; o VertexAI fala quatro desses formatos. A distinção é fácil de erodir, e a regra que proíbe providers de referenciarem RubyLLM::Protocol existe para impedir que um adaptador invente um formato de wire próprio - foi o que aconteceu, no desenvolvimento do RubyLLM 2.0, quando a API de áudio da ElevenLabs e a família de embeddings InvokeModel, da AWS, haviam se tornado formatos completos escondidos dentro de adaptadores; movê-los para fora também eliminou código que só existia para disfarçar o deslocamento. Outras regras exigem que famílias de protocolo implementem render_payload, completion_url e parse_completion_body, mantenham as convenções render_*/parse_*, garantam paridade entre setters Chat#with_x e macros de Agent e impeçam que o domínio referencie RubyLLM::ActiveRecord, para que require "ruby_llm" continue funcionando sem Rails.

Packwerk e adoção

O Packwerk é bom, diz o autor, e deve ser usado quando pacotes são o que se precisa; o ArchSpec cobre esse caso com o preset modular_monolith e vai além. O Packwerk checa referências de constantes entre pacotes, ignora chamadas de método por design e depende do Zeitwerk, o que o molda a uma aplicação Rails. O ArchSpec checa constantes, chamadas, herança, mixins, métodos exigidos, ciclos e convenções de nomeação, em um arquivo Ruby, em qualquer base Ruby. Para adotar, usa-se um preset ou pede-se a um agente de código que rascunhe o Archspec.rb - agentes são bons nisso, mas o spec é a parte que permanece sua. archspec check --update-todo registra violações existentes e deixa o build verde no código atual, falhando diante de novos desvios; daí o passo seguinte é pre-commit e CI.

Origem

A ideia nasceu na RubyConf Austria, em maio, em conversas em torno de um painel sobre IA, sobretudo com Chad Fowler e José Valim: se os modelos escrevem o código, o trabalho humano se concentra nas decisões acima do código. A versão 0.1 saiu discretamente em junho e desde então roda em todo commit do próprio ArchSpec, do RubyLLM e de outros projetos Ruby do autor. Cada release é testada contra checkouts fixados do Discourse, do Mastodon e do Fizzy, da Basecamp.