Projetado para extensibilidade: as decisões técnicas do DevStation
Hexagonal, DDD tático, CQRS, eventos internos e contratos JSON-RPC. Por que um conjunto que pode soar como overengineering virou a aposta central — e o que a evidência sobre IA e código complexo tem a dizer sobre isso.
Um CLI que toca infraestrutura real acumula responsabilidades depressa. O DevStation modela clusters, nodes, VMs, images, sizes, vault, provisionamento, stations e blueprints — e cada um desses carrega regras próprias. A lista de features que cabem num projeto assim é, na prática, ilimitada. Por isso a pergunta que orientou o design não foi “como entregar a feature de hoje”, e sim “como acomodar a próxima sem comprometer o que já existe”. O fio condutor é a extensibilidade.
Hexagonal: o domínio isolado do mundo
A arquitetura hexagonal — ports & adapters, proposta por Alistair Cockburn em 2005 — existe justamente para isolar a lógica de negócio da infraestrutura e permitir testá-la de forma independente. No DevStation, Proxmox, a TUI, o sistema de arquivos e o OpenTofu vivem na borda; o núcleo os enxerga apenas como ports. Testes de arquitetura validam essa fronteira a cada commit: o domínio não importa infraestrutura, e o lado de entrada nunca importa o de saída. O efeito prático é direto — adicionar um provider ou trocar a interface não toca a regra de negócio.
O desenho coincide com o que Herberto Graça catalogou como Explicit Architecture — a compilação dele de hexagonal, onion e clean num único mapa, a partir do que já se praticava: um App Core — Domain envolvido pela Application — com os ports como fronteira e todas as dependências apontando para dentro. A nomenclatura aqui é inbound (driving) e outbound (driven), no lugar de primário/secundário.
DDD tático + CQRS: contextos pequenos que crescem sem fricção
Os recursos são organizados em bounded contexts isolados — cluster, vault, station, service, images, size, blueprint, auth — cada um com seus agregados, comandos e eventos. Leitura e escrita são separadas seguindo CQRS. Como Martin Fowler descreve o padrão, trata-se de usar modelos distintos para ler e para escrever; convém a precisão de que CQRS não exige banco separado nem event sourcing. Aqui é CQRS de store único, em que as queries projetam registros direto, sem passar pelos agregados.
O retorno aparece na manutenção. Extrair images para um contexto próprio foi replicar um padrão, não inventar um. Renomear definition para size no stack inteiro foi mecânico porque a fronteira era explícita. E renomear deploy → install e destroy → uninstall de ponta a ponta — contrato, domínio, eventos, persistência e UI — permaneceu uma operação disciplinada, precisamente porque cada contexto sabe o que é seu.
Eventos internos entre contextos
O DevStation é um binário único, não um sistema distribuído. Ainda assim, os contextos se integram por eventos de domínio: uma policy reage a um evento de outro contexto e dispara um comando do próprio. O context map do projeto registra isso como regra — a comunicação cross-context não é direta. Quando uma station conclui uma instalação, o contexto de cluster registra a projeção dos serviços na VM e o vault guarda os secrets publicados, ambos por policy, sem acoplamento direto entre os contextos.
Num binário único, isso pode soar exagerado. A justificativa é de prazo: separar os contextos desde o início, com comunicação eventual, mantém a porta aberta para extrair um backend no futuro — um serviço compartilhado, um PaaS — sem reescrever regra. É barato fazer agora e caro fazer depois.
Contratos JSON-RPC: a interface é destacável
O engine expõe uma fronteira JSON-RPC sobre stdio, e os contratos (OpenRPC, com código gerado a partir deles) são o limite de verdade. A migração para essa fronteira foi deliberadamente incremental: um único contexto primeiro, sem caminho duplo, com revisão formal antes de expandir aos demais — porque erros de modelagem de envelope e de contrato são caros de reverter depois de espalhados. O resultado é que a TUI em React Ink é apenas um cliente. Outra TUI, um app desktop ou até uma web são, do ponto de vista do engine, o mesmo contrato com outra tela. O contrato é o que importa; a interface é detalhe.
Complexidade, IA e o papel do harness
Vale reconhecer o trade-off: estrutura tem custo, e ele ficou mensurável. A METR mediu desenvolvedores experientes 19% mais lentos usando IA em repositórios maduros que já dominavam, enquanto eles próprios estimavam estar 20% mais rápidos. Benchmarks recentes apontam na mesma direção: a taxa de resolução de agentes despenca quando a mudança atravessa muitos arquivos, e modelos degradam à medida que o contexto cresce. Daí uma crítica que ganhou força: cada camada é mais um arquivo para ler, cada indireção é mais um salto para rastrear, cada abstração sem propósito é ruído competindo por atenção. Humanos nunca pagaram por token para entender o código; agentes pagam.
A crítica acerta onde mira cerimônia. Interface com uma única implementação para sempre, use case que apenas organiza, mapper entre DTOs idênticos: se a resposta honesta para “que problema real essa camada resolve” é “organização”, o custo não se justifica — nem para pessoas, nem para modelos. Nenhum padrão do DevStation está isento dessa pergunta.
A divergência está na generalização. Aqui, cada camada responde à pergunta que abriu este artigo. Os ports existem porque o provider é substituível por decisão de design, e porque TUI e MCP já são dois clientes do mesmo contrato. Os bounded contexts existem porque o domínio acumula regras de verdade — e contexto bem delimitado é justamente o que reduz o escopo de arquivos que um agente precisa carregar para mexer em uma feature. Isso não é cerimônia; é otimização de contexto. Frameworks mentais e modelos de organização foram inventados para caber domínios complexos em cabeças humanas, e modelos treinados em código humano herdam o benefício. Num domínio com regras demais e possibilidades infinitas de extensão, convenção sistemática vence software ingênuo: é ela que transforma a próxima feature em replicar um padrão, não em redecidir tudo.
O que mudou a economia foi o harness somado à verificação. O gargalo que os estudos descrevem — contexto espalhado, padrões implícitos, fronteiras que só existem na cabeça do time — é o que um bom harness ataca: regras sempre carregadas, skills sob demanda e testes de arquitetura que quebram o build quando uma fronteira é violada. A evidência aponta na mesma direção: agentes melhoram quando a estrutura do repositório se torna explícita e verificável — grafos de dependência e specs de interface elevam taxas de resolução em bases multi-arquivo — enquanto arquivos de contexto genéricos, sozinhos, não ajudam. Manter a disciplina sempre foi a parte cara dessas arquiteturas. Com um agente que segue as regras por construção e uma suíte que acusa cada violação, a disciplina virou a parte barata; o que sobra é o retorno.
Extensibilidade, no DevStation, não é enfeite de arquitetura. É a decisão que torna tudo o que vem depois mais barato — e por isso veio primeiro.
Referências
- Explicit Architecture — Herberto Graça
- CQRS — Martin Fowler
- Produtividade de desenvolvedores experientes com IA em projetos maduros — METR (2025)
- SWE-Bench Pro: agentes em tarefas multi-arquivo de nível enterprise — Scale AI (2025)
- LongCodeBench: modelos de código em contextos de 1M tokens — arXiv (2025)
- RepoGraph: estrutura explícita do repositório melhora agentes — arXiv (2024)
- Avaliando AGENTS.md: arquivos de contexto genéricos ajudam agentes? — ETH Zürich (2026)
- Harness engineering — Birgitta Böckeler, martinfowler.com (2026)