dsh-locator 0.7.6 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README-pt.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  # 🔎 dsh-locator
4
4
 
5
- **Busca de arquivos em todo o disco, em milissegundos, para o DeepSeek Harness — sem o Everything.**
5
+ **Busque por nome quando lembra do nome e por conteúdo quando lembra da frase; depois abra o arquivo ou volte para a conversa.**
6
6
 
7
- Índice próprio multiplataforma (Windows USN/MFT · macOS FSEvents · Linux inotify), seis ferramentas para o agente — nomes, conteúdo e sessões — e um painel web ordenável.
7
+ Busca de arquivos em todo o disco para o [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) com **índice próprio**: sem instalar o Everything, sem `es.exe`, com as mesmas ferramentas e o mesmo painel no Windows, macOS e Linux.
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/dsh-locator)](https://www.npmjs.com/package/dsh-locator)
10
10
  [![npm downloads](https://img.shields.io/npm/dm/dsh-locator)](https://www.npmjs.com/package/dsh-locator)
@@ -12,7 +12,8 @@
12
12
  [![version](https://img.shields.io/github/v/tag/PerryLink/dsh-locator?label=version)](https://github.com/PerryLink/dsh-locator/releases)
13
13
  [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
14
14
  [![DSH plugin](https://img.shields.io/badge/dsh--plugin-✅-green)](https://github.com/topics/dsh-plugin)
15
- [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#)
15
+ [![Awesome DSH](https://img.shields.io/badge/awesome--dsh--plugin-listed-2ea44f)](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin)
16
+ [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-brightgreen.svg)](#versão-e-compatibilidade)
16
17
  [![Gitee](https://img.shields.io/badge/Gitee-mirror-c71d23?logo=gitee)](https://gitee.com/perrylink/dsh-locator)
17
18
  [![GitCode](https://img.shields.io/badge/GitCode-mirror-1f6feb)](https://gitcode.com/PerryLink/dsh-locator)
18
19
 
@@ -24,15 +25,62 @@ dsh plugin --profile web add dsh-locator
24
25
 
25
26
  </div>
26
27
 
27
- > **Repositório oficial:** [GitHub `PerryLink/dsh-locator`](https://github.com/PerryLink/dsh-locator). Gitee e GitCode são espelhos sincronizados automaticamente; o GitHub é a fonte da verdade.
28
- >
29
- > Faz parte da [família de plugins DSH](https://github.com/PerryLink) (Apache-2.0). Se ajudar, **uma ⭐ ajuda a próxima pessoa a encontrar**; nada é liberado por isso.
28
+ > **Repositório oficial:** [GitHub `PerryLink/dsh-locator`](https://github.com/PerryLink/dsh-locator); Gitee e GitCode são espelhos sincronizados automaticamente, e o GitHub é a fonte da verdade. Faz parte da [família de plugins do DSH](https://github.com/PerryLink) (Apache-2.0) e está listado no [awesome-dsh-plugin](https://github.com/awesome-dsh-plugin/awesome-dsh-plugin). Uma ⭐ ajuda a próxima pessoa a encontrá-lo; nada fica bloqueado atrás dela.
29
+
30
+ ## Índice
31
+
32
+ - [De relance](#de-relance)
33
+ - [Como difere de Everything / Spotlight / grep](#como-difere-de-everything--spotlight--grep)
34
+ - [Instalação](#instalação)
35
+ - [Primeira execução](#primeira-execução)
36
+ - [Duas buscas](#duas-buscas)
37
+ - [Painel web](#painel-web)
38
+ - [Ferramentas](#ferramentas)
39
+ - [Linguagem de consulta](#linguagem-de-consulta)
40
+ - [Configuração](#configuração)
41
+ - [Desempenho e recursos](#desempenho-e-recursos)
42
+ - [Suporte de plataformas](#suporte-de-plataformas)
43
+ - [Solução de problemas](#solução-de-problemas)
44
+ - [Compilar a partir do código-fonte](#compilar-a-partir-do-código-fonte)
45
+ - [Design](#design)
46
+ - [Limitações](#limitações)
47
+ - [Memória](#memória)
48
+ - [Segurança e privacidade](#segurança-e-privacidade)
49
+ - [Versão e compatibilidade](#versão-e-compatibilidade)
50
+ - [Roteiro](#roteiro)
51
+ - [Licença](#licença)
52
+
53
+ ## De relance
54
+
55
+ Buscar arquivos tem duas formas:
56
+
57
+ - **Você lembra do nome mas não do local.** `glob`/`grep` percorrem o workspace a cada chamada: ótimo quando você conhece o diretório, doloroso quando lembra só de metade do nome.
58
+ - **Você lembra de uma frase, de uma decisão ou de um trecho, não do arquivo nem da conversa.** Um índice de nomes não ajuda, e os logs de sessão do DSH também são dados de primeira classe.
59
+
60
+ O `dsh-locator` junta os dois em um único plugin:
61
+
62
+ | Recurso | Como usar |
63
+ |---|---|
64
+ | Busca por nome / caminho | `locator_search`, ou o modo padrão do painel |
65
+ | Busca no corpo dos arquivos | `locator_find`, ou o modo **Buscar conteúdo** do painel |
66
+ | Busca em sessões do DSH | As mesmas ferramentas; os resultados trazem `sessionId` / `messageId` e o painel pode voltar à conversa |
67
+ | Abrir / revelar | As ferramentas devolvem caminhos; o painel revela com duplo clique, `Ctrl+O` abre e `Ctrl+Enter` insere `@"caminho"` no compositor |
68
+ | Consumo externo | `locator_export` grava um espelho SQLite somente leitura |
69
+
70
+ O índice é local: sem chamadas de rede, sem telemetria, sem uploads; o plugin nunca modifica, move ou apaga os arquivos indexados.
30
71
 
31
- `dsh-locator` indexa uma vez os diretórios escolhidos, guarda o resultado num instantâneo compacto, aplica as mudanças do sistema de arquivos e responde consultas de nome/caminho em dezenas de milissegundos sobre mais de um milhão de entradas. O agente recebe `locator_search`, `locator_status`, `locator_rebuild` e `locator_export`; as pessoas têm um **painel global** na Web GUI (`Ctrl+Shift+F` ou a lupa no rodapé da barra lateral).
72
+ ## Como difere de Everything / Spotlight / grep
32
73
 
33
- ## Por que outro buscador?
74
+ | | dsh-locator | Everything | Spotlight | `glob` / `grep` |
75
+ |---|---|---|---|---|
76
+ | Plataformas | Windows / macOS / Linux / WSL | Windows | macOS | Multiplataforma |
77
+ | Índice | Persistente, próprio | Persistente (USN do NTFS) | Índice do sistema (metadados/conteúdo) | Percorre a cada chamada |
78
+ | Busca no conteúdo | Arquivos de texto + mensagens de sessão do DSH | Só nomes por padrão | Sim, varia por sistema | Sim, sem índice |
79
+ | Salto para sessão | Resultados trazem `sessionId` / `messageId` | Não | Não | Não |
80
+ | Ferramentas para agentes | Seis ferramentas, uma linguagem de consulta | Precisa de CLI/serviço | Precisa de scripts próprios | Nativas, sem índice persistente |
81
+ | Velocidade no Windows | Perto do Everything (USN opcional) | Mais rápido e leve | Não se aplica | Mais lento que um índice |
34
82
 
35
- `glob` e `grep` percorrem o workspace a cada chamada: rápidos quando você sabe o diretório, lentos quando lembra só parte de um nome. O Everything é excelente no Windows, mas só existe no Windows; envolvê-lo deixa macOS, Linux, WSL e hosts remotos de fora. O `dsh-locator` é dono do índice, então as mesmas ferramentas funcionam onde Node e Go rodam.
83
+ Resumindo: a **ideia** do Everything (índice persistente + consultas estruturadas) foi implementada de forma independente e multiplataforma, com as sessões do DSH por cima. Não é um invólucro do Everything.
36
84
 
37
85
  ## Instalação
38
86
 
@@ -40,150 +88,335 @@ dsh plugin --profile web add dsh-locator
40
88
  # npm (recomendado)
41
89
  dsh plugin --profile web add dsh-locator
42
90
 
43
- # GitHub main
91
+ # fixar uma versão
92
+ dsh plugin --profile web add dsh-locator@0.7.7
93
+
94
+ # branch principal do GitHub
44
95
  dsh plugin --profile web add github:PerryLink/dsh-locator
45
96
 
46
- # do código
97
+ # a partir de um checkout
47
98
  pnpm install
48
99
  pnpm build
49
- pnpm build:engine
100
+ pnpm build:engine # motor Go da plataforma atual
50
101
  dsh plugin --profile web add /caminho/absoluto/dsh-locator
51
102
 
52
- # tarball
103
+ # a partir de um tarball (saída do npm pack; troque pela versão real)
53
104
  npm pack
54
- dsh plugin --profile web add /caminho/absoluto/dsh-locator-0.5.0.tgz
105
+ dsh plugin --profile web add /caminho/absoluto/dsh-locator-0.7.7.tgz
106
+ ```
107
+
108
+ - O pacote inclui motores pré-compilados para `linux-x64`, `linux-arm64`, `win32-x64`, `win32-arm64`, `darwin-x64` e `darwin-arm64`; não é preciso Go local.
109
+ - Se o espelho npm estiver atrasado, adicione `--registry=https://registry.npmjs.org` ao comando.
110
+ - Depois de instalar em um perfil Web **em execução**, **recarregue a página** (`F5`): as ferramentas do host podem montar na hora, mas o painel do navegador é carregado do boot graph ao abrir a página. Perfis headless/TUI só têm as ferramentas.
111
+ - Atualizar: `dsh plugin --profile web add dsh-locator@latest` e depois `F5`. Uma mudança de esquema do conteúdo reconstrói o banco uma vez.
112
+ - Desinstalar: `dsh plugin --profile web remove dsh-locator`; para manter a configuração mas desativar, `enabled: false`.
113
+
114
+ ## Primeira execução
115
+
116
+ Na primeira montagem o motor indexa as raízes configuradas (padrão: seu diretório pessoal) e grava o snapshot e o banco de conteúdo no diretório de cache da plataforma:
117
+
118
+ | Plataforma | Diretório de estado padrão |
119
+ |---|---|
120
+ | Windows | `%LOCALAPPDATA%\dsh-locator` |
121
+ | macOS | `~/Library/Application Support/dsh-locator` |
122
+ | Linux | `$XDG_CACHE_HOME/dsh-locator` ou `~/.cache/dsh-locator` |
123
+
124
+ A primeira varredura de um diretório pessoal grande lê o disco; os próximos inícios carregam o snapshot. As requisições são atendidas **durante** essa varredura: a busca devolve o que já foi indexado com `indexing: true`, e o rodapé do painel avisa que o índice ainda está sendo construído.
125
+
126
+ Por padrão, `node_modules`, `.git`, `.hg`, `.svn`, `.cache`, `__pycache__`, `.venv`, `venv` e `.next` são ignorados por nome; `excludes` altera a lista.
127
+
128
+ Experimente:
129
+
130
+ ```text
131
+ Encontre os PDFs que alterei na semana passada
132
+ Onde "contentRefreshMs" foi discutido?
133
+ Em qual conversa este desenho foi decidido?
55
134
  ```
56
135
 
57
- O pacote npm inclui motores pré-compilados para `linux-x64`, `linux-arm64`, `win32-x64`, `win32-arm64`, `darwin-x64` e `darwin-arm64`.
136
+ ## Duas buscas
58
137
 
59
- Ao instalar num perfil Web já em execução, **recarregue a página** (`F5`): as ferramentas podem montar a quente, mas o painel (`client.js`) vem do boot graph no carregamento. Perfis headless/TUI não montam painel.
138
+ ### Por nome: `locator_search`
139
+
140
+ Sintaxe no estilo Everything devolvendo caminho, tamanho, data de modificação, extensão e tipo. Ideal para “o nome contém report”, “PDFs alterados esta semana”, “vídeos com mais de 50 MB”.
141
+
142
+ Ordenação, paginação e `limit`/`offset` são feitos no motor do host; consultas comuns sobre 1,51 M de entradas respondem em dezenas de milissegundos.
143
+
144
+ ### Por conteúdo: `locator_find`
145
+
146
+ Pesquisa no **corpo** de arquivos de texto e mensagens de sessão do DSH e devolve trechos com a origem:
147
+
148
+ - resultados de arquivo trazem caminho e podem ser abertos ou revelados;
149
+ - resultados de sessão trazem `sessionId` e `messageId`, então o painel abre a conversa e destaca a mensagem;
150
+ - substrings em chinês e inglês funcionam (tokenizador trigram, sem segmentação de palavras).
151
+
152
+ Como o índice de conteúdo se comporta:
153
+
154
+ - **Preguiçoso por padrão.** Nada é construído na inicialização; a primeira busca de conteúdo (`locator_find` ou o modo conteúdo do painel) inicia a construção em segundo plano, e `contentLazy: false` volta à construção no arranque. A primeira consulta informa `building: true` em vez de devolver vazio sem explicação.
155
+ - **Reinício reaproveitando.** Se o banco existe, ele é atualizado de forma incremental; a construção completa (primeiro logs de sessão, depois corpos de arquivo) só acontece se o banco não existe, tem esquema antigo, ficou incompleto por uma construção interrompida ou não abre.
156
+ - **Atualização incremental** a cada `contentRefreshMs` (5 minutos por padrão), relendo só arquivos e sessões cujo mtime mudou; `0` desativa.
157
+ - **Sessões arquivadas e ativas.** Arquivadas são ignoradas a menos que `contentIncludeArchived: true`; um log que ainda está sendo escrito só é indexado após `contentActiveSessionDelayMs` (2 minutos) de quietude, para não descomprimi-lo a cada atualização. Sessões apagadas saem do índice quando os arquivos desaparecem.
158
+ - **Orçamento e truncamento.** Padrões: 1 MB por arquivo de texto, 200.000 arquivos, 1 GB de corpos e as 100 sessões mais recentes. Ao atingir o orçamento, arquivos que chegam depois na ordem de varredura são ignorados; o `locator_find` informa `content budget reached` e o estado HTTP traz `truncated: true`. Aumente `contentMaxTotalBytes` ou reduza `contentExcludes`.
159
+ - **Árvores de dependências não são lidas.** `node_modules`, `.cargo`, `.bun`, `.pnpm`, `site-packages`, `toolchain`, … são ignorados por padrão via `contentExcludes`; caso contrário, código de bibliotecas esgotaria o orçamento antes dos seus documentos. O índice de nomes continua cobrindo esses caminhos.
160
+
161
+ A construção roda dentro do processo anfitrião do DSH, mas leituras de arquivo e descompressão zstd são assíncronas e os dois laços cedem o controle a cada ~8 ms: em um corpus de 28,6 MB o maior bloqueio do laço de eventos caiu de 968 ms para cerca de 20 ms, então carregar e trocar sessões continua fluido. As **consultas** de conteúdo rodam em uma worker thread com conexão somente leitura: palavras comuns levam cerca de 100 ms e termos raros alguns milissegundos, sem bloquear o host.
60
162
 
61
163
  ## Painel web
62
164
 
63
- ![Painel de busca do dsh-locator: resultados Markdown filtrados por caminho, com contagem, tempo e colunas ordenáveis](docs/assets/panel-en.png)
165
+ ![Painel de busca do dsh-locator: modo conteúdo ativado, mostrando correspondências no corpo e trechos](docs/assets/panel-en.png)
166
+
167
+ Pressione `Ctrl+Shift+F` em qualquer lugar da GUI web, ou clique na lupa no pé da barra lateral.
64
168
 
65
- Pressione `Ctrl+Shift+F` em qualquer lugar da Web GUI, ou clique na lupa no rodapé da barra lateral. O painel se comunica com o host por rotas na mesma origem (`/dsh-locator/search`, `/dsh-locator/content`, `/dsh-locator/status`, `/dsh-locator/reveal` e `/dsh-locator/open`), sem segundo servidor e sem porta extra.
169
+ - Consulta vazia lista as entradas modificadas mais recentemente; ao digitar, a mesma sintaxe das ferramentas é usada após 110 ms de debounce.
170
+ - Clique no cabeçalho de uma coluna para ordenar por nome, tamanho, data de modificação ou caminho.
171
+ - Alterne **somente arquivos** / **somente diretórios** para filtrar o tipo.
172
+ - Marque **Buscar conteúdo** para trocar nomes por corpos de arquivo e mensagens de sessão; enquanto o índice é construído o rodapé mostra o estado e o painel consulta de novo.
173
+ - `↑`/`↓` selecionam, `Enter` copia o caminho, `Ctrl+O` abre, `Ctrl+Enter` insere `@"caminho"` no compositor e `Esc` fecha.
174
+ - Duplo clique em um arquivo revela no Explorer/Finder/`xdg-open`; duplo clique em uma sessão abre a conversa na mensagem encontrada.
175
+ - O texto do painel segue `navigator.language` (zh/en/es/pt/hi).
66
176
 
67
- * Consulta vazia: entradas recentes por data; ao digitar, debounce de 110 ms e a mesma sintaxe das ferramentas.
68
- * Clique no cabeçalho para ordenar por nome, tamanho, data ou caminho; outro clique inverte.
69
- * `Somente arquivos` / `Somente pastas` filtram o tipo; marcar **Buscar conteúdo** alterna entre a busca por nomes e a busca no conteúdo dos arquivos e das mensagens de sessão, e os acertos mostram um trecho de uma linha. O rodapé mostra resultados, limite e tempo.
70
- * `↑`/`↓` seleciona, `Enter` copia, `Ctrl+O` abre, `Ctrl+Enter` insere `@"caminho"` no compositor; o clique duplo revela um arquivo no gerenciador de arquivos e, num resultado de sessão, abre a conversa correspondente e destaca a mensagem encontrada por um instante. `Esc` fecha.
71
- * A interface segue `navigator.language` (zh/en/es/pt/hi).
177
+ O painel usa rotas de mesma origem — `/dsh-locator/search`, `/dsh-locator/content`, `/dsh-locator/content/rebuild`, `/dsh-locator/combined`, `/dsh-locator/status`, `/dsh-locator/reveal`, `/dsh-locator/open` — então não precisa de outro servidor nem de outra porta. Perfis sem servidor web não o montam.
178
+
179
+ - **Os três escopos vêm ativados por padrão**: conteúdo (corpos + sessões), arquivos e pastas; desmarque qualquer um para restringir. Os resultados são agrupados **conteúdo → arquivos → pastas** com a contagem por grupo; o conteúdo é ordenado por relevância e os grupos de nomes seguem o menu de ordem.
180
+ - **Duplo clique ou `Enter` ativa um resultado**: uma sessão abre a conversa e pinta as palavras encontradas com destaque âmbar translúcido que acompanha a rolagem, é centralizado ao chegar e é limpo com `Esc`; arquivos e pastas são mostrados no gerenciador de arquivos. `Ctrl+Shift+C` copia o caminho, `Ctrl+O` abre, `Ctrl+Enter` insere `@file` e `Alt+1–3` alterna os escopos.
181
+ - Consultas de conteúdo exigem pelo menos dois caracteres; consultas vazias ou de um caractere não iniciam a construção do índice.
72
182
 
73
183
  ## Ferramentas
74
184
 
75
- | Ferramenta | Uso |
185
+ | Ferramenta | O que faz |
186
+ |---|---|
187
+ | `locator_search` | Consulta nomes e caminhos com filtros `ext:`, `size:`, `dm:`, `path:`, ordenação e paginação. |
188
+ | `locator_find` | Busca em corpos de arquivo e mensagens de sessão; devolve trechos, `sessionId`/`messageId` e o estado do índice de conteúdo. |
189
+ | `locator_status` | Raízes, contagens do índice de nomes, estado do watcher, diretório de estado e caminho do motor. (O progresso do conteúdo é informado pelo `locator_find` e pelo painel.) |
190
+ | `locator_rebuild` | Substitui o índice de nomes por uma varredura em segundo plano; as buscas usam o índice antigo até o novo ficar pronto. |
191
+ | `locator_reindex` | Atualiza ou reconstrói o índice de conteúdo: incremental por padrão, `full: true` apaga e reconstrói. |
192
+ | `locator_export` | Grava um espelho SQLite somente leitura do índice de nomes (tabela `entries`) para ferramentas SQL externas. |
193
+
194
+ ## Linguagem de consulta
195
+
196
+ Palavras soltas são substrings do nome unidas por AND. Filtros no estilo Everything se combinam com elas:
197
+
198
+ | Exemplo | Significado |
76
199
  |---|---|
77
- | `locator_search` | Consulta com sintaxe estilo Everything. |
78
- | `locator_find` | Busca no corpo de arquivos e nas mensagens de sessão do DSH; os acertos trazem um trecho e, em conversas, `sessionId`/`messageId`. |
79
- | `locator_status` | Raízes, entradas, watcher, modo USN e erros. |
80
- | `locator_rebuild` | Reconstrói em segundo plano; buscas continuam no índice antigo. |
81
- | `locator_reindex` | Atualiza ou reconstrói o índice de conteúdo: incremental por padrão, `full: true` descarta e reconstrói. |
82
- | `locator_export` | Cópia somente leitura em SQLite (`entries(path, name, dir, size, mtime_ms, ext)`). |
200
+ | `report` | o nome contém `report` |
201
+ | `report ext:pdf` | …e a extensão é `pdf` |
202
+ | `ext:ts,js` / `ext:!tmp` | incluir ou excluir extensões |
203
+ | `*.sln` / `?ata` | curingas `*` e `?` |
204
+ | `"annual report"` | frase com espaço |
205
+ | `!archive` | negar um termo |
206
+ | `path:src` | o caminho completo contém `src` |
207
+ | `size:>10mb` / `size:1kb..2mb` | comparações de tamanho |
208
+ | `dm:today` / `dm:thisweek` / `dm:2026-01-01` | data de modificação |
209
+ | `folder:` / `file:` | somente diretórios / somente arquivos |
210
+ | `case:1` / `wholeword:1` | sensível a maiúsculas / limites de palavra |
211
+
212
+ O `locator_search` também aceita `sort` (`name`, `path`, `size`, `mtime`, `ext`), `desc`, `offset`, `limit`, `regex`, `caseSensitive` e `wholeWord`.
213
+
214
+ ## Configuração
215
+
216
+ Cada campo é um campo de configuração do Schemastery; sobrescreva a entrada `dsh-locator` no patch do perfil, por exemplo:
217
+
218
+ ```yaml
219
+ - id: dsh-locator
220
+ name: dsh-locator
221
+ config:
222
+ roots: ['/home/me/Documents', '/home/me/notes']
223
+ contentMaxTotalBytes: 2000000000
224
+ contentExcludes: ['node_modules', '.git', '.cargo', 'site-packages']
225
+ ```
83
226
 
84
- ### Busca por conteúdo
227
+ | Chave | Padrão | Significado |
228
+ |---|---|---|
229
+ | `enabled` | `true` | Chave geral; `false` não monta ferramentas nem inicia o motor. |
230
+ | `roots` | diretório pessoal | Diretórios a indexar; pode haver vários. |
231
+ | `excludes` | nomes de desenvolvimento/cache | Globs por nome ignorados pelo índice de nomes. |
232
+ | `watch` | `true` | Aplicar notificações do sistema de arquivos. |
233
+ | `refreshIntervalMs` | `1800000` | Cadência de reconstrução quando não há watcher nativo (kqueue ou falha do watcher); `0` desativa. |
234
+ | `scanWorkers` | `0` | Concorrência de leitura de diretórios; `0` usa o número de CPUs. |
235
+ | `windowsUsn` | `false` | Tentar a enumeração USN/MFT do NTFS antes da varredura (Windows, administrador; com fallback automático). |
236
+ | `memoryLimitMB` | `0` | Limite suave do heap Go do motor em MiB; `0` deixa com `GOMEMLIMIT`/`GOGC`. |
237
+ | `contentIndex` | `true` | Construir o índice de corpos e mensagens de sessão; `false` deixa a busca por nome com custo de conteúdo quase zero. |
238
+ | `contentLazy` | `true` | Construir o índice de conteúdo na primeira busca em vez de no arranque. |
239
+ | `contentMaxFileBytes` | `1000000` | Bytes lidos de um arquivo de texto. |
240
+ | `contentMaxTotalBytes` | `1000000000` | Total de bytes de corpos guardados; `0` = sem limite. |
241
+ | `contentMaxFiles` | `200000` | Arquivos de texto indexados por construção; `0` = sem limite. |
242
+ | `contentMaxSessions` | `100` | Logs de sessão mais recentes indexados; `0` = todos. |
243
+ | `contentRefreshMs` | `300000` | Cadência de atualização incremental do conteúdo; `0` desativa. |
244
+ | `contentIncludeArchived` | `false` | Indexar também sessões arquivadas. |
245
+ | `contentActiveSessionDelayMs` | `120000` | Indexar um log de sessão só após esse tempo de quietude. |
246
+ | `contentSessionDirs` | `[]` | Diretórios de sessão extras; vazio = `$DSH_HOME/sessions`. |
247
+ | `contentExcludes` | nomes de dependências/toolchains | Segmentos ou substrings de caminho ignorados pelo índice de conteúdo; o de nomes continua cobrindo. |
248
+ | `stateDir` | `''` | Diretório do snapshot e do banco de conteúdo; vazio = cache da plataforma. Use um diretório por processo do DSH. |
249
+
250
+ `binaryPath`, `maxResults`, `startupTimeoutMs` e `requestTimeoutMs` também existem para motores personalizados, limites de página e prazos; os padrões atendem a maioria dos casos.
251
+
252
+ ## Desempenho e recursos
253
+
254
+ Medido em uma máquina de desenvolvimento WSL2 (Linux, cache de página quente) e um diretório pessoal real; sua máquina varia com disco, número de arquivos, cache e GC.
255
+
256
+ **Índice de nomes**
257
+
258
+ | Métrica | Resultado |
259
+ |---|---|
260
+ | Varredura a frio | ~1,51 M de entradas em 11–12 s |
261
+ | Tamanho do snapshot | ~171 MB para 1,51 M de entradas |
262
+ | Consulta a quente (`locator_search`) | 6–25 ms para consultas comuns; varreduras `path:` ~70 ms |
263
+ | Busca durante uma reconstrução | O índice antigo continua servindo até o novo ficar pronto |
264
+ | Memória de pico na varredura | Centenas de MB; o motor é um processo filho e respeita `memoryLimitMB` / `GOMEMLIMIT` |
85
265
 
86
- `locator_find` procura no corpo de arquivos de texto e nas mensagens de sessão do DSH por meio de um índice FTS5 local em SQLite. Subcadeias em chinês e inglês funcionam sem segmentação de palavras; cada acerto traz um trecho e, quando vem de uma conversa, `sessionId` e `messageId`.
266
+ **Índice de conteúdo** (diretório pessoal real, orçamento de 1 GB)
87
267
 
88
- O índice de conteúdo é preguiçoso por padrão: nada é construído na inicialização e a primeira busca de conteúdo inicia a construção em segundo plano (`contentLazy: false` constrói desde o início). Ao reiniciar, o plugin reaproveita o banco existente e o atualiza de forma incremental; a indexação completa (primeiro os logs de sessão, depois o corpo dos arquivos) só roda quando o banco não existe, tem uma versão de esquema antiga ou não pode ser aberto. Depois disso, uma atualização incremental a cada `contentRefreshMs` (5 minutos) relê apenas os arquivos e as sessões cujo mtime mudou. O `locator_reindex` dispara um dos dois modos manualmente.
268
+ | Métrica | Resultado (0.7.x, diretório real) |
269
+ |---|---|
270
+ | Cobertura | ~95,8 k arquivos de texto / 95 sessões / 1.050 mensagens |
271
+ | Reconstrução completa | ~3,5 min em segundo plano; host p95 14 ms / máx 115 ms durante ela |
272
+ | Atualização incremental (sem mudanças) | ~12 s (dominado pelo dump de 1,51 M de entradas do motor) |
273
+ | Latência do host ocioso | p50 2 ms / p95 3 ms / máx 6 ms |
274
+ | Tamanho do banco | ~3,1 GB (cerca de 3× o orçamento de corpos) |
275
+ | Consulta de conteúdo | ~100 ms para palavras comuns, poucos ms para raras (worker thread, host não bloqueia) |
89
276
 
90
- Enquanto uma indexação está em andamento, as buscas continuam respondendo com o que já está indexado; a ferramenta e o painel mostram o estado da indexação.
277
+ **Configurações mais econômicas**
91
278
 
92
- Os limites padrão são 1 MB por arquivo de texto, 200.000 arquivos, as 100 sessões mais recentes e 1 GB de texto — tudo configurável. Pastas de dependências e toolchains (`node_modules`, `.cargo`, `.bun`, `.pnpm`, `site-packages`, `toolchain`, …) ficam de fora por padrão — senão consomem o orçamento antes dos seus próprios documentos — e `contentExcludes` muda essa lista. O índice lê e descomprime de forma assíncrona e cede o event loop a cada ~8 ms (28,6 MB: 968 ms → 19 ms), então não trava o carregamento nem a troca de sessão; sessões arquivadas ficam de fora a menos que `contentIncludeArchived: true`, e uma sessão que está sendo escrita espera `contentActiveSessionDelayMs`.
279
+ - Só busca por nome: `contentIndex: false` zera o trabalho de conteúdo.
280
+ - Manter conteúdo usando menos disco: reduza `contentMaxTotalBytes` (ex.: 256000000) ou `contentMaxFileBytes`, ou aumente `contentRefreshMs`.
281
+ - Cobrir mais arquivos: aumente `contentMaxTotalBytes` / `contentMaxFiles` e confira se `contentExcludes` não está excluindo árvores de documentos reais.
282
+ - O banco de conteúdo é cache: apagar `stateDir` reconstrói e nunca toca nos arquivos originais.
93
283
 
94
- ### Sintaxe de consulta
284
+ ## Suporte de plataformas
95
285
 
96
- ```text
97
- relatorio palavras AND no nome
98
- "duas palavras" frase literal
99
- *.go ? curingas
100
- ext:pdf,docx ext:!tmp por extensão (ou negação)
101
- path:src subcadeia do caminho completo
102
- size:>10mb 1kb..2mb tamanho
103
- dm:today dm:thisweek data de modificação
104
- folder: file: só pastas / só arquivos
105
- !tmp negar
106
- case:1 wholeword:1 maiúsculas / palavra inteira
286
+ | Plataforma | Varredura + snapshot | Atualizações ao vivo | Observações |
287
+ |---|---|---|---|
288
+ | Linux | sim | inotify, recursivo | Descritores de vigilância são por diretório; árvores enormes podem atingir `fs.inotify.max_user_watches`. |
289
+ | Windows | sim | `ReadDirectoryChangesW`, recursivo | Não precisa de administrador nem do Everything. Enumeração USN/MFT opcional com privilégios elevados. Mudanças do WSL em `/mnt/<drive>` podem não gerar notificações; reconstrua essas raízes. |
290
+ | macOS | sim | FSEvents nos binários cgo publicados, recursivo e sem limite | kqueue é o fallback com `CGO_ENABLED=0` (até 4.096 diretórios); mudanças de conteúdo dependem da reconstrução periódica. |
291
+
292
+ ### Windows e o diário USN
293
+
294
+ O motor inclui um decodificador USN, um caminho rápido opcional e uma sonda. O caminho fica **desativado por padrão** (`windowsUsn: false`) porque o ioctl do volume exige privilégios de administrador; foi validado de ponta a ponta em um runner Windows do GitHub Actions (administrador, volume NTFS real):
295
+
296
+ - 1.345.546 registros MFT lidos, 1.345.539 caminhos resolvidos
297
+ - 164.209 entradas em `C:\Windows` (122.915 arquivos, 41.294 diretórios)
298
+ - `scan --usn --root C:\Windows` indexou 164.216 entradas em 7,8 s; uma consulta respondeu em 9,6 ms
299
+ - o diário de mudanças foi lido (8.233 registros em uma execução) e um diário inativo em `D:` caiu para a varredura com aviso
300
+
301
+ Teste você mesmo:
302
+
303
+ ```powershell
304
+ # PowerShell elevado (ou: Start-Process -Verb RunAs <caminho> ...)
305
+ & ".\bin\win32-x64\indexd.exe" usn-probe --volume C: --root "C:\Windows" --limit 5 --journal 5
107
306
  ```
108
307
 
109
- ## Configuração essencial
308
+ Ele imprime o id/USNs do diário, enumera a MFT (registros por segundo, arquivos/diretórios sob a raiz, caminhos de exemplo) e decodifica os últimos registros do diário. Sem elevação falha com `Access is denied`; o parser e a reconstrução de caminhos são cobertos por testes unitários em todas as plataformas.
110
309
 
111
- | Chave | Valor |
112
- |---|---|
113
- | `roots` | Diretórios indexados; vazio = diretório pessoal. |
114
- | `excludes` | Globs por nome (`node_modules`, `.git`, …). |
115
- | `watch` | Ativa notificações do sistema. |
116
- | `refreshIntervalMs` | Reconstrução periódica quando não há watcher nativo. |
117
- | `windowsUsn` | Caminho rápido USN/MFT (Windows, administrador; padrão `false`). |
118
- | `scanWorkers` | Leitores de diretório em paralelo; 0 = CPU. |
119
- | `contentIndex` | Constrói o índice de conteúdo de arquivos e sessões (padrão `true`). |
120
- | `contentLazy` | Constrói o índice de conteúdo na primeira busca de conteúdo em vez de na inicialização; `false` constrói em segundo plano desde o início (padrão `true`). |
121
- | `contentMaxFileBytes` | Bytes lidos de cada arquivo de texto (padrão `1000000`). |
122
- | `contentMaxTotalBytes` | Total de bytes de conteúdo mantido; `0` = sem limite (padrão `1000000000`). |
123
- | `contentMaxFiles` | Máximo de arquivos de texto indexados a cada execução; `0` = sem limite (padrão `200000`). |
124
- | `contentMaxSessions` | Sessões mais recentes indexadas; `0` = todas (padrão `100`). |
125
- | `contentRefreshMs` | Ritmo da atualização incremental de conteúdo; `0` desativa (padrão `300000`). |
126
- | `contentIncludeArchived` | Indexa também sessões arquivadas; padrão `false`. |
127
- | `contentActiveSessionDelayMs` | Só indexa um log de sessão depois de ficar quieto esse tempo (padrão `120000`). |
128
- | `contentSessionDirs` | Diretórios adicionais de sessões; vazio = `$DSH_HOME/sessions`. |
129
- | `contentExcludes` | Trechos de caminho que a busca por conteúdo ignora (dependências e toolchains); o índice de nomes continua igual. |
130
- | `stateDir` | Diretório do instantâneo; vazio = cache do sistema. |
131
-
132
-
133
- ## Plataformas
134
-
135
- | Plataforma | Varredura | Atualizações |
136
- |---|---|---|
137
- | Linux | varredura paralela | inotify recursivo |
138
- | Windows | varredura ou USN/MFT (admin) | `ReadDirectoryChangesW`; USN retoma após reinício |
139
- | macOS | varredura | FSEvents nos binários cgo; kqueue como fallback |
310
+ Com `windowsUsn: true` (ou `indexd scan --usn`) o motor enumera a MFT em vez de percorrer diretórios e monta caminhos a partir do mapa de pais FRN. Uma varredura USN bem-sucedida grava `usn-state.json` (id do diário, próximo USN, raízes) e mantém o FRN em cada registro; no próximo `serve --usn` o motor reproduz o diário a partir desse cursor antes de responder, então arquivos criados enquanto estava parado aparecem sem varredura completa. Um diário envolvido, apagado ou inconsistente cai para o watcher portátil. Ele mantém o handle do volume e consulta o diário a cada dois segundos, aplicando criações, exclusões e renomeações via `usn.ApplyChanges` (o mesmo mapa FRN, atualizado no local). Registros USN **não trazem tamanho nem data de modificação**: os resultados são corretos para nomes e caminhos, o `locator_status` marca esse índice com `USN`, e o daemon faz stat da página devolvida para que as linhas mostrem tamanhos e datas reais; filtros `size:`/`dm:` sobre o índice inteiro continuam aproximados até uma passada de metadados. Qualquer falha (sem elevação, volume não suportado, registros demais) cai para a varredura portátil com aviso; nunca desativa a busca.
140
311
 
141
- No Windows, `scan --usn` grava `usn-state.json` (id do diário, próximo USN, raízes) e `serve --usn` reproduz o diário antes de servir: um arquivo criado com o daemon parado aparece após reiniciar sem reescanear. Diário desatualizado ou removido cai no watcher portátil.
312
+ O Everything lê a Master File Table do NTFS pelo diário USN, e é por isso que seu primeiro índice é quase instantâneo. O `dsh-locator` mantém a varredura portátil como padrão (sem serviço, sem UAC, qualquer sistema de arquivos) e usa USN/MFT como caminho rápido opcional onde o processo tem `GENERIC_READ` (administrador), com reprodução do diário entre reinícios. O caminho portátil continua sendo o fallback.
142
313
 
143
- ## Desempenho
314
+ ## Solução de problemas
144
315
 
145
- Conteúdo medido na mesma máquina (cache quente): 20.000 arquivos / 40 MB → 15,1 s e 71 MB; 200.000 arquivos / 331 MB → 31,5 s e 711 MB; atualização incremental do índice completo (1,3 M entradas) 2,9 s; reiniciar reaproveita o banco e leva 4,6 s no corpus de 200.000 arquivos. O banco ocupa 2–3 vezes o texto indexado.
316
+ **O painel não aparece depois de instalar.**
317
+ Recarregue a página (`F5`); confirme que instalou no perfil `web` e que o painel carrega do boot graph. Perfis headless/TUI nunca montam painel.
146
318
 
147
- - 1,2 M de entradas: consulta a quente 25–35 ms; busca durante a varredura ~2 ms.
148
- - `C:\Windows` (164.216 entradas) indexado por USN em 7,8 s num runner de CI; consulta 9,6 ms.
149
- - `locator_export` de 1,24 M de linhas: 477 MB, 6,4 s.
319
+ **Um arquivo recém-criado não aparece.**
320
+ A notificação pode não ter chegado (comum com gravações do WSL em `/mnt/c`, compartilhamentos de rede e alguns overlays de contêiner). Espere um instante ou rode `locator_rebuild` para essa raiz. O modo USN reproduz o diário ao reiniciar.
150
321
 
151
- ## Design
322
+ **A busca de conteúdo não devolve nada.**
323
+ Veja `building` no resultado do `locator_find`: a primeira busca dispara a construção preguiçosa e os resultados podem ser parciais até terminar (o painel consulta de novo sozinho). Confirme também que a extensão é de texto, o arquivo não passa de `contentMaxFileBytes`, não é excluído por `contentExcludes` e a sessão não está arquivada (arquivadas são ignoradas por padrão).
324
+
325
+ **O banco de conteúdo está enorme / o disco cresce rápido.**
326
+ Veja [Desempenho e recursos](#desempenho-e-recursos): reduza o orçamento ou use `contentIndex: false`. Apagar `stateDir` dispara uma reconstrução.
152
327
 
153
- ![Arquitetura do dsh-locator: sistemas de arquivos → varredura/vigilância → instantâneo compacto → motor de consulta → ferramentas / painel](docs/assets/architecture.svg)
328
+ **Aparece um aviso de `inotify`.**
329
+ Diretórios demais atingem o limite do kernel; o índice continua utilizável e as mudanças dependem de reconstruções periódicas. Aumente `fs.inotify.max_user_watches` ou reduza `roots`.
154
330
 
155
- * **Varredura paralela**: fila limitada e lotes por diretório para o pai existir antes dos filhos.
156
- * **Memória**: registros de 40 B, nomes numa arena compartilhada, tabela de caminhos aberta; o caminho completo só é reconstruído ao devolver resultados.
157
- * **Consulta**: termos compilados uma vez, divididos em fragmentos e um heap limitado escolhe `offset+limit`.
158
- * **Persistência**: arquivo temporário + rename atômico; o instantâneo é a fonte de inicialização.
159
- * **Protocolo**: NDJSON por stdio; sem porta nem superfície de rede.
331
+ **O comportamento mudou após atualizar.**
332
+ Rode `dsh plugin --profile web add dsh-locator@latest` e `F5`. Uma mudança de esquema do conteúdo reconstrói o banco uma vez. Veja o [CHANGELOG](CHANGELOG.md).
160
333
 
161
- ## Compilar do código
334
+ ## Compilar a partir do código-fonte
162
335
 
163
- Requer Node `^22.19 || >=24.9`, pnpm e Go 1.22+.
336
+ Requisitos: Node `^22.19 || >=24.9`, pnpm e Go 1.22+ para o motor.
164
337
 
165
338
  ```sh
166
339
  pnpm install
167
340
  pnpm build
168
- pnpm build:engine:all
169
- pnpm check
341
+ pnpm build:engine:all # ou build:engine para a plataforma atual
342
+ pnpm check # typecheck + testes + verificação de empacotamento/instalação
170
343
  ```
171
344
 
172
- O motor Go fica em `engine/`; testes: `cd engine && go test ./...`.
345
+ O motor é um módulo Go separado em `engine/`; seus testes rodam com `cd engine && go test ./...`. O backend FSEvents do macOS precisa de cgo e é compilado no CI de macOS. Os testes Node rodam em Linux, Windows e macOS no CI.
173
346
 
174
- ## Limites
347
+ ## Design
348
+
349
+ ![Arquitetura do dsh-locator: sistemas de arquivos → varredura/vigilância → snapshot compacto → motor de consulta → ferramentas do agente / painel web](docs/assets/architecture.svg)
350
+
351
+ ```
352
+ DeepSeek Harness
353
+ └─ dsh-locator (plugin TypeScript)
354
+ ├─ locator_search / locator_find / locator_status / locator_rebuild /
355
+ │ locator_reindex / locator_export
356
+ ├─ client.js: overlay Ctrl+Shift+F (slot shell.overlay)
357
+ ├─ POST /dsh-locator/{search,content,status,reveal,open} (mesma origem)
358
+ ├─ armazenamento de conteúdo: SQLite FTS5 (trigram) no processo anfitrião,
359
+ │ consultas em worker thread
360
+ └─ processo filho: indexd serve (Go, NDJSON por stdio)
361
+ ├─ scanner: varredura recursiva, exclusões, progresso
362
+ ├─ index: arena de nomes + registros fixos + tabela de caminhos aberta
363
+ ├─ query: parser, matcher, seleção top-K, ordenação, paginação
364
+ ├─ watcher: inotify (Linux) / ReadDirectoryChangesW (Windows)
365
+ └─ snapshot: arquivo único, mmap-friendly, renomeação atômica
366
+ ```
367
+
368
+ - **Scanner paralelo.** Leitores de diretório drenam uma fila limitada e gravam um lote por diretório (`AddBatch`), então o registro pai existe antes dos filhos entrarem na fila. A fila não bloqueia: se estiver cheia, aquela subárvore é varrida em linha.
369
+ - **Layout de memória.** Registros guardam deslocamento/comprimento do nome em uma arena de bytes e um id de pai; caminhos completos só são reconstruídos para a página de resultados e filtros `path:`. Isso evita um cabeçalho de string por arquivo.
370
+ - **Tabela de caminhos.** Uma tabela de endereçamento aberto com slots `id+1` mantém busca/atualização perto de 12 bytes por entrada em vez dos ~50 de um `map[string]int32`.
371
+ - **Motor de consulta.** Termos e filtros são compilados uma vez, comparados em blocos paralelos e reduzidos com um max-heap limitado: as `offset+limit` linhas são selecionadas sem ordenar milhões de correspondências.
372
+ - **Índice de conteúdo.** SQLite FTS5 no host com tokenizador trigram (substrings UTF-8, CJK); a lista de arquivos vem da própria varredura do motor e logs de sessão são descomprimidos com zstd do Node.
373
+ - **Consistência do conteúdo.** Um lock de construção por processo serializa escritores que compartilham `stateDir`, uma marca de construção completa força reconstrução após uma interrompida, e um handle obsoleto é detectado por dispositivo+inode para que a reconstrução de outro processo não deixe o host lendo um banco desvinculado.
374
+ - **Persistência.** O snapshot é gravado em arquivo temporário e renomeado; um contador de geração permite ao daemon salvar só quando o índice mudou. Lápides são compactadas quando as exclusões passam de um limite.
375
+ - **Protocolo.** Uma requisição/resposta JSON por linha em stdio, com eventos `scan`, `stats`, `warning`, `error` e `rebuilt`. Sem portas, sem superfície de autenticação, sem listeners de rede.
376
+ - **Somente leitura.** O motor abre arquivos apenas para metadados; nunca escreve nos caminhos indexados.
377
+
378
+ ## Limitações
175
379
 
176
- * A busca por conteúdo lê apenas arquivos de texto (por extensão) e os logs de sessão do DSH; PDFs, documentos do Office e imagens não têm o texto extraído. Por padrão o corpo indexado fica limitado a 1 GB / 200.000 arquivos, então um diretório pessoal enorme guarda só a primeira fatia alcançada.
177
- * Não é um driver de sistema de arquivos; cobre apenas as raízes configuradas.
178
- * inotify usa um descritor por diretório; árvores enormes podem estourar o limite do kernel (há aviso e o instantâneo continua utilizável).
179
- * Escritas do WSL em `/mnt/c` podem não gerar notificações do Windows; reconstrua essas raízes.
180
- * macOS: FSEvents nos binários publicados; kqueue (máx. 4.096 diretórios) em builds `CGO_ENABLED=0`. Mudanças de conteúdo dependem da reconstrução periódica.
380
+ - A busca de conteúdo lê apenas arquivos de texto (por extensão) e logs de sessão do DSH; PDF, Office e imagens não têm texto extraído.
381
+ - O orçamento de conteúdo é consumido na ordem de varredura, não por importância do arquivo; arquivos posteriores não são buscáveis ao atingir o limite (`truncated` é true).
382
+ - O índice cobre as raízes configuradas; não é um driver do sistema de arquivos.
383
+ - O inotify do Linux vigia um descritor por diretório; um diretório pessoal com centenas de milhares de diretórios pode exceder o limite do kernel. O plugin avisa e o snapshot continua utilizável; reconstruções se recuperam.
384
+ - Gravações do WSL em `/mnt/c` podem não produzir notificações do Windows (o watcher não vê o fluxo do escritor 9p). Reconstrua essas raízes.
385
+ - Compartilhamentos de rede só são varridos se acessíveis como diretórios comuns; não há feed de mudanças específico de SMB.
386
+ - O conteúdo das sessões vem de logs locais; mensagens ainda não gravadas em disco não são buscáveis.
387
+ - Dois processos do DSH compartilhando um `stateDir` devem ser evitados: o lock de construção serializa escritores, mas não compartilha um handle de banco aberto.
388
+ - O macOS usa FSEvents (recursivo) nos binários publicados; uma compilação com `CGO_ENABLED=0` cai para kqueue, limitado a 4.096 diretórios, com mudanças de conteúdo dependendo da reconstrução periódica.
389
+ - USN/MFT do Windows é opcional e só é usado se o processo puder ler o volume e o diário estiver ativo; caso contrário, usa-se a varredura portátil.
390
+
391
+ - Resultados no corpo de arquivos abrem o gerenciador de arquivos por enquanto (a visualização por linha dentro do DSH é o próximo passo); mensagens do assistente são localizadas por frase porque as linhas do DOM não carregam o messageId.
392
+ - O destaque dentro da conversa usa a API CSS Custom Highlight; navegadores antigos sem ela caem para um contorno na linha.
393
+
394
+ ## Memória
395
+
396
+ O motor é um único processo Go e respeita as variáveis padrão `GOMEMLIMIT` e `GOGC` (ou `memoryLimitMB` na configuração). Um índice de 1,2–1,5 M de entradas chega a várias centenas de MB de RSS com o GC padrão; use `GOMEMLIMIT=600MiB` (limite suave, o runtime troca CPU por memória) ou `GOGC=50` quando o host estiver apertado de RAM. Nenhum altera o formato do snapshot. Na instalação ao vivo usada para os números acima, o processo anfitrião do DSH (incluindo o cache de páginas do banco de conteúdo) ficava por volta de 700 MB de RSS com o índice construído, e a latência do host ocioso permanecia em p50 2 ms.
181
397
 
182
398
  ## Segurança e privacidade
183
399
 
184
- O banco de dados de conteúdo e o bloqueio de compilação são criados com permissões `0600`, e o diretório de estado com `0700`: outros usuários locais não podem ler os documentos indexados nem o texto das sessões.
400
+ - O índice é local: sem chamadas de rede, sem telemetria, sem uploads. O plugin nunca modifica, move ou apaga arquivos indexados.
401
+ - O banco de conteúdo e o lock de construção são criados `0600`, e o diretório de estado `0700`: outros usuários locais não conseguem ler documentos indexados nem o texto de sessões.
402
+ - O snapshot e o banco de conteúdo contêm nomes, caminhos e corpos; trate o diretório de estado como dado privado. Apagá-lo limpa o cache.
403
+ - Dê a cada processo concorrente do DSH um `stateDir` separado.
404
+
405
+ ## Versão e compatibilidade
406
+
407
+ - Node `^22.19.0 || >=24.9.0`; DSH `>=0.2.1-rc.2 <0.3.0` (veja `engines` no `package.json`).
408
+ - As versões são publicadas com procedência do GitHub Actions, então a origem do pacote npm é verificável; Gitee / GitCode são sincronizados por um workflow de espelho.
409
+ - Registro de mudanças: [CHANGELOG.md](CHANGELOG.md); dúvidas e relatos: [Issues](https://github.com/PerryLink/dsh-locator/issues).
410
+
411
+ ## Roteiro
412
+
413
+ Não é um compromisso, apenas a direção atual:
185
414
 
186
- O índice é local: sem rede, sem telemetria, sem uploads. O instantâneo contém nomes e caminhos; trate-o como dado privado. O plugin nunca modifica, move ou apaga os arquivos indexados.
415
+ 1. Verificar o runtime desktop Electron em uma instalação real do Windows.
416
+ 2. Pré-visualizações e agrupamento de resultados no painel.
417
+ 3. Cobertura de runtime em Windows on ARM / Linux ARM.
418
+ 4. Arena de nomes em minúsculas e pré-filtro trigram para índices muito grandes.
419
+ 5. Compactação incremental do snapshot e diários por raiz.
187
420
 
188
421
  ## Licença
189
422