sqlite-graphrag 1.0.90

Persistent GraphRAG memory for Claude Code, Codex, Cursor, and 24+ AI agents in a single 14.6 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). No daemon. No ONNX runtime. No model download. Graph-native retrieval with FTS5 + cosine + multi-hop traversal. OAuth-only enforcement: API keys ABORT the spawn.
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
---
name: sqlite-graphrag
description:Para memória persistente, GraphRAG, ou contexto de longo prazo em Claude Code, Codex, OpenCode, Cursor, Windsurf, agentes AI. Em: lembrar, salvar, recuperar, busca híbrida, grafo entidades, memória SQLite, RAG local, embedding LLM-only, OAuth, BLOB-backed, migrate, embedding-dim, llm-parallelism, re-embed, force-reembed, OAuth-only, endurecimento codex claude opencode, mock LLM CI, ADR-0041 ADR-0051, OpenRouter Bedrock, --dry-run-backend, backend_invoked, preflight exit 16, llm-backend codex claude opencode none auto, llm-model gpt-5.4-mini claude-sonnet-4-6 opencode/big-pickle, headless fallback chain, v1.0.86-v1.0.90. KW: memória RAG GraphRAG SQLite one-shot OAuth offline persistente grafo entidade opencode codex claude.
---


## Versão Atual (v1.0.90)
- Versão atual do binário: v1.0.90 (lançada em 2026-06-22)
- Versão atual do schema: v15 (após init ou migrate em banco fresco)
- Esta skill documenta features de v1.0.86 até v1.0.90
- Versões anteriores (v1.0.85.2 e abaixo) estão fora do escopo
- Para versões mais antigas, consulte o histórico git desta skill


## Quando Esta Skill Ativa
- USE quando o usuário pede para lembrar, salvar, recordar, recuperar, buscar, ou persistir algo entre sessões
- USE para contexto de longo prazo, grafo de conhecimento, GraphRAG, RAG, ligação de entidades, gestão de memória
- USE quando sqlite, sqlite-graphrag, embedding, FTS5, hybrid-search, ou memória LLM for mencionado
- NÃO USE para dados efêmeros pontuais, I/O simples de arquivo, ou tarefas sem relação a contexto persistente


## Regras de Instrução para LLMs (Prompt Rules)
- QUANDO usuário disser "lembre disso", "salve isso", "persista isso" → EXECUTE `remember --force-merge` com `--graph-stdin` incluindo entidades curadas e relações canônicas
- QUANDO usuário perguntar "o que você sabe sobre X", "recall X", "busque X" → EXECUTE `hybrid-search "X" --k 10 --json` PRIMEIRO, depois EXPANDA resultados top com `read --name <nome> --json`
- QUANDO usuário perguntar "como X se relaciona com Y" → EXECUTE `graph traverse --from X --depth 2 --json` ou `related X --hops 2 --json`
- QUANDO usuário pedir "pesquise profundamente sobre X" → EXECUTE `deep-research "X" --k 20 --max-hops 3 --json`
- ANTES de criar QUALQUER memória → EXECUTE `hybrid-search "<nome ou descrição>" --k 5 --json` para VERIFICAR duplicatas; se encontrar, USE `--force-merge` para ATUALIZAR em vez de criar nova
- APÓS criar ou atualizar memória → VERIFIQUE com `read --name <nome> --json | jaq '{name, description, body_length}'`
- APÓS CADA turno com achados novos → AVALIE se deve persistir via `remember --force-merge`; se nada novo, DECLARE "Nenhum achado novo para persistir neste turno"
- QUANDO exit code for não-zero → LEIA envelope JSON de erro do stdout (`jaq '{code, message, error_class}'`), REPORTE ao usuário com passos de remediação
- QUANDO exit code 9 (duplicada) → RETENTE com flag `--force-merge`
- QUANDO exit code 19 (SHUTDOWN) → RETRY OBRIGATÓRIO; trabalho parcial foi descartado
- QUANDO exit code 75 (singleton locked) → AGUARDE e retente; NÃO aumente concorrência
- QUANDO exit code 16 (preflight) → CORRIJA o problema de config MCP; NÃO bypass com `SKIP_PREFLIGHT`
- SEMPRE parseie saída JSON com `jaq` (NUNCA `jq`)
- SEMPRE passe flag `--json` em toda invocação de `sqlite-graphrag`
- SEMPRE use `--llm-backend codex --llm-model gpt-5.4-mini` OU `--llm-backend claude --llm-model claude-sonnet-4-6` OU `--llm-backend opencode --llm-model opencode/big-pickle` para comandos de embedding
- SEMPRE use APENAS relações canônicas: `applies-to`, `uses`, `depends-on`, `causes`, `fixes`, `contradicts`, `supports`, `follows`, `related`, `mentions`, `replaces`, `tracked-in`
- SEMPRE mapeie relações não-canônicas ANTES de persistir: `adds|creates → causes`, `implements → supports`, `blocks → contradicts`, `tested-by → related`, `part-of → applies-to`
- SEMPRE normalize nomes de entidade para kebab-case ASCII lowercase ANTES de passar à CLI
- NUNCA use MCP Serena ou arquivos `.md` de memória para persistência
- NUNCA escreva MEMORY.md ou qualquer memória baseada em arquivo
- NUNCA inicie ou referencie daemon (removido na v1.0.76)
- NUNCA passe `ANTHROPIC_API_KEY` ou `OPENAI_API_KEY` no ambiente
- PREFIRA `remember --force-merge` sobre `edit` para atualizações para garantir re-indexação
- PREFIRA `--graph-stdin` com entidades curadas sobre `--enable-ner` para qualidade de extração
- LIMITE entidades do grafo a conceitos específicos do domínio: projetos, ferramentas, pessoas, decisões, arquivos, incidentes
- REJEITE palavras genéricas, pronomes, UUIDs, hashes, timestamps como nomes de entidade
```bash
# REGRA: SEMPRE verifique duplicatas ANTES de criar memória
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  hybrid-search "auth JWT design" --k 5 --json | jaq '.results[].name'
# Se encontrar: ATUALIZE com --force-merge
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name decisao-auth --type decision --force-merge \
  --description "Estrategia JWT atualizada" --body-file auth.md

# REGRA: SEMPRE use --graph-stdin com entidades curadas e relações canônicas
echo '{"body":"JWT com 15 min de expiracao","entities":[{"name":"jwt","entity_type":"concept"},{"name":"servico-auth","entity_type":"tool"}],"relationships":[{"source":"servico-auth","target":"jwt","relation":"uses","strength":0.9}]}' \
  | sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
    remember --name decisao-auth --type decision --description "Rotacao JWT" --graph-stdin --force-merge

# REGRA: SEMPRE verifique após escrita
sqlite-graphrag read --name decisao-auth --json | jaq '{name, description, body_length}'

# REGRA: QUANDO exit 9 (duplicada) → retente com --force-merge
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name mem-existente --type note --description "x" --body "y" --force-merge
```


## Princípios Fundamentais
- INVOKE sempre como subprocesso via `std::process::Command`
- READ stdout para dados estruturados JSON ou NDJSON
- READ stderr para logs de tracing e mensagens humanas
- CHECK exit code ANTES de parsear stdout
- TRUST em contratos JSON como API versionada por SemVer
- SAIBA que BUILD é LLM-only e one-shot; binário tem 14.6 MiB stripped ELF (NÃO 6 MB como em docs antigos)
- SAIBA que BUILD NÃO tem daemon, NÃO tem ONNX runtime, NÃO tem cache de modelo
- SAIBA que OAUTH-ONLY: spawn ABORTA exit 1 se `ANTHROPIC_API_KEY` estiver setada
- SAIBA que OAUTH-ONLY: spawn ABORTA exit 1 se `OPENAI_API_KEY` estiver setada
- PASSE NAMESPACE por projeto via `--namespace <ns>` ou env
- SAIBA que NAMESPACE default é `global` quando omitido
- NUNCA exponha o binário como servidor MCP ou serviço HTTP
- NUNCA escreva arquivo `.sqlite` em paralelo ao binário
- NUNCA edite o arquivo `.sqlite` a partir de outra ferramenta
```bash
# INVOQUE sempre como subprocesso e verifique o exit code ANTES de parsear stdout
sqlite-graphrag health --json | jaq '.integrity_ok'
echo "exit=$?"
```


## Cartão de Referência Rápida
- INIT primeira vez: `sqlite-graphrag init --namespace <ns>`
- VERIFIQUE saúde: `sqlite-graphrag health --json | jaq '.integrity_ok'`
- ARMAZENE (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini remember --name <kebab> --type note --description "x" --body "y"`
- ARMAZENE (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 remember --name <kebab> --type note --description "x" --body "y"`
- ARMAZENE (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle remember --name <kebab> --type note --description "x" --body "y"`
- INGIRA pasta (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini ingest ./docs --mode codex --recursive --pattern "*.md" --type document --json`
- INGIRA pasta (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 ingest ./docs --mode claude-code --recursive --pattern "*.md" --type document --json`
- INGIRA pasta (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle ingest ./docs --mode opencode --recursive --pattern "*.md" --type document --json`
- BUSQUE semântica (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini recall "query" --k 5 --json`
- BUSQUE semântica (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 recall "query" --k 5 --json`
- BUSQUE semântica (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle recall "query" --k 5 --json`
- BUSQUE híbrida (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini hybrid-search "query" --k 10 --rrf-k 60 --json`
- BUSQUE híbrida (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 hybrid-search "query" --k 10 --rrf-k 60 --json`
- BUSQUE híbrida (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle hybrid-search "query" --k 10 --rrf-k 60 --json`
- PESQUISE profunda (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini deep-research "question" --k 20 --max-hops 3 --json`
- PESQUISE profunda (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 deep-research "question" --k 20 --max-hops 3 --json`
- PESQUISE profunda (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle deep-research "question" --k 20 --max-hops 3 --json`
- ENRIQUEÇA (Codex): `sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini enrich --operation re-embed --limit 100 --resume --json`
- ENRIQUEÇA (Claude): `sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 enrich --operation memory-bindings --mode claude-code --json`
- ENRIQUEÇA (OpenCode): `sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle enrich --operation re-embed --limit 100 --resume --json`
- LEIA (sem embedding): `sqlite-graphrag read --name <kebab> --json | jaq '{name, description, body_length}'`
- LISTE (sem embedding): `sqlite-graphrag list --type decision --limit 50 --json | jaq '.items[].name'`
- TRAVESSE grafo (sem embedding): `sqlite-graphrag graph traverse --from <entity> --depth 2 --json`
- VEJA stats do grafo (sem embedding): `sqlite-graphrag graph stats --json | jaq '{node_count, edge_count, avg_degree}'`
- LIGUE entidades (sem embedding): `sqlite-graphrag link --from jwt --to servico-auth --relation uses --weight 0.8 --create-missing --json`
- DELEÇÃO física (sem embedding): `sqlite-graphrag forget --name <n>` depois `purge --retention-days 30 --yes`


## Inicialização, Saúde e Config Global
- EXECUTE `sqlite-graphrag init --namespace <ns>` no primeiro uso
- EXECUTE `health --json` para verificar `integrity_ok` e `schema_ok`
- VERIFIQUE `schema_version >= 15` após `init` ou `migrate`
- EXECUTE `migrate --json` após cada upgrade do binário
- USE `migrate --to-llm-only --drop-vec-tables --json` para bancos v1.0.74 ou v1.0.75
- USE `migrate --rehash --json` para reparar drift de checksum SipHasher13 V002
- USE `migrate --dry-run --json` para PREVIEW de migrações pendentes sem aplicar
- TRATE exit code 10 como erro de banco; execute `vacuum` e `health`
- TRATE exit code 15 como ocupado; amplie `--wait-lock`
- TRATE exit code 16 como falha preflight (v1.0.87+); corrija config MCP ou defina `SQLITE_GRAPHRAG_SKIP_PREFLIGHT=1`
- ABORTE pipeline quando `integrity_ok` retornar `false`
- EXECUTE `optimize --json` para refrescar estatísticas do planner; resposta inclui `fts_rebuilt`
- USE `optimize --skip-fts --json` quando FTS5 foi reconstruído recentemente
- EXECUTE `fts rebuild --json` quando `health.fts_degraded` for true
- INSPECIONE `wal_size_mb` em `health` para fragmentação
- VERIFIQUE `journal_mode` igual a `wal` em produção
- USE `debug-schema --json` para troubleshooting de drift de schema
- PASSE `--db <PATH>` para sobrescrever localização do banco (agora aceito em `embedding status/list/abandon`, `pending list/show` desde v1.0.89, ADR-0049)
- PASSE `--namespace <NS>` em `health` desde v1.0.89 para filtrar contagens para um namespace
- DEFINA env `SQLITE_GRAPHRAG_DB_PATH` para configuração persistente
- DEFINA env `SQLITE_GRAPHRAG_NAMESPACE` para namespace persistente
- PASSE `--lang en` ou `--lang pt` para forçar idioma do stderr
- PASSE `--tz America/Sao_Paulo` para localizar timestamps
- DEFINA env `SQLITE_GRAPHRAG_DISPLAY_TZ` para timezone persistente
- DEFINA `SQLITE_GRAPHRAG_LOG_FORMAT=json` para agregadores de log
- USE `-v` para info, `-vv` para debug, `-vvv` para trace
- ATIVE `SQLITE_GRAPHRAG_LOW_MEMORY=1` em containers restritos
- DEFINA env `SQLITE_GRAPHRAG_EMBEDDING_DIM` na faixa `[8, 4096]` (default 64 MRL)
- DEFINA `SQLITE_GRAPHRAG_STRICT_ENV_CLEAR=1` para modo compliance (ADR-0041)
- DEFINA `SQLITE_GRAPHRAG_IGNORE_SHUTDOWN=1` APENAS para harnesses de teste CI
- USE valores válidos de `--type`: `user`, `feedback`, `project`, `reference`, `decision`, `incident`, `skill`, `document`, `note`
- CONHEÇA as FLAGS globais: `--db`, `--namespace`, `--lang`, `--tz`, `--json`, `--low-memory`, `--max-concurrency N`, `--wait-lock SECS`, `--llm-parallelism N`, `--llm-backend claude|codex|opencode|none|auto[,fallback...]`, `--llm-model <MODEL>`, `--dry-run-backend`, `--llm-fallback-mode <claude|codex|opencode>`, `--graceful-shutdown-secs N`, `--claude-binary <PATH>`, `--codex-binary <PATH>`, `--opencode-binary <PATH>`, `--opencode-model <MODEL>`, `--opencode-timeout <SECS>`, `--skip-embedding-on-failure`
```bash
# INICIALIZE namespace, VERIFIQUE saúde e CONFIRME schema_version
sqlite-graphrag init --namespace meuprojeto
sqlite-graphrag health --json | jaq '{integrity_ok, schema_ok, schema_version}'

# PREVIEW de migrações pendentes ANTES de aplicar
sqlite-graphrag migrate --dry-run --json | jaq '.would_apply[]? | {name, version}'

# APLIQUE migração após upgrade do binário
sqlite-graphrag migrate --json | jaq '{applied, schema_version}'

# FORCE idioma do stderr e timezone de exibição
sqlite-graphrag --lang pt --tz America/Sao_Paulo health --json | jaq '.integrity_ok'

# DEFINA config persistente via env vars
export SQLITE_GRAPHRAG_DB_PATH=/data/projeto.sqlite
export SQLITE_GRAPHRAG_NAMESPACE=meuprojeto
sqlite-graphrag health --json | jaq '.db_path'
```


## Contrato de Arquitetura (OAuth/LLM/One-Shot)
- SAIBA que BUILD é LLM-only; build padrão NÃO tem `fastembed`, `ort`, `ndarray`, `tokenizers`, `huggingface-hub`, `sqlite-vec`, `GLiNER`
- SAIBA que BUILD removeu subcomando `daemon` inteiramente (ADR-0021)
- SAIBA que COSINE similarity é pure Rust em `src/similarity.rs`
- SAIBA que COSINE roda sobre `memory_embeddings`, `entity_embeddings`, `chunk_embeddings` com BLOB
- SAIBA que SCHEMA é v15 após `init` ou `migrate` em banco fresco
- SAIBA que MIGRAÇÃO V013 dropa virtual tables `vec_memories`, `vec_entities`, `vec_chunks`
- SAIBA que MIGRAÇÃO V014 cria tabela de checkpoint `pending_memories`
- SAIBA que MIGRAÇÃO V015 cria fila de retry `pending_embeddings`
- SAIBA que OAUTH-ONLY: `ANTHROPIC_API_KEY` ABORTA spawn com `AppError::Validation` (ADR-0011)
- SAIBA que OAUTH-ONLY: `OPENAI_API_KEY` ABORTA spawn com `AppError::Validation` (ADR-0011)
- SAIBA que OAUTH-ONLY: ambas API keys EXCLUÍDAS do whitelist de env-clear
- SAIBA que OAUTH-ONLY: flag `--bare` REMOVIDA de todos os caminhos executáveis
- SAIBA que OAUTH-ONLY: 7 flags de endurecimento SEMPRE passadas para `claude -p`
- CONHEÇA as FLAGS de endurecimento para claude: `--model claude-sonnet-4-6 --strict-mcp-config --mcp-config '{}' --settings '{"hooks":{}}' --dangerously-skip-permissions --output-schema`
- CONHEÇA as FLAGS de endurecimento para codex: `--model gpt-5.5 --json --output-schema --ephemeral --skip-git-repo-check --sandbox read-only --ignore-user-config --ignore-rules -c mcp_servers='{}' --ask-for-approval never`
- SAIBA que ADR-0041 v1.0.83: `ANTHROPIC_AUTH_TOKEN` PRESERVADA para providers Anthropic-compatíveis
- SAIBA que ADR-0041 v1.0.83: `ANTHROPIC_BASE_URL` PRESERVADA para endpoints customizados
- SAIBA que ADR-0041 v1.0.83: `OPENAI_BASE_URL` PRESERVADA para endpoints OpenAI-compatíveis
- SAIBA que ADR-0041 v1.0.83: `CLAUDE_CODE_ENTRYPOINT`, `DISABLE_TELEMETRY`, `OTEL_EXPORTER_OTLP_ENDPOINT` PRESERVADAS
- SAIBA que ADR-0041 v1.0.83: providers suportados incluem OpenRouter, AWS Bedrock, gateways corporativos
- SAIBA a PRECEDÊNCIA de DIM de embedding: env `SQLITE_GRAPHRAG_EMBEDDING_DIM` depois `schema_meta.dim` depois default 64 MRL
- SAIBA que DIM de embedding adapta tamanho de lote: base 8 chunks / 25 nomes de entidade em dim 64
- USE MOCK LLM CLI para CI: prefixe `tests/mock-llm` ao PATH
- USE a RECEITA de bypass de SHUTDOWN: `PATH=tests/mock-llm:$PATH SQLITE_GRAPHRAG_IGNORE_SHUTDOWN=1 setsid -w timeout 120 sqlite-graphrag …`
- NUNCA instale com `--features embedding-legacy` ou `--features ner-legacy`
- NUNCA dependa do daemon ou flag `--bare` (REMOVIDOS em v1.0.76 e v1.0.79)
- NUNCA misture queries em `vec_memories` (REMOVIDO em v1.0.76)
- NUNCA chame `migrate --to-llm-only` sem guarda de segurança `--drop-vec-tables`
```bash
# CONFIRME que o build é OAuth-only: ANTHROPIC_API_KEY aborta com exit 1
ANTHROPIC_API_KEY=sk-test sqlite-graphrag init --namespace x 2>&1 || echo "exit=$?"

# CONFIRME que OPENAI_API_KEY também aborta com exit 1
OPENAI_API_KEY=sk-test sqlite-graphrag init --namespace x 2>&1 || echo "exit=$?"

# PRESERVE provider customizado via ANTHROPIC_BASE_URL (ADR-0041, OpenRouter/Bedrock)
export ANTHROPIC_BASE_URL=https://openrouter.ai/api/v1
export ANTHROPIC_AUTH_TOKEN=sk-or-...
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name nota --type note --description x --body y
```


## Seleção de Backend LLM — Codex, Claude e OpenCode Headless
- NOTA: exemplos dedicados do OpenCode estão na seção "Seleção de Backend LLM — OpenCode Headless (v1.0.90)" abaixo
- PASSE `--llm-backend codex` para FORÇAR backend Codex em comandos de embedding
- PASSE `--llm-backend claude` para FORÇAR backend Claude Code headless em comandos de embedding
- PASSE `--llm-model <MODEL>` para selecionar o modelo de embedding em QUALQUER backend (v1.0.89, ADR-0050)
- SAIBA que o DEFAULT de `--llm-backend` é `codex`
- SAIBA que o MODELO padrão para backend codex é `gpt-5.5` e para backend claude é `claude-sonnet-4-6`
- PASSE `--llm-backend codex,claude` para codex-PRIMEIRO com fallback claude (ADR-0038)
- PASSE `--llm-backend claude,codex` para claude-PRIMEIRO com fallback codex
- PASSE `--llm-backend codex,claude,none` para cair em embedding null quando ambos falharem
- PASSE `--llm-fallback-mode <claude|codex>` para trocar backend mid-job em rate-limit
- PASSE `--skip-embedding-on-failure` APENAS quando `--llm-backend …,none` está ativo
- PASSE `--dry-run-backend` para PLANEJAR a operação de backend sem executá-la (preview idempotente)
- PARSEE o campo `backend_invoked` no envelope para CONFIRMAR o backend efetivo
- DEFINA env `SQLITE_GRAPHRAG_LLM_BACKEND` para fixar backend de forma persistente
- DEFINA env `SQLITE_GRAPHRAG_LLM_MODEL` para fixar modelo de forma persistente
- DEFINA env `SQLITE_GRAPHRAG_CODEX_BINARY` para sobrescrever o path do binário codex
- PASSE `--codex-binary <PATH>` para sobrescrever o path do binário codex inline
- PASSE `--claude-binary <PATH>` para sobrescrever o path do binário claude inline
- SAIBA que backend claude divide-se em embedder local via `embed_via_claude_local` (zero-token, compatível com OAuth)
- USE `LlmEmbeddingBuilder` para compor pipeline: `with_backend(Codex).or_fallback(Claude).or_skip()`
- EXECUTE `codex login` após upgrade para refrescar o refresh token OAuth do codex
- ATUALIZE OAuth do claude quando erro de OAuth expirado for reportado
- NUNCA passe `--llm-backend codex` esperando que ele use credenciais de API key (OAuth-only, exit 1)
```bash
# BACKEND Codex headless — gpt-5.4-mini explícito
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT com rotacao" --body "15 min de expiracao com refresh"

# BACKEND Claude Code headless — claude-sonnet-4-6 explícito
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT com rotacao" --body "15 min de expiracao com refresh"

# CODEX exclusivo — FALHA em erro, sem fallback
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "autenticacao JWT" --k 5 --json | jaq '.backend_invoked'

# CODEX-PRIMEIRO com fallback claude — cadeia de fallback
sqlite-graphrag --llm-backend codex,claude --llm-model gpt-5.5 \
  hybrid-search "fluxo de auth" --k 10 --json | jaq '.backend_invoked'

# CADEIA tripla — codex, depois claude, depois embedding null
sqlite-graphrag --llm-backend codex,claude,none --skip-embedding-on-failure \
  remember --name nota --type note --description x --body y | jaq '.backend_invoked'

# DRY-RUN do backend — PLANEJE sem executar (preview idempotente)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini --dry-run-backend \
  recall "query" --k 5 --json | jaq '{backend_invoked, planned: true}'

# CONFIGURE backend codex persistente via env vars
export SQLITE_GRAPHRAG_LLM_BACKEND=codex
export SQLITE_GRAPHRAG_LLM_MODEL=gpt-5.4-mini
export SQLITE_GRAPHRAG_CODEX_EMBED_MODEL=gpt-5.4-mini
sqlite-graphrag recall "query" --k 5 --json | jaq '.backend_invoked'

# CONFIGURE backend claude persistente via env vars
export SQLITE_GRAPHRAG_LLM_BACKEND=claude
export SQLITE_GRAPHRAG_LLM_MODEL=claude-sonnet-4-6
sqlite-graphrag hybrid-search "query" --k 10 --json | jaq '.backend_invoked'

# SOBRESCREVA path do binario codex
export SQLITE_GRAPHRAG_CODEX_BINARY=/usr/local/bin/codex
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini recall "query" --k 5 --json

# SOBRESCREVA path do binario claude inline
sqlite-graphrag --claude-binary /usr/local/bin/claude --llm-backend claude \
  remember --name x --type note --description "x" --body "y"

# REFRESQUE OAuth do codex quando token expirar
codex login
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini recall "query" --k 5 --json
```


## Seleção de Backend LLM — OpenCode Headless (v1.0.90)
- PASSE `--llm-backend opencode` para spawnar OpenCode CLI headless para embedding e extração
- PASSE `--llm-backend codex,claude,opencode,none` para fallback chain completo
- SAIBA que opencode é a TERCEIRA prioridade no auto-detect: codex > claude > opencode > none
- SAIBA que opencode usa seu PRÓPRIO sistema de auth (NÃO OAuth); `ANTHROPIC_API_KEY` e `OPENAI_API_KEY` NÃO são necessárias
- SAIBA que opencode NÃO tem `--output-schema` ou `--json-schema`; structured output via role-setting prompts + parsing JSON
- SAIBA que output NDJSON do opencode tem 3 tipos de evento: `step_start`, `text` (`.part.text`), `step_finish`
- DEFINA env `SQLITE_GRAPHRAG_OPENCODE_BINARY` para path persistente do binário
- DEFINA env `SQLITE_GRAPHRAG_OPENCODE_MODEL` para seleção persistente de modelo (default: `opencode/big-pickle`)
- DEFINA env `SQLITE_GRAPHRAG_OPENCODE_EMBED_MODEL` para modelo de embedding persistente
- DEFINA env `SQLITE_GRAPHRAG_OPENCODE_TIMEOUT` para timeout persistente (default: 300s)
- PASSE `--opencode-binary <PATH>` para override de binário por invocação
- PASSE `--opencode-model <MODEL>` para seleção de modelo no ingest/enrich
- PASSE `--opencode-timeout <SECONDS>` para timeout no ingest/enrich
- PASSE `--mode opencode` para pipelines de ingest e enrich
- SAIBA que embedding via opencode usa role-setting prompt "You are an embedding function" para produzir vetores numéricos reais
- SAIBA que `SQLITE_GRAPHRAG_OPENCODE_MODEL` NÃO faz fallback para `SQLITE_GRAPHRAG_LLM_MODEL` (fix de cross-contamination v1.0.90)
- SAIBA que `propagate_opencode_env()` propaga OPENCODE_*, OPENROUTER_*, XDG_*, LANG, TERM, USER, LOGNAME, TMPDIR para subprocesso
- SAIBA modelos gratuitos: `opencode/big-pickle`, `opencode/deepseek-v4-flash-free`, `opencode/mimo-v2.5-free`, `opencode/nemotron-3-ultra-free`, `opencode/north-mini-code-free`
- SAIBA versão mínima: 1.17.0

```bash
# OPENCODE HEADLESS — backend explícito e modelo gratuito
sqlite-graphrag --llm-backend opencode \
  remember --name auth-design --type decision \
  --description "JWT rotation strategy" --body "15-min expiry with refresh"

# OPENCODE COM MODELO ESPECÍFICO
sqlite-graphrag --llm-backend opencode --llm-model opencode/deepseek-v4-flash-free \
  remember --name auth-design --type decision \
  --description "JWT rotation strategy" --body-file auth.md

# FALLBACK CHAIN COMPLETO: codex primeiro, depois claude, depois opencode, depois none
sqlite-graphrag --llm-backend codex,claude,opencode,none --skip-embedding-on-failure \
  remember --name auth-design --type decision \
  --description "JWT rotation strategy" --body-file auth.md

# INGEST COM EXTRAÇÃO OPENCODE
sqlite-graphrag ingest ./docs --mode opencode --recursive --json

# INGEST COM MODELO E TIMEOUT ESPECÍFICOS
sqlite-graphrag ingest ./docs --mode opencode --opencode-model opencode/mimo-v2.5-free \
  --opencode-timeout 600 --recursive --json

# ENRICH COM OPENCODE
sqlite-graphrag enrich --operation memory-bindings --mode opencode --json

# DRY-RUN COM BACKEND OPENCODE
sqlite-graphrag --llm-backend opencode --dry-run-backend \
  remember --name preview --type note --description x --body y | jaq '.backend_invoked'
```

```bash
# BACKEND opencode persistente via env vars
export SQLITE_GRAPHRAG_LLM_BACKEND=opencode
export SQLITE_GRAPHRAG_OPENCODE_MODEL=opencode/big-pickle
export SQLITE_GRAPHRAG_OPENCODE_EMBED_MODEL=opencode/big-pickle

# OVERRIDE de path do binário opencode
export SQLITE_GRAPHRAG_OPENCODE_BINARY=~/.opencode/bin/opencode
```


## CRUD — Caminho de Escrita (remember, remember-batch, ingest)
- INVOKE `remember --name <kebab> --type <kind> --description <text> --body-stdin` para corpos longos
- INVOKE `remember --name <kebab> --body-file <path>` para evitar escape shell
- INVOKE `remember --name <kebab> --body <text>` para corpos curtos
- PASSE `--force-merge` para updates idempotentes e restauração de soft-deleted
- PASSE `--clear-body` para limpar corpo durante update com `--force-merge`
- PASSE `--dry-run` para validar inputs sem persistir
- PASSE `--max-rss-mb <MiB>` para abortar quando RSS exceder threshold (default 8192)
- RESPEITE limite de 512000 bytes e 512 chunks por corpo
- INVOKE `remember --graph-stdin` para anexar `{body, entities, relationships}` em único JSON
- PASSE entities como `[{name, entity_type}]` com kebab-case ASCII
- PASSE relationships como `[{source, target, relation, strength}]` onde `strength ∈ [0.0, 1.0]`
- USE `--enable-ner` para extração de entidades URL-regex (URL-regex APENAS desde v1.0.79)
- NUNCA envie `entity_type` e `type` juntos no mesmo objeto JSON
- NUNCA use `--gliner-variant` (no-op desde v1.0.79)
- INVOKE `remember-batch` para 10+ memórias via NDJSON stdin
- ESPERE evento por item: `name`, `status ∈ {created, updated, skipped, failed}`, `memory_id?`, `error?`, `elapsed_ms`
- ESPERE linha de summary: `total`, `created`, `updated`, `skipped`, `failed`, `elapsed_ms`
- INVOKE `ingest <DIR> --recursive --pattern "*.md"` para importar diretório
- PASSE `--type <kind>` para aplicar mesmo tipo a todos arquivos ingeridos
- RESPEITE cap `--max-files 10000` como validação all-or-nothing
- USE `--fail-fast` para parar na primeira falha por arquivo
- USE `--max-name-length N` para sobrescrever truncamento de nomes em 60 chars
- ESPERE linha NDJSON por arquivo: `file`, `name`, `status`, `truncated`, `original_name?`, `memory_id?`, `action?`, `error?`
- ESPERE linha de summary: `files_total`, `files_succeeded`, `files_failed`, `files_skipped`, `elapsed_ms`
- USE `--llm-parallelism N` em `ingest` (default 2, clamp [1, 32])
- DISTINGA `--max-concurrency N` (fan-out CLI) de `--ingest-parallelism N` (per-file extract+embed)
- USE `--auto-describe` (default true desde v1.0.89) para extrair descrição da primeira linha significativa do corpo; opt-out via `--no-auto-describe`
- INVOKE `ingest --mode claude-code` para extração curada por LLM
- INVOKE `ingest --mode codex` para extração curada por OpenAI Codex
- ESPERE eventos claude-code: contagem `entities`, contagem `rels`, `cost_usd` (Omite cost para OAuth)
- USE `--resume` para continuar do queue DB após interrupção
- USE `--retry-failed` para retentar apenas arquivos que falharam
- NUNCA use `fd | xargs remember`; use `ingest` em vez disso
- NUNCA misture `--body`, `--body-file`, `--body-stdin`, `--graph-stdin` em única invocação
- NUNCA passe corpo vazio sem entities via `--graph-stdin` (exit 1 desde v1.0.54)
- NUNCA use `--force-merge` em `ingest` (exclusivo de `remember`)
- NUNCA misture tipos diferentes de memória em mesma invocação de `ingest`
```bash
# REMEMBER com backend Codex headless — gpt-5.4-mini
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT com rotacao" --body "15 min de expiracao com refresh"

# REMEMBER com backend Claude Code headless — claude-sonnet-4-6
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT com rotacao" --body "15 min de expiracao com refresh"

# REMEMBER com backend OpenCode headless — opencode/big-pickle
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT com rotacao" --body "15 min de expiracao com refresh"

# REMEMBER Codex exclusivo — corpo de arquivo, falha em erro sem fallback
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT" --body-file auth.md

# REMEMBER Codex-primeiro com fallback claude
sqlite-graphrag --llm-backend codex,claude --llm-model gpt-5.5 \
  remember --name decisao-auth --type decision \
  --description "Estrategia JWT" --body-file auth.md

# REMEMBER corpo longo via stdin (Claude headless)
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name design-cache --type decision \
  --description "Cache LRU com TTL 5 min" --body-stdin <<'EOF'
Escolhemos cache LRU porque:
- TTL de 5 min equilibra frescor e custo
- Eviction LRU evita estouro de memoria
EOF

# REMEMBER com grafo anexado via --graph-stdin (Codex headless)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name nota-grafo --type note \
  --graph-stdin <<'EOF'
{"body":"JWT usa servico de auth","entities":[{"name":"jwt","entity_type":"concept"},{"name":"servico-auth","entity_type":"tool"}],"relationships":[{"source":"jwt","target":"servico-auth","relation":"uses","strength":0.8}]}
EOF

# REMEMBER-BATCH 10+ memorias via NDJSON (Codex headless)
printf '%s\n' \
  '{"name":"nota-a","type":"note","description":"a","body":"corpo a"}' \
  '{"name":"nota-b","type":"note","description":"b","body":"corpo b"}' \
  | sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
    remember-batch --json | jaq -c 'select(.status) // {summary: .}'

# REMEMBER-BATCH com backend Claude headless
printf '%s\n' \
  '{"name":"nota-c","type":"note","description":"c","body":"corpo c"}' \
  | sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
    remember-batch --json

# REMEMBER-BATCH com backend OpenCode headless
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  remember-batch --json < batch.ndjson | jaq -c 'select(.summary != true)'

# INGEST com extracao Codex
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  ingest ./docs --mode codex --recursive --pattern "*.md" --json

# INGEST com extracao Claude Code
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  ingest ./docs --mode claude-code --recursive --pattern "*.md" --json

# INGEST com extração OpenCode
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  ingest ./docs --mode opencode --recursive --pattern "*.md" --json

# INGEST com auto-describe e retomada de fila
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  ingest ./corpus --mode codex --recursive --auto-describe --resume --json \
  | jaq -c 'select(.status == "done") | {file, entities, rels}'
```


## CRUD — Leitura, Histórico, Atualização
- INVOKE `read --name <kebab>` para fetch O(1) por nome
- INVOKE `read --id <N>` para lookup direto por memory_id
- INVOKE `read --with-graph` para incluir entidades e relacionamentos vinculados
- PARSEE campos `body`, `description`, `created_at_iso`, `updated_at_iso`
- TRATE exit code 4 como memória não encontrada no namespace
- ESPERE v1.0.85 G55 mensagem bilíngue: `--lang en` emite `Memory not found`, `--lang pt` emite `Memória não encontrada`
- INVOKE `list --type <kind> --limit N` para filtrar por tipo de memória
- USE `--offset N` para paginar datasets grandes
- USE `--include-deleted` para incluir memórias soft-deleted
- ESPERE resposta de `list`: `items[]`, `total_count`, `truncated`, `body_length`, `elapsed_ms`
- INVOKE `history --name <n>` para listar versões em ordem cronológica reversa
- USE `--diff` para incluir estatísticas de diff de caracteres entre versões
- ESPERE `versions[]`: `version`, `created_at_iso`, `body_length`, `deleted?`, `changes?`
- INVOKE `edit --name <n> --body-file <path>` para atualizar corpo de arquivo
- USE `--description <text>` para atualizar apenas descrição
- USE `--type <kind>` para mudar tipo de memória sem recriar (v1.0.66)
- USE `--force-reembed` para regenerar embedding sem mudança de corpo (v1.0.79)
- USE `--llm-parallelism N` em `edit` (default 4, clamp [1, 32])
- USE `--expected-updated-at <ts>` para optimistic locking
- TRATE exit code 3 como conflito de optimistic lock; recarregue `read --json` e retente
- INVOKE `rename --from <old> --to <new>` para renomear preservando histórico
- TRATE exit 1 quando novo nome for igual ao antigo (v1.0.64)
- INVOKE `restore --name <n> --version <N>` para restaurar versão antiga
- OMITA `--version` para selecionar última versão não-restore automaticamente
- ESPERE que cada `edit` ou `restore` crie nova versão imutável
- ESPERE correção de desync do FTS5 aplicada (v1.0.56); memórias editadas ficam imediatamente localizáveis
- NUNCA pule optimistic locking em pipelines concorrentes
```bash
# READ por nome — fetch O(1), SEM embedding (leitura pura)
sqlite-graphrag read --name decisao-auth --json | jaq '{name, description, body_length}'

# READ por id com grafo vinculado
sqlite-graphrag read --id 42 --with-graph --json | jaq '{name, entities: (.entities | length)}'

# LIST por tipo com paginacao, SEM embedding
sqlite-graphrag list --type decision --limit 50 --offset 0 --json | jaq '.items[].name'

# HISTORY com diff de caracteres entre versoes
sqlite-graphrag history --name decisao-auth --diff --json | jaq '.versions[] | {version, body_length, changes}'

# EDIT do corpo via arquivo — RE-EMBEDA, use backend Codex
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  edit --name decisao-auth --body-file revisado.md

# EDIT do corpo via arquivo — RE-EMBEDA, use backend Claude
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  edit --name decisao-auth --body-file revisado.md

# EDIT do corpo via arquivo — RE-EMBEDA, use backend OpenCode
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  edit --name decisao-auth --body-file revisado.md

# EDIT apenas descricao — NÃO re-embeda, SEM backend
sqlite-graphrag edit --name decisao-auth --description "JWT 15min com refresh HTTP-only"

# EDIT com force-reembed — regenera embedding sem mudar corpo (Codex)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  edit --name decisao-auth --force-reembed

# EDIT com force-reembed — regenera embedding sem mudar corpo (OpenCode)
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  edit --name decisao-auth --force-reembed

# EDIT com optimistic locking — TRATE exit 3 como conflito
TS=$(sqlite-graphrag read --name decisao-auth --json | jaq -r '.updated_at_iso')
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  edit --name decisao-auth --description "novo" --expected-updated-at "$TS" || echo "exit=$?"

# RENAME preservando historico, SEM embedding
sqlite-graphrag rename --from decisao-auth --to decisao-autenticacao --json

# RESTORE versao antiga, SEM embedding
sqlite-graphrag restore --name decisao-autenticacao --version 2 --json
```


## CRUD — Deleção (forget, purge, unlink, prune, cleanup)
- INVOKE `forget --name <n>` para soft-delete reversível
- ESPERE que `forget` desapareça das saídas de `recall` e `list`
- TRATE exit 4 como memória ausente (desde v1.0.52)
- INVOKE `restore` para reverter soft-delete antes de qualquer purge
- INVOKE `purge --retention-days <N> --yes` para deleção física
- USE `--dry-run` primeiro para auditar contagem
- ESPERE retenção default de 90 dias para memórias soft-deleted
- INVOKE `unlink --from <a> --to <b> --relation <type>` para remoção direcionada de aresta
- OMITA `--relation` para remover todas arestas entre `--from` e `--to`
- USE `--entity <name> --all` para remover em massa todos relacionamentos de uma entidade
- TRATE exit code 4 como aresta inexistente
- INVOKE `prune-relations --relation <type> --yes` para deleção em massa de relacionamentos
- USE `--show-entities` com `--dry-run` para listar nomes de entidades afetadas
- INVOKE `cleanup-orphans --dry-run` para auditar entidades órfãs
- APLIQUE `--yes` em pipelines automatizados para `cleanup-orphans`
- INVOKE `prune-ner --entity <n>` para remover bindings NER de entidade específica
- INVOKE `prune-ner --all --yes` para remover todos bindings NER no namespace
- USE pipeline padrão: bulk `forget` depois `cleanup-orphans --yes` depois `vacuum --json`
- NUNCA delete manualmente via shell `sqlite3`; use apenas comandos do binário
```bash
# FORGET soft-delete reversivel, SEM embedding
sqlite-graphrag forget --name design-antigo --json

# PURGE deleção física — SEMPRE faça dry-run primeiro
sqlite-graphrag purge --retention-days 30 --yes --dry-run
sqlite-graphrag purge --retention-days 30 --yes --json

# UNLINK remoção direcionada de aresta
sqlite-graphrag unlink --from jwt --to servico-auth --relation uses --json

# UNLINK em massa de todos relacionamentos de uma entidade
sqlite-graphrag unlink --entity jwt --all --json

# PRUNE-RELATIONS em massa por tipo — dry-run lista entidades afetadas
sqlite-graphrag prune-relations --relation mentions --yes --dry-run --show-entities
sqlite-graphrag prune-relations --relation mentions --yes --json

# CLEANUP-ORPHANS auditoria depois execução
sqlite-graphrag cleanup-orphans --dry-run --json
sqlite-graphrag cleanup-orphans --yes --json

# PIPELINE padrão de limpeza
sqlite-graphrag forget --name obsoleto
sqlite-graphrag cleanup-orphans --yes --json
sqlite-graphrag vacuum --json
```


## Grafo de Entidades (link, graph, memory-entities, rename, delete, merge, reclassify, normalize)
- INVOKE `link --from <a> --to <b> --relation <type>` para criar aresta
- PASSE `--create-missing` para auto-criar entidades inexistentes durante link
- PASSE `--entity-type <kind>` para entidades auto-criadas (default `concept`)
- PASSE `--weight <float>` para peso da aresta (default 0.5)
- USE `--strict-relations` para falhar em tipos de relação não-canônicos
- USE `--max-entity-degree N` para avisar quando entidade excede N conexões
- INVOKE `graph entities --json` para listar todas entidades
- ACESSE via `.entities[]` (campo é `entities` NÃO `items`)
- FILTRE via `--entity-type <kind>`
- ORDENE via `--sort-by degree|name|created_at` (default `name`)
- DEFINA direção via `--order asc|desc` (default `asc`)
- PAGINE via `--limit N --offset N`
- INVOKE `graph stats --json` para inspecionar `node_count`, `edge_count`, `avg_degree`, `max_degree`
- INVOKE `graph traverse --from <root> --depth <N>` para travessia de subgrafo
- ESPERE `hops[]`: `entity`, `relation`, `direction`, `weight`, `depth`
- TRATE exit 4 como entidade raiz inexistente
- USE `--format json|dot|mermaid` com `--output <path>` para exportar grafo
- INVOKE `memory-entities --name <memory>` para lookup forward de entidades
- INVOKE `memory-entities --entity <name>` para lookup reverso de memórias
- INVOKE `rename-entity --name <old> --new-name <new>` para renomear entidade
- TRATE exit 4 como entidade não encontrada
- TRATE exit 1 se novo nome falhar validação
- INVOKE `delete-entity --name <n> --cascade` para remover entidade e todos bindings
- PASSE `--cascade` que é OBRIGATÓRIO quando entidade tem relacionamentos (senão exit 1)
- INVOKE `merge-entities --names "a,b,c" --into <target>` para mesclar entidades
- INVOKE `reclassify --name <n> --new-type <kind>` para reclassificação individual
- INVOKE `reclassify --from-type <old> --to-type <new> --batch` para reclassificação em massa
- INVOKE `reclassify-relation --from-relation <old> --to-relation <new> --batch`
- INVOKE `normalize-entities --yes` para normalizar todos nomes para kebab-case ASCII
- VALIDE nomes: mínimo 2 chars, sem newlines, sem ALL_CAPS curtos (4 chars ou menos rejeitados desde fix BUG-13 v1.0.88)
- NORMALIZE nomes via NFKD depois ASCII depois lowercase depois hífens
- CONHEÇA as RELAÇÕES canônicas: `applies-to`, `uses`, `depends-on`, `causes`, `fixes`, `contradicts`, `supports`, `follows`, `related`, `mentions`, `replaces`, `tracked-in`
- CONHEÇA o MAPEAMENTO não-canônico: `adds|creates → causes`, `implements → supports`, `blocks → contradicts`, `tested-by → related`, `part-of → applies-to`
- CONHEÇA os TIPOS canônicos de entidade: `project`, `tool`, `person`, `file`, `concept`, `incident`, `decision`, `memory`, `dashboard`, `issue_tracker`, `organization`, `location`, `date`
- NUNCA use `mentions` como relação padrão (adiciona ruído)
- NUNCA persista estado efêmero em entidades
```bash
# LINK cria aresta com auto-criacao, SEM embedding
sqlite-graphrag link --from jwt --to servico-auth --relation uses \
  --weight 0.8 --create-missing --entity-type tool --json

# GRAPH ENTITIES listagem ordenada por grau, SEM embedding
sqlite-graphrag graph entities --sort-by degree --order desc --limit 10 --json \
  | jaq -r '.entities[] | "\(.name) grau=\(.degree)"'

# GRAPH STATS inspeção de densidade ANTES de travessia
sqlite-graphrag graph stats --json | jaq '{node_count, edge_count, avg_degree, max_degree}'

# GRAPH TRAVERSE subgrafo de 2 hops
sqlite-graphrag graph traverse --from jwt --depth 2 --json \
  | jaq -r '.hops[] | "\(.entity) \(.relation) (\(.depth))"'

# GRAPH exportacao para mermaid
sqlite-graphrag graph --format mermaid --output grafo.mmd

# MEMORY-ENTITIES lookup forward e reverso
sqlite-graphrag memory-entities --name decisao-auth --json | jaq '.entities[].name'
sqlite-graphrag memory-entities --entity jwt --json | jaq '.memories[].name'

# RENAME-ENTITY preservando relacionamentos
sqlite-graphrag rename-entity --name jwt --new-name json-web-token --json

# DELETE-ENTITY com cascade OBRIGATORIO se tem relacionamentos
sqlite-graphrag delete-entity --name obsoleto --cascade --json

# MERGE-ENTITIES mescla duplicatas
sqlite-graphrag merge-entities --names "auth,authentication,autenticacao" --into auth --json

# RECLASSIFY individual e em massa
sqlite-graphrag reclassify --name jwt --new-type concept --json
sqlite-graphrag reclassify --from-type tool --to-type concept --batch --json

# NORMALIZE-ENTITIES para kebab-case ASCII
sqlite-graphrag normalize-entities --yes --json
```


## Busca GraphRAG (recall, hybrid-search, related, deep-research, enrich)
- USE o padrão canônico de três camadas: `hybrid-search` depois `read --name` depois `related|graph traverse`
- INVOKE `recall <query> --k N` para busca semântica pura KNN
- PASSE `--no-graph` para desabilitar expansão automática de grafo
- INTERPRETE `distance` crescente como similaridade decrescente
- INTERPRETE `score` como `1.0 - distance` clamped em `[0.0, 1.0]`
- ESPERE `source ∈ {direct, graph}` e `graph_depth` para resultados de grafo
- ESPERE resposta: `direct_matches[]`, `graph_matches[]`, `results[]`, `elapsed_ms`
- INVOKE `hybrid-search <query> --k N` para fusão FTS5 e KNN via RRF
- PASSE `--rrf-k 60` para constante RRF padrão
- PASSE `--weight-vec 1.0` e `--weight-fts 1.0` para fusão balanceada
- USE `--with-graph --max-hops 2 --min-weight 0.3` para expansão de grafo
- ESPERE resposta `hybrid-search`: `results[]`, `graph_matches[]`, `fts_degraded`, `vec_degraded_reason?`, `backend_invoked`, `elapsed_ms`
- LEIA TANTO `results[]` QUANTO `graph_matches[]` quando `--with-graph` ativo
- INVOKE `related <name> --hops N` para travessia multi-hop a partir de memória
- PASSE `--relation <type>` para filtrar travessia por relação
- ESPERE `hop_distance` explícito por hop
- INVOKE `deep-research "<query>" --k 20` para pesquisa paralela multi-hop
- PASSE `--max-sub-queries 7` para cap de decomposição de query
- PASSE `--max-hops 3 --min-weight 0.3 --max-results 50` para travessia de grafo
- PASSE `--with-bodies` para incluir corpos completos de memórias nos resultados
- ESPERE resposta: `sub_queries[]`, `results[]`, `evidence_chains[]`, `graph_context?`, `stats`
- INVOKE `enrich --operation <op> --mode claude-code` para qualidade de grafo via LLM
- CONHEÇA as OPERAÇÕES: `memory-bindings`, `entity-descriptions`, `body-enrich` (Jaccard >=0.7), `re-embed --limit N --resume`
- PASSE `--llm-parallelism N` para controlar subprocessos LLM concorrentes
- PASSE `--max-cost-usd N` para cap de gasto acumulado (ignorado para usuários OAuth)
- PASSE `--resume` e `--retry-failed` para resiliência a crash
- USE `--dry-run` para preview sem spawnar LLM
- USE query AMPLA para `recall --k 5`
- USE query MISTA de tokens para `hybrid-search --k 10`
- USE query MISTA com grafo para `hybrid-search --with-graph --max-hops 2`
- USE query EXPLORATÓRIA de memória para `related --hops 2`
- USE query EXPLORATÓRIA de entidade para `graph traverse --depth 2`
- NUNCA confunda `distance` com `combined_score` em ranking
- NUNCA aumente `--hops` sem inspecionar `graph stats` antes
- NUNCA pule camada 2 quando snippet for insuficiente
- NUNCA leia apenas `.results[]` quando `--with-graph` estiver ativo
```bash
# RECALL com embedding Codex — gpt-5.4-mini
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "autenticacao JWT" --k 5 --json | jaq '.results[] | {name, score, source}'

# RECALL com embedding Claude — claude-sonnet-4-6
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  recall "autenticacao JWT" --k 5 --json | jaq '.results[] | {name, score, source}'

# RECALL com embedding OpenCode — opencode/big-pickle
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  recall "autenticacao JWT" --k 5 --json | jaq '.results[] | {name, score, source}'

# RECALL KNN puro sem expansao de grafo (Codex)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "fluxo de refresh" --k 5 --no-graph --json | jaq '.direct_matches[].name'

# HYBRID-SEARCH com embedding Codex e expansao de grafo
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  hybrid-search "fluxo de auth" --k 10 --with-graph --max-hops 2 --json \
  | jaq -r '(.results[].name), (.graph_matches[].name)' | sort -u

# HYBRID-SEARCH com embedding Claude e fusao balanceada
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  hybrid-search "fluxo de auth" --k 10 --rrf-k 60 --weight-vec 1.0 --weight-fts 1.0 --json \
  | jaq '{backend_invoked, fts_degraded, results: (.results | length)}'

# HYBRID-SEARCH com embedding OpenCode e expansão de grafo
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  hybrid-search "fluxo de auth" --k 10 --with-graph --json \
  | jaq -r '(.results[].name), (.graph_matches[].name)' | sort -u

# RELATED travessia multi-hop a partir de memoria, SEM embedding
sqlite-graphrag related decisao-auth --hops 2 --relation uses --json \
  | jaq '.results[] | {name, hop_distance}'

# DEEP-RESEARCH com backend Codex — pesquisa paralela multi-hop
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  deep-research "Como o binario se autentica em providers OAuth?" \
  --k 20 --max-hops 3 --max-sub-queries 5 --with-bodies --json \
  | jaq '{stats, evidence_chains: (.evidence_chains | length)}'

# DEEP-RESEARCH com backend Claude
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  deep-research "estrategia de cache e TTL" --k 20 --max-hops 3 --json \
  | jaq '.sub_queries[]'

# DEEP-RESEARCH com backend OpenCode
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  deep-research "estrategia de cache e TTL" --k 20 --max-hops 3 --json \
  | jaq '.sub_queries[]'

# ENRICH re-embed com backend Codex
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  enrich --operation re-embed --limit 100 --resume --json

# ENRICH memory-bindings com backend Claude
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  enrich --operation memory-bindings --mode claude-code --json

# ENRICH memory-bindings com backend OpenCode
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  enrich --operation memory-bindings --mode opencode --json

# ENRICH dry-run para preview sem spawnar LLM
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  enrich --operation entity-descriptions --mode claude-code --dry-run --json
```


## Superfície v1.0.86+ (pending, slots, embedding, llm-backend, shutdown)
- INVOKE `pending list --filter-status queued` para inspecionar fila de checkpoint de três estágios do remember
- INVOKE `pending show <id>` para inspecionar linha única de checkpoint
- INVOKE `pending cleanup --yes` para remover linhas em estado terminal
- SAIBA que é RESPALDADO pela tabela `pending_memories` criada pela migração V014 (ADR-0036)
- PASSE `--db <PATH>` em `pending list`/`pending show` (v1.0.89, ADR-0049)
- INVOKE `pending-embeddings list` para inspecionar fila de retry de embeddings que falharam
- INVOKE `pending-embeddings process` para reprocessar com próximo backend
- SAIBA que é RESPALDADO pela tabela `pending_embeddings` criada pela migração V015 (ADR-0040)
- INVOKE `slots status` para inspecionar semáforo de slots host-wide
- INVOKE `slots release --slot-id <N> --yes` para colher slots órfãos
- SAIBA que LOCK usa `fs4 = "0.9"` com `fcntl(F_SETLK)` em Unix e `LockFileEx` em Windows (ADR-0039)
- INVOKE `embedding status` para contagens agregadas por status
- INVOKE `embedding list` para inspeção por entrada
- PASSE `--db <PATH>` em `embedding status`/`embedding list`/`embedding abandon` (v1.0.89, ADR-0049)
- PASSE `--llm-backend codex,claude` para codex-primeiro com fallback claude (ADR-0038)
- PASSE `--llm-backend codex,claude,none` para fallback de embedding null
- SAIBA que o DEFAULT de `--llm-backend` é `codex`
- PASSE `--llm-fallback-mode <claude|codex>` para trocar backend mid-job em rate-limit
- PASSE `--max-concurrency N` flag global para limitar invocações CLI pesadas concorrentes
- PASSE `--wait-lock SECS` flag global para ampliar janela de aquisição de lock
- PASSE `--llm-parallelism N` flag global para cap de fan-out de subprocessos de embedding (default 4, clamp [1, 32])
- PASSE `--ingest-parallelism N` para controlar paralelismo extract+embed por arquivo em `ingest`
- PASSE `--graceful-shutdown-secs N` para reservar orçamento de cleanup antes de SIGKILL
- PASSE `--skip-embedding-on-failure` APENAS quando `--llm-backend …,none`
- PASSE ADR-0041 `--strict-env-clear` para descartar credenciais de provider customizado em subprocesso
- PASSE `--dry-run-backend` para planejar operação de backend sem executá-la (preview idempotente)
- PARSEE campo `backend_invoked` nos envelopes de recall, hybrid-search, remember, edit, ingest, enrich, read para confirmar backend efetivo
- LEIA `vec_degraded_reason` nos envelopes de recall/hybrid-search quando caminho vec estiver degradado
- SAIBA que backend claude divide-se em embedder local via `embed_via_claude_local` (zero-token, compatível com OAuth)
- USE `LlmEmbeddingBuilder` para compor pipeline de embedding: `with_backend(Codex).or_fallback(Claude).or_skip()`
- INVOKE `codex-models --json` desde v1.0.89 para emitir envelope JSON `{"action":"codex_models","count":N,"default":"...","models":[...]}` (alias no-op)
- EXECUTE `codex login` após upgrade para refrescar refresh token OAuth (incidente 2026-06-14)
- AÇÃO do operador para OAuth stale: `codex login` depois retry
```bash
# PENDING list e show da fila de checkpoint, com --db explicito
sqlite-graphrag --db /data/projeto.sqlite pending list --filter-status queued --json
sqlite-graphrag --db /data/projeto.sqlite pending show 7 --json
sqlite-graphrag pending cleanup --yes --json

# PENDING-EMBEDDINGS inspecao e reprocessamento com proximo backend
sqlite-graphrag pending-embeddings list --json | jaq '.[] | {id, status}'
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  pending-embeddings process --json

# SLOTS status e colheita de slot orfao
sqlite-graphrag slots status --json | jaq '{max_concurrency, acquired, waiting}'
sqlite-graphrag slots release --slot-id 3 --yes --json

# EMBEDDING status e listagem com --db explicito
sqlite-graphrag --db /data/projeto.sqlite embedding status --json | jaq '{pending, done, failed}'
sqlite-graphrag --db /data/projeto.sqlite embedding list --json | jaq '.[] | {id, status}'

# CODEX-MODELS whitelist de modelos (alias no-op)
sqlite-graphrag codex-models --json | jaq '{count, default, models: .models[:3]}'

# REFRESQUE OAuth do codex em caso de token expirado
codex login
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini recall "query" --k 5 --json
```


## Camada de Validação Pre-Flight v1.0.87+ (ADR-0045, GAP-META-005)
- SAIBA que `src/spawn/preflight.rs` porta todo spawn de subprocesso LLM através de 7 guards ANTES do fork
- SAIBA que exit code 16 (`EX_CONFIG`) é o código universal de falha preflight (adicionado v1.0.87)
- SAIBA que 7 guards rodam 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`
- SAIBA que `check_argv_size` rejeita argv excedendo `ARG_MAX - 4096` bytes (margem para env vars do kernel)
- SAIBA que `check_binary_exists` aborta quando `claude` ou `codex` não está em PATH
- SAIBA que `check_mcp_config_inline` reescreve `--mcp-config '{}'` literal para tempfile com `{"mcpServers":{}}` (Claude Code 2.1.177 rejeita a forma literal)
- SAIBA que `check_mcp_config_path` valida conteúdo JSON de arquivos `--mcp-config <PATH>`
- SAIBA que `check_walkup_mcp_json` rejeita `.mcp.json` inválido na cadeia ancestral do CWD (até 16 níveis via `Path::ancestors()`)
- SAIBA que `check_output_buffer` dobra buffer do parser acima de 64 KB para lidar com saídas grandes
- SAIBA que `check_claude_config_dir` evita vazamento MCP de `~/.claude/` user-level
- DEFINA `SQLITE_GRAPHRAG_SKIP_PREFLIGHT=1` APENAS em emergências; bypass reverte para `Command::spawn()` direto e herda todas as 5 classes de bug GAP-META-005
- LEIA envelope JSON `AppError::PreFlightFailed(PreFlightError)` para remediação específica por variante
- SAIBA que fix BUG-11 v1.0.88 garante que falha preflight propaga via `embed_via_backend_strict`; NUNCA espere sucesso silencioso quando preflight falha
- NUNCA prossiga após exit code 16 sem resolver a variante específica reportada
```bash
# DIAGNOSTIQUE falha preflight — config MCP ruim aborta com exit 16
CLAUDE_CONFIG_DIR=/tmp/bad-mcp sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name teste --type note --description x --body y 2>&1 || echo "exit=$?"

# BYPASS de emergencia do preflight — APENAS em emergencias
SQLITE_GRAPHRAG_SKIP_PREFLIGHT=1 sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name teste --type note --description x --body y

# LEIA envelope de erro preflight para remediacao por variante
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name teste --type note --description x --body y --json 2>/dev/null \
  | jaq 'select(.error == true) | {code, message}'
```


## Hotfixes v1.0.88+ (BUG-11, BUG-12, BUG-13)
- SAIBA que BUG-11 (CRÍTICO) foi CORRIGIDO: falha preflight em `extract/llm_embedding.rs:563-565` agora propaga para `remember` via `embed_via_backend_strict` em vez de persistência silenciosa com `backend_invoked: "none"` e zero chunks
- REPRODUZA o fix BUG-11: `CLAUDE_CONFIG_DIR=/tmp/bad-config-with-mcp sqlite-graphrag remember --name X --type note --description x --body y` retorna exit 11 com envelope JSON de erro
- SAIBA que BUG-12 (MÉDIO) foi CORRIGIDO: enforço OAuth-only emite exatamente 1 linha stderr (eram 2 — `eprintln!` duplicado removido em `src/output.rs`)
- VERIFIQUE o fix BUG-12: `ANTHROPIC_API_KEY=sk-test sqlite-graphrag init` emite 1 linha stderr
- SAIBA que BUG-13 (MÉDIO) foi CORRIGIDO: `link --create-missing` valida nomes de entidade ANTES de normalizar (estava bypassando validação; abreviações ALL_CAPS de 3-4 chars como `API`, `WAL`, `RUST` agora corretamente rejeitadas via CLI casando com o caminho `remember --graph-stdin`)
- VERIFIQUE o fix BUG-13: `sqlite-graphrag link --from api --to service --create-missing --relation uses` retorna exit 1 com erro de validação
- INVOKE a variante `AppError::PreFlightFailed(PreFlightError)` no tratamento de erros; exit code 16, `is_permanent() == true`
```bash
# REPRODUZA fix BUG-11 — preflight ruim propaga exit 11 (Codex headless)
CLAUDE_CONFIG_DIR=/tmp/bad-config-with-mcp sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name X --type note --description x --body y --json 2>/dev/null \
  | jaq 'select(.error == true)'; echo "exit=$?"

# VERIFIQUE fix BUG-12 — OAuth-only emite exatamente 1 linha stderr
ANTHROPIC_API_KEY=sk-test sqlite-graphrag init 2>&1 1>/dev/null | wc -l

# VERIFIQUE fix BUG-13 — ALL_CAPS curto rejeitado em link, SEM embedding
sqlite-graphrag link --from api --to service --create-missing --relation uses 2>&1 || echo "exit=$?"
```


## Remediação de Deadlock de Embedding v1.0.89+ (ADR-0050)
- PASSE `--llm-model <MODEL>` como flag global para selecionar modelo de embedding para TODOS os backends (v1.0.89, ADR-0050)
- SAIBA que o MODELO padrão para backend codex é `gpt-5.5`; para backend claude é `claude-sonnet-4-6`
- DEFINA env `SQLITE_GRAPHRAG_LLM_MODEL` como override persistente para `--llm-model`
- PASSE `--codex-binary <PATH>` para sobrescrever localização do binário codex (v1.0.89, ADR-0050)
- DEFINA env `SQLITE_GRAPHRAG_CODEX_BINARY` como override persistente para `--codex-binary`
- PASSE `--claude-binary <PATH>` para sobrescrever localização do binário claude (propagado via set_var desde v1.0.89)
- PASSE `--skip-embedding-on-failure` para retornar exit 0 quando embedding LLM falha (cabeado end-to-end desde v1.0.89, ADR-0050)
- SAIBA que 7 flags CLI mortas foram corrigidas na v1.0.89 via propagação `set_var` em `main.rs`: `--llm-model`, `--llm-fallback`, `--skip-embedding-on-failure`, `--claude-binary`, `--codex-binary`, `--llm-max-host-concurrency`, `--llm-slot-wait-secs`
- SAIBA que `deep-research` e `remember-batch` agora recebem `llm_backend` do main.rs (v1.0.89, ADR-0050)
- SAIBA que timeout adaptativo escala com tamanho do batch: `base + 15s × (batch_size - 1)` (v1.0.89, ADR-0050)
- SAIBA que erros de OAuth expirado agora incluem hint acionável: "execute codex login" ou "atualize OAuth do claude" (v1.0.89)
- SAIBA que `BoolishValueParser` aceita `1/yes/on/true` e `0/no/off/false` para env vars booleanas (v1.0.89, ADR-0050)
- SAIBA que flag `--yes` em `slots release`, `purge`, `cleanup-orphans` foi cabeada end-to-end (v1.0.89, BUG-YES-FLAG-IGNORED)
```bash
# SELECIONE modelo via flag global para QUALQUER backend (Codex)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "query" --k 5 --json | jaq '.backend_invoked'

# SELECIONE modelo via flag global para QUALQUER backend (Claude)
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  hybrid-search "query" --k 10 --json | jaq '.backend_invoked'

# DEFINA modelo persistente via env var
export SQLITE_GRAPHRAG_LLM_MODEL=gpt-5.4-mini
sqlite-graphrag --llm-backend codex remember --name nota --type note --description x --body y

# SOBRESCREVA path do binario codex via flag
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  --codex-binary /usr/local/bin/codex recall "query" --k 5 --json

# SKIP-EMBEDDING-ON-FAILURE retorna exit 0 quando embedding falha
sqlite-graphrag --llm-backend codex,claude,none --skip-embedding-on-failure \
  remember --name nota --type note --description x --body y; echo "exit=$?"
```


## Drift de Schema e Paridade de Flag v1.0.89+ (ADR-0048, ADR-0049)
- SAIBA que `health.schema.json` foi regenerado via macro derive `schemars` (ADR-0048); `additionalProperties: true` conforme política Must-Ignore (RFC 7493 I-JSON)
- SAIBA que 17 novos campos foram adicionados ao envelope `health` desde v1.0.88: `fts_query_ok`, `vec_memories_missing`, `vec_memories_orphaned`, `sqlite_version`, `mentions_ratio`, `mentions_warning`, `top_relation`, `top_relation_ratio`, `applies_to_ratio`, `relation_concentration_warning`, `super_hub_count`, `super_hub_warning`, `top_hub_entity`, `top_hub_degree`, `hub_warning`, `non_normalized_count`, `normalization_warning`
- REGENERE schemas via `cargo run --bin dump-schema` (ordenamento BTreeMap idempotente)
- PASSE `--namespace <NS>` em `health` para filtrar contagens para um namespace
- USE `migrate --dry-run --json` para PREVIEW de migrações pendentes sem aplicar; lista nomes+versões, valida checksums, verifica pré-condições
- USE `codex-models --json` como alias no-op retornando envelope JSON
- USE `--auto-describe` (default true) em `ingest` para extrair descrição da primeira linha significativa do corpo; opt-out via `--no-auto-describe`
- PASSE `--db <PATH>` em `embedding status`/`embedding list`/`embedding abandon`/`pending list`/`pending show` (ADR-0049)
- SAIBA que `--db <PATH>` NÃO é global; cada subcomando aceita independentemente (`clap::Arg::global = true` foi REJEITADO como invasivo)
- TRATE o tamanho do binário como 14.6 MiB stripped ELF (NÃO 6 MB como em docs antigos); veja descrição em `Cargo.toml:6`
```bash
# REGENERE schemas e CONFIRME idempotencia
cargo run --bin dump-schema -- --check
git diff --stat docs/schemas/
cargo run --bin dump-schema  # se --check falhou

# HEALTH escopado para namespace (paridade de flag --db e --namespace)
sqlite-graphrag --db /data/projeto.sqlite health --namespace prod --json \
  | jaq '{integrity_ok, schema_version, counts}'

# MIGRATE dry-run preview SEM aplicar
sqlite-graphrag migrate --dry-run --json | jaq '.would_apply[]? | {name, version}'
```


## Contratos JSON (Top-5 Campos por Comando)
- PARSEE TOP campos `recall`: `results[].name`, `snippet`, `distance`, `score`, `source`
- PARSEE TOP campos `hybrid-search`: `results[].name`, `combined_score`, `vec_rank`, `fts_rank`, `source`
- PARSEE TOP campos `health`: `integrity_ok`, `schema_ok`, `counts`, `wal_size_mb`, `schema_version`
- PARSEE TOP campos `list`: `items[].name`, `type`, `description`, `updated_at_iso`, `deleted_at_iso?`
- PARSEE TOP campos `edit`: `memory_id`, `name`, `action`, `version`, `elapsed_ms`
- PARSEE TOP campos `read`: `name`, `body`, `description`, `created_at_iso`, `updated_at_iso`
- PARSEE TOP campos `forget`: `action`, `forgotten`, `name`, `namespace`, `elapsed_ms`
- PARSEE TOP campos `link`: `action`, `from`, `to`, `relation`, `weight`
- PARSEE TOP campos `graph entities`: `entities[].id`, `name`, `entity_type`, `degree`, `description?`
- PARSEE TOP campos `deep-research`: `sub_queries[]`, `results[]`, `evidence_chains[]`, `graph_context`, `stats`
- PARSEE EVENTOS NDJSON de `enrich`: `phase`, `name`, `status`, `entities?`, `rels?`, `cost_usd?`, `elapsed_ms?`
- PARSEE TOP campos `pending list`: `id`, `name`, `status`, `created_at`, `namespace`
- PARSEE TOP campos `slots status`: `max_concurrency`, `acquired`, `waiting`, `held_by_pid[]`
- PARSEE TOP campos `embedding status`: `pending`, `processing`, `done`, `failed`, `skipped`
- PARSEE envelopes `remember`/`edit`/`ingest`/`enrich`/`read`: incluem `backend_invoked` e `vec_degraded_reason?`
- SAIBA que `health.schema.json` usa `"additionalProperties": true` conforme política Must-Ignore (RFC 7493 I-JSON) desde v1.0.89 (ADR-0048); os outros 49 schemas em `docs/schemas/` ainda usam `"additionalProperties": false` (Must-Validate) pendentes de regeneração em v1.0.90+
- CONSULTE SCHEMAS completos em `docs/schemas/*.schema.json` (nunca inline schema completo em skill)
```bash
# PARSEE backend_invoked no envelope de recall (Codex)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "query" --k 5 --json | jaq '{backend_invoked, vec_degraded_reason}'

# PARSEE top-5 campos de hybrid-search
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  hybrid-search "query" --k 10 --json \
  | jaq '.results[] | {name, combined_score, vec_rank, fts_rank, source}'

# PARSEE envelope de health
sqlite-graphrag health --json | jaq '{integrity_ok, schema_ok, counts, wal_size_mb, schema_version}'
```


## Códigos de Saída e Retry
- TRATE EXIT 0 como sucesso; parsee stdout
- TRATE EXIT 1 como erro de validação (peso inválido, self-link, max-files excedido, bypass ALL_CAPS em link)
- TRATE EXIT 2 como erro de parsing de argumento Clap
- TRATE EXIT 3 como conflito de optimistic lock; recarregue `read --json` e retente
- TRATE EXIT 4 como entidade, memória ou versão não encontrada
- TRATE EXIT 5 como erro de namespace
- TRATE EXIT 6 como payload acima do limite de tamanho
- TRATE EXIT 9 como memória duplicada (use `--force-merge` para update ou restore)
- TRATE EXIT 10 como erro de banco; execute `vacuum` e `health`
- TRATE EXIT 11 como falha de embedding (erro de subprocesso LLM, incluindo falha preflight desde fix BUG-11)
- TRATE EXIT 13 como falha parcial de batch; reprocesse apenas os que falharam
- TRATE EXIT 14 como erro de I/O (permissão, disco cheio)
- TRATE EXIT 15 como banco ocupado; amplie `--wait-lock`
- TRATE EXIT 16 como falha de validação preflight (v1.0.87+, ADR-0045); cheque envelope JSON para variante
- TRATE EXIT 19 como SHUTDOWN_EXIT_CODE (ADR-0037); trabalho parcial descartado; RETRY OBRIGATÓRIO
- PARSEE EXIT 19 envelope: `{error:true, code:19, signal, graceful, message}`
- TRATE EXIT 20 como erro interno ou falha de serialização JSON
- TRATE EXIT 75 como slots esgotados OU `JobSingletonLocked`
- PARSEE EXIT 75 de `enrich`/`ingest --mode claude-code|codex|opencode`: `job '(\w+)'.*namespace '(\w+)'`
- RESPEITE EXIT 75 circuit breaker: janela de cooldown por namespace; NÃO retente imediatamente
- TRATE EXIT 77 como pressão de RAM; aguarde memória livre
- NUNCA ignore exit code não-zero como sucesso
- NUNCA reprocesse batch inteiro após exit 13
- NUNCA aumente concorrência após exit 75 ou 77
- NUNCA confunda exit 1 (validação) com exit 9 (duplicada)
- NUNCA trate exit 16 como transitório; corrija o problema preflight subjacente
```bash
# VERIFIQUE exit code ANTES de parsear stdout
sqlite-graphrag read --name inexistente --json; echo "exit=$?"  # exit 4

# TRATE exit 9 (duplicada) com --force-merge para update
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name nota --type note --description x --body y --force-merge

# TRATE exit 11 (falha de embedding) com fallback de backend
sqlite-graphrag --llm-backend codex,claude --llm-model gpt-5.5 \
  remember --name nota --type note --description x --body y; echo "exit=$?"
```


## Concorrência, RAM, Paralelismo, Slots
- RESPEITE teto rígido `2 × nCPUs` para comandos pesados
- TRATE como pesados: `init`, `remember`, `ingest`, `recall`, `hybrid-search`
- DISTINGA `--max-concurrency` (fan-out CLI) de `--ingest-parallelism` (per-file)
- DEFINA `--llm-parallelism N` default 4 em `remember`/`edit`, default 2 em `ingest`
- CLAMP `--llm-parallelism` na faixa `[1, 32]`
- USE `--llm-max-host-concurrency N` para cap de subprocessos LLM cross-process
- USE `--llm-slot-wait-secs N` para esperar slot ou `--llm-slot-no-wait` para abortar
- AMPLIE `--wait-lock SECS` quando contenção for esperada
- ATIVE `SQLITE_GRAPHRAG_LOW_MEMORY=1` para paralelismo unitário (3-4x mais lento)
- USE `--strict-env-clear` (ADR-0041) para preservar apenas `PATH` em compliance
- USE a RECEITA de bypass de SHUTDOWN: prefixe `tests/mock-llm` ao PATH depois sete `SQLITE_GRAPHRAG_IGNORE_SHUTDOWN=1` depois envolva com `setsid -w timeout`
- SAIBA que JOB SINGLETON: `enrich`, `ingest --mode claude-code`, `ingest --mode codex`, `ingest --mode opencode` adquirem singleton por namespace
- USE `--wait-job-singleton SECS` para esperar lock ou `--force-job-singleton` para quebrar lock stale
- LIMITE ingestão paralela em CI para evitar rate limits da LLM
- NUNCA rode `enrich` em paralelo contra mesmo banco
```bash
# LIMITE fan-out de embedding com --llm-parallelism (Codex)
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini --llm-parallelism 8 \
  ingest ./docs --mode codex --recursive --json

# LIMITE concorrencia de invocacoes CLI pesadas
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 --max-concurrency 2 \
  recall "query" --k 5 --json

# AMPLIE wait-lock sob contencao esperada
sqlite-graphrag --wait-lock 30 remember --name nota --type note --description x --body y

# ATIVE low-memory para paralelismo unitario em container restrito
SQLITE_GRAPHRAG_LOW_MEMORY=1 sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  ingest ./docs --mode codex --recursive --json
```


## Manutenção (fts, backup, vacuum, optimize, migrate, export, debug-schema, vec, completions)
- INVOKE `fts rebuild --json` para reconstruir totalmente o índice full-text FTS5
- INVOKE `fts check --json` para executar verificação de integridade FTS5
- INVOKE `fts stats --json` para inspecionar saúde FTS5 (`total_rows`, `fts_functional`)
- INVOKE `optimize --fts-dry-run` para preview de rebuild FTS5
- INVOKE `optimize --fts-progress N` para imprimir progresso a cada N segundos
- PASSE `--no-fts-skip-when-functional` para forçar rebuild FTS5 mesmo quando saudável
- INVOKE `backup --output <path> --json` para backup online seguro via API SQLite
- INVOKE `sync-safe-copy --dest <path>` para snapshot atômico antes de operações críticas
- INVOKE `export --namespace <ns> --type <kind> --json` para exportar memórias como NDJSON
- INVOKE `vacuum --json` após purge grande para reclamar espaço
- INVOKE `migrate --rehash --json` para reparar drift de checksum V002
- INVOKE `migrate --to-llm-only --drop-vec-tables --json` para upgrades v1.0.74/75
- INVOKE `migrate --dry-run --json` para preview de migrações (v1.0.89)
- INVOKE `debug-schema --json` (oculto do `--help`) para inspecionar estado de schema
- INVOKE `completions <bash|zsh|fish|elvish|powershell>` para gerar completions de shell
- INVOKE `vec orphan-list --json` para listar vetores órfãos de memória
- INVOKE `vec purge-orphan --yes --dry-run` para PREVIEW de purge
- INVOKE `vec purge-orphan --yes` para purgar PERMANENTEMENTE órfãos
- INVOKE `vec stats --json` para inspecionar saúde das tabelas vec
- REGENERE schemas via `cargo run --bin dump-schema` (v1.0.89, ADR-0048)
- AGENDE semanal: `purge --retention-days 30 --yes` depois `cleanup-orphans --yes` depois `prune-relations --relation mentions --yes` depois `vacuum --json` depois `optimize --json` depois `sync-safe-copy --dest ~/backups/`
- SAIBA que DESDE v1.0.53 toda escrita executa `PRAGMA wal_checkpoint(TRUNCATE)` após commit
- SE corrupção ocorrer apesar do checkpoint: `sqlite3 broken.sqlite ".recover" | sqlite3 repaired.sqlite`
```bash
# FTS rebuild, check e stats — todos SEM embedding
sqlite-graphrag fts rebuild --json
sqlite-graphrag fts check --json | jaq '.integrity_ok'
sqlite-graphrag fts stats --json | jaq '{total_rows, fts_functional}'

# BACKUP online seguro e snapshot atomico
sqlite-graphrag backup --output ~/backups/graphrag-$(date +%Y%m%d).sqlite --json
sqlite-graphrag sync-safe-copy --dest ~/backups/snap.sqlite

# EXPORT memorias como NDJSON
sqlite-graphrag export --namespace prod --type decision --json | jaq -c '{name, description}'

# VACUUM e OPTIMIZE apos purge grande
sqlite-graphrag vacuum --json
sqlite-graphrag optimize --json | jaq '.fts_rebuilt'

# VEC orphan-list e purge com dry-run
sqlite-graphrag vec orphan-list --json | jaq 'length'
sqlite-graphrag vec purge-orphan --yes --dry-run --json
sqlite-graphrag vec stats --json

# COMPLETIONS de shell
sqlite-graphrag completions bash > ~/.local/share/bash-completion/completions/sqlite-graphrag
```


## Exemplos Prontos

### Exemplo 1 — Bootstrap de namespace de projeto
```bash
sqlite-graphrag init --namespace meuprojeto
sqlite-graphrag health --json | jaq '.integrity_ok'
sqlite-graphrag health --json | jaq '{schema_version, counts}'
```
- ESPERE: exit 0, `integrity_ok: true`, `schema_version >= 15`

### Exemplo 2 — Armazenar e recuperar memória (backend Codex)
```bash
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  remember --name decisao-auth --type decision \
  --description "JWT 15 min de expiração com fluxo de refresh" \
  --body-stdin <<'EOF'
Escolhemos JWT com 15 minutos de expiração porque:
- Refresh tokens são cookies HTTP-only
- 15min reduz blast radius de XSS
- Fluxo de refresh reemite tokens em atividade do usuário
EOF

sqlite-graphrag read --name decisao-auth --json | jaq '{description, body_length}'
```
- ESPERE: memória persistida, body contém texto completo, `body_length` > 100

### Exemplo 3 — Busca híbrida com expansão de grafo (backend Claude)
```bash
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  hybrid-search "autenticação JWT" --k 5 --with-graph --max-hops 2 --json \
  | jaq -r '(.results[] | .name), (.graph_matches[] | .name)' | sort -u
```
- ESPERE: top 5 resultados KNN+FTS5 fundidos mais 0-N vizinhos multi-hop

### Exemplo 3b — Busca híbrida com expansão de grafo (backend OpenCode)
```bash
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  hybrid-search "autenticação JWT" --k 5 --with-graph --max-hops 2 --json \
  | jaq -r '(.results[] | .name), (.graph_matches[] | .name)' | sort -u
```
- ESPERE: top 5 resultados KNN+FTS5 fundidos via OpenCode embedding

### Exemplo 4 — Ingest em massa de pasta de documentação (backend Codex)
```bash
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  ingest ./docs --mode codex --recursive --type document \
  --pattern "*.md" --max-files 1000 --auto-describe --json \
  | jaq -c 'select(.status)' | jaq -s 'group_by(.status) | map({status: .[0].status, count: length})'
```
- ESPERE: progresso NDJSON; summary mostra `files_total`, `files_succeeded`, `files_failed`

### Exemplo 4b — Ingest em massa (backend OpenCode)
```bash
sqlite-graphrag --llm-backend opencode --llm-model opencode/big-pickle \
  ingest ./docs --mode opencode --recursive --type document \
  --pattern "*.md" --auto-describe --json \
  | jaq -c 'select(.status)' | jaq -s 'group_by(.status) | map({status: .[0].status, count: length})'
```
- ESPERE: progresso NDJSON; OpenCode extrai entidades e relações por arquivo

### Exemplo 5 — Travessia de grafo a partir de entidade conhecida
```bash
sqlite-graphrag graph entities --json | jaq -r '.entities[].name' | head -10
sqlite-graphrag graph traverse --from jwt --depth 2 --json | jaq -r '.hops[] | "\(.entity) \(.relation)"'
```
- ESPERE: lista de entidades; travessia mostra vizinhança de 2 hops via relações canônicas

### Exemplo 6 — Pergunta de pesquisa profunda (backend Claude)
```bash
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  deep-research "Como o binário se autentica em providers OAuth?" \
  --k 20 --max-hops 3 --max-sub-queries 5 --json \
  | jaq '{stats, evidence_chains: (.evidence_chains | length)}'
```
- ESPERE: sub-queries decompostas, cadeias de evidência ligando seed ao alvo, graph_context populado

### Exemplo 7 — Extração de entidades curada por LLM (backend Codex)
```bash
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  ingest ./corpus --mode codex --recursive --resume --json \
  | jaq -c 'select(.status == "done") | {file, entities, rels}'
```
- ESPERE: NDJSON por arquivo com `entities` count, `rels` count; `--resume` continua após interrupção

### Exemplo 8 — Diagnosticar falha preflight (exit 16, backend Claude)
```bash
CLAUDE_CONFIG_DIR=/tmp/bad-mcp sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name teste --type note --description x --body y 2>&1
echo "exit=$?"
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 \
  remember --name teste --type note --description x --body y 2>&1 || echo "exit=$?"
```
- ESPERE: primeira invocação retorna exit 16 com envelope `AppError::PreFlightFailed`
- ESPERE: segunda invocação sem diretório MCP ruim retorna exit 0

### Exemplo 9 — Recuperação de soft-delete (backend Codex)
```bash
sqlite-graphrag forget --name decisao-auth
sqlite-graphrag history --name decisao-auth --json | jaq '.versions[0].deleted'
sqlite-graphrag restore --name decisao-auth
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini \
  recall "JWT" --k 3 --json | jaq '.results[].name'
```
- ESPERE: soft-delete esconde de recall; restore traz de volta; recall mostra novamente

### Exemplo 10 — Health check com filtro de namespace e tabelas vec
```bash
sqlite-graphrag health --namespace prod --json | jaq '{integrity_ok, schema_version, counts}'
sqlite-graphrag vec stats --json | jaq '.'
sqlite-graphrag embedding status --json | jaq '{pending, done, failed}'
```
- ESPERE: contagens escopadas para o namespace `prod`; saúde de tabelas vec; status da fila de embedding

### Exemplo 11 — Regenerar schemas JSON após mudanças de tipo
```bash
cargo run --bin dump-schema -- --check
git diff --stat docs/schemas/
cargo run --bin dump-schema  # se --check falhou
```
- ESPERE: `--check` sai com 0 quando schemas estão sincronizados; regeneração produz output idempotente

### Exemplo 12 — Pipeline de manutenção (semanal)
```bash
sqlite-graphrag purge --retention-days 30 --yes --dry-run
sqlite-graphrag cleanup-orphans --yes --dry-run
sqlite-graphrag prune-relations --relation mentions --yes --dry-run
sqlite-graphrag vacuum --json
sqlite-graphrag optimize --json
sqlite-graphrag sync-safe-copy --dest ~/backups/graphrag-$(date +%Y%m%d).sqlite
```
- ESPERE: cada dry-run reporta contagens; pipeline completo reclama espaço e gera snapshot seguro

### Exemplo 13 — Inspecionar whitelist de modelos Codex (v1.0.89, alias no-op, GAP-E2E-010a)
```bash
sqlite-graphrag codex-models --json | jaq '{count, default, models: .models[:3]}'
sqlite-graphrag codex-models  # modo texto para humanos
sqlite-graphrag codex-models --json | jaq '.models | length'
```
- ESPERE: envelope JSON `{"action":"codex_models","count":N,"default":"gpt-5.5","models":[...]}`
- ESPERE: modo texto emite lista legível de modelos suportados
- USE ao validar que o escopo OAuth atual inclui os nomes de modelo codex necessários

### Exemplo 14 — Health check escopado para um namespace (v1.0.89, GAP-E2E-002)
```bash
sqlite-graphrag health --namespace prod --json | jaq '{integrity_ok, schema_version, counts}'
sqlite-graphrag health --namespace dev --json | jaq '.counts'  # contagens diferentes
sqlite-graphrag health --json | jaq '.counts'  # contagens globais
```
- ESPERE: contagens filtradas para o namespace especificado; campos integrity e schema_version inalterados
- USE em ambientes multi-tenant para verificar isolamento por namespace
- REGRA DE OMISSÃO: quando `--namespace` é omitido, contagens agregam entre todos namespaces (visão global)

### Exemplo 15 — Preview de migração em dry-run (v1.0.89, GAP-E2E-009)
```bash
sqlite-graphrag migrate --dry-run --json | jaq '.would_apply[]? | {name, version}'
sqlite-graphrag migrate --to-llm-only --drop-vec-tables --dry-run --json | jaq '.'
sqlite-graphrag migrate --dry-run --json  # sempre faça PREVIEW antes de migrações destrutivas
```
- ESPERE: lista de migrações pendentes com nome+versão sem aplicá-las; banco permanece inalterado
- ESPERE: `--to-llm-only --dry-run` reporta plano de drop de tabelas vec sem executar
- USE em pipelines CI e antes de qualquer passo de migração irreversível

### Exemplo 16 — Cadeia de fallback de backend (Codex primeiro, Claude reserva)
```bash
sqlite-graphrag --llm-backend codex,claude --llm-model gpt-5.5 \
  remember --name decisao-fallback --type decision \
  --description "Cadeia de backend" --body "Codex primeiro, Claude reserva" --json \
  | jaq '{backend_invoked, vec_degraded_reason}'

sqlite-graphrag --llm-backend codex,claude,none --skip-embedding-on-failure \
  remember --name decisao-null --type note --description x --body y --json \
  | jaq '.backend_invoked'
```
- ESPERE: `backend_invoked` reporta qual backend efetivamente gerou o embedding
- ESPERE: cadeia tripla cai em embedding null e retorna exit 0 com `--skip-embedding-on-failure`

### Exemplo 16b — Cadeia de fallback completa: codex → claude → opencode → none
```bash
sqlite-graphrag --llm-backend codex,claude,opencode,none --skip-embedding-on-failure \
  remember --name max-resiliencia --type note \
  --description "sobrevive a falha de todos os backends" --body-file nota.md

sqlite-graphrag read --name max-resiliencia --json | jaq '.backend_invoked'
```
- ESPERE: tenta codex, depois claude, depois opencode, depois degrada para embedding null; `backend_invoked` confirma qual rodou

### Exemplo 17 — Seleção de modelo por backend e env var persistente
```bash
# Modelo explicito por backend via flag
sqlite-graphrag --llm-backend codex --llm-model gpt-5.4-mini recall "query" --k 5 --json | jaq '.backend_invoked'
sqlite-graphrag --llm-backend claude --llm-model claude-sonnet-4-6 recall "query" --k 5 --json | jaq '.backend_invoked'

# Backend e modelo persistentes via env vars
export SQLITE_GRAPHRAG_LLM_BACKEND=codex
export SQLITE_GRAPHRAG_LLM_MODEL=gpt-5.4-mini
sqlite-graphrag recall "query" --k 5 --json | jaq '.backend_invoked'
```
- ESPERE: `--llm-model` seleciona o modelo de embedding para o backend ativo
- ESPERE: env vars fixam backend e modelo sem repetir flags em cada invocação


## Referências para Documentação Estendida

Para detalhes além do escopo de uso diário desta skill, os seguintes documentos do projeto estendem a cobertura:

- `docs/HOW_TO_USE.md` — quickstart, instalação, workflows comuns
- `docs/COOKBOOK.md` — 50+ receitas para padrões avançados (diagnóstico preflight, recovery de drift de schema, etc.)
- `docs/MIGRATION.md` — caminhos de upgrade entre versões
- `docs/CROSS_PLATFORM.md` — comportamento em Linux, macOS, Windows ARM64
- `docs/AGENTS.pt-BR.md` — documentação PT-BR estendida para agentes de IA
- `docs/schemas/*.schema.json` — contratos JSON Schema completos (versionados por SemVer)
- `docs/decisions/adr-*.md` — Architecture Decision Records (justificativas para cada escolha de design)
- `llms-full.txt` — dump completo de contexto LLM com todas as regras
- `gaps.md` — gaps abertos e fechados atualmente
- `CHANGELOG.md` — release notes versão por versão
- `Cargo.toml` — metadados do pacote e documentação de tamanho do binário (14.6 MiB)


## Resumo de Regras Ativas e Anti-padrões
- NUNCA passe `ANTHROPIC_API_KEY` ou `OPENAI_API_KEY` (OAuth-only, exit 1)
- NUNCA dependa do daemon ou use flag `--bare` (REMOVIDOS v1.0.76 e v1.0.79)
- NUNCA instale com `--features embedding-legacy` ou `--features ner-legacy` (REMOVIDOS)
- NUNCA use crates `fastembed`, `tokenizers`, `sqlite-vec`, ou `GLiNER`
- NUNCA espere KNN sqlite-vec; cosine é pure Rust em `src/similarity.rs`
- NUNCA rode `enrich` em paralelo contra mesmo banco (job singleton via `lock::acquire_job_singleton`)
- NUNCA escreva no arquivo `.sqlite` fora do binário
- NUNCA ignore exit 19 (envelope SHUTDOWN_EXIT_CODE); trabalho parcial descartado, RETRY OBRIGATÓRIO
- NUNCA ignore exit 16 (falha preflight); corrija config MCP ou `SQLITE_GRAPHRAG_SKIP_PREFLIGHT=1`
- NUNCA duplique conteúdo já existente em `CHANGELOG.md`
- NUNCA use `mentions` como relação padrão de grafo
- NUNCA passe corpo vazio via `--graph-stdin` (exit 1 desde v1.0.54)
- NUNCA use `--gliner-variant` (no-op desde v1.0.79)
- NUNCA chame `migrate --to-llm-only` sem guarda de segurança `--drop-vec-tables`
- NUNCA ignore flag `--wait-lock` quando contenção for esperada
- NUNCA assuma exit 1 igual a exit 9 (validação vs duplicada)
- NUNCA assuma que o tamanho do binário é 6 MB; o real é 14.6 MiB stripped ELF
- NUNCA passe `--llm-backend codex` esperando uso de API key (OAuth-only, exit 1)
- SEMPRE passe `--llm-backend` e `--llm-model` em comandos de embedding para backend determinístico
- SEMPRE parsee `backend_invoked` para confirmar qual backend gerou o embedding