Codebase Copilot
Pergunte qualquer coisa sobre um repositório e receba uma resposta em que cada afirmação aponta para o arquivo e as linhas de onde saiu.
- Java 25
- Spring Boot 4.1
- PostgreSQL 17 + pgvector
- React 19
- TypeScript
- Vite
- TanStack Query
- Radix UI
- OpenAI SDK
Contexto e problema
Entrar num projeto desconhecido significa descobrir onde estão as regras de negócio, como um fluxo atravessa as camadas e quais módulos fazem o quê. Perguntar a um modelo de linguagem sem contexto controlado produz respostas convincentes, mas sem como conferir.
O Codebase Copilot indexa o repositório na máquina de quem usa, recupera os trechos relevantes para cada pergunta e só aceita uma resposta cujas citações apontem para trechos que o modelo de fato recebeu. Toda afirmação pode ser conferida no código com um clique. Quando não há evidência suficiente, a ferramenta diz que não sabe.
Por que RAG
Um modelo de linguagem responde com o que aprendeu no treino. Ele nunca viu o seu repositório, então qualquer resposta sobre ele é um palpite bem escrito.
RAG (Retrieval-Augmented Generation, ou Geração Aumentada por Recuperação) muda a pergunta que o modelo responde. Em vez de "o que você sabe sobre este código?", passa a ser "com base nestes trechos, o que dá para afirmar?". A cada pergunta, o sistema:
- recupera os trechos do repositório mais relevantes;
- entrega esses trechos ao modelo, numerados como evidências;
- exige que cada afirmação cite a evidência de onde saiu.
É a diferença entre uma prova de memória e uma prova com consulta em que cada resposta precisa indicar a página do livro. O modelo continua escrevendo o texto, mas a base de verdade passa a ser o próprio código. Neste projeto, cada etapa (indexação, recuperação, montagem do contexto e validação das citações) é implementada de forma explícita, testada e medida.
Arquitetura
A primeira linha acontece uma vez por versão do repositório. A segunda, a cada pergunta.
- Importar: a aplicação lê apenas pastas dentro das raízes autorizadas, ou extrai um ZIP com limites contra zip bombs e path traversal.
- Pré-análise: mostra antes de indexar o que entra, as linguagens, o tamanho e o que foi excluído (dependências, artefatos gerados,
.env, chaves e binários). - Indexação: os arquivos viram chunks com caminho e linhas, termos de identificador e vetores, guardados num snapshot imutável. Reindexar sem mudanças não reprocessa nada.
- Busca híbrida: três canais. O lexical usa um tokenizador de identificadores (
getUserById→get user by id). O vetorial usa pgvector. O de caminhos encontra arquivos citados pelo nome. - Fusão e contexto: os rankings são combinados por Reciprocal Rank Fusion (k = 60) e os trechos escolhidos entram num orçamento de tokens, com os rótulos
E1…En. - Validação de citações: o modelo responde num formato estruturado estrito, e cada citação é conferida contra as evidências e as linhas que ele recebeu antes de chegar à tela.
O backend é um monólito modular em Java 25 e Spring Boot 4.1, com módulos de workspace, importação, indexação, recuperação, respostas, provedores e histórico. O frontend é React 19 com Vite e TypeScript, e os tipos da API são gerados do contrato OpenAPI.
Decisões técnicas e trade-offs
Monólito modular, não microsserviços
Menos complexidade operacional para um produto que roda na máquina de quem usa. A separação em módulos e portas internas permite extrair um worker no futuro, se as medições mostrarem necessidade. A indexação usa uma fila em tabela com SKIP LOCKED, heartbeat e limite de tentativas: um job interrompido é retomado e chega ao mesmo resultado de uma execução sem falha.
Provedores substituíveis
Embeddings e geração ficam atrás de portas internas (EmbeddingProvider, GenerationProvider). O SDK oficial openai-java só existe dentro do módulo de provedores, e um teste de arquitetura (ArchUnit) garante que os tipos dele não vazam. O Spring AI chegou a ser usado e saiu: o modelo de chat dele confundia tokens ausentes com zero e podia registrar o prompt em log.
Local-first
Com os provedores desligados (none, o padrão), nada sai do computador. Com um provedor remoto, só vão os trechos selecionados como evidência e o texto das perguntas, nunca arquivos excluídos.
Orçamento de tokens
O contexto é montado na ordem da fusão: até 8 evidências por padrão, até 3 trechos por conteúdo, sem sobrepor linhas já escolhidas e dentro de 6.000 tokens estimados no prompt final. Um trecho que não cabe é pulado e os seguintes ainda são tentados. Não há reranking: ele só entra se a avaliação mostrar que compensa o custo e a latência.
SQL explícito na recuperação
Spring Data JDBC para agregados pequenos e JdbcClient com SQL explícito para indexação e busca, sem JPA. O ranking híbrido precisa ser observável e testável, e abstrações genéricas esconderiam esse comportamento.
Segurança e privacidade
O repositório importado é tratado como conteúdo não confiável: pode ter segredos, código malicioso, instruções de prompt injection, arquivos gigantes ou caminhos malformados.
- Nenhum código importado é executado, em nenhuma etapa. O importador lê texto e não roda scripts, ferramentas de build nem hooks.
- Leitura restrita: caminhos são canonicalizados e validados dentro da raiz, links simbólicos não são seguidos e há limites de quantidade, profundidade e tamanho. ZIPs são verificados contra path traversal, caminhos absolutos e expansão excessiva, contando os bytes realmente gravados.
- Segredos: arquivos sensíveis são excluídos pelo nome, em regras que não podem ser desativadas, e por conteúdo (blocos de chave privada e chaves de formatos publicados), antes de qualquer chunk, embedding ou envio.
- Prompt injection: cada evidência vai num bloco delimitado por um nonce aleatório de 128 bits por pedido, então um arquivo não consegue fechar o próprio bloco. A geração não tem ferramentas, a saída é JSON estrito e o backend decide o status final.
- API restrita à própria máquina: o backend escuta em
127.0.0.1, recusa outros hosts e origens e envia Content Security Policy estrita. - Logs sem conteúdo: chaves de API, código e prompts não aparecem em logs nem em mensagens de erro.
Como medi a qualidade
A avaliação existe antes de qualquer otimização de prompt ou troca de modelo. O corpus tem 80 perguntas sobre quatro repositórios (uma fixture sintética, o próprio Codebase Copilot, pallets/click e honojs/hono), metade em português e metade em inglês. Catorze exigem abstenção, e outras catorze testam injeção de instruções ou vazamento de segredos.
Harnesses próprios medem:
- Recuperação: Recall@k, MRR@10, Precision@10 e cobertura de arquivos em perguntas que atravessam módulos.
- Respostas: validade das citações, respostas sustentadas por ao menos uma citação válida, abstenção correta e indevida, e vazamento de texto proibido.
- Operação: tokens, custo estimado e latência média e p95.
O primeiro baseline publicado é o do canal lexical, em 66 perguntas com intervalo esperado. Ele virou piso de não regressão: nenhuma mudança é promovida se o resultado cair abaixo dele.
| Canal | Perguntas | Recall@10 | MRR@10 |
|---|---|---|---|
| Lexical (todos os corpora) | 66 | 0,492 | 0,291 |
As metas de desempenho, medidas com provedores simulados, foram atendidas:
| Meta | Medido |
|---|---|
| Busca híbrida p95 ≤ 1 s com 50 mil chunks | 676 ms com cerca de 46 mil chunks |
| Pergunta sem o tempo do provedor ≤ 1 s com 50 mil chunks | 620 ms |
| Reindexação sem mudanças < 10% da completa | 3,1 s contra 41–45 s (7–8%) |
A comparação dos canais vetorial e híbrido e a avaliação das respostas com o modelo real ainda não rodaram. Elas saem do mesmo harness, sem código novo. Até lá, duas garantias valem por construção e por teste: nenhuma citação inválida é aceita em silêncio, e nenhum conteúdo excluído é enviado ao provedor.
Telas
Resposta com evidências — Citações validadas, ranks da busca e o trecho no código. Visão geral do projeto — Snapshot ativo, linguagens, indexações e perguntas. Arquivos — A árvore do snapshot exatamente como foi indexada. Histórico — Conversas guardadas para retomar e auditar.
Próximos passos
- Rodar a avaliação dos canais vetorial e híbrido e das respostas com o modelo real, seguida de auditoria humana, e definir as metas a partir dessa medição.
- Adaptadores de análise estrutural (AST) para as linguagens prioritárias.
- Comparação entre snapshots.
- Exportação de um mapa arquitetural.
- Provedor local de modelos.
Links
- Repositório no GitHub (abre em nova aba)
- Documentação técnica (abre em nova aba): PRD, arquitetura, pipeline RAG, segurança, avaliação e o registro de decisões.