
Construindo coldstart: o que quebrou, o que funcionou
Esta é a versão longa. Se você quiser o resumo curto para coldstart — o que é e por que existe — leia o post principal primeiro. Este é para pessoas que querem ver a história da iteração: as decisões de design que não funcionaram, as que funcionaram e por quê.
A trajetória é mais ou menos: eu comecei com uma ideia simples, atingi bases de código reais e assisti a ela quebrar de maneiras interessantes. Cada seção abaixo é uma coisa que quebrou e o que eu fiz a respeito.
O ponto de partida: um domínio de caminho de pasta por arquivo
A primeira versão do índice atribuía a cada arquivo um único "domínio" com base em seu caminho de pasta. A ideia era simples — arquivos em src/auth/ pertencem ao domínio auth, arquivos em src/billing/ pertencem a billing, e assim por diante.
Isso funcionou por cerca de dez minutos de teste no mundo real.
O problema: arquivos profundamente aninhados perderam toda a especificidade. Um arquivo em src/features/billing/components/invoices/list/InvoiceListRow.tsx seria marcado como list ou invoices ou billing dependendo de onde você cortasse, e nenhum desses é identificador único. Dois arquivos Row.tsx completamente não relacionados em diferentes árvores de recursos colidiriam no mesmo domínio. Pior, o agente não tinha como consultar "a linha da lista de faturas" porque o domínio era apenas uma fatia do caminho.
A solução foi parar de pensar em um único domínio e começar a pensar em todos os tokens significativos.
Domínios como um array de tokens
Eu mudei para um array domains[] — cada token significativo dos segmentos do caminho mais cada símbolo exportado do arquivo. Assim, InvoiceListRow.tsx em src/features/billing/components/invoices/list/InvoiceListRow.tsx seria indexado como algo como:
{
path: "src/features/billing/components/invoices/list/InvoiceListRow.tsx",
domains: [
"features", "billing", "components", "invoices", "list",
"invoice", "list", "row", // do nome do arquivo, dividido por caso
"InvoiceListRow", "InvoiceListRowProps" // símbolos exportados
],
exports: ["InvoiceListRow", "InvoiceListRowProps"]
}
Isso funcionou muito melhor. Uma consulta por "invoice list" atingiria tanto os segmentos do caminho quanto o nome do símbolo. Uma consulta por "InvoiceListRow" atingiria a exportação diretamente.
Então eu tentei adicionar caminhos de importação como uma fonte de token — o raciocínio sendo "arquivos que importam de auth/ provavelmente estão relacionados a autenticação." Isso foi um erro.
Um arquivo middleware que importa de muitos arquivos específicos de recursos (um padrão comum — configuração de roteador global, um componente de layout de nível superior, um arquivo de configuração de cliente de API) começaria a corresponder a qualquer consulta para qualquer um desses recursos. Ruído puro. O arquivo middleware era estruturalmente importante, mas não sobre nenhum recurso específico, e indexar suas importações fazia parecer que era sobre todos eles. Eu o removi.
A lição: o que um arquivo importa diz sobre suas dependências, não sua identidade. A identidade vem do próprio caminho do arquivo e das exportações. Essa foi a fronteira que eu tracei.
O desastre da correspondência de substring
No início, a correspondência era baseada em substring. Um token de consulta corresponderia a um token de índice se aparecesse em qualquer lugar dentro dele. Isso parecia razoável — "user" deveria corresponder a "UserProfile", afinal.
Isso causou falhas em cascata.
O token "in" é uma substring de "login", "signin", "settings", "admin", "binding", "PluginConfig", e aproximadamente mil outros tokens. Uma consulta como "sign in form" seria tokenizada para ["sign", "in", "form"], com "in" correspondendo como uma substring em centenas de arquivos não relacionados, e a lista de resultados aumentaria com arquivos que não tinham nada a ver com fluxos de login.
Eu tentei correções nesta ordem:
-
Penas baseadas em comprimento — penalizar correspondências onde o token de consulta é muito mais curto que o token de índice. Ajudou um pouco; quebrou para tokens curtos legítimos como
id,db,api. - Limites de comprimento mínimo para correspondência de substring — permitir correspondências de substring apenas se o token de consulta tiver pelo menos N caracteres. Cortou um pouco de ruído; introduziu novas falsas negativas onde um token de 3 caracteres era realmente significativo.
- Correspondência exata apenas com um fallback — corresponder exatamente primeiro, voltar para substring apenas se não houver correspondências exatas. Melhor, mas o fallback ainda acionava ruído em consultas raras, mas reais, de zero exato. Nenhuma dessas soluções parecia principiada. Todas eram heurísticas sobre um sinal fundamentalmente ruidoso.
Pontuação de raridade baseada em IDF
O que finalmente funcionou foi pontuar tokens pela frequência inversa de documentos no momento da construção do índice. Tokens comuns — index, utils, helper, component, types — recebem baixo peso. Tokens raros — seus nomes de recursos específicos, seus nomes de símbolos específicos — recebem alto peso.
// No momento da construção do índice, calcule IDF para cada token
function computeIDF(tokenCounts: Map<string, number>, totalFiles: number) {
const idf = new Map<string, number>;O artigo fornece insights sobre a construção de sistemas de indexação que podem ser aplicados por empresas brasileiras. A compreensão de como estruturar dados e otimizar buscas é crucial para melhorar a eficiência em ambientes de desenvolvimento. Isso pode impactar diretamente a forma como as empresas gerenciam e acessam informações em seus sistemas.
Noticias relacionadas

Auditei um SaaS Vibe-Coded e encontrei 5 vulnerabilidades críticas em 5 minutos.
O artigo relata a auditoria de segurança em um SaaS que utiliza agentes de IA, revelando vulnerabilidades críticas e a importância de uma segurança ágil para empresas que escalam rapidamente.

Anthropic cria um mercado de testes para comércio entre agentes de IA
Anthropic criou um mercado classificado onde agentes de IA atuaram como compradores e vendedores, realizando negócios reais. O experimento gerou 186 transações, totalizando mais de $4,000 em valor.

Deixei a IA solta na minha caixa de entrada de 300 mil e-mails. Veja o que aconteceu.
Uma análise sobre como a IA pode organizar e gerenciar caixas de entrada lotadas, utilizando o IMAP-MCP para conectar assistentes de IA a e-mails, melhorando a produtividade e a eficiência.
Gostou do conteudo?
Receba toda semana as principais novidades sobre WebMCP.