diff --git a/.gitignore b/.gitignore
index b6b2bac..1b7f05c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
.env
+docs/
__pycache__/
*.py[cod]
*$py.class
diff --git a/TIPOS_ATUACAO_ELASTICSEARCH.md b/TIPOS_ATUACAO_ELASTICSEARCH.md
deleted file mode 100644
index dbd450c..0000000
--- a/TIPOS_ATUACAO_ELASTICSEARCH.md
+++ /dev/null
@@ -1,407 +0,0 @@
-# Tipos de Atuação Disponíveis no Elasticsearch (AtuaCAPES)
-
-> Mapeamento completo dos tipos de atuação encontrados no índice `atuacapes` do Elasticsearch CAPES
-
-## Visão Geral
-
-Este documento lista todos os tipos de atuação (`atuacoes.tipo`) disponíveis no índice Elasticsearch do sistema AtuaCAPES, identificados através da análise do código implementado e da documentação do projeto.
-
----
-
-## Tipos de Atuação Implementados
-
-### Componente A - Coordenação CAPES
-
-| Tipo | Descrição | Boost | Pontuação Base |
-|------|-----------|-------|----------------|
-| `Coordenação de Área de Avaliação` | Coordenadores ativos (CA, CAJ, CAJ-MP, CAM) | 10 | 200-100 pts |
-| `Histórico de Coordenação de Área de Avaliação` | Coordenadores históricos (mandatos encerrados) | 5 | 200-100 pts |
-
-**Subtipos identificados em `dadosCoordenacaoArea.tipo`:**
-- `Coordenador de Área` (CA) - Base: 200 pts
-- `Coordenador Adjunto` (CAJ) - Base: 150 pts
-- `Coordenador Adjunto de Mestrado Profissionalizante` (CAJ-MP) - Base: 120 pts
-- `Coordenador de Câmara Temática` (CAM) - Base: 100 pts
-
-### Componente C - Consultoria
-
-| Tipo | Descrição | Boost | Pontuação Base |
-|------|-----------|-------|----------------|
-| `Consultor` | Registro de consultoria ativa ou histórica | 2 | 150 pts (ativo) |
-| `Histórico de Consultoria` | Consultorias encerradas | 1 | 100 pts (histórico) |
-
-**Valores de `situacaoConsultoria`:**
-- `Atividade Contínua` - Consultor Ativo
-- `Ativo` - Consultor Ativo
-- Outros valores ou com `inativacaoSituacao` preenchido = Histórico
-
-### Componente D - Premiações
-
-| Tipo | Descrição | Boost | Pontuação |
-|------|-----------|-------|-----------|
-| `Premiação Prêmio` | Prêmio recebido | 3 | 60-180 pts |
-| `Avaliação Prêmio` | Participação em avaliação/comissão | 2 | 2-115 pts |
-| `Inscrição Prêmio` | Inscrição em prêmio | 1 | 1-2 pts |
-
-**Níveis de Premiação:**
-
-#### Nível 1 - Grande Prêmio CAPES
-- `dadosPremiacaoPremio.premiacao`: "Grande Prêmio"
-- Pontuação: 150 + 50 = 200 pts (limitado a 180)
-
-#### Nível 1 - Prêmio CAPES de Tese (PCT)
-- `dadosPremiacaoPremio.premio`: "PCT"
-- `dadosPremiacaoPremio.premiacao`: "Prêmio" (+25) ou "Menção Honrosa" (+15)
-- Pontuação base: 100 pts (máx 150 pts)
-
-#### Nível 2 - Institucionais
-- Interfarma, Vale-CAPES, etc.
-- Base: 30 pts
-- Prêmio: +20 pts / Menção: +10 pts
-- Máximo: 60 pts
-
-#### Nível 3 - Autoinscrição
-- CDTDN, Vínculos Familiares, etc.
-- Base: 10 pts
-- Prêmio: +5 pts / Menção: +3 pts
-- Máximo: 20 pts
-
-### Outros Tipos Identificados
-
-| Tipo | Descrição | Uso no Ranking |
-|------|-----------|----------------|
-| `Evento` | Participação em eventos SAE | Sim - bônus consultoria |
-
-**Campos relacionados a eventos:**
-- `dadosEvento.consultorResponsavel`: "Sim" ou "Não"
-- Eventos recentes (últimos 2 anos): bonus para consultoria ativa
-- Responsável por evento: +5 pts por vez (máx 25)
-
----
-
-## Estrutura de Dados por Componente
-
-### Coordenação CAPES
-
-```json
-{
- "tipo": "Coordenação de Área de Avaliação",
- "inicio": "01/01/2020",
- "fim": null,
- "dadosCoordenacaoArea": {
- "tipo": "Coordenador de Área",
- "areaAvaliacao": {
- "id": 123,
- "nome": "CIÊNCIAS AMBIENTAIS"
- },
- "inicioVinculacao": "01/01/2020",
- "fimVinculacao": null,
- "colegio": [
- {"nome": "Colégio de Ciências Exatas, Tecnológicas e Multidisciplinar"}
- ],
- "portaria": "123/2020",
- "ies": {
- "nome": "Universidade Federal do Brasil",
- "sigla": "UFB"
- }
- }
-}
-```
-
-### Consultoria
-
-```json
-{
- "tipo": "Consultor",
- "inicio": "15/03/2018",
- "fim": null,
- "dadosConsultoria": {
- "situacaoConsultoria": "Atividade Contínua",
- "inicioSituacao": "15/03/2018",
- "inativacaoSituacao": null,
- "ies": {
- "nome": "Universidade Federal do Brasil",
- "sigla": "UFB"
- },
- "areaConhecimentoPos": [
- {
- "areaAvaliacao": {
- "nome": "CIÊNCIAS AMBIENTAIS"
- }
- }
- ],
- "areaPesquisa": [
- {"descricao": "Mudanças Climáticas"}
- ]
- }
-}
-```
-
-### Premiações
-
-```json
-{
- "tipo": "Premiação Prêmio",
- "dadosPremiacaoPremio": {
- "nomePremio": "Prêmio CAPES de Tese",
- "premio": "PCT",
- "premiacao": "Prêmio",
- "ano": 2022,
- "areaConhecimento": {
- "areaAvaliacao": {
- "nome": "CIÊNCIAS AMBIENTAIS"
- }
- },
- "papelPessoa": "Autor"
- }
-}
-```
-
-### Participação em Prêmios
-
-```json
-{
- "tipo": "Avaliação Prêmio",
- "dadosParticipacaoPremio": {
- "tipo": "Membro de Comissão",
- "premio": "PCT",
- "ano": 2023,
- "comissao": {
- "nome": "Comissão Julgadora",
- "tipo": "Avaliação"
- },
- "areaAvaliacao": {
- "nome": "CIÊNCIAS AMBIENTAIS"
- }
- }
-}
-```
-
-### Eventos
-
-```json
-{
- "tipo": "Evento",
- "inicio": "10/05/2023",
- "fim": "15/05/2023",
- "dadosEvento": {
- "consultorResponsavel": "Sim",
- "nome": "Seminário de Avaliação",
- "tipo": "Presencial"
- }
-}
-```
-
----
-
-## Query de Agregação - Descobrir Todos os Tipos
-
-Para descobrir todos os tipos de atuação disponíveis no índice:
-
-```json
-{
- "size": 0,
- "aggs": {
- "tipos": {
- "nested": {"path": "atuacoes"},
- "aggs": {
- "tipos_unicos": {
- "terms": {
- "field": "atuacoes.tipo.keyword",
- "size": 100
- }
- }
- }
- }
- }
-}
-```
-
----
-
-## Mapeamento de Tipos vs. Componentes de Pontuação
-
-| Componente | Tipos Relacionados | Pontuação Máxima |
-|------------|-------------------|------------------|
-| **A - Coordenação CAPES** | `Coordenação de Área de Avaliação`
`Histórico de Coordenação de Área de Avaliação` | 450 pts (CA) |
-| **B - Coordenação PPG** | *Não existe no ES - usar Oracle* | 180 pts |
-| **C - Consultoria** | `Consultor`
`Histórico de Consultoria`
`Evento` (bônus) | 230 pts |
-| **D - Premiações** | `Premiação Prêmio`
`Avaliação Prêmio`
`Inscrição Prêmio` | 180 pts |
-
----
-
-## Campos Faltantes / Limitações
-
-### Não Disponíveis no Elasticsearch
-
-1. **Coordenação de Programa (PPG)**
- - Não existe tipo `atuacoes.tipo` para coordenação de programa
- - Fonte alternativa: Oracle `SUCUPIRA_PAINEL.VM_COORDENADOR`
-
-2. **Nota do PPG**
- - Não disponível em `dadosGestaoPrograma`
- - Fonte alternativa: Oracle `VM_PROGRAMA_SUCUPIRA.DS_CONCEITO`
-
-3. **Dados detalhados de Câmara Temática**
- - Inferido pelo campo `dadosCoordenacaoArea.tipo` ou `nome`
- - Pode haver imprecisão na classificação
-
-4. **Situação "Falecido"**
- - Existe `dadosPessoais.anoObito` mas não `situacaoConsultoria="Falecido"`
-
----
-
-## Implementação no Código
-
-### Arquivo: `backend/src/infrastructure/elasticsearch/client.py`
-
-Query principal com boost por tipo:
-
-```python
-async def buscar_candidatos_ranking(self, size: int = 1000) -> List[Dict[str, Any]]:
- query = {
- "size": size,
- "query": {
- "bool": {
- "should": [
- # Coordenação CAPES
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Coordenação de Área de Avaliação", "boost": 10}}},
- {"term": {"atuacoes.tipo": {"value": "Histórico de Coordenação de Área de Avaliação", "boost": 5}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- },
- # Consultoria
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Consultor", "boost": 2}}},
- {"term": {"atuacoes.tipo": {"value": "Histórico de Consultoria", "boost": 1}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- },
- # Premiações
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Premiação Prêmio", "boost": 3}}},
- {"term": {"atuacoes.tipo": {"value": "Avaliação Prêmio", "boost": 2}}},
- {"term": {"atuacoes.tipo": {"value": "Inscrição Prêmio", "boost": 1}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- }
- ],
- "minimum_should_match": 1
- }
- },
- "_source": ["id", "dadosPessoais", "atuacoes"],
- "sort": [{"_score": "desc"}]
- }
-```
-
-### Arquivo: `backend/src/infrastructure/repositories/consultor_repository_impl.py`
-
-Extração de tipos:
-
-```python
-# Consultoria
-consultorias = [
- a for a in atuacoes
- if a.get("tipo") in ["Consultor", "Histórico de Consultoria"]
-]
-
-# Coordenação CAPES
-coordenacoes = [
- a for a in atuacoes
- if a.get("tipo") in [
- "Coordenação de Área de Avaliação",
- "Histórico de Coordenação de Área de Avaliação",
- ]
-]
-
-# Eventos (bônus consultoria)
-eventos_sae = [
- a for a in atuacoes
- if a.get("tipo") == "Evento"
-]
-
-# Premiações (todos os tipos são processados genericamente)
-premiacoes = [
- a for a in atuacoes
- if a.get("dadosPremiacaoPremio") or
- a.get("dadosParticipacaoPremio") or
- a.get("dadosParticipacaoInscricaoPremio")
-]
-```
-
----
-
-## Estatísticas
-
-### Estimativas de Volume (baseado em documentação)
-
-| Tipo | Quantidade Estimada |
-|------|---------------------|
-| Coordenadores de área (ativos) | ~200 |
-| Coordenadores históricos | ~322 |
-| Consultores | ~52.551 |
-| Premiações | ~63.799 |
-| **Total de registros com atuações** | **~90.482** |
-
-### Boost Aplicado
-
-O boost é usado para priorizar candidatos no score inicial do Elasticsearch:
-
-| Tipo | Boost | Justificativa |
-|------|-------|---------------|
-| Coordenação de Área (ativa) | 10 | Máxima prioridade (200-450 pts) |
-| Coordenação de Área (histórica) | 5 | Alta prioridade histórica |
-| Premiação Prêmio | 3 | Mérito significativo |
-| Consultor | 2 | Base importante |
-| Avaliação Prêmio | 2 | Participação ativa |
-| Histórico de Consultoria | 1 | Relevância histórica |
-| Inscrição Prêmio | 1 | Participação básica |
-
----
-
-## Notas de Implementação
-
-1. **Paginação**: Query principal retorna top 1000 candidatos ordenados por score ES
-2. **Recálculo**: Python recalcula pontuação completa e reordena por pontuação real
-3. **Cache**: Resultados cacheados por 5 minutos (TTL=300s)
-4. **Performance**: Primeira requisição ~1m34s, cacheadas ~0.27s
-5. **Timeout**: 120s para queries ES
-
----
-
-## Referências
-
-- **Documentação**: `/home/fred/projetos/ranking/.claude/rules/ranking-queries-elasticsearch.md`
-- **Critérios**: `/home/fred/projetos/ranking/.claude/rules/ranking-consultores-capes.md`
-- **Implementação ES**: `/home/fred/projetos/ranking/backend/src/infrastructure/elasticsearch/client.py`
-- **Extração**: `/home/fred/projetos/ranking/backend/src/infrastructure/repositories/consultor_repository_impl.py`
-
----
-
-**Última atualização**: 2025-12-13
-**Índice Elasticsearch**: `atuacapes` (servidor: `elastic-atuacapes.hom.capes.gov.br:9200`)
diff --git a/TOP_10_RANKING_CAPES.md b/TOP_10_RANKING_CAPES.md
deleted file mode 100644
index 1836915..0000000
--- a/TOP_10_RANKING_CAPES.md
+++ /dev/null
@@ -1,291 +0,0 @@
-# TOP 10 CONSULTORES - RANKING CAPES
-
-**Data da Consulta:** 13/12/2025
-**Base de Dados:** Elasticsearch AtuaCAPES (índice: atuacapes)
-**Total de Candidatos Analisados:** 100
-**Critérios:** Sistema de Ranking Integrado CAPES v1.0
-
----
-
-## Resumo Executivo
-
-O ranking foi calculado com base em 4 componentes principais:
-
-- **Componente A:** Coordenação CAPES (máx 450 pts) - CA, CAJ, CAJ-MP, CAM
-- **Componente B:** Coordenação de Programa PPG (máx 180 pts) - *Não disponível nesta consulta*
-- **Componente C:** Consultoria (máx 230 pts)
-- **Componente D:** Premiações (máx 180 pts)
-
-**Pontuação Máxima Teórica:** 1.040 pontos
-**Pontuação Máxima Observada:** 685 pontos (65,9% do máximo)
-
----
-
-## Top 10 Consultores
-
-### 1º LUGAR - EDSON APARECIDO MITISHITA
-**ID:** 519524
-**Pontuação Total:** 685 pontos
-
-**Breakdown de Pontuação:**
-- **Componente A (Coordenação CAPES):** 340 pts
- - Base: 200 (Coordenador de Área)
- - Tempo: 90 (9 anos completos)
- - Áreas Adicionais: 0
- - Bônus Atualidade: 30 (coordenação ativa)
- - Retorno: 20 (já coordenou antes)
-
-- **Componente B (Coordenação PPG):** 0 pts
-
-- **Componente C (Consultoria):** 165 pts
- - Base: 100 (histórico)
- - Tempo: 50 (10+ anos)
- - Total eventos: 2
- - Eventos recentes: 0 (último há mais de 2 anos)
- - Bônus continuidade: 15 (8+ anos consecutivos)
-
-- **Componente D (Premiações):** 180 pts
- - Total de premiações: 7
-
-**Perfil:**
-- Anos de atuação: 11,3 anos
-- Status: Inativo (sem eventos recentes)
-- Veterano: Sim
-- Área principal: GEOCIÊNCIAS
-- Coordenações: 3 (incluindo 1 ativa)
-
-**Destaque:** Possui a maior pontuação no Componente A devido à combinação de coordenação ativa (bônus de 30 pts) + retorno (20 pts) + 9 anos completos de experiência.
-
----
-
-### 2º LUGAR - ANDRE MOREIRA CUNHA
-**ID:** 45997
-**Pontuação Total:** 675 pontos
-
-**Breakdown de Pontuação:**
-- **Componente A:** 330 pts
- - Base: 200
- - Tempo: 100 (10 anos - máximo permitido)
- - Bônus Atualidade: 30
- - Retorno: 0 (sem retorno)
-
-- **Componente C:** 165 pts
-- **Componente D:** 180 pts (7 premiações)
-
-**Perfil:**
-- Anos de atuação: 14,2 anos
-- Status: Inativo
-- Área principal: ECONOMIA
-- Coordenações: 2 (1 ativa)
-
-**Destaque:** Atingiu o teto máximo de pontuação por tempo (100 pts) no Componente A.
-
----
-
-### 3º LUGAR - FLAVIO AUGUSTO SENRA RIBEIRO
-**ID:** 7794
-**Pontuação Total:** 665 pontos
-
-**Breakdown de Pontuação:**
-- **Componente A:** 320 pts
- - Base: 200
- - Tempo: 100
- - Áreas Adicionais: 20 (coordenou 2 áreas diferentes)
- - Bônus Atualidade: 0 (coordenação encerrada)
- - Retorno: 0
-
-- **Componente C:** 165 pts
-- **Componente D:** 180 pts (11 premiações)
-
-**Perfil:**
-- Anos de atuação: 14,5 anos
-- Status: Inativo
-- Áreas: FILOSOFIA, CIÊNCIAS DA RELIGIÃO E TEOLOGIA
-- Coordenações: 3 (todas encerradas)
-
-**Destaque:** Único no top 10 com pontuação por áreas adicionais (coordenou múltiplas áreas). Maior número de premiações entre os 10 primeiros (11 premiações).
-
----
-
-### 4º ao 10º LUGAR (Empate em 655 pontos)
-
-Os consultores da 4ª à 10ª posição compartilham a mesma pontuação total de **655 pontos**, com o seguinte padrão:
-
-**Componente A:** 310 pts
-- Base: 200
-- Tempo: 60 (6 anos)
-- Bônus Atualidade: 30
-- Retorno: 20
-
-**Componente C:** 165 pts
-**Componente D:** 180 pts
-
----
-
-#### 4º - CARLOS FREDERICO MARTINS MENCK
-**ID:** 20912
-**Área:** CIÊNCIAS BIOLÓGICAS I
-**Anos:** 14,5 | **Status:** Inativo
-**Premiações:** 25 (maior número absoluto)
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 5º - MARCELO ALBANO MORET SIMOES GONCALVES
-**ID:** 5888
-**Área:** INTERDISCIPLINAR
-**Anos:** 11,0 | **Status:** Ativo ✓
-**Premiações:** 9
-**Eventos recentes:** 2
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 6º - CARLOS PELLESCHI TABORDA
-**ID:** 15100
-**Área:** CIÊNCIAS BIOLÓGICAS III
-**Anos:** 12,6 | **Status:** Inativo
-**Premiações:** 15
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 7º - CLÁUDIA LUCIA DE MORAES FORJAZ
-**ID:** 14569
-**Área:** EDUCAÇÃO FÍSICA, FISIOTERAPIA, FONOAUDIOLOGIA E TERAPIA OCUPACIONAL
-**Anos:** 14,5 | **Status:** Inativo
-**Premiações:** 9
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 8º - ALTAIR ANTONINHA DEL BEL CURY
-**ID:** 8639
-**Área:** ODONTOLOGIA
-**Anos:** 12,1 | **Status:** Ativo ✓
-**Premiações:** 11
-**Eventos recentes:** 2
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 9º - DEBORA FOGUEL
-**ID:** 12271
-**Área:** CIÊNCIAS BIOLÓGICAS II
-**Anos:** 14,5 | **Status:** Inativo
-**Premiações:** 7
-**Coordenações:** 2 (1 ativa)
-
----
-
-#### 10º - MARCELO TÁVORA MIRA
-**ID:** 509665
-**Área:** MEDICINA I
-**Anos:** 11,3 | **Status:** Ativo ✓
-**Premiações:** 7
-**Eventos recentes:** 1
-**Coordenações:** 2 (1 ativa)
-
----
-
-## Análise Estatística
-
-### Distribuição de Pontuação
-
-| Posição | Pontuação | Diferença para 1º |
-|---------|-----------|-------------------|
-| 1º | 685 | - |
-| 2º | 675 | -10 |
-| 3º | 665 | -20 |
-| 4º-10º | 655 | -30 |
-
-**Média (top 10):** 661 pontos
-**Desvio padrão:** ~10 pontos
-
-### Componentes - Análise
-
-**Componente A (Coordenação CAPES):**
-- Média: 319 pts (71% do máximo)
-- Variação: 310-340 pts
-- Padrão dominante: CA (Coordenador de Área) com coordenação ativa
-
-**Componente B (Coordenação PPG):**
-- Todos: 0 pts (dados não disponíveis no Elasticsearch)
-
-**Componente C (Consultoria):**
-- Todos: 165 pts
-- Padrão: Base 100 + Tempo 50 + Bônus continuidade 15
-- Uniformidade total no top 10
-
-**Componente D (Premiações):**
-- Todos: 180 pts (máximo permitido)
-- Média de premiações: 10,3 por consultor
-- Variação: 7-25 premiações
-
-### Perfil dos Líderes
-
-**Anos de Atuação:**
-- Média: 12,7 anos
-- Variação: 11,0 - 14,5 anos
-- Todos são veteranos (10+ anos)
-
-**Status de Atividade:**
-- Ativos: 3 (30%)
-- Inativos: 7 (70%)
-
-**Áreas de Conhecimento:**
-- Ciências Biológicas: 3 consultores
-- Áreas diversas: 7 consultores
-
-**Padrão de Coordenação:**
-- Todos possuem coordenação ATIVA no momento
-- Todos exceto 1 tiveram retorno à coordenação
-- Média de 2,3 coordenações por consultor
-
----
-
-## Observações Técnicas
-
-### Limitações da Análise
-
-1. **Componente B = 0:** O Elasticsearch não contém dados de coordenação de PPG. Esses dados estão no Oracle (SUCUPIRA_PAINEL). Se incluídos, o ranking poderia mudar significativamente.
-
-2. **Amostra de 100 candidatos:** A query com boost buscou apenas 100 candidatos pré-ordenados pelo Elasticsearch. É possível que candidatos com alta pontuação real estejam fora dessa amostra.
-
-3. **Dados de Consultoria incompletos:** O campo "áreas" da consultoria retornou vazio para todos os consultores, sugerindo possível problema na extração de dados do Elasticsearch.
-
-### Critérios de Desempate
-
-Quando há empate na pontuação total (casos 4º-10º), a ordenação segue a ordem de retorno do Elasticsearch, que não necessariamente reflete um critério definido.
-
-**Sugestão:** Implementar critério de desempate explícito:
-1. Componente A (maior)
-2. Anos de atuação (maior)
-3. Status ativo (preferencial)
-4. ID menor (mais antigo no sistema)
-
-### Validação dos Cálculos
-
-Os cálculos seguem rigorosamente os critérios definidos em:
-- `/home/fred/projetos/ranking/.claude/rules/ranking-consultores-capes.md`
-- `/home/fred/projetos/ranking/.claude/rules/ranking-queries-implementadas.md`
-
-**Implementação:** `CalculadorPontuacao` em `/home/fred/projetos/ranking/backend/src/domain/services/calculador_pontuacao.py`
-
----
-
-## Próximos Passos Recomendados
-
-1. **Integrar dados do Oracle** para calcular Componente B (Coordenação PPG)
-2. **Expandir amostra** para 1.000+ candidatos para garantir cobertura completa
-3. **Corrigir extração de áreas** na consultoria
-4. **Implementar critério de desempate** explícito
-5. **Validar dados de premiações** (verificar se todas as 7-25 premiações são válidas)
-
----
-
-**Script de Geração:**
-`/home/fred/projetos/ranking/backend/scripts/top10_ranking.py`
-
-**Método de Consulta:**
-Query Elasticsearch com boost por tipo de atuação (conforme especificação técnica)
diff --git a/docs/ranking-queries-implementadas.md b/docs/ranking-queries-implementadas.md
deleted file mode 100644
index b0425b1..0000000
--- a/docs/ranking-queries-implementadas.md
+++ /dev/null
@@ -1,441 +0,0 @@
-# Queries Implementadas - Sistema de Ranking de Consultores CAPES
-
-> Documentação das queries efetivamente implementadas no sistema, com regras de pontuação aplicadas.
-
-## Visão Geral da Arquitetura
-
-```
-┌─────────────────────────────────────────────────────────────────────┐
-│ FLUXO DE DADOS │
-├─────────────────────────────────────────────────────────────────────┤
-│ │
-│ 1. Elasticsearch (AtuaCAPES) │
-│ └─> Query com boost por tipo de atuação │
-│ └─> Retorna top 1000 candidatos pré-ordenados │
-│ │
-│ 2. Oracle - Opcional │
-│ └─> Busca coordenações de PPG por ID_PESSOA │
-│ │
-│ 3. Python (Backend) │
-│ └─> Calcula pontuação completa (A + B + C + D) │
-│ └─> Reordena por pontuação real │
-│ └─> Cache por 5 minutos │
-│ │
-└─────────────────────────────────────────────────────────────────────┘
-```
-
----
-
-## Query Principal - Elasticsearch
-
-### Objetivo
-Buscar candidatos relevantes para o ranking, priorizando por tipo de atuação usando boost.
-
-### Query Implementada
-
-```json
-{
- "size": 1000,
- "query": {
- "bool": {
- "should": [
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Coordenação de Área de Avaliação", "boost": 10}}},
- {"term": {"atuacoes.tipo": {"value": "Histórico de Coordenação de Área de Avaliação", "boost": 5}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- },
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Consultor", "boost": 2}}},
- {"term": {"atuacoes.tipo": {"value": "Histórico de Consultoria", "boost": 1}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- },
- {
- "nested": {
- "path": "atuacoes",
- "query": {
- "bool": {
- "should": [
- {"term": {"atuacoes.tipo": {"value": "Premiação Prêmio", "boost": 3}}},
- {"term": {"atuacoes.tipo": {"value": "Avaliação Prêmio", "boost": 2}}},
- {"term": {"atuacoes.tipo": {"value": "Inscrição Prêmio", "boost": 1}}}
- ]
- }
- },
- "score_mode": "sum"
- }
- }
- ],
- "minimum_should_match": 1
- }
- },
- "_source": ["id", "dadosPessoais", "atuacoes"],
- "sort": [{"_score": "desc"}]
-}
-```
-
-### Explicação dos Boosts
-
-| Tipo de Atuação | Boost | Justificativa |
-|-----------------|-------|---------------|
-| Coordenação de Área de Avaliação | 10 | Máxima pontuação (base 200 pts) |
-| Histórico de Coordenação de Área | 5 | Alta pontuação histórica |
-| Premiação Prêmio | 3 | 60 pts por premiação |
-| Consultor | 2 | Base 150 pts se ativo |
-| Avaliação Prêmio | 2 | 40 pts por avaliação |
-| Histórico de Consultoria | 1 | Base 100 pts |
-| Inscrição Prêmio | 1 | 20 pts por inscrição |
-
-### Estatísticas de Candidatos
-
-| Tipo | Quantidade no ES |
-|------|------------------|
-| Coordenadores de área | 522 |
-| Consultores | 52.551 |
-| Premiações | 63.799 |
-| **Total com atuações relevantes** | **90.482** |
-
----
-
-## Query Oracle - Coordenação de Programa (PPG)
-
-### Objetivo
-Buscar coordenações de programa por ID_PESSOA para calcular o Componente B.
-
-### Query Implementada
-
-```sql
-SELECT
- c.ID_PESSOA,
- c.ID_PROGRAMA_SNPG,
- p.NM_PROGRAMA,
- p.CD_PROGRAMA_PPG,
- p.DS_CONCEITO AS NOTA_PPG,
- p.NM_PROGRAMA_MODALIDADE,
- aa.NM_AREA_AVALIACAO,
- c.DT_INICIO_VIGENCIA,
- c.DT_FIM_VIGENCIA
-FROM SUCUPIRA_PAINEL.VM_COORDENADOR c
-INNER JOIN SUCUPIRA_PAINEL.VM_PROGRAMA_SUCUPIRA p
- ON c.ID_PROGRAMA_SNPG = p.ID_PROGRAMA
-LEFT JOIN SUCUPIRA_PAINEL.VM_AREA_CONHECIMENTO ac
- ON p.ID_AREA_CONHECIMENTO_ATUAL = ac.ID_AREA_CONHECIMENTO
-LEFT JOIN SUCUPIRA_PAINEL.VM_AREA_AVALIACAO aa
- ON ac.ID_AREA_AVALIACAO = aa.ID_AREA_AVALIACAO
-WHERE c.ID_PESSOA = :id_pessoa
-ORDER BY c.DT_INICIO_VIGENCIA
-```
-
-### Campos Retornados
-
-| Campo | Tipo | Uso |
-|-------|------|-----|
-| ID_PROGRAMA_SNPG | NUMBER | Identificador único do programa |
-| NM_PROGRAMA | VARCHAR2 | Nome do programa |
-| CD_PROGRAMA_PPG | VARCHAR2 | Código do PPG |
-| NOTA_PPG | VARCHAR2 | Nota CAPES (3-7, A) |
-| NM_PROGRAMA_MODALIDADE | VARCHAR2 | Acadêmico/Profissional |
-| NM_AREA_AVALIACAO | VARCHAR2 | Área de avaliação |
-| DT_INICIO_VIGENCIA | DATE | Início da coordenação |
-| DT_FIM_VIGENCIA | DATE | Fim (null = ativo) |
-
----
-
-## Regras de Pontuação Implementadas
-
-### Componente A - Coordenação CAPES (máx 450 pts)
-
-**Arquivo**: `backend/src/domain/services/calculador_pontuacao.py`
-
-```python
-# Apenas coordenações ATIVAS pontuam
-coord_atual = next((c for c in coordenacoes if c.periodo.ativo), None)
-if not coord_atual:
- return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0, retorno=0)
-
-# Valores por tipo
-base_map = {"CA": 200, "CAJ": 150, "CAJ-MP": 120, "CAM": 100}
-tempo_max_map = {"CA": 100, "CAJ": 80, "CAJ-MP": 60, "CAM": 50}
-bonus_atual_map = {"CA": 30, "CAJ": 20, "CAJ-MP": 15, "CAM": 10}
-
-# Cálculo
-base = base_map.get(coord_atual.tipo, 0)
-anos = coord_atual.periodo.anos_decorridos
-tempo = min(int(anos * 10), tempo_max_map.get(coord_atual.tipo, 0))
-extras = min(len(coord_atual.areas_adicionais) * 20, 100)
-bonus = bonus_atual_map.get(coord_atual.tipo, 0) if coord_atual.periodo.ativo else 0
-retorno = 20 if coord_atual.ja_coordenou_antes else 0
-```
-
-**Tabela de Pontuação**:
-
-| Tipo | Base | Tempo (máx) | Bônus Ativo | Áreas (máx) | Retorno |
-|------|------|-------------|-------------|-------------|---------|
-| CA | 200 | 100 (10 pts/ano) | 30 | 100 | 20 |
-| CAJ | 150 | 80 (10 pts/ano) | 20 | 100 | 20 |
-| CAJ-MP | 120 | 60 (10 pts/ano) | 15 | 100 | 20 |
-| CAM | 100 | 50 (10 pts/ano) | 10 | 100 | 20 |
-
-### Componente B - Coordenação PPG (máx 180 pts)
-
-```python
-if not coordenacoes:
- return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0)
-
-base = 70
-anos_totais = sum(c.periodo.anos_decorridos for c in coordenacoes)
-tempo = min(int(anos_totais * 5), 50)
-
-programas_distintos = len({c.id_programa for c in coordenacoes})
-extras = min((programas_distintos - 1) * 20, 40)
-
-coord_ativa = any(c.periodo.ativo for c in coordenacoes)
-bonus = 20 if coord_ativa else 0
-```
-
-**Tabela de Pontuação**:
-
-| Critério | Pontos | Máximo |
-|----------|--------|--------|
-| Base (ser coordenador) | 70 | 70 |
-| Tempo | 5 pts/ano | 50 |
-| Programas extras | 20 pts/programa | 40 |
-| Bônus ativo | 20 | 20 |
-| **TOTAL** | - | **180** |
-
-### Componente C - Consultoria (máx 230 pts)
-
-```python
-if not consultoria:
- return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0)
-
-# Base depende de ter eventos recentes (últimos 2 anos)
-base = 150 if consultoria.eventos_recentes > 0 else 100
-
-# Tempo desde primeiro evento
-anos = (datetime.now() - consultoria.primeiro_evento).days / 365.25
-tempo = min(int(anos * 5), 50)
-
-# Extras
-extras_eventos = min(consultoria.total_eventos * 2, 20)
-extras_responsavel = min(consultoria.vezes_responsavel * 5, 25)
-extras_areas = min((len(consultoria.areas) - 1) * 10, 30) if len(consultoria.areas) > 1 else 0
-extras = extras_eventos + extras_responsavel + extras_areas
-```
-
-**Tabela de Pontuação**:
-
-| Critério | Pontos | Máximo |
-|----------|--------|--------|
-| Base (ativo/recente) | 150 | 150 |
-| Base (histórico) | 100 | 100 |
-| Tempo | 5 pts/ano | 50 |
-| Eventos | 2 pts/evento | 20 |
-| Responsável | 5 pts/vez | 25 |
-| Áreas extras | 10 pts/área | 30 |
-| **TOTAL** | - | **230** |
-
-### Componente D - Premiações (máx 180 pts)
-
-```python
-if not premiacoes:
- return ComponentePontuacao(base=0, tempo=0, extras=0, bonus=0)
-
-# Pontos por tipo de premiação
-mapa = {
- "Premiação Prêmio": 60,
- "Avaliação Prêmio": 40,
- "Inscrição Prêmio": 20,
-}
-
-total_pontos = sum(mapa.get(p.tipo, 0) for p in premiacoes)
-total_pontos = min(total_pontos, 180) # Teto
-
-return ComponentePontuacao(base=total_pontos, tempo=0, extras=0, bonus=0)
-```
-
-**Tabela de Pontuação**:
-
-| Tipo | Pontos | Descrição |
-|------|--------|-----------|
-| Premiação Prêmio | 60 | Recebeu prêmio |
-| Avaliação Prêmio | 40 | Participou de banca/comissão |
-| Inscrição Prêmio | 20 | Inscreveu trabalho |
-| **Máximo total** | **180** | - |
-
----
-
-## Extração de Dados do Elasticsearch
-
-### Coordenações CAPES
-
-```python
-def _extrair_coordenacoes_capes(self, atuacoes: List[Dict[str, Any]]) -> List[CoordenacaoCapes]:
- coordenacoes = [
- a for a in atuacoes
- if a.get("tipo") in [
- "Coordenação de Área de Avaliação",
- "Histórico de Coordenação de Área de Avaliação",
- ]
- ]
-
- # Inferir tipo pelo campo 'nome'
- def _inferir_tipo_coordenacao(coord):
- nome = coord.get("nome", "").lower()
- if "câmara" in nome or "camara" in nome:
- return "CAM"
- elif "mestrado profissional" in nome:
- return "CAJ-MP"
- elif "adjunta" in nome:
- return "CAJ"
- else:
- return "CA"
-```
-
-### Consultoria
-
-```python
-def _extrair_consultoria(self, atuacoes: List[Dict[str, Any]]) -> Optional[Consultoria]:
- consultorias = [
- a for a in atuacoes
- if a.get("tipo") in ["Consultor", "Histórico de Consultoria"]
- ]
-
- # Calcula eventos recentes (últimos 2 anos)
- limite_recente = datetime.now() - timedelta(days=730)
- eventos_recentes = sum(1 for d in datas_fim if d >= limite_recente)
-
- # Extrai áreas únicas
- areas = list({c.get("areaAvaliacao", "N/A") for c in consultorias if c.get("areaAvaliacao")})
-
- # Conta vezes como responsável
- vezes_responsavel = sum(1 for c in consultorias if c.get("responsavel", False))
-```
-
-### Premiações
-
-```python
-def _extrair_premiacoes(self, atuacoes: List[Dict[str, Any]]) -> List[Premiacao]:
- premiacoes_data = [
- a for a in atuacoes
- if a.get("tipo") in [
- "Premiação Prêmio",
- "Avaliação Prêmio",
- "Inscrição Prêmio",
- ]
- ]
-
- for prem in premiacoes_data:
- pontos = self._calcular_pontos_premiacao(prem.get("tipo", ""))
- # tipo vem de atuacoes.tipo
- # nome_premio vem de atuacoes.descricao
- # ano vem de atuacoes.inicio (parse para extrair ano)
-```
-
----
-
-## Cache de Ranking
-
-### Implementação
-
-```python
-class RankingCache:
- def __init__(self, ttl_seconds: int = 300): # 5 minutos
- self.ttl = ttl_seconds
- self._cache: List[Consultor] = []
- self._last_update: Optional[datetime] = None
- self._loading = False
- self._lock = asyncio.Lock()
-
- def is_valid(self) -> bool:
- if not self._cache or not self._last_update:
- return False
- return (datetime.now() - self._last_update).total_seconds() < self.ttl
-```
-
-### Performance
-
-| Métrica | Valor |
-|---------|-------|
-| Primeira requisição (cold) | ~1m34s |
-| Requisições cacheadas | ~0.27s |
-| TTL do cache | 5 minutos |
-| Candidatos processados | 1000 |
-
----
-
-## Fluxo Completo de Ranking
-
-```python
-async def buscar_ranking(self, limite: int = 100) -> List[Consultor]:
- # 1. Verificar cache
- if _ranking_cache.is_valid():
- return _ranking_cache.get()[:limite]
-
- async with _ranking_cache._lock:
- # 2. Double-check cache
- if _ranking_cache.is_valid():
- return _ranking_cache.get()[:limite]
-
- # 3. Buscar candidatos do ES (ordenados por score ES)
- tamanho_busca = max(limite * 3, 1000)
- docs = await self.es_client.buscar_candidatos_ranking(size=tamanho_busca)
-
- # 4. Construir consultores (calcula pontuação completa)
- consultores = []
- for doc in docs:
- consultor = await self._construir_consultor(doc)
- # _construir_consultor busca dados do Oracle se disponível
- consultores.append(consultor)
-
- # 5. Reordenar por pontuação real
- consultores_ordenados = sorted(
- consultores, key=lambda c: c.pontuacao_total, reverse=True
- )
-
- # 6. Cachear resultado
- _ranking_cache.set(consultores_ordenados)
-
- return consultores_ordenados[:limite]
-```
-
----
-
-## Limitações Conhecidas
-
-1. **Cobertura de candidatos**: Buscamos 1000 candidatos do ES. Se alguém com alta pontuação estiver fora do top 1000 do score ES, não aparecerá.
-
-2. **Oracle opcional**: Se Oracle não estiver disponível (TNS error no Docker), Componente B = 0 para todos.
-
-3. **Tipos de coordenação**: Inferência pelo campo `nome` pode não ser 100% precisa.
-
-4. **Datas inconsistentes**: ES usa formatos `dd/MM/yyyy` e `yyyy-MM-dd` misturados.
-
----
-
-## Arquivos de Implementação
-
-| Arquivo | Responsabilidade |
-|---------|------------------|
-| `backend/src/infrastructure/elasticsearch/client.py` | Query ES com boost |
-| `backend/src/infrastructure/oracle/client.py` | Query Oracle PPG |
-| `backend/src/infrastructure/repositories/consultor_repository_impl.py` | Cache e orquestração |
-| `backend/src/domain/services/calculador_pontuacao.py` | Regras de pontuação |
-| `backend/src/domain/entities/consultor.py` | Entidades de domínio |