Metadata-Version: 2.4
Name: br-address-normalize
Version: 0.3.0.dev20260323001305
Summary: Biblioteca de normalização de endereços brasileiros
Author-email: Inspire / F1 Qualidade <contact@inspire-f1.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/inspire-f1/br-address-normalize
Project-URL: Bug Tracker, https://github.com/inspire-f1/br-address-normalize/issues
Project-URL: Repository, https://github.com/inspire-f1/br-address-normalize.git
Keywords: address,normalization,brazilian,endereco
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: Portuguese (Brazilian)
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Text Processing :: Linguistic
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.0.0
Requires-Dist: httpx>=0.24.0
Requires-Dist: redis>=5.0.0
Dynamic: license-file

# Pipeline de Normalização de Endereços

Sistema de normalização de endereços brasileiros com expansão de abreviações e tratamento de encoding corrompido.

## Arquitetura Geral

```
+-----------------------------------------------------------------------------------+
|                               NormalizerFacade                                    |
|                                                                                   |
|  +----------+  +----------+  +-------------+  +-------------+                    |
|  |Uppercase |->| Encoding |->|Abbreviation |->|Preprocessing|                    |
|  |  Step    |  |   Step   |  |    Step     |  |    Step     |                    |
|  +----------+  +----------+  +-------------+  +-------------+                    |
|                                                                                   |
+-----------------------------------------------------------------------------------+
```

## Fluxo de Processamento

O pipeline processa endereços em 4 etapas sequenciais. A ordem é crítica:
encoding é corrigido logo após o uppercase para que abreviações operem
sobre texto íntegro, e abreviações são expandidas antes da limpeza para
que a remoção de prefixo duplicado funcione corretamente.

### 1. UppercaseStep

Converte todos os campos de texto para UPPERCASE. Executado primeiro para
garantir que tokens sejam identificados corretamente nas etapas seguintes.

**Campos processados:** `logradouro`, `numero`, `complemento`, `bairro`, `municipio`, `uf`

**Arquivo:** `src/pipeline/steps/uppercase.py`

### 2. EncodingStep (Correção de Encoding)

Corrige nomes corrompidos por conversão ISO-8859-1 → ASCII. Executado antes
das abreviações para que o texto esteja íntegro na hora da expansão.

**Exemplos de correção:**
- `ANT NIO` → `ANTÔNIO`
- `JOO` → `JOÃO`
- `CORA OES` → `CORAÇÕES`
- `GET LIO` → `GETÚLIO`

**Campos processados:** `logradouro`, `complemento`, `bairro`

**Arquivo:** `src/modules/encoding.py`

### 3. AbbreviationStep (Expansão de Abreviações)

Expande abreviações usando o provider configurado (local, API ou orchestrator).
Executado antes da limpeza para que tipos expandidos sejam reconhecidos
na remoção de prefixo duplicado (ex: `R RUA SILVA` → `RUA RUA SILVA` → `RUA SILVA`).

**Campos processados:** `logradouro`, `complemento`, `bairro`

**Arquitetura L1/L2:**
- **L1 (Determinística):** Regras hardcoded com confiança 100%
- **L2 (Probabilística):** Fallback opcional via API externa

**Arquivo principal:** `src/modules/abbreviation/orchestrator.py`

### 4. PreprocessingStep (Limpeza)

Normaliza e limpa dados brutos.

**Operações (em ordem):**
1. Remoção de placeholders (`LOGRADOURO`, `ENDERECO`, `INDEFINIDO`)
2. Remoção de prefixos duplicados (`RUA RUA` → `RUA`)
3. Remoção de códigos numéricos no início
4. Separação de número colado no logradouro
5. Normalização de CEP (com detecção de inválidos)
6. Normalização de UF (2 caracteres)

**Campos processados:** todos

**Arquivo:** `src/modules/preprocessing.py`

#### Normalização de CEP

O CEP passa por 3 etapas:

**1. Limpeza:** Remove absolutamente tudo que não for dígito.

**2. Padding/Ajuste:**
| Tamanho | Ação | Motivo |
|---------|------|--------|
| 8 dígitos | Mantém | CEP íntegro |
| 7 dígitos | Adiciona `0` à esquerda | Perda de formatação Excel |
| 9 dígitos começando com `0` | Remove primeiro `0` | Exportação errônea (080010-000) |
| Outros | Mantém + flag `cep_invalido=True` | CEP incorreto |

**3. Filtro de Lixo:**
CEPs que passam na contagem mas são falsos:
- Sequências repetidas: `00000000`, `11111111`, ..., `99999999`
- Sequências óbvias: `12345678`, `87654321`

Quando detectado, o campo `cep_invalido` é setado como `True` no resultado.

---

## Sistema de Abreviações (Detalhado)

### Camada L1 — Gates de Decisão

O motor determinístico processa tokens através de 8 gates em ordem:

| Gate | Nome | Descrição | Ação |
|------|------|-----------|------|
| 1 | TOKENS_TO_REMOVE_FIELD | `ND`, `NINF` | Nulifica campo inteiro |
| 1.5 | SIGLA_SISTEMA | `NI`, `END` | Expande + flag para consumidor |
| 2 | DO_NOT_EXPAND | Siglas de órgãos | Preserva sem tocar |
| 3 | BCO | Ambiguidade BECO/BANCO | Resolução posicional |
| 4 | PENDING_SAMPLE | Tokens em análise | Preserva + flag |
| 5 | POSITIONAL_AMBIGUOUS | `CD`, `CM`, `PA`, `LG`, `GL`, `BX` | Resolução contextual |
| 6 | Dicionários por Categoria | Ver tabela abaixo | Expansão por campo |
| 7 | Dicionário Geral | Injetado/configurado | Fallback |
| 8 | SIGLA+dígito | Padrão `ABC123` | Flag código interno |

**Arquivo:** `src/modules/abbreviation/deterministic.py`

### Dicionários por Categoria

| Dicionário | Campos Aplicáveis | Posições |
|------------|-------------------|----------|
| TIPO_LOGRADOURO | logradouro, bairro | 0-1 (logradouro), qualquer (bairro) |
| TITULO_PROPRIO | logradouro, bairro | qualquer |
| MUNICIPIO_SAFE | municipio | qualquer |
| COMPLEMENTO | complemento | qualquer |

**Arquivo de regras:** `src/modules/abbreviation/entity_rules.py`

### Resolução de Ambiguidades

**BCO (Beco vs Banco):**
- Posição 0 em logradouro → `BECO`
- Outras posições → `BANCO`

**PA (Passagem vs Projeto de Assentamento):**
- Em logradouro → `PASSAGEM`
- Em complemento com `zona_rural=True` → `PROJETO DE ASSENTAMENTO`

---

## Arquivos de Dados

Todos os dicionários de abreviações ficam centralizados em `src/data/` para fácil manutenção:

| Arquivo | Descrição |
|---------|-----------|
| `abbreviations.json` | Dicionário geral de abreviações |
| `complement_expansions.json` | Expansões específicas de complemento |
| `null_markers.json` | Marcadores de campo vazio/nulo |
| `brasilia_prefixes.json` | Prefixos de Brasília para expansão contextual |
| `whitelist.json` | Nomes que não devem ser alterados |

---

## Abreviações Implementadas

### Tipos de Logradouro

| Sigla | Expansão |
|-------|----------|
| R | Rua |
| AV | Avenida |
| TV, TRA | Travessa |
| RD, ROD | Rodovia |
| AL | Alameda |
| RM, RAM | Ramal |
| ET, ESTR | Estrada |
| PCA | Praça |
| BEC, BCO | Beco |
| PSG | Passagem |
| VIL, VLA | Vila |
| CGO, CRG | Córrego |
| FZ | Fazenda |
| IG | Igarapé |
| JRD | Jardim |
| CHAC | Chácara |
| DIST | Distrito |
| LG | Largo |
| PQ, PARQ, PQE | Parque |
| COND | Condomínio |
| CONJ | Conjunto |
| BALN | Balneário |
| UNIV | Universidade |
| ST | Setor |
| QD | Quadra |
| VC | Vicinal |
| LIN, LI | Linha |

### Títulos e Tratamentos

| Sigla | Expansão |
|-------|----------|
| PRES | Presidente |
| GEN | General |
| MAL | Marechal |
| CAP | Capitão |
| CEL | Coronel |
| DR | Doutor |
| PE | Padre |
| PROF, PRF | Professor |
| VER | Vereador |
| SEN | Senador |
| DEP | Deputado |
| GOV | Governador |
| PREF | Prefeito |
| DES | Desembargador |
| DQ | Duque |
| MARQ | Marquês |
| CDE | Conde |
| CDR, CDOR | Comendador |
| DNA | Dona |
| FCO | Francisco |
| JOS | José |
| JORN | Jornalista |
| MNS | Monsenhor |
| NS | Nossa Senhora |
| NSA | Nossa Senhora Aparecida |
| NSRA | Nossa Senhora |
| JK | Juscelino Kubitschek |
| JR | Júnior |
| FREI | Frei |
| STA | Santa |
| STO | Santo |

### Complemento

| Sigla | Expansão |
|-------|----------|
| APTO, APT | Apartamento |
| BL, BLC | Bloco |
| QD, QDA | Quadra |
| LT | Lote |
| SL | Sala |
| LJ | Loja |
| AND | Andar |
| COND | Condomínio |
| CONJ | Conjunto |
| EDIF | Edifício |
| FD, FUND | Fundos |
| FR | Frente |
| KIT | Kitnet |
| MOD | Módulo |
| NR | Número |
| PV | Pavimento |
| PROX, PX | Próximo |
| SOB | Sobrado |
| SS | Subsolo |
| ST | Setor |
| BX | Box |
| KM | Quilômetro |

### Siglas de Órgãos (Preservadas)

Estas siglas são preservadas sem expansão:

`ABC`, `CEEE`, `CTG`, `DAER`, `DNER`, `IBGE`, `PTB`, `SESI`, `SHIS`, `DF`, `KVA`

---

## Uso do Pipeline

```python
from address_normalizer.facade import NormalizerFacade
from address_normalizer.modules.abbreviation.local_provider import LocalAbbreviationProvider

# Inicializar provider
abbreviation_provider = LocalAbbreviationProvider()

# Criar facade
normalizer = NormalizerFacade(
    abbreviation_provider=abbreviation_provider,
)

# Normalizar endereço
endereco = {
    "logradouro": "R DR JOAO SILVA",
    "numero": "123",
    "complemento": "APTO 45",
    "bairro": "JRD AMERICA",
    "municipio": "SAO PAULO",
    "uf": "SP",
    "cep": "01234567",
}

result = await normalizer.normalize(endereco)
```

---

## Parâmetros de Configuração

### NormalizerFacade

| Parâmetro | Tipo | Default | Descrição |
|-----------|------|---------|-----------|
| abbreviation_provider | AbbreviationProvider | - | Provider de abreviações (Local, API ou Orchestrator) |
| separar_numero_logradouro | bool | False | Separa número colado no final do logradouro |
| normalizar_cep | bool | False | Ativa normalização de CEP (padding, detecção de inválidos) |

### ExpanderConfig

| Parâmetro | Tipo | Default | Descrição |
|-----------|------|---------|-----------|
| use_default_dictionaries | bool | True | Carrega dicionários padrão |
| custom_general_dict | dict | {} | Dicionário adicional customizado |
| preserve_unknown_codes | bool | True | Preserva códigos internos (ABC123) |
| l2_caller | Callable | None | Função async para L2 probabilístico |
| min_l2_confidence | float | 0.85 | Confiança mínima para aceitar L2 |
| nullify_sistema_siglas | bool | False | Nulifica siglas de sistema (NI, END) |

---

## Estrutura de Diretórios

```
src/
├── core/
│   └── base.py                 # Interface PipelineStep
├── data/
│   ├── __init__.py             # Funções de carregamento de dados
│   ├── abbreviations.json      # Dicionário geral de abreviações
│   ├── complement_expansions.json  # Expansões específicas de complemento
│   ├── null_markers.json       # Marcadores nulos
│   ├── brasilia_prefixes.json  # Prefixos de Brasília
│   └── whitelist.json          # Whitelist ortográfica
├── facade.py                   # Fachada pública do módulo
├── modules/
│   ├── abbreviation/
│   │   ├── base.py             # Interface AbbreviationProvider
│   │   ├── api_provider.py     # Provider via API externa
│   │   ├── local_provider.py   # Provider via JSON local
│   │   ├── orchestrator.py     # Orquestrador L1/L2
│   │   ├── orchestrator_adapter.py  # Adapter para interface Provider
│   │   ├── deterministic.py    # Camada L1 determinística
│   │   ├── entity_rules.py     # Regras por campo
│   │   ├── heuristics.py       # Heurísticas de confiança L2
│   │   ├── models.py           # Dataclasses do módulo
│   │   └── complement_expander.py  # Expansor específico de complemento
│   ├── encoding.py             # Correção de encoding corrompido
│   └── preprocessing.py        # Limpeza e normalização
├── pipeline/
│   ├── orchestrator.py         # Pipeline principal
│   └── steps/
│       ├── uppercase.py        # Step de uppercase
│       ├── encoding.py         # Step de encoding
│       ├── abbreviation.py     # Step de abreviações
│       └── preprocessing.py    # Step de limpeza
└── schemas/
    └── endereco.py             # Schemas Pydantic/dataclass
```

---

## Inconsistências Arquiteturais Identificadas

### ⚠️ Duplicação: Encoding e Preprocessing

**Problema:** Lógica está em `modules/` mas steps em `pipeline/steps/` são apenas wrappers.

- `src/address_normalizer/modules/encoding.py` (450 linhas) → `src/address_normalizer/pipeline/steps/encoding.py` (15 linhas)
- `src/address_normalizer/modules/preprocessing.py` (300 linhas) → `src/address_normalizer/pipeline/steps/preprocessing.py` (20 linhas)

**Impacto:** Confusão arquitetural, difícil manutenção, código redundante.

**Solução:** Consolidar lógica nos steps, remover módulos duplicados. Ver `.kiro/steering/refactoring-roadmap.md` para detalhes.

### ⚠️ Inconsistência: Providers de Abbreviation

**Problema:** Duas implementações fazem a mesma coisa de formas diferentes.

- `LocalAbbreviationProvider` reimplementa lógica de `AddressExpander`
- `OrchestratorAdapter` adapta `AddressExpander` para `AbbreviationProvider`

**Impacto:** Comportamento inconsistente dependendo de qual provider é usado.

**Solução:** Fazer `LocalAbbreviationProvider` usar `OrchestratorAdapter`. Ver `.kiro/steering/refactoring-roadmap.md` para detalhes.

### ⚠️ Separação Confusa: Módulos vs Steps

**Problema:** Responsabilidades ambíguas entre `modules/` e `pipeline/steps/`.

- Alguns steps têm módulos correspondentes (encoding, preprocessing)
- Alguns módulos têm steps (abbreviation)
- Alguns steps não têm módulos (uppercase, remove_accents)

**Impacto:** Difícil de entender onde adicionar nova lógica.

**Solução:** Padronizar: steps contêm lógica, módulos são apenas para código compartilhado. Ver `.kiro/steering/project-standards.md` para padrões.

---

## Boas Práticas do Projeto

### 📋 Regra: Nunca Criar Documentação .md Nova

**Regra:** Não criar novos arquivos `.md` para documentação. Sempre atualizar o `README.md`.

**Exceções:**
- Arquivos de configuração (`.kiro/steering/`, `.kiro/skills/`)
- Documentação de especificações (`.kiro/specs/`)

**Quando Adicionar Informação:**
1. Mudança de arquitetura → Atualizar seção "Arquitetura" do README
2. Novo módulo → Adicionar em "Módulos" do README
3. Novo step → Adicionar em "Pipeline" do README
4. Novo provider → Adicionar em "Providers" do README
5. Mudança de API → Atualizar "Uso" do README

### 🏗️ Padrão de Step

Todos os steps devem:

```python
from address_normalizer.core.base import PipelineStep

class MyStep(PipelineStep):
    def name(self) -> str:
        return "my_step"
    
    async def process(self, data: dict, context: dict) -> tuple[dict, list[dict]]:
        transformacoes = []
        # Lógica aqui
        return data, transformacoes
```

**Retorno:**
- `data`: Dicionário do endereço completo (modificado)
- `transformacoes`: Lista de transformações aplicadas

**Estrutura de Transformação:**
```python
{
    "campo": "logradouro",      # Campo modificado
    "tipo": "my_step",          # Tipo de transformação
    "de": "valor_original",     # Valor antes
    "para": "valor_novo",       # Valor depois
    "regra_aplicada": "regra_x" # (opcional) Qual regra foi aplicada
}
```

### 🔍 Validação de Código

Antes de fazer commit:

- [ ] Código segue padrões do projeto (ver `.kiro/steering/project-standards.md`)
- [ ] Sem duplicação (usar `grepSearch` para verificar)
- [ ] Interfaces são consistentes
- [ ] Testes passam
- [ ] Sem erros de tipo/lint (usar `getDiagnostics`)
- [ ] README foi atualizado (se necessário)
- [ ] Docstrings foram adicionadas
- [ ] Sem código morto

### 📚 Skills e Steering Files

O projeto inclui skills e steering files para guiar desenvolvimento:

- `.kiro/skills/refactoring-guide.md` - Guia de refatoração
- `.kiro/skills/architecture-validation.md` - Validação arquitetural
- `.kiro/skills/testing-strategy.md` - Estratégia de testes
- `.kiro/skills/code-quality-review.md` - Revisão de qualidade
- `.kiro/steering/project-standards.md` - Padrões do projeto
- `.kiro/steering/refactoring-roadmap.md` - Roadmap de refatoração

### 🔗 Hooks Automáticos

O projeto inclui hooks que automatizam validações:

- `update-readme-on-change` - Lembra de atualizar README
- `validate-architecture` - Valida padrões arquiteturais
- `check-duplications` - Procura por duplicações
- `validate-on-save` - Valida código ao salvar

---

## Histórico de Versões

### v0.3.0 (Atual)
- Refatoração arquitetural iniciada
- Consolidação de módulos de encoding e preprocessing
- Unificação de providers de abreviação
- Adição de skills e steering files para guiar desenvolvimento
- Implementação de hooks automáticos para validação

### v0.2.1
- Versão anterior com funcionalidades base de normalização

---

## Notas de Implementação

1. **Ordem do Pipeline:** Uppercase → Encoding → Abreviações → Limpeza. Encoding vem antes de abreviações para que o texto esteja íntegro. Abreviações vêm antes da limpeza para que `R RUA` seja expandido para `RUA RUA` e depois deduplicado.

2. **Ordem dos Gates:** A ordem dos gates no `DeterministicLayer` é crítica. Gates anteriores têm prioridade sobre posteriores.

3. **Resolução Posicional:** Tokens como `BCO`, `PA`, `BX` têm significados diferentes dependendo do campo e posição.

4. **L2 Probabilístico:** Só é acionado para posição 0 do logradouro e requer `l2_caller` configurado.

5. **Encoding:** O módulo de encoding usa regex ordenadas por especificidade (mais longas primeiro).

6. **Conflitos Conhecidos:**
   - `PRF`: No sistema = Professor. Na lista de referência = Polícia Rodoviária Federal. Mantido como Professor por ser mais comum em endereços.
   - `PA`: Tratado como PASSAGEM em logradouro, PROJETO DE ASSENTAMENTO em complemento rural.
