generateMetadata still derived the page <title>/OG title from the generic
auto frontmatter topic ("Dow Uap D44 …"). Search engines, link cards, and
AI crawlers show that string, so it must be the human magazine headline the
narrator wrote as the body H1. Mirror the page component's H1 extraction.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
||
|---|---|---|
| .claude/agents | ||
| .forgejo/workflows | ||
| .nirvana/outputs/disclosure-bureau | ||
| case/gaps | ||
| docs/adrs | ||
| infra | ||
| investigator-runtime | ||
| scripts | ||
| tests/rag | ||
| web | ||
| wiki/entities/events | ||
| .gitignore | ||
| CHANGELOG.md | ||
| CLAUDE-schema-full.md | ||
| CLAUDE.md | ||
| CORPUS-SNAPSHOT.md | ||
| README.md | ||
The Disclosure Bureau
Investigative wiki + agentic chat sobre o corpus declassificado do US Department of War em
war.gov/ufo(116 PDFs, 3.435 páginas, 34k+ entidades, 28 vídeos UAP).
Live: disclosure.top
O que é
Pipeline de IA que transforma documentos UAP/UFO declassificados em uma wiki investigativa navegável + chat agêntico com retrieval semântico bilíngue (EN + PT-BR) e citações com bbox crop no PDF original.
A premissa metodológica é o padrão Karpathy LLM Wiki: ler tudo, compilar conhecimento em markdown cross-referenciado, navegar via wiki-links — não por busca vetorial. Em cima dessa wiki rodamos uma camada de hybrid retrieval (BM25 + BGE-M3 dense + cross-encoder rerank) para perguntas livres no chat.
A camada investigativa segue protocolo Investigation Bureau (Holmes/Poirot/Dupin/Locard + Schneier/Tetlock/Taleb): chain-of-custody, hypothesis tournament, residual uncertainty.
Arquitetura
PDFs (raw/)
↓ pdftoppm 72 DPI + pdftotext
processing/ (png + ocr)
↓ Sonnet 4.6 subagents (page-rebuilder, image-analyst, table-stitcher)
raw/<doc>--subagent/ (chunks bilíngues + bbox + anomaly flags)
↓ scripts/30 (BGE-M3 embed) + 31 (entity_mentions)
Postgres + pgvector + tsvector
↓ hybrid_search RPC + reranker
chat agente (OpenRouter) cita [[doc/p007#c0042]] → frontend renderiza crop bbox
Stack
- Embedding: BGE-M3 self-hosted (1024-dim, multilíngue, $0)
- Reranker: BGE-Reranker-v2-M3 self-hosted ($0)
- Vetor + texto: Postgres 15 + pgvector + tsvector bilíngue (
pt_unaccent,en_unaccent) - LLM (chat): OpenRouter — DeepSeek v4 free como default
- Frontend: Next.js 15 + React 19 + Tailwind + assistant-ui (Pattern C streaming)
- Auth + persistência: Supabase self-hosted (GoTrue, PostgREST, Storage, Imgproxy)
- Reverse proxy: Traefik + Let's Encrypt
- Imagens: sharp via
/api/crop(bbox on-demand, cached 1ano)
Layout
/Users/guto/ufo/
├── CLAUDE.md # contrato vinculante (24 tipos de markdown)
├── CLAUDE-schema-full.md # schema detalhado
├── README.md # este arquivo
├── raw/ # 116 PDFs imutáveis + chunks v0.2.0 derivados
│ ├── <pdfs>
│ ├── <doc-id>--subagent/ # chunks rebuilt (chunks/c*.md + _index.json + document.md)
│ └── _batch-rebuild/ # logs do orchestrator
├── processing/ # intermediários (PNG, OCR, vision JSON)
├── wiki/ # markdown gerado (documents/, pages/, entities/, tables/, images/)
├── case/ # artefatos Investigation Bureau (case-report, hypotheses, gaps)
├── scripts/ # 33 scripts numerados (Phase 0 → manutenção)
├── infra/ # docker-compose, embed-service, migrations, deploy
└── web/ # Next.js frontend
Quick start
# 1. Converter PDFs em PNG + OCR (uma vez)
./scripts/01-convert-pdfs.sh
# 2. Rebuild chunks bilíngues (Sonnet 4.6 via Claude Code subagents)
python3 scripts/28-batch-rebuild-all.py --workers 2
# 3. (após batch) Indexar em Postgres + embeddings
python3 scripts/30-index-chunks-to-db.py --skip-existing
# 4. (opcional) Materializar entity_mentions p/ grafo
python3 scripts/31-populate-entity-mentions.py
# 5. Deploy
cd infra/disclosure-stack && ./scripts/deploy.sh
Detalhes completos em infra/DEPLOY-CHECKLIST.md.
Features do frontend
| URL | Função |
|---|---|
/ |
Lista de documentos com resumo de 3 linhas, filtros (collection, classification, sort), busca |
/d/<doc> |
Visão legado (page grid + frontmatter) |
/d/<doc>/v2 |
Render rico de chunks com lang toggle (PT/EN/both), paged vs flow |
/d/<doc>/v2/<page> |
Single page V2 com PNG side-by-side |
/d/<doc>/full |
Texto consolidado bilíngue |
/e/<class> |
Lista paginada de entidades por classe (people, locations, ...) |
/e/<class>/<id> |
Detalhe da entidade + co-mentions + chunks live |
/search?q=... |
Hybrid search URL-shareable |
/timeline |
Cronologia de eventos por década |
/graph |
Grafo força-direcionado de co-menções (Obsidian-style) |
/admin/stats |
Analytics do corpus (FS + DB) |
/admin/batch |
Monitor de progresso do rebuild |
/admin/indexer |
Estado da camada de retrieval |
Atalhos globais:
⌘K/Ctrl+Kem qualquer página → command palette com hybrid_search- Toggle 🌐 EN ↔ PT-BR fixo bottom-left (cookie 1ano)
- Chat 💬 botão flutuante bottom-right com 12 ferramentas
Os 12 tools do agente
🔍 Retrieval: hybrid_search, read_chunk, get_page_chunks, list_anomalies
🔗 Grafo: entity_neighbors, entity_path, co_mention_chunks
📄 Wiki: read_document, read_page, read_entity, search_corpus
🧭 UI: navigate_to
Citações tipo [[doc-id/p007#c0042]] viram cards interativos com crop bbox + texto bilíngue + link.
Custos
| Item | Custo |
|---|---|
| Rebuild chunks (Sonnet 4.6 via Claude Code Max 20x) | ~$200 one-shot p/ 116 docs |
| Embedding BGE-M3 self-host | $0/mês |
| Reranker BGE-Reranker-v2-M3 self-host | $0/mês |
| Postgres + pgvector | já incluso no VPS |
| Chat LLM (DeepSeek free via OpenRouter) | $0/req |
| VPS (16GB / 4 CPU) | ~€10/mês |
Documentação
CLAUDE.md— contrato vinculante para agentes (schema v0.2.0)CLAUDE-schema-full.md— schema dos 24 tiposinfra/RETRIEVAL.md— arquitetura da camada de retrievalinfra/DEPLOY-CHECKLIST.md— runbook end-to-endinfra/embed-service/README.md— microsserviço BGE-M3
Licença + procedência
- PDFs declassificados: domínio público (US Department of War / FBI / DOS / NASA)
- Código deste projeto: MIT
- Modelos: BGE-M3 (MIT), DeepSeek v4 (proprietary via OpenRouter free tier)
- Branding: The Disclosure Bureau / disclosure.top — pessoal
Wiki investigativa, não advocacy. Toda claim tem chain-of-custody até a página + bbox do PDF original.