sqlite-graphrag 1.0.99

Persistent GraphRAG memory for Claude Code, Codex, Cursor, and 24+ AI agents in a single 19 MiB Rust binary. LLM-only and one-shot in v1.0.78: every `remember` / `ingest` spawns a headless claude code or codex subprocess (OAuth, no MCP, no hooks). v1.0.93: optional OpenRouter API embedding backend (~100-500ms vs 20-60s subprocess). No daemon. No ONNX runtime. No model download. Graph-native retrieval with FTS5 + cosine + multi-hop traversal. OAuth-only enforcement for LLM backends: API keys ABORT the spawn.
Documentation
# sqlite-graphrag (v1.0.99 LLM-Only One-Shot)

> Memória persistente para 27 agentes de IA em um único binário Rust de 14.6 MiB

27 agentes de IA. Um binário de 14.6 MiB. Zero download de modelo. sqlite-graphrag v1.0.99 (atual; v1.0.99 GAP-SG-67 removeu a poda destrutiva do degree-cap + a flag `--max-entity-degree` de remember/link (QUEBRANTE, clap exit 2; escritas puramente aditivas, nunca deletam arestas); GAP-SG-68 alinhou o doc de `graph entities --sort-by degree` ao comportamento ascendente (`--order desc` para o mais-conectado-primeiro); GAP-SG-69 `enrich body-enrich --until-empty` converge (o scan pula corpos vetados pela preservação); sem migração, schema v15; v1.0.97 recuperação dead-letter no enrich + ergonomia de escrita: `--requeue-dead`/`--list-dead`/`--ignore-backoff`/`--prune-dead-orphans` (deleta entradas dead de memory da fila cujo item_key não existe mais no banco principal, GAP-SG-66, ADR-0058), `--status`/`--list-dead`/`--requeue-dead`/`--prune-dead-orphans` rodam sem `--operation`/`--mode`, nova operação `augment-bindings` (exige `--names`), `body-extract --body-extract-graph-only`, default de `--max-attempts` 8, default de `--openrouter-timeout` 600s; `remember --graph-file`/`--strict-name`/`--replace-graph`; `ingest --force-merge` com dedup por `body_hash` e auto-split nativo de corpos grandes; `read --format raw`; `unlink --memory/--entity`; objeto `coverage` em `embedding status`; `total_memories` no topo de `stats`; `--db` vem depois do subcomando enquanto `SQLITE_GRAPHRAG_DB_PATH` é o override canônico (GAP-20, SG-32); v1.0.96 dead-letter no enrich + fan-out REST bounded (ADR-0055): `enrich --until-empty` roda um loop interno scan->drain até a fila elegível esvaziar ou `--max-runtime` expirar, uma fila dead-letter adiciona as colunas `error_class`/`next_retry_at` mais o status terminal `dead` para o backlog convergir estritamente (GAP-ENRICH-BACKLOG-CONVERGE), novas flags `--max-attempts`/`--status`/`--rest-concurrency`, e o embedding REST OpenRouter faz fan-out por lote de 32 chunks via um `tokio::task::JoinSet` bounded (GAP-OPENROUTER-REST-CONCURRENCY); v1.0.95 enrich chat OpenRouter (ADR-0054, GAP-OR-ENRICH): `enrich --mode openrouter` roteia o judge do enrich para o endpoint REST `/chat/completions` do OpenRouter sem CLI local; v1.0.94 remediação de quatro gaps: dim de embedding padrão 384, enrich --mode obrigatório, timeout de embedding 300s, embedding de entidades honra o backend selecionado; v1.0.93 adicionou backend de embedding via API REST OpenRouter com `--embedding-backend openrouter` com latência de ~100-500ms vs 20-60s do subprocesso LLM, flag `--enrich-after` para ingest, 5 correções BUG-OR; v1.0.91 corrigiu isolamento de CWD em spawn, BUG-17 correção de degree; v1.0.90 adicionou backend OpenCode; v1.0.89 schema drift via schemars; v1.0.87 camada de validação pre-flight; v1.0.79 fundação LLM-only) entrega a qualquer assistente de programação IA uma camada de memória local, rápida e privada, baseada em um único arquivo SQLite. Geração de embedding usa TANTO subprocesso LLM headless (claude/codex/opencode via OAuth) QUANTO a API REST OpenRouter (v1.0.93, via `--embedding-backend openrouter`). Sem daemon, sem runtime ONNX, sem modelo local. Recuperação nativa em grafo. Saída JSON determinística pronta para orquestração em pipelines.

## Arquitetura v1.0.85 (apenas LLM, substitui v1.0.79)
### Build one-shot sem modelo local
- Todo build é LLM-only e one-shot: não há daemon (removido na v1.0.79), não há runtime ONNX, não há download de modelo
- Features `embedding-legacy`, `ner-legacy` e `full` REMOVIDAS na v1.0.79 com as dependências opcionais fastembed/ort/ndarray/tokenizers/hf-hub
- Pipeline de embedding (G42): dimensionalidade padrão 384 (`--embedding-dim`, `SQLITE_GRAPHRAG_EMBEDDING_DIM`, faixa [8, 4096]; precedência flag > env > `schema_meta.dim` > 384); chamadas em lote (bases de calibração de 8 chunks / 25 nomes de entidade em dim 64, adaptadas por clamp(base×64/dim, 1, base) — G44); paralelismo limitado via `--llm-parallelism` em `remember` (padrão 4), `ingest` (padrão 2) e `edit`
- Re-embed canônico: `enrich --operation re-embed --limit N --resume`; memória individual via `edit --force-reembed`
- Todo subprocesso LLM usa `kill_on_drop` mais `SQLITE_GRAPHRAG_EMBED_TIMEOUT_SECS` (padrão 300s)
- Busca vetorial: cosseno em Rust puro sobre embeddings BLOB (`memory_embeddings`, `entity_embeddings`, `chunk_embeddings`); a extensão `sqlite-vec` não existe mais

- Leia este documento em [inglês (EN)](llms.txt).


## Arquitetura v1.0.86 → v1.0.91 (Pre-flight, Schema Drift, Flag Parity, Backend OpenCode, Isolamento de Spawn)
- v1.0.86 adicionou 10 subcomandos do pipeline LLM: `pending list|show|cleanup`, `embedding status|list|abandon`, `pending-embeddings list|process`, `slots status|release`. Novas flags globais: `--max-concurrency`, `--wait-lock`, `--llm-parallelism`, `--ingest-parallelism`, `--graceful-shutdown-secs`, `--skip-embedding-on-failure`. Semáforo de slots host-wide via `fs4` com `fcntl(F_SETLK)` em Unix e `LockFileEx` em Windows (ADR-0036, 0037, 0038, 0039, 0040)
- v1.0.87 adicionou a camada de validação pre-flight: `src/spawn/preflight.rs` (≥200 linhas, 7 guards, 15 testes unitários) porta todo spawn de subprocesso LLM ANTES do fork. Nova variante `AppError::PreFlightFailed(PreFlightError)` com `exit_code() == 16` (`EX_CONFIG`, `is_permanent() == true`). Os 7 guards em ordem: `check_argv_size`, `check_binary_exists`, `check_mcp_config_inline`, `check_mcp_config_path`, `check_walkup_mcp_json`, `check_output_buffer`, `check_claude_config_dir`. Bypass via `SQLITE_GRAPHRAG_SKIP_PREFLIGHT=1` (ADR-0045, GAP-META-005)
- v1.0.88 hotfixes: BUG-11 (CRÍTICO) falha de pre-flight em `extract/llm_embedding.rs:563-565` agora propaga para `remember` via `embed_via_backend_strict`; BUG-12 (MÉDIO) enforço OAuth-only emite 1 linha stderr (era 2); BUG-13 (MÉDIO) `link --create-missing` respeita validação de nome de entidade. 11 novos regression tests (ADR-0046, ADR-0047)
- v1.0.89 schema drift + flag parity: `health.schema.json` regenerado via `schemars` derive macro (política Must-Ignore por RFC 7493 I-JSON, `additionalProperties: true`); 17 novos campos adicionados. 5 subcomandos agora aceitam `--db <PATH>`: `embedding status|list|abandon`, `pending list|show`. `migrate --dry-run --json` reporta migrações pendentes sem aplicar. `codex-models --json` aceito como no-op. `ingest --auto-describe` (padrão true) extrai descrição da primeira linha significativa do corpo. `health --namespace <NS> --json` filtra contagens. Tamanho do binário 14.6 MiB documentado em `Cargo.toml:6` (ADR-0048, ADR-0049)
- v1.0.90 integração do backend OpenCode (ADR-0051): terceiro backend LLM `opencode run` ao lado de `codex exec` e `claude -p`. Novo `--llm-backend opencode`, `--mode opencode` para ingest/enrich, flags `--opencode-binary/model/timeout` e env vars `SQLITE_GRAPHRAG_OPENCODE_*`. Cadeia de fallback estendida para `codex → claude → opencode → none`. Remediação de 24 bugs incluindo ativação de `--skip-embedding-on-failure`, correção de flag morto `--llm-fallback`, dessincronia FTS em batch/enrich, compilação cruzada Windows, timeout hardcoded de embedding, paginação de `list`, enforço de `--yes` em comandos destrutivos. 875+ testes passando
- v1.0.91 isolamento de CWD em spawn: `spawn_isolation_dir()` e `apply_cwd_isolation()` em `src/spawn/mod.rs` definem `current_dir` para diretório temporário efêmero e `CLAUDE_CONFIG_DIR` para o mesmo diretório em TODOS os 10 spawn sites de produção. Subprocessos LLM não herdam mais `.mcp.json` do projeto do chamador — embedding funciona zero-config em qualquer diretório. `cleanup_spawn_dir()` remove o diretório temporário ao final do processo. BUG-17 corrigiu inflação de `entities.degree`: `increment_degree()` substituído por `recalculate_degree()` após inserção de todas as relações. BUG-15/16 corrigiram 8 JSON schemas com valores de enum e campos ausentes


## Arquitetura v1.0.93 (Backend de Embedding OpenRouter)
- v1.0.93 adiciona backend de embedding via API REST OpenRouter com flag global `--embedding-backend auto|openrouter|llm` (ADR-0052, GAP-OR-INGEST)
- Enum `EmbeddingBackendChoice` (`Auto`, `Openrouter`, `Llm`) é separado de `LlmBackendChoice` — seleção de embedding e extração LLM são independentes
- `--embedding-model MODEL` seleciona o modelo OpenRouter; SEM padrão — usuário DEVE especificar ao usar `--embedding-backend openrouter`
- Variável `OPENROUTER_API_KEY` ou flag `--openrouter-api-key` fornece a chave (tratada via `secrecy::SecretString` com zeroize-on-drop, JAMAIS logada)
- API REST direta via `reqwest+rustls-tls` para `POST https://openrouter.ai/api/v1/embeddings` — ~100-500ms vs 20-60s do subprocesso LLM
- Truncamento MRL (Matryoshka Representation Learning) para `--embedding-dim` configurado (padrão 384)
- 10 modelos verificados: `qwen/qwen3-embedding-4b`, `qwen/qwen3-embedding-8b`, `nvidia/llama-nemotron-embed-vl-1b-v2:free`, `openai/text-embedding-3-small`, `openai/text-embedding-3-large`, `perplexity/pplx-embed-v1-0.6b`, `mistralai/mistral-embed-2312`, `baai/bge-m3`, `google/gemini-embedding-001`, `google/gemini-embedding-2`
- `EmbeddingBackendChoice` propagado para TODOS os 8 comandos de embedding: `remember`, `remember-batch`, `ingest`, `recall`, `edit`, `restore`, `hybrid-search`, `deep-research`
- Flag `--enrich-after` no `ingest` dispara `enrich --operation memory-bindings` sequencialmente após todos os arquivos serem ingeridos
- BUG-OR-1 a BUG-OR-5: input_type por modelo, detecção MRL, validação de modelo, retry em HTTP 200 malformado, override de dimensão


## Documentação Principal
### Fontes canônicas em inglês para ingestão por LLMs
- [README](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/README.md): instalação completa, referência de comandos, tabela de integrações e FAQ
- [HOW_TO_USE](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/docs/HOW_TO_USE.md): passo a passo da instalação até o primeiro hybrid search em 60 segundos
- [COOKBOOK](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/docs/COOKBOOK.md): trinta receitas cobrindo ingestão, recuperação, travessia de grafo, backup e auditoria
- [AGENTS](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/docs/AGENTS.md): guia persuasivo para autores de agentes IA: economia, contrato JSON, roteamento por exit codes
- [INTEGRATIONS](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/INTEGRATIONS.md): configuração específica por fornecedor para todos os 27 agentes e IDEs suportados
- [CHANGELOG](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/CHANGELOG.md): histórico completo de versões com notas de migração
- [CONTRIBUTING](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/CONTRIBUTING.md): fluxo de pull request e padrões de código
- [SECURITY](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/SECURITY.md): política de divulgação responsável e canal de contato
- [CODE_OF_CONDUCT](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/CODE_OF_CONDUCT.md): padrões da comunidade


## Comandos Principais
### Subcomandos agrupados por ciclo de vida
- `init` inicializa o banco SQLite e valida que uma CLI `claude`/`codex`/`opencode` está alcançável (sem download de modelo desde a v1.0.76)
- `remember` salva uma memória com nome, tipo, descrição, corpo e grafo de entidades opcional; use `--max-rss-mb` para limitar o RSS do processo durante embedding (padrão 8192 MiB)
- `recall` realiza busca por similaridade vetorial KNN sobre as memórias armazenadas
- `hybrid-search` funde FTS5 full-text e KNN vetorial via Reciprocal Rank Fusion
- `deep-research` decompõe uma query em até 7 sub-queries, computa embedding separado por sub-query, executa busca híbrida vetorial+FTS paralela fundida via RRF mais travessia de grafo de 3 hops por sub-query, deduplica e monta cadeias de evidência direcionadas; flags: `--k` (padrão 20), `--max-sub-queries` (padrão 7), `--max-hops` (padrão 3), `--min-weight`, `--max-concurrency`, `--timeout`, `--with-bodies`, `--max-results` (padrão 50), `--rrf-k` (padrão 60), `--graph-decay` (padrão 0.7), `--graph-min-score` (padrão 0.05), `--max-neighbors-per-hop`
- `read` `list` `forget` `rename` `edit` `history` `restore` gerenciam o ciclo de vida da memória; `read --id <id>` busca pelo ID numérico da memória como alternativa ao `--name`; `edit --type` muda o tipo da memória
- `remember-batch` ingere múltiplas memórias a partir de um stream NDJSON em uma única invocação
- `completions` gera scripts de autocompletar para bash, zsh, fish, elvish e powershell
- `link` `unlink` `related` gerenciam relacionamentos tipados entre entidades para travessia multi-hop
- `health` `stats` `migrate` `vacuum` `optimize` `sync-safe-copy` gerenciam o banco de dados; `health` reporta `vec_memories_missing` e `vec_memories_orphaned` para diagnósticos do índice vetorial; `health` também reporta `relation_concentration_warning` e detecção de super-hub quando qualquer entidade ou tipo de relação domina o grafo
- `backup` cria backup consistente do banco usando a API SQLite Online Backup, seguro com WAL
- `fts rebuild` `fts check` `fts stats` reparam, verificam e inspecionam o índice FTS5 full-text
- `memory-entities` lista todas as entidades vinculadas a uma memória pelo nome
- `delete-entity` remove uma entidade e opcionalmente propaga a exclusão para seus relacionamentos
- `rename-entity` renomeia uma entidade do grafo preservando todos os relacionamentos baseados em FK e re-gera embedding para busca vetorial
- `reclassify` muda o `entity_type` de uma entidade ou de uma categoria inteira via `--batch`
- `merge-entities` mescla nós de entidade duplicados em um único nó canônico
- `prune-ner` remove vínculos gerados por NER de uma entidade (`--entity`) ou de todas (`--all --yes`)
- `remember --dry-run` faz preview do parsing e extração do grafo sem gravar no banco
- `cleanup-orphans` `prune-relations` removem entidades órfãs e relações fracas ou não utilizadas do grafo
- `purge` `namespace-detect` cuidam de manutenção e resolução de namespace
- `reclassify-relation` renomeia tipos de relacionamento no grafo; modo individual: `--source A --target B --from-relation antigo --to-relation novo`; modo batch: `--from-relation antigo --to-relation novo --batch`; filtros opcionais: `--filter-source-type`, `--filter-target-type`; `--dry-run` faz preview; trata colisões UNIQUE via `UPDATE OR IGNORE` + `DELETE`
- `normalize-entities` normaliza todos os nomes de entidade no namespace para kebab-case ASCII minúsculo; mescla colisões automaticamente (ex.: `Claude Code` e `claude-code` viram um nó com relacionamentos combinados); `--dry-run` faz preview, `--yes` aplica
- `enrich` pipeline de qualidade do grafo aumentada por LLM via `--mode claude-code` ou `--mode codex`; padrão scan-judge-persist com queue DB para resume/retry; 3 operações implementadas: `--operation memory-bindings` (extrai entidades de memórias órfãs), `--operation entity-descriptions` (gera descrições para entidades sem descrição), `--operation body-enrich` (expande corpos curtos de memória); `--dry-run` faz preview sem spawnar LLM; `--max-cost-usd` limita orçamento; `--llm-parallelism <N>` controla subprocessos LLM simultâneos (padrão 1); saída é NDJSON (eventos de fase, eventos por item, resumo)


## Variáveis de Ambiente
### Superfície de configuração em tempo de execução
- `SQLITE_GRAPHRAG_DB_PATH` override explícito para o caminho do banco SQLite
- O comportamento padrão cria ou abre `graphrag.sqlite` no diretório atual
- `SQLITE_GRAPHRAG_CACHE_DIR` diretório para arquivos de cache e locks (cache de modelo apenas em builds ≤ v1.0.75)
- `SQLITE_GRAPHRAG_EMBEDDING_DIM` override da dimensionalidade do embedding (v1.0.79, faixa [8, 4096], padrão 64)
- `SQLITE_GRAPHRAG_CLAUDE_EMBED_MODEL` override de modelo para chamadas de embedding `claude -p` (v1.0.79)
- `SQLITE_GRAPHRAG_EMBED_TIMEOUT_SECS` timeout por chamada de subprocesso LLM de embedding (v1.0.79, padrão 300)
- `SQLITE_GRAPHRAG_LOG_LEVEL` nível de filtro de rastreamento com valores de `error` a `trace`
- `SQLITE_GRAPHRAG_LANG` idioma de saída da CLI com valores `en` ou `pt`
- `SQLITE_GRAPHRAG_NAMESPACE` override de namespace respeitado por todos os comandos (corrigido em v1.0.51)
- `OPENROUTER_API_KEY` chave de API para backend de embedding OpenRouter (v1.0.93); tratada via `secrecy::SecretString`
- `SQLITE_GRAPHRAG_EMBEDDING_BACKEND` seleção persistente de backend de embedding (`auto`, `openrouter`, `llm`)
- `SQLITE_GRAPHRAG_EMBEDDING_MODEL` modelo persistente de embedding para backend OpenRouter


## Entrada do Grafo
### Contrato mínimo de payload para `remember`
- `--entities-file` espera um array JSON de objetos de entidade
- Cada entidade deve incluir `name` mais `entity_type` ou alias `type`
- Valores válidos de `entity_type`: `project`, `tool`, `person`, `file`, `concept`, `incident`, `decision`, `memory`, `dashboard`, `issue_tracker`, `organization`, `location`, `date`
- `--relationships-file` espera um array JSON de objetos de relacionamento
- Cada relacionamento deve incluir `source`/`from`, `target`/`to`, `relation` e `strength`
- `strength` deve ser float em `[0.0, 1.0]` e é mapeado para `weight` nas saídas do grafo
- Payloads de arquivo usam relações com underscore como `applies_to`, `depends_on` e `tracked_in`; aliases com hífen são normalizados antes da gravação
- As flags CLI de `link` e `unlink` usam relações com hífen como `applies-to`, `depends-on` e `tracked-in`


## Extração Automática
### Extração de URL por regex (GLiNER removido na v1.0.79)
- Passe `--enable-ner` ou defina `SQLITE_GRAPHRAG_ENABLE_NER=1` para ativar no `remember` e no `ingest`
- Desde a v1.0.79 isso executa APENAS extração de URL por regex — o pipeline GLiNER zero-shot foi removido com a feature `ner-legacy`
- `--gliner-variant`, `SQLITE_GRAPHRAG_GLINER_MODEL` e `SQLITE_GRAPHRAG_GLINER_THRESHOLD` são aceitas por compatibilidade mas NÃO têm efeito
- Campo de resposta `extraction_method`: `url-regex`, `regex-only` ou `none:extraction-failed`
- Para extração curada por LLM use `ingest --mode claude-code` ou `ingest --mode codex`; para controle exato use `--graph-stdin`
- `--skip-extraction` está depreciado desde v1.0.45 e não tem efeito
- `--max-rss-mb <MiB>` em `remember` e `ingest` aborta embedding quando o RSS do processo excede o limite (padrão 8192 MiB)

## Modos de Ingestão (v1.0.62)
### Três modos de extração para ingestão em massa
- `--mode none` (padrão): ingestão apenas do body, sem extração de entidades/relações
- `--mode gliner`: aceito por compatibilidade, mas apenas extração de URL por regex desde a v1.0.79 (GLiNER/ONNX removidos)
- `--mode claude-code`: extração curada por LLM via binário Claude Code instalado localmente
- Modo Claude Code spawna `claude -p` headless com `--json-schema` para saída estruturada
- Requer Claude Code >= 2.1.0 instalado na máquina com assinatura Pro/Max ativa
- Resumível via flag `--resume` com queue DB SQLite rastreando progresso por arquivo
- Timeout por arquivo via `--claude-timeout <S>` (padrão 300s); mata processos `claude -p` travados
- Controle de orçamento via `--max-cost-usd <N>` para limitar gasto acumulado
- Rate limit com backoff exponencial automático (60s → 120s → 300s → 900s)
- `--mode codex` spawna `codex exec --json` por arquivo para extração curada por LLM via OpenAI Codex CLI
- Requer Codex CLI instalado localmente; usa `--output-schema` para saída JSON estruturada
- Flags específicas do Codex: `--codex-binary <PATH>`, `--codex-model <MODEL>`, `--codex-timeout <S>` (padrão 300)
- Variável de ambiente `SQLITE_GRAPHRAG_CODEX_BINARY` substitui a busca no PATH
- Rastreamento de uso de tokens via campos `input_tokens` e `output_tokens` (cost_usd não disponível no Codex CLI)
- Pipeline completo de embeddings aplicado às memórias ingeridas via Codex para recall e hybrid-search

Autenticação: OAuth funciona automaticamente em ambos os modos — nenhuma chave de API necessária.
--mode claude-code lê OAuth de ~/.claude/.credentials.json (Claude Pro/Max/Team).
--mode codex lê autenticação de dispositivo via codex auth login (OpenAI).
Chaves de API (ANTHROPIC_API_KEY, OPENAI_API_KEY) ABORTAM o spawn com AppError::Validation. OAuth é o ÚNICO fluxo de credencial aceito.


## Exit Codes
### Status determinístico para roteamento em pipelines
- `0` sucesso: continue o loop do agente
- `1` falha de validação ou runtime: registre e informe o operador
- `2` argumento CLI inválido: corrija o uso e tente novamente
- `9` memória duplicata detectada: ignore ou use `--force-merge`
- `3` conflito de atualização otimista: releia `updated_at` e tente novamente
- `4` memória ou entidade não encontrada: trate o recurso ausente com elegância
- `5` namespace não pôde ser resolvido: passe `--namespace` explicitamente
- `6` payload excedeu os limites configurados: divida o corpo em partes menores
- `10` erro no banco de dados SQLite: execute `health` para inspecionar integridade
- `11` geração de embedding falhou: verifique disponibilidade da CLI LLM e tente novamente
- `13` falha parcial em batch: respeite o backoff e tente novamente
- `14` erro de I/O no sistema de arquivos: diretório de cache não gravável, diretório de ingestão inexistente
- `15` banco de dados ocupado após tentativas: aguarde e tente novamente
- `16` validação pre-flight falhou (v1.0.87+): corrija config MCP ou caminho do binário, veja envelope para variante
- `19` SHUTDOWN: shutdown graceful interrompeu trabalho, estado parcial descartado, RETRY OBRIGATÓRIO
- `20` erro interno ou de serialização JSON
- `75` EX_TEMPFAIL: todos os slots de concorrência ocupados OU singleton de job travado, tente com backoff
- `77` RAM disponível abaixo do mínimo necessário para subprocesso LLM


## O Que Mudou na v1.0.79
### G42: pipeline de embedding LLM rápido, paralelo e robusto
- Dimensionalidade de embedding configurável, padrão 384 (`--embedding-dim`; precedência flag > `SQLITE_GRAPHRAG_EMBEDDING_DIM` > `schema_meta.dim` > 384; bancos 384-dim existentes continuam funcionando sem mudança; ZERO alteração de schema)
- Chamadas LLM em lote: bases de calibração de 8 chunks / 25 nomes de entidade em dim 64, adaptadas por clamp(base×64/dim, 1, base) por chamada (schema `{items:[{i,v}]}`, G44) — 39 spawns viram 4-5
- Paralelismo limitado (`Semaphore` + `JoinSet`): nova flag `--llm-parallelism` em `remember` (padrão 4), `ingest` (padrão 2) e `edit`; permits com clamp [1, 32]
- Overrides via env `SQLITE_GRAPHRAG_CLAUDE_EMBED_MODEL` e `SQLITE_GRAPHRAG_EMBED_TIMEOUT_SECS` (padrão 300s); `kill_on_drop` em todo subprocesso LLM
- `CLAUDE_CONFIG_DIR` vazio por padrão no caminho de embedding (~40-50s → ~10-15s por chamada)
- Handler de sinais sem panic: segundo sinal sai com 130 e zero I/O; SIGPIPE sai com 141
- Re-embed canônico: `enrich --operation re-embed --limit N --resume` mais `edit --force-reembed`
- `validate_dim` falha em vetores divergentes em vez de truncar/preencher silenciosamente
- REMOVIDOS: infraestrutura do daemon; features `embedding-legacy`/`ner-legacy`/`full` e dependências opcionais fastembed/ort/ndarray/tokenizers/hf-hub

## O Que Mudou na v1.0.68
### Correções críticas (G28 + G29)
- v1.0.68 é o primeiro release desde v1.0.65 que compila no Windows via `cargo install`.  v1.0.66 e v1.0.67 quebravam com `error[E0308]` em `src/terminal.rs:29` porque `HANDLE` em `windows-sys >= 0.59` é `*mut c_void` (era `isize` em 0.48/0.52).  Correção: `!handle.is_null() && handle != INVALID_HANDLE_VALUE` mais `windows-sys` fixado em `=0.59.0` exato, mais job de CI `windows-build-check`.
- `enrich`, `ingest --mode claude-code` e `ingest --mode codex` agora adquirem um singleton por namespace via `lock::acquire_job_singleton(job_type, namespace, wait_seconds)`.  Uma segunda invocação concorrente no mesmo banco retorna `AppError::JobSingletonLocked { job_type, namespace }` (exit 75, retryable) em vez de empilhar 4 × N workers × 10 servidores MCP.
- `claude_runner::build_claude_command` agora respeita `SQLITE_GRAPHRAG_CLAUDE_EMPTY_CONFIG_DIR` (opt-in).  Quando definida para um diretório vazio, o subprocesso é iniciado com `CLAUDE_CONFIG_DIR=<esse dir>`, suprimindo servidores MCP do escopo user.  Este é o único mecanismo que o Claude Code realmente honra — `--strict-mcp-config` e `--mcp-config '{}'` são silenciosamente ignorados conforme [anthropics/claude-code#10787].
- `enrich` emite `tracing::warn!` quando `--llm-parallelism > 4`, recomendando a combinação com o override `CLAUDE_CONFIG_DIR`.
- Helper `retry::CircuitBreaker` adicionado com `AttemptOutcome::{Success, Transient, HardFailure}`.  Erros rate-limited e timeout são explicitamente excluídos da contagem de falhas.
- 3 falhas de teste pré-existentes em `src/commands/{history,list,read}.rs` corrigidas (asserções timezone-agnostic).

## Referências Opcionais
### Materiais complementares para contexto mais profundo
- [Guia CLAUDE](https://github.com/daniloaguiarbr/sqlite-graphrag/blob/main/docs/CLAUDE.md): padrões de invocação específicos para Claude Code e estratégias de memória de sessão
- [Definições de SKILL](https://github.com/daniloaguiarbr/sqlite-graphrag/tree/main/skill/sqlite-graphrag-en): skills de slash-command pré-construídas para o harness Claude Code
- [Pacote crates.io](https://crates.io/crates/sqlite-graphrag): binário publicado com semver e metadados de MSRV
- [Referência API docs.rs](https://docs.rs/sqlite-graphrag): rustdoc para consumidores da biblioteca


## Fatos Estáveis
### Identidade e metadados de versão
- Nome do pacote `sqlite-graphrag` publicado no crates.io sob MIT OR Apache-2.0
- Versão atual 1.0.99. v1.0.99 = GAP-SG-67 removeu a poda destrutiva do degree-cap + a flag `--max-entity-degree` de remember/link (QUEBRANTE, clap exit 2; escritas agora puramente aditivas, nunca deletam arestas); GAP-SG-68 alinhou o doc de `graph entities --sort-by degree` ao comportamento ascendente (`--order desc` para o mais-conectado-primeiro); GAP-SG-69 `enrich body-enrich --until-empty` converge (o scan pula corpos vetados pela preservação); sem migração, schema v15. v1.0.97 = recuperação dead-letter no enrich + ergonomia de escrita: `--requeue-dead` (dead→pending), `--list-dead` (lista dead com `error_class`/`message`), `--ignore-backoff` (ignora `next_retry_at`), `--prune-dead-orphans` (inspetor read-only, deleta entradas dead de memory órfãs cujo item_key sumiu do banco, GAP-SG-66, ADR-0058); `--status`/`--list-dead`/`--requeue-dead`/`--prune-dead-orphans` não precisam de `--operation`/`--mode`; nova operação `augment-bindings` (exige `--names`) e `body-extract --body-extract-graph-only`; default de `--max-attempts` 8; default de `--openrouter-timeout` 600s; `remember --graph-file`/`--strict-name`/`--replace-graph`; `ingest --force-merge` + dedup por `body_hash` + auto-split nativo; `read --format raw`; `unlink --memory/--entity`; objeto `coverage` em `embedding status`; `total_memories` no topo de `stats`; `--db` depois do subcomando, `SQLITE_GRAPHRAG_DB_PATH` canônico (GAP-20, SG-32). v1.0.96 = dead-letter no enrich + fan-out REST bounded (ADR-0055): `enrich --until-empty` loop interno scan->drain, fila dead-letter (`error_class`/`next_retry_at`/terminal `dead`) converge o backlog (GAP-ENRICH-BACKLOG-CONVERGE), novas flags `--max-runtime`/`--max-attempts`/`--status`/`--rest-concurrency`, fan-out REST OpenRouter via `tokio::task::JoinSet` bounded (GAP-OPENROUTER-REST-CONCURRENCY). v1.0.95 = enrich chat OpenRouter (ADR-0054, GAP-OR-ENRICH): `enrich --mode openrouter` roteia o judge para o REST `/chat/completions` do OpenRouter sem CLI local. v1.0.94 = remediação de quatro gaps (ADR-0053): dim de embedding padrão 384, enrich --mode obrigatório (exit 2 se omitido), timeout de embedding 300s, embedding de entidades honra --embedding-backend/--llm-backend. v1.0.93 = backend de embedding via API REST OpenRouter (ADR-0052, GAP-OR-INGEST), `--embedding-backend auto|openrouter|llm`, `--enrich-after` para ingest, BUG-OR-1 a BUG-OR-5, `EmbeddingBackendChoice` propagado para todos os 8 comandos. v1.0.91 = isolamento de CWD em spawn. v1.0.90 = backend OpenCode. v1.0.89 = schema drift. v1.0.87 = validação pre-flight. v1.0.79 = fundação LLM-only. MSRV Rust 1.88. Binário 14.6 MiB
- Repositório `https://github.com/daniloaguiarbr/sqlite-graphrag` com CI em push e tag
- Modelo de embeddings: delegado a API REST OpenRouter (v1.0.93, ~100-500ms) OU subprocesso headless `claude code` / `codex` / `opencode` (OAuth, ~20-60s) por chamada; sem modelo em processo
- Camada de armazenamento `rusqlite` com SQLite bundled e módulo FTS5. Extensão `sqlite-vec` REMOVIDA na v1.0.76; similaridade vetorial é cosseno em Rust puro sobre embeddings BLOB
- Até quatro instâncias simultâneas suportadas via semáforo de contagem com locks advisory `fs4`