
# Pesquisa de texto indexada

A pesquisa de texto indexada é a versão com cache aquecido da [pesquisa de texto](https://greph.inline0.dev/pt/docs/modes/text). A primeira chamada cria um armazenamento em disco de trigramas e ocorrências de identificadores; as chamadas seguintes o usam para ignorar arquivos que claramente não podem conter o padrão. O resultado é uma latência muito menor em consultas repetidas em repositórios grandes, sem introduzir um processo de daemon ou monitoramento.

A superfície de pesquisa de texto aquecida agora inclui:

- pesquisa com índice único
- pesquisa repetida `--index-dir` com vários índices
- pesquisa de conjuntos baseados em manifestos
- tratamento de dados obsoletos ciente do ciclo de vida
- diagnósticos do planejador via `--trace-plan`

O índice fica disponível em `greph-index` CLI e nos métodos de fachada `Greph::buildTextIndex()` / `Greph::searchTextIndexed()`.

## Criar o índice

```bash
# Full build at the current directory
./vendor/bin/greph-index build .

# Full build at an explicit root
./vendor/bin/greph-index build path/to/repo

# Use a non-default index directory
./vendor/bin/greph-index build . --index-dir /tmp/greph-index

# Build with an explicit lifecycle policy
./vendor/bin/greph-index build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
```

Por padrão, o índice é armazenado em `<root>/.greph-index/`.

Uma criação bem-sucedida exibe um resumo de uma linha:

```text
Built index for 2547 files in .greph-index (193428 trigrams, +2547 ~0 -0 =0)
```

Os quatro contadores indicam o número de arquivos adicionados, atualizados, excluídos e inalterados. Em uma criação nova, o contador de adicionados é igual à quantidade de arquivos e os demais ficam em zero.

## Atualizar o índice

```bash
./vendor/bin/greph-index refresh .
```

`refresh` percorre novamente a raiz indexada, calcula o hash de cada arquivo e regrava somente as entradas cujos metadados mudaram. A saída usa os mesmos quatro contadores para mostrar exatamente o que mudou:

```text
Refreshed index for 2547 files in .greph-index (193428 trigrams, +3 ~7 -1 =2536)
```

Execute `refresh` após editar arquivos rastreados ao usar `manual-refresh`. Para índices `opportunistic-refresh`, Greph pode atualizar o índice automaticamente durante a pesquisa se o conjunto alterado ainda for pequeno o bastante.

## Perfis do ciclo de vida

Greph dispensa daemons. Os perfis do ciclo de vida controlam o comportamento de um índice aquecido quando a árvore de origem muda:

- `static`: nunca verifica a atualidade nem altera dados automaticamente
- `manual-refresh`: mostra informações desatualizadas em `stats`, mas nunca atualiza durante a pesquisa
- `opportunistic-refresh`: atualiza durante a pesquisa somente quando o conjunto alterado fica abaixo dos limites configurados
- `strict-stale-check`: rejeita pesquisas aquecidas desatualizadas em vez de atualizá-las

Use `greph-index stats --dry-refresh` para inspecionar o que a pesquisa aquecida faria antes de executá-la:

```bash
./vendor/bin/greph-index stats . --dry-refresh
```

## Consultar o índice

```bash
# Fixed-string search
./vendor/bin/greph-index search -F "function" .

# Case-insensitive whole-word
./vendor/bin/greph-index search -F -i -w "function" .

# Counts
./vendor/bin/greph-index search -F -c "function" .

# Files only
./vendor/bin/greph-index search -F -l "function" .

# Multi-index search
./vendor/bin/greph-index search -F "apply_filters" . \
  --index-dir wordpress/.greph-index \
  --index-dir wp-content/plugins/my-plugin/.greph-index \
  --show-index-origin

# Regex search
./vendor/bin/greph-index search "function\s+\w+" .

# JSON output
./vendor/bin/greph-index search --json -F "function" .

# Planner trace to stderr
./vendor/bin/greph-index search --trace-plan -F "function" .
```

O conjunto de sinalizadores é o mesmo da pesquisa de texto nativa. Consulte a [CLIreferência](https://greph.inline0.dev/pt/docs/cli#greph-index) para ver a lista completa.

Se o índice não existir no local solicitado, `greph-index search` gera um erro. Este comando não recorre automaticamente a uma varredura sem índice (os comandos AST têm uma opção `--fallback scan`, mas o comando de texto não). Crie o índice primeiro.

## Conjuntos de índices nomeados

Se você pesquisa repetidamente o mesmo layout aquecido, use um manifesto em vez de repetir sinalizadores `--index-dir`:

```json
{
  "name": "wordpress-local",
  "indexes": [
    {
      "name": "core-text",
      "root": "wordpress",
      "mode": "text",
      "lifecycle": "static",
      "priority": 100
    },
    {
      "name": "plugin-text",
      "root": "wp-content/plugins/my-plugin",
      "mode": "text",
      "lifecycle": "opportunistic-refresh",
      "max_changed_files": 16,
      "max_changed_bytes": 262144,
      "priority": 200
    }
  ]
}
```

Salve como `.greph-index-set.json` e, em seguida:

```bash
./vendor/bin/greph-index set build
./vendor/bin/greph-index set stats --dry-refresh
./vendor/bin/greph-index set search --show-index-origin -F "apply_filters" .
```

## O que o índice armazena

O índice de texto é um armazenamento de trigramas e ocorrências de identificadores. Para cada arquivo indexado, Greph extrai:

- **Conjunto de trigramas**: o conjunto de sequências de três bytes presentes no conteúdo do arquivo. Usado como pré-filtro aproximado em consultas literais e de regex.
- **Ocorrências de identificadores**: o conjunto de tokens com formato de identificador (`[A-Za-z_][A-Za-z0-9_]*`) presentes no arquivo. Usado para acelerar consultas por palavra inteira.
- **Metadados do ciclo de vida**: limites armazenados e comportamento de verificação de dados desatualizados.
- **Metadados do conteúdo**: tamanho e mtime para decisões de atualização e inspeção de dados desatualizados.

Quando uma consulta chega, Greph extrai as mesmas formas do padrão (trigramas de trechos literais, tokens de identificador de padrões de palavra inteira), cruza as ocorrências e relê somente os arquivos correspondentes. Os arquivos que passam pelo cruzamento são pesquisados com o mesmo mecanismo do modo de texto nativo.

Em algumas consultas de resumo aquecidas, Greph pode responder diretamente usando as ocorrências:

- `-l` de palavra inteira
- `-L` de palavra inteira
- `-q` de palavra inteira

Isso evita reabrir arquivos candidatos quando as ocorrências já comprovam a resposta.

A ideia é a mesma do pré-indexamento opcional de ripgrep e do índice de trigramas de codesearch, mas foi desenvolvida especificamente para as formas em disco que a pesquisa aquecida PHP consegue acessar mais rapidamente.

## Diagnósticos do planejador

`--trace-plan` envia a decisão do planejador de texto aquecido para `stderr` sem alterar o fluxo normal de resultados.

O rastreamento inclui:

- perfil do ciclo de vida
- quantidade de arquivos selecionados
- origem dos candidatos (`full-scan`, `trigram-postings`, `word-postings` ou `invert-scan`)
- quantidade de termos nas ocorrências
- quantidade de arquivos candidatos e verificados
- elegibilidade para resumo direto
- elegibilidade para cache de consultas e decisão de preenchimento

## Quando usar

O modo indexado é a ferramenta certa quando:

- Você consulta o mesmo repositório várias vezes seguidas (tarefas de CI, ciclos de agentes, integrações com IDEs).
- O repositório é grande o bastante para que a varredura nativa seja o gargalo.
- Os padrões incluem trechos literais ou tokens de identificador que o índice pode usar como pré-filtro.

A varredura nativa ainda é a ferramenta certa quando:

- Você consulta um repositório pequeno, onde o custo de criação predomina.
- Você pesquisa um caminho pontual que não consultará novamente.
- Você precisa de todas as correspondências em uma única chamada improvisada e não quer manter um índice.

Os números publicados de benchmark em [README](https://github.com/inline0/greph#performance) mostram o modo indexado aquecido à frente de `rg` e `grep` tanto nas consultas de regex quanto nas consultas de contagem, arquivos com correspondências e arquivos sem correspondências, no corpus WordPress. Em consultas literais simples, ele supera `grep`, mas fica um pouco atrás de `rg`.

## Uso programático

```php
use Greph\Greph;
use Greph\Text\TextSearchOptions;
use Greph\Index\IndexLifecycleProfile;

// Build once
Greph::buildTextIndex('.', lifecycle: IndexLifecycleProfile::OpportunisticRefresh);

// Refresh after edits
Greph::refreshTextIndex('.');

// Query
$results = Greph::searchTextIndexed(
    'function',
    'src',
    new TextSearchOptions(fixedString: true),
);
```

`searchTextIndexed` aceita os mesmos `TextSearchOptions` da pesquisa de texto nativa e retorna a mesma estrutura de `list<TextFileResult>`. Para fluxos com vários índices ou baseados em manifestos, use `searchTextIndexedMany(...)` e `searchTextIndexedSet(...)`.
