Uma busca que você troca: okf 1.9.0
🇺🇸 Read in EnglishAté a 1.9.0, a okf buscava no seu bundle de exatamente um jeito. Agora você escolhe a engine, e a escolha vem com um resultado que merece atenção: a nova engine full-text é de 44 a 56 vezes mais rápida por consulta, e vem desligada.
Isso não é um meio-termo defensivo. Uma invocação de CLI constrói um índice, faz uma pergunta e termina, então a vazão que ela comprou é vazão que ela nunca vive para gastar. O que você leva da release é uma escolha que não existia antes: casamento exato que começa na hora, ou casamento ranqueado e tolerante a erro de digitação que você pede pelo nome quando a pergunta vale a espera.
Duas engines, e como você escolhe uma
Trocar a engine não muda o formato do que volta. Duas engines podem discordar completamente sobre quais conceitos casam e ainda entregar linhas com as mesmas chaves na mesma ordem, então um script que lê --json nunca precisa saber qual delas rodou. O que muda é o casamento e o ranqueamento:
scan (padrão) | index | |
|---|---|---|
| casa | texto cru, literalmente | tokens inteiros e os tokens que eles prefixam |
| ranqueia por | soma dos pesos de campo | BM25+ |
| capacidade | regexp | fuzzy, prefix |
acha ustomer dentro de customer | sim | não |
A seleção é por capacidade quando a consulta exige uma. --fuzzy exige :fuzzy, então ela vai para o índice sem você nomear uma engine, e esse roteamento não imprime nada: sem nota, sem mudança de cabeçalho, sem chave nova no JSON. --engine NAME escolhe uma diretamente, para o caso em que uma flag de capacidade não dá conta, já que um modelo de casamento não exige nada e portanto nenhuma flag seleciona um.
Errar é um erro de uso que nomeia a engine capaz de fazer o serviço:
$ okf search @okf rate --engine index -e
error: --engine index does not support --regexp (try --engine scan)
$ okf search @okf rate --engine bogus
error: unknown search engine: bogus (available: index, scan)
Uma terceira engine agora pode chegar como uma gem instalada em vez de um fork. O --help lista o que estiver registrado em vez de um par fixo no código, então uma engine de que a okf nunca ouviu falar aparece no texto de ajuda assim que você a instala, e ela precisa passar o mesmo contrato que as duas nativas passam antes de ter permissão para responder qualquer coisa. Nada disso vem junto hoje; a questão é que um backend SQLite ou FTS5 não precisa mais ser escrito por este projeto para existir.
Por que a engine rápida está desligada
Os números por consulta não são apertados. Medido com benchmark-ips no Ruby 4.0.5 contra o bundle @okf real, replicado para corpora maiores, o índice sustenta de 44 a 56 vezes a vazão de consultas do scan, e o múltiplo se mantém quase constante porque as duas abordagens escalam linearmente neste corpus.
Essa é a medida certa para qualquer coisa que indexa uma vez e depois responde por horas, que é o que uma página de grafo ou um servidor rodando fazem.
É a medida errada para um processo que termina. Uma invocação de CLI constrói um índice, faz uma pergunta e morre. De ponta a ponta, com 1.000 conceitos, são 3,00 s contra 0,24 s, com a construção respondendo por cerca de 95% disso. A vantagem de vazão é real e o processo nunca vive o bastante para colher.
Então o padrão não se mexeu, e o tradeoff está escrito no --help em vez de ficar num benchmark que ninguém roda. O mergulho no minifts cobre o port em si, o que o tokenizador custa, e a única mudança arquitetural que faria o caminho rápido virar padrão.
A página do grafo desenha a camada de índices
Todo bundle OKF carrega um index.md autorado por diretório, o mapa da §6. A página do grafo só conseguia mostrá-los dentro do modo árvore de arquivos, onde um nó de pasta fazia as vezes do mapa do diretório.
Show indexes transforma isso numa camada: cada mapa vira um ladrilho ligado por arestas aos conceitos que lista e aos mapas abaixo dele, desenhado sobre qualquer layout que já esteja rodando, então ligá-lo não custa mais o arranjo que você estava lendo. A autoria aparece como forma, sólida onde um autor escreveu um mapa e vazada onde o bundle apenas implica um, então o toggle se lê tanto como curadoria quanto como navegação.
A view de Files mudou de forma na mesma release: a árvore aninha por segmento de caminho, a aba Indexes separada se dissolveu num toggle "Indexes only" sobre essa mesma árvore, e quem lê pela primeira vez agora recebe uma nota dizendo onde está o índice. Essa metade da release tem post próprio, com capturas de tela.
@slug é um alvo, não um caminho
A 1.8.0 trouxe o registry. A 1.9.0 termina de ensinar ao resto do sistema que um nome é um jeito de dizer qual bundle.
O erro cru de não é um diretório agora carrega a gramática:
$ okf lint ./nope
error: ./nope is not a directory or a registry ref
(@slug names a registered bundle, @ the default; okf registry list)
Essa mensagem é compartilhada por todo verbo, que é a razão de @all ficar de fora: @all pertence só ao search. A agent skill que vem junto fez a mudança correspondente, trocando "Which directory?" por "Which target?", e seus playbooks de consume e search nomeiam @slug nos passos de orientação.
A skill também parou de sondar pela CLI. Ela gastava uma rodada de ferramenta num teste de presença command -v okf antes de toda tarefa. Esse teste morreu: rode o verbo, e trate um "command not found" do shell como o único sinal para instalar. Uma linha começando com error: é a CLI respondendo com um resultado de bundle ou de uso, nunca uma toolchain ausente, então o caso comum agora não paga rodada de guarda nenhuma.
Também nesta release
- A busca entre bundles ranqueia um corpus só sob
--engine index. Ranquear cada bundle em separado e intercalar produziria uma lista que parece ordenada e não compara nada, então os bundles buscados são ranqueados juntos e a primeira linha é a melhor resposta entre todos eles. As pontuações do padrão seguem absolutas. - O bundle nomeia a própria raiz.
(root)é como um sistema de arquivos a chama. A linha raiz da árvore, o nó raiz do modo árvore de arquivos, o mapa raiz da camada de índices e o inspetor agora carregam todos o nome que o cabeçalho da página mostra,--titleincluído. Esclimpa a seleção do grafo, porque um grafo denso quase não deixa canvas vazio para clicar.- A clusterização parou de deixar caixas fantasma quando um filtro escondia todo conceito de uma área.
- Um conceito sem título usa um nome só em toda view. O
cataloge a listagem da §6 caíam para o id completo enquanto o nó do grafo caía para o basename, então um conceito atendia por dois rótulos em duas views de um mesmo bundle.
Atualizando
gem install okf # or: bundle add okf
Nada nesta release exige mudança num bundle existente, e o comportamento padrão de busca é byte a byte idêntico ao da 1.8.0: mesmos campos, mesmos pesos, mesmo casamento literal. O minifts chega como terceira dependência de runtime, Ruby puro, sem extensão nativa, sem árvore de dependências própria, e com o mesmo piso Ruby 2.4 que as outras duas seguram.
A imagem multi-arch acompanha a release como sempre em ghcr.io/serradura/okf:1.9.0, e toda a superfície acima está no demo ao vivo.
O que fecha o círculo. Quase tudo que você faz com o okf search deve continuar igual, porque continua mesmo. O que mudou é que as duas perguntas que a busca antiga não respondia, "ache isso mesmo eu tendo escrito errado" e "ranqueie direito entre quatro bundles", agora têm uma flag cada, e uma terceira engine não precisa mais ser escrita por este projeto para existir.