feat: add deterministic content extractor selector engine with F1 consensus

This commit is contained in:
2026-08-20 22:09:43 -03:00
parent 6a45368cb0
commit ff7a50e0eb
46 changed files with 18503 additions and 2813 deletions
@@ -0,0 +1,93 @@
# Implementation Plan: Deterministic Article Content Selection
**Branch**: `004-deterministic-content-selection` | **Date**: 2026-08-20 | **Spec**: [spec.md](spec.md)
**Input**: Feature specification from `specs/004-deterministic-content-selection/spec.md`
---
## Summary
Implementação do motor determinístico de seleção de extratores (`scripts/select_article_extractor.py`), capaz de consumir arquivos JSON consolidados com saídas do **Trafilatura**, **Newspaper4k** e **Readability**, aplicar normalização de texto, geração de shingles (5-tokens), pontuação $F_1$ baseada em consenso e regras de desempate técnico / hierárquico estritas, gerando um novo arquivo JSON enriquecido exclusivamente com a chave `selected_extractor` em cada artigo de forma não-destrutiva e atômica.
---
## Technical Context
**Language/Version**: Python 3.10+
**Primary Dependencies**: Standard Library (`json`, `re`, `unicodedata`, `html`, `argparse`, `dataclasses`, `pathlib`, `tempfile`, `os`)
**Storage**: Arquivos JSON locais no diretório `out/`
**Testing**: `pytest` com testes unitários e de integração cobrindo 100% dos casos de teste obrigatórios (CT-001 a CT-014)
**Target Platform**: Windows / Linux / macOS (Terminal CLI & Módulo Python)
**Project Type**: CLI tool & modular selection engine
**Performance Goals**: Processamento em lote de centenas de artigos em menos de 1 segundo (complexidade linear $O(N)$ em memória)
**Constraints**: 100% determinístico, 0 chamadas de rede, sem uso de LLMs ou embeddings, escrita atômica em disco
**Scale/Scope**: Lotes de 1 a 10.000+ artigos
---
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Princípio | Avaliação | Status |
|---|---|---|
| **I. Library / Modular Design** | Módulo estruturado com funções puras e dataclasses desacopladas (`normalize_text`, `generate_shingles`, `calculate_consensus_metrics`, `select_best_candidate`, `process_batch`). | ✅ Aprovado |
| **II. CLI Interface** | CLI via `scripts/select_article_extractor.py` com flags descritivas, streams padronizados (`stdout` para resumo e `stderr` para logs/erros) e códigos de saída específicos. | ✅ Aprovado |
| **III. Test-First (NON-NEGOTIABLE)** | TDD com suíte automatizada em `tests/test_select_article_extractor.py` cobrindo todos os cenários (CT-001 a CT-014) e validação end-to-end com o arquivo real `out/river_plate_extracted.json`. | ✅ Aprovado |
| **IV. Integration Testing** | Testes de integração validando leitura, enriquecimento de `selected_extractor`, não-destrutividade de campos e escrita atômica. | ✅ Aprovado |
| **V. Simplicity & YAGNI** | Uso exclusivo da biblioteca padrão do Python, sem dependências adicionais pesadas. | ✅ Aprovado |
---
## Project Structure
### Documentation (this feature)
```text
specs/004-deterministic-content-selection/
├── spec.md # Especificação de requisitos funcionais e critérios
├── plan.md # Este plano de implementação (/speckit-plan)
├── research.md # Decisões técnicas e algoritmos (Phase 0)
├── data-model.md # Entidades e modelos de dados (Phase 1)
├── quickstart.md # Guia de validação e execução (Phase 1)
├── contracts/
│ ├── cli-contract.md # Contrato de linha de comando
│ └── json-schema.md # Esquemas JSON de entrada e saída
└── checklists/
└── requirements.md # Checklist de validação da especificação
```
### Source Code Layout
```text
scripts/
├── extract_google_news.py # Extrator RSS do Google News
├── extract_article_contents.py # Extrator multimotor de artigos
└── select_article_extractor.py # [NEW] Seletor determinístico de extrator por artigo
tests/
├── test_extract_google_news.py # Testes do extrator Google News
├── test_extract_article_contents.py # Testes do extrator multimotor
└── test_select_article_extractor.py # [NEW] Testes unitários e de integração do seletor
```
**Structure Decision**: Criação de `scripts/select_article_extractor.py` como ferramenta CLI e biblioteca modular autônoma, e `tests/test_select_article_extractor.py` contendo a suíte de testes de alta fidelidade aos requisitos do PRD.
---
## Implementation Phases
### Phase 0: Outline & Research *(Completed)*
- Normalização de texto via biblioteca padrão (`html.unescape`, `unicodedata.normalize('NFKC')`, regex Unicode).
- Estratégia de geração de shingles de 5 tokens e cálculo de $F_1$ sobre consenso compartilhado por $\ge 2$ motores.
- Regras de desempate técnico (`<= 0.03`), desempate sem consenso (mediana/máximo) e fallback prioritário (`newspaper4k` > `readability` > `trafilatura`).
- Documentado em [research.md](research.md).
### Phase 1: Design & Contracts *(Completed)*
- Modelos de dados e dataclasses estruturados em [data-model.md](data-model.md).
- Contratos de linha de comando e JSON schema definidos em [contracts/](contracts/).
- Guia prático de execução e validação estruturado em [quickstart.md](quickstart.md).
### Phase 2: Tasks & Execution *(Next Step via `/speckit-tasks`)*
- Criação das tarefas de implementação e testes orientados a TDD em `tasks.md`.