AGENTS.md · git:20261028.073130e · 2026-10-28 · sha256 9405d9724b7ef2ad
AGENTS.md git:20261028.073130eC
Immutable. This exact content never changes and is served at /api/v1/blob/9405d9724b7ef2ad.
# Repository Guidelines
## Canonical Workspace
- The only writable source of truth for this project is `~/arvor/PNAD`.
- `~/clawd/projects/PNAD` is a replicated vault mirror. Treat it as read-only: never create, edit, generate, copy, or retain project artifacts there.
- Project reports, sources, datasets, scripts, tests, images, and temporary work must stay under `~/arvor/PNAD`.
## Single Source of Truth
- Agent instructions live in `AGENTS.md`.
- `CLAUDE.md` and `GEMINI.md` should be symlinks to this file.
## Project Structure & Module Organization
- Runtime data layout (local, heavy files ignored):
- `data/raw/`: PNADC trimestral `.zip` / `.txt`.
- `data/raw/pnadc_anual_visita1/`: PNADC anual visita 1.
- `data/raw/pnadc_anual_visita5/`: PNADC anual visita 5.
- `data/raw/tse_eleitorado/`: pacotes de perfil do eleitorado (TSE), incluindo `perfil_eleitorado_ATUAL.zip`.
- `data/originals/`: IBGE docs/layouts + `salario_minimo.csv`.
- `data/originals/pnadc_anual_visita1/`: documentacao anual visita 1.
- `data/originals/pnadc_anual_visita5/`: documentacao anual visita 5.
- `data/originals/censo_2022_renda_responsavel/`: agregados do Censo 2022 (renda do responsavel).
- `data/outputs/`: `base*.csv`, `ipca.csv`, `brasil.sqlite`, `tse_eleitorado_perfil.sqlite`, `tse_eleitorado_perfil_summary.csv`, `tse_eleitorado_perfil_benchmark.json`.
- Root docs/metadata:
- `README.md`: usage and operational docs.
- `AGENTS.md`: repository guidance.
- Published site (`docs/`, served by GitHub Pages at `brasil.arvor.co`):
- `docs/index.html`: hand-written library hub linking every report. Not generated; edit directly.
- `docs/pnad.html`: interactive PNADC essay, generated by `python docs/build_index.py` from `docs/index.template.html`.
- `docs/<instituto>_<data>.html`: poll audit dossiers, plus `_thread.html` / `_slides.html` companions.
- Code and analysis:
- `scripts/` for Python CLI/utilities.
- `notebooks/` for exploratory analyses.
- `tests/` for `pytest` automated tests.
- `skills/` for project-local agent skills (e.g., `skills/brasil-cli-analyst/SKILL.md`).
- `data/` scaffold only (`.gitkeep`).
## Core Commands
- Inspect raw file: `head -n 20 data/raw/PNADC_032025.txt`
- Validate size: `wc -l data/raw/PNADC_032025.txt`
- Run tests: `pytest -q`
- Main CLI help: `python scripts/pnad.py --help`
- Legacy command help: `python scripts/pnad.py help-legacy`
- Inspect TSE electorate profile summary: `sqlite3 data/outputs/tse_eleitorado_perfil.sqlite "SELECT * FROM atlas_comparison"`
- Inspect TSE electorate profile metadata: `sqlite3 data/outputs/tse_eleitorado_perfil.sqlite "SELECT * FROM metadata"`
- Rebuild TSE compact profile: `python3 scripts/tse-electorate-profile.py`
## Installable CLI (`brasil`)
- Install locally: `pip install -e .`
- Compatibility alias: `pnad` remains available for legacy scripts.
- Then use directly:
- `brasil --help`
- `brasil ibge-sync`
- `brasil ibge-sync --full`
- `brasil pipeline-run --raw latest`
- `brasil query --db data/outputs/brasil.sqlite --sql "SELECT name FROM sqlite_master WHERE type='table'"`
- `brasil renda-por-faixa-sm --input data/outputs/base_labeled.csv --group-by pais`
- `brasil dashboard --input data/outputs/base_labeled.csv --interactive`
## Pipeline Defaults
- Pipeline command: `brasil pipeline-run`
- Steps executed:
- emit code tables (`emit-codes`)
- fixed-width extraction (`fwf-extract`)
- code label join (`join-codes`)
- IPCA refresh (`fetch_ipca.py`)
- NPV adjustment (`npv_deflators.py apply`)
- SQLite build (optional, on by default in pipeline)
- Outputs in `data/outputs/`:
- `base.csv`, `base_labeled.csv`, `base_labeled_npv.csv`
- `ipca.csv`
- `brasil.sqlite` (table `base_labeled_npv`)
- Automatic defaults in `pipeline-run`:
- If `--target` is omitted, use latest month from `--ipca-csv`.
- If `--min-wage` is omitted, resolve from `--salario-minimo-csv` at or before target.
- Manifest includes `target`, `min_wage`, `min_wage_source_month`.
## Key Data Variables
- TSE electorate profile:
- Raw source: `data/raw/tse_eleitorado/perfil_eleitorado_ATUAL.zip`.
- Summary DB: `data/outputs/tse_eleitorado_perfil.sqlite`.
- Summary CSV: `data/outputs/tse_eleitorado_perfil_summary.csv`.
- Tables: `metadata`, `summary`, `atlas_comparison`.
- Useful summary dimensions: `genero_atlas_binario`, `idade_atlas`, `regiao`, `uf`, `cor_raca`, `escolaridade_tse`.
- Income:
- `VD4019__rendim_habitual_qq_trabalho`
- `VD4020__rendim_efetivo_qq_trabalho`
- NPV-adjusted suffix: `_<YYYYMM>`
- Minimum-wage suffix: `_mw`
- Replicate weights for sampling uncertainty: `V1028001..V1028200`
- Geography:
- `UF__unidade_da_federacao`, `Capital__municipio_da_capital`, `RM_RIDE__reg_metr_e_reg_adm_int_des`
- Household:
- `dom_id` composed from `Ano`, `Trimestre`, `UPA`, `V1008`
## Income Methodology
- Bands: `0-2`, `2-5`, `5-10`, `10+` minimum wages.
- Minimum wage source: `data/originals/salario_minimo.csv` (updated by `brasil ibge-sync`).
- Deflator: IPCA monthly index to target month (default = latest month in series).
- Per-capita income: household total divided by `VD2003__nmero_de_componentes_do_domic`.
- Weighted estimation default:
- Use `V1028` (fallback `V1027`) for population distribution.
- `--unweighted` is diagnostic only (not official estimate).
## Electorate Profile Methodology
- For electoral polling audits, use TSE electorate data to complement PNAD.
- Use TSE for age, sex/gender, UF and macro-region because the target universe is the electorate.
- Use PNAD for income and schooling when auditing social composition:
- TSE has no income.
- TSE schooling is cadastro-based and can be stale when voters do not update education after registration.
- Treat TSE race/color cautiously. In the current `perfil_eleitorado_ATUAL.zip`, `DS_COR_RACA` has very high `Nao informado`; do not use it as a strong calibration target without checking missingness.
- For national comparisons, exclude `SG_UF='ZZ'` (exterior) unless the poll universe includes voters abroad.
- Do not extract huge TSE CSVs to disk by default. Process the ZIP in streaming mode and persist compact summaries in SQLite/CSV.
## Previsão presidencial experimental (03/10/2026)
- `python3 scripts/predicao-2026-build.py --refresh-agregador --hoje 2026-10-04` atualiza a previsão e o card após integrar pesquisas. Fonte: `docs/predicao_2026_1T_presidente.template.html` e `scripts/predicao_2026/`; nunca editar a página gerada diretamente.
- Preparar dados oficiais com `predicao-2026-fontes.py`, `predicao-2026-tse.py` e `predicao-2026-validar.py`. Usar eleitorado federal final de 2026; registrar datas, hashes e diferenças de totais. Snapshots preservam cada versão.
- A retrospectiva 2018→2022 não favoreceu o modelo por seção (RMSE ponderado 1,24 contra 1,19 pp da UF). Central estadual; seções para diagnóstico e cenários. Valida apenas comparecimento, não preferências ou probabilidades de vitória.
- Efeitos de casa são diferenças relativas a pares contemporâneos, não erros eleitorais identificados. PNAD e voto útil extra são hipóteses explícitas. Preservar eleitorado = válidos + brancos/nulos + abstenção e paridade Python/navegador. Nunca inferir voto dos ausentes pelo endereço da seção.
- Recência da previsão: meia-vida nacional 3 dias e estadual 7 dias pelo ponto médio do campo; uma onda por casa/UF, com campo mais recente prioritário. CLI permite ajustar ambas. Central inclusiva usa PNAD onde há cruzamento e publicada onde falta; nunca imputar renda ausente. Agregador descritivo continua com peso igual. Transcrições estaduais novas em `analysis/predicao_2026/estaduais/`, com páginas e hashes da fonte.
- Para cruzamentos Quaest recentes, `predicao-2026-estaduais.py` guarda conferência visual e OCR. Recomposição admite ±0,5 pp por número inteiro e preferência livre do NS/NR de hábito; envelope aritmético não é IC. Selecionar os que pretendem votar dentro do grupo irregular assume o voto do grupo agregado, pois o subconjunto não é publicado. Expor resíduos, cobertura e alternativa sem seleção; não carregar sinal de onda anterior como atual.
## Previsão presidencial, segunda versão (03/10/2026, véspera da eleição)
- A página ganhou mapa interativo (`scripts/predicao_2026/mapa.py`, `docs/assets/predicao_2026_mapa.js` e `.css`), simulador com cenários prontos e link compartilhável (`scripts/predicao_2026/simulador.py`, parte DOM de `docs/assets/predicao_2026.js`; fragmento `#sim=vf:50;rNE:-5;SP:cp2,vf60`), âncora dinâmica e validação preditiva (`scripts/predicao_2026/dinamico.py` e `preditiva.py`). Contrato entre simulador e mapa: evento `predicao:cenario` em `document`, com `{result, params, central}`, e cópia em `window.predicaoCenario`.
- **Machine learning supervisionado não é treinável aqui**: o acervo tem uma eleição de referência (2022, mais 2018 só para comparecimento), as pesquisas finais de 2022 arquivadas desde 03/10 e nenhuma de 2018. Treinar pesquisa→urna com um ponto é ajustar ruído. A avaliação completa está em `analysis/predicao_2026/avaliacao_ml.md`. O caminho defensável é o modelo dinâmico bayesiano de espaço de estados (Jackman 2005; Linzer 2013; Heidemanns, Gelman e Morris 2020), com efeitos de casa, passeio aleatório e pooling parcial estadual, que é o que o motor já faz em parte.
- **Âncora dinâmica (DLM)**: nível local nas cinco categorias, efeitos de casa de soma zero, variâncias por máxima verossimilhança com filtro de Kalman, multiplicador de erro não amostral phi estimado em 2,10 (deff efetivo 3,15; phi = 1 rejeitado por razão de verossimilhança). Entra no simulador e nas sensibilidades, não na central: nos válidos dá Lula 44,21 × Flávio 42,63 contra 44,0 × 43,0 da central.
- **Validação preditiva de origem móvel** (prevê as pesquisas seguintes, nunca a urna; origens 01/09 a 01/10, horizonte 1 a 7 dias, 204 pares): a central (recência 3 dias, janela 7) tem MAE 3,43 pp na diferença L−F; o DLM, 3,53; pareado por onda a diferença é +0,10 com erro-padrão 0,14. Nenhuma meia-vida ou janela se separa da central. Todas as âncoras tiveram viés positivo em setembro: as ondas seguintes vieram menos favoráveis a Lula, e âncora sem termo de deriva não antecipa tendência. Efeitos de casa servem para prever a próxima onda da mesma casa (MAE 2,07 contra 3,19 da central), não o nível do país.
- **Central desde 03/10 à noite = recência + tendência encolhida + indecisos por disponibilidade.** `DEFAULTS["base"] = "central_inclinacao"` em `motor.py` e no espelho JS: a média por recência (inclusivo) deslocada pelas inclinações de 28 dias da regressão de efeito fixo de casa, cada uma encolhida por b² / (b² + ep²), projetada da data efetiva da média até 04/10 (`base.sloped_central`). O destino central dos indecisos é a disponibilidade (1 − rejeição, `rejeicao.py`), resolvida para número no build e gravada em `central.parametros`; `DEFAULTS["indecisos_flavio"]` continua `None`, e o simulador (link, frase, detector de central) compara com `central.parametros`, nunca com os defaults crus. Proporcional vira `if:p` no link.
- Critério declarado antes do teste (origem móvel, horizonte 1 a 3 dias): MAE pareado não pior e viés menor em módulo. Central + inclinação passou (MAE 3,04 contra 3,16, pareado −0,12 com ep 0,15; viés +0,42 contra +1,17); o DLM com tendência reprovou (3,41, viés +1,63). Ganho modesto, não significativo, escolhido entre quatro variantes; validação contra pesquisas, não contra a urna. Os números da página saem do JSON por `texto.trend_values` e `texto.learning_values`.
- Monte Carlo (`motor.simulate` e `Prediction2026.simulate`): toda âncora calculada sobre as casas centrais reutiliza o bootstrap delas recentrado por `alvos[base] − alvos.inclusivo` (`motor.bootstrap_design`); a incerteza da projeção (`nacional.incerteza_projecao_pp`: horizonte × dp(β_F − β_L) para a central, √(dp_proj² − dp_corte²) para a tendência do DLM) soma-se em quadratura ao erro comum de 2 pp; o destino dos indecisos central entra nos sorteios. Documentado em `configuracao.incerteza`.
- **Consolidação sem dupla contagem**: os presets e sensibilidades de consolidação (proporção medida e disponibilidade) partem de `base: "inclusivo"`, porque a central já projeta a queda da terceira via; `consolidacao.anchor_start` usa a data efetiva da âncora inclusivo. `consolidacao.comparacao_central` registra que central e consolidação de 28 dias ficam a centésimos e por quê.
- **Erro das pesquisas de 2022** (`python3 scripts/predicao-2026-erro-2022.py` grava `analysis/predicao_2026/erro_2022/erro_2022.json`; memorando ao lado; documentos e `fonte.json` com SHA-256 em `data/originals/pesquisas_2022/<casa>/`, no LFS e no `git lfs pull` do CI). O build copia o bloco para `erro_2022` do payload (`scripts/predicao_2026/erro_2022.py`) e a seção 06 o publica por `view.erro_2022_table`, `view.erro_2022_vs_2026` e `texto.error_2022_values`, com o desvio relativo de 2026 relido do build corrente.
- Números de 2022 (12 casas): erro comum na diferença L−B +3,92 pp dos válidos (mediana +4,96), Lula −0,42, Bolsonaro −4,33; dispersão entre casas 4,96, maior que o erro comum; piores Datafolha, Ipec e Ipespe (+8,77, citar as três), melhor Paraná Pesquisas (+1,87); sinal estável e tamanho de +1,96 a +5,03 conforme a regra de inclusão.
- Regra de uso: medição histórica e cenário nas duas direções (sensibilidades `vies_pp = ±erro comum`, lido do JSON), nunca prognóstico nem ajuste da central; o desvio de 2 pp do erro comum continua parâmetro declarado e 2022 é referência de magnitude. Falta 2018: arquivar as últimas ondas nacionais com URL, SHA-256 e página, transcrever no formato de `pesquisas_2022.json` e rodar a mesma conta; ainda assim seriam dois pontos.
- `tests/conftest.py` coloca `scripts/` no caminho de importação; testes novos importam no topo, sem `sys.path` nem `noqa`. Lint zero agora inclui `tests/`.
- Snapshots: cada build com código alterado grava um snapshot novo; ao fechar uma rodada, manter só o snapshot do hash publicado.
- CNT/MDA 171ª rodada (03/10/2026, `analysis/reponderacao/pesquisas/mda_2026-10-02.json`, PDF em `data/originals/mda_102026_03/`): a íntegra sai no upload público da CNN (`admin.cnnbrasil.com.br/wp-content/uploads/sites/12/AAAA/MM/Relatorio-Pesquisa-CNT-de-Opiniao-R<rodada>-<MES><AA>.pdf`); o site da CNT e o Poder360 não a tinham na hora. Os cruzamentos são imagem: ler na renderização a 130 dpi com recorte ampliado dos rótulos da borda direita e recompor o placar por renda e por sexo antes de usar. A p. 2 passou a declarar ponderação por escolaridade e renda. Em `cdn.cnt.org.br/diretorioVirtualPrd/` há relatórios antigos (rodada 151, fev/2022): pista para arquivar as pesquisas de 2022 que a calibração do erro comum exige.
## Centrais do segundo turno (09/10/2026)
- Atualização de 13/10: `pesquisas-131026-renda.py` integra Gerp, PoderData, Nexus, Ipespe, DataTrends e Futura; revisa a onda Datafolha de 08/10 com a íntegra recebida. Campo Datafolha 06–07/10, bases ponderadas atuais 1.187/874/337 (2.398 de 2.520); não usar mais perfil anterior. Campo Gerp em 08, 09 e 12/10; pesos de renda 20/20/28/12/5/2, recusa 14, soma 101. `renda.parcela_ajustada_pct` limita o delta PNAD à massa com renda conhecida (Datafolha 2.398/2.520; Gerp 87/101). Ausentes da renda conservam o topline; nenhuma preferência imputada. Campo opcional, regra legada intacta onde não existe, snapshots publicados preservados.
- Arquivo desde 13/10: `reponderacao-arquivo.close` fixa séries e cobertura do 1º turno em 04/10 e os sete cards de setembro em 15/09. `reponderacao-validos-view.section_html` apenas calcula e renderiza, sem gravar JSON/CSV: renderizar o passado não pode sobrescrever o 2º turno atual. Persistência em `reponderacao-validos.write`, chamada pelo build atual. Texto e apresentação da superthread em `superthread_092026_cards.py`; não regenerar a página histórica de setembro ao atualizar o 2º turno.
- Futura de 13/10: íntegra de 18 páginas tem perfil de renda familiar (p. 7), mas não voto por renda; entra pelo publicado somente na Projeção. DataTrends de 11/10: íntegra de 31 páginas tem cruzamento (p. 25), mas rotula renda per capita na p. 7 e total na p. 4; manter publicado sem ajuste até reconciliação. NS/NR 1% na p. 12 versus 2% na p. 4: usar o gráfico principal e registrar ambas. Ipespe de 10/10: CATI e indecisos 3% no PDF, apesar de metadados diferentes em matérias. Quaest DF de 12/10 (campo 08–11/10) adicionada ao diagnóstico; cobertura continua 1,4%, sem alimentar a âncora nacional. Nexus de 13/10 declara presença 95%; não confundir com previsão calibrada de comparecimento.
- Transferência de indecisos desde 10/10: controles visíveis no topo (`reponderacao-indecisos-view.py`), conversão 0–100% para válidos e divisão livre F/L em décimos. `undecided_policy="central_proportion"`: automático usa média das razões F/(F+L) entre os presentes antes da conversão e das saídas extras; uma proporção comum aplicada a todas as casas. Na Projeção, é a razão da âncora; no Monte Carlo fica fixada nessa âncora, sem sortear um novo destino. `indecisos_flavio=None` conserva o automático no link; número fixa a divisão. Motor Python/JS e `undecided()` expõem tamanho na base, presentes, transferências iniciais e impacto final contra automático com demais controles iguais. Branco/nulo residual não vira ausência; 100% de conversão é hipótese editável. Fontes 09/10: Datafolha 1%, PoderData 2%, Vox 9,7%; não impor 1% ao agregado. Sem o novo campo de política, versões arquivadas mantêm a regra antiga por pesquisa e seu motor. Preservar todos os snapshots publicados.
- Atualizar com `python3 scripts/reponderacao-build.py`; fonte da interface em `scripts/reponderacao-simulador-view.py` e `scripts/reponderacao-projecao-view.py`, contas em `scripts/reponderacao-simulador.py` e espelho JS. A Central Média Arvor preserva peso igual entre casas com renda; a Central Projeção Arvor usa vetores completos inclusivos, uma onda por casa na semana e recência de três dias.
- `scripts/reponderacao-projecao.py` reutiliza `base.sloped_central`, `tendencia.shrunk_slopes` e `motor.target_draws`. Só campos após 04/10; nunca transportar inclinação ou rejeição do 1º turno. Projeta a 25/10; sem série dentro de casa suficiente, inclinação zero explicitada. Monte Carlo com 20.000 sorteios congelados desde a revisão de 16/10 (links anteriores preservam 2.000); teto amostral de 2.000 por casa permanece independente do número de sorteios. Erro comum de 2 pp e deff de 1,5 são hipóteses, sem probabilidade de vitória validada.
- Ambos os centros compartilham ajuste relativo +3,8% extra e propensões Nexus. `reponderacao-presenca.py` compara a predição pré-urna (hash fixo, commit 1688f007) com a urna nas 27 UFs, sem ZZ nos dois recortes: resíduo F/L +3,83%, média PNAD + Nexus +4,35%. Não é presença por candidato identificada: mistura erro das pesquisas e escolhas finais; o transporte ao 2T é hipótese, pode repetir ajuste já absorvido nas ondas pós-urna e não entra automaticamente na incerteza Monte Carlo. Zero e +5% seguem cenários. Cobertura pode diferir: Projeção conserva o publicado quando falta renda (Vox), sem imputar PNAD. Mostrar os pesos e a diferença de cobertura; não atribuir toda diferença ao algoritmo. Links congelam a central, os controles, o motor, os dados e os sorteios. Preservar todos os snapshots publicados; eliminar só rascunhos inéditos ao fechar a rodada.
- Estaduais pós-urna em `analysis/reponderacao/estaduais/`, compiladas por `scripts/reponderacao-estaduais.py`: atualmente diagnóstico, separado da âncora nacional. Datafolha DF de 09/10 cobre 1,4% do eleitorado; uma estadual não é mais uma casa nacional. Preservar válidos divulgados e normalização dos totais arredondados separadamente. Upload posterior à urna pode conter campo anterior: a ficha técnica prevalece. O arquivo da predição do 1º turno continua fechado.
- Comparecimento 2T desde 09/10: `reponderacao-comparecimento.py` ancora ambas as centrais nos 79,157882% efetivos do 1T/2026, Brasil sem ZZ (124.934.069 presentes / 157.828.968 aptos). Central sem desconto automático: MAE 1,02 pp em apenas três retrospectivas 2014/2018/2022, melhor que médias; escolha exploratória e sensível ao corte (desde 2010, última variação vence). As seis variações presidenciais 2002–2022, médias recente/completa e aumento de presença de 2022 ficam como cenários que alteram só o total, sem aprender voto dos ausentes. Série e fontes em `analysis/reponderacao/comparecimento/`; reextrair 2018/2022 dos ZIPs locais com `reponderacao-comparecimento-fontes.py`. Documentar percentuais arredondados, exterior e resíduos de aptos sem comparecimento/ausência; envelope histórico não é IC. Monte Carlo dos votos permanece condicional ao comparecimento selecionado. Preservar links antigos com os defaults antigos.
## Dossiês de segundo turno (13/10/2026)
- `python3 scripts/dossies-2t-2026-build.py` gera `docs/nexus_btg_13102026.html` e `docs/datafolha_08102026.html`; módulos em `scripts/dossies_2t_2026/`. Extração/contas em `dossies-2t-2026-audit.py`, fontes e regras em `analysis/dossies_2t_2026/CONTRATO.md`. Não editar as páginas geradas. Não recalcular as centrais ou regravar snapshots para atualizar esses dossiês.
- Datafolha: dez perguntas do anexo inteiro, 31 recortes por pergunta, bases ponderadas atuais. Decisão usa 2.488, motivação 2.366, renda 2.398 de 2.520. Transferência agregada 46/32/15 vem da apresentação p. 5; os 7% restantes não são indecisos identificados. Preservar traços como null e distinguir bases da apresentação, cuja natureza não está explicitada.
- Nexus: nove perguntas cruzadas, 29 recortes por pergunta, catálogo das 86 páginas com formulações. Transferências são voto lembrado, sem bases publicadas. Bolsa Família pergunta pelo domicílio; presença de 95% é declarada. Pisos/tetos, escalas de polarização, rejeição, motivação e expectativa de vitória não são votos equivalentes nem intervalos validados. Economia presente, passada e futura têm horizontes distintos; duas menções de problemas não somam 100%.
- PesqEle de ambas conferido e transcrito em `docs/fontes/*_13102026_registro.txt` e `datafolha_08102026_registro.txt`. Calibração pelo voto do 1º turno não está declarada no registro/relatório consultados; não afirmar ausência de ajustes internos. Datafolha mantém alvo de renda 49/47/4 e fator previsto 1, PNADC-A 2024; Nexus mantém perfil 19/18/40/23 e referência PNADC anual 2025.
- CSS/JS compartilhados em `docs/assets/dossies_2t_2026.*`; explorador identifica universo, base e página ao mudar a pergunta. Gráficos móveis são HTML legível; tabelas e fontes funcionam sem JS. Cards gerados pelo manifesto via `social-card-dossies-2t.py`. Validação em `tests/test_dossies_2t_2026.py` e Playwright. Cada fonte e rótulo são conferidos antes de promover um diagnóstico.
## Quaest nacional de 14/10/2026
- Íntegra de 152 páginas preservada via LFS em `data/originals/quaest_102026_14/Quaest_14102026.pdf` e `docs/fontes/quaest_14102026.pdf`; leituras dos 23 temas e proveniência em `analysis/quaest_141026/integra/`. Módulos `scripts/quaest_141026/integra/`; `quaest-141026-integra.py --render-pages` recria as imagens. Não editar o HTML gerado. Grupo p. 19 junta BN e ausência: 43% Lula/38% Flávio, saldo aritmético +1,10 pp Lula no total; não identifica abstencionistas nem matriz completa. Os 9% não são previsão de abstenção. Não se localizou regra publicada de likely voter; interesse não é presença. Cenários ilustrativos não entram nas centrais.
- `python3 scripts/quaest-141026-build.py` gera o dossiê completo e os dados do painel G1 a partir das fontes locais em `data/originals/quaest_102026_14/`; módulos em `scripts/quaest_141026/`. Cinco perguntas, 26 recortes por pergunta; bases ausentes continuam null. Rejeição não é voto nem partição de 100%.
- Campo 10–13/10, n = 2.154, BR-08729/2026, publicado Flávio 46 × Lula 44. Cruzamentos atuais por renda conferidos no HTML salvo e na API arquivada. A íntegra recebida em 15/10 publica o perfil 31/42/27 (p. 147), com etapa antes/depois da ponderação não identificada; `perfil_tipo=perfil_publicado`. Sensibilidade PNAD permanece 45,398 × 44,531, incluída nas duas centrais com essa condição explícita.
- Após rever a ficha, regenerar dossiê, `reponderacao-pnad.py calcular --hoje AAAA-MM-DD`, `reponderacao-build.py`, cards Quaest/centrais/hub e sitemap. Atualizar textos e metadados da home à mão; preservar snapshots publicados e o arquivo do 1º turno. Renderização histórica não pode persistir dados; `--refresh-archive` é somente para revisão explícita do arquivo.
## Rodada nacional de 15/10/2026
- `python3 scripts/pesquisas-151026-renda.py`, `reponderacao-pnad.py calcular --hoje 2026-10-15` e `reponderacao-build.py` integram Datafolha, Palver e Indexa. Fontes arquivadas com hashes em `data/originals/*_102026_15/`; inventário em `analysis/reponderacao/auditoria_20261015.json`. Preservar arquivo do 1º turno e snapshots publicados.
- Datafolha, BR-00466/2026: Folha de 15/10 informa campo efetivo 13–14/10, 47/45/6/2 e válidos 51/49. G1 consultado ainda devolvia 08/10; não reutilizar seus cruzamentos como atuais. A matéria só informa duas faixas de renda. Entrou inicialmente pelo publicado na Projeção; pendência resolvida pela íntegra oficial de 42 páginas publicada em 16/10 (ver revisão abaixo).
- Palver onda 7: PDF pp. 20/23/24, perfil final ponderado arredondado 36/41/23, voto F/L por renda 48/51, 52/48, 52/48; 50/49/1/0 no total. Zero de indecisos é arredondado. Método v3 usa PNADC 2025 visita 1 e voto declarado no 1T/2026 por região, quebrando comparação direta com onda 6. Relatório confirma BR-08028/2026, campo 10–13/10; release tem códigos errados. Explorador ainda terminava na onda 6.
- Indexa/Broadcast: campo 13–14/10, BR-04629/2026, 44/42/4/2 e `nao_vai_votar=8`. Voto por renda existe, perfil ponderado não localizado: sem ajuste PNAD. Guardar não votantes separados na ficha; motor agrega em não escolha, sem substituir comparecimento. Atlas conferida no catálogo oficial: última nacional continua 09/10, sem nova onda duplicada.
## Rodada nacional de 16/10/2026
- `python3 scripts/pesquisas-161026-renda.py`, `reponderacao-pnad.py calcular --hoje 2026-10-16` e `reponderacao-build.py` integram Gerp, PoderData, CNT/MDA e Futura. Fontes com SHA-256 em `data/originals/*_102026_16/`; inventário `analysis/reponderacao/auditoria_20261016.json`. Preservar snapshots publicados e o arquivo do primeiro turno.
- Gerp: perfil ponderado 22/22/32/13/5/2, recusa 3, soma 99; parcela ajustável 96/99. Íntegra pp. 14/16 confirma 50/45/2/3, sem adicionar branco/nulo da matéria. Válidos 52/48 publicados permanecem separados da divisão dos inteiros 50/45.
- PoderData: relatório de 33 páginas, BR-04258/2026, campo 13–15/10, perfil atual 46/33/21. CNT/MDA: 172ª rodada, BR-00652/2026, 2.014 entrevistas efetivas, perfil 42,4/36/20,6 e NS/NR 1%; ajuste limitado a 99%. Ambas declaram ponderação pelo voto do primeiro turno; a etapa do perfil publicado não está explícita, por isso `perfil_tipo=perfil_publicado` e sensibilidade condicional.
- Futura: BR-03764/2026, campo 14–15/10 na ficha p. 4 e divulgação, divergente da capa (13–15/10). Estimulada 49/47,5/1,5/2,1, sem voto por renda na íntegra. Somente publicado na Projeção. P. 5 repete a nota de troca da escolaridade TSE pela PNAD já presente em 13/10; não afirmar nova mudança entre as duas ondas.
- Revisão Datafolha 15/10: `datafolha-151026-renda.py` integra a íntegra oficial publicada em 16/10, arquivada em `data/originals/datafolha_102026_15_integra/`; chamada também por `pesquisas-161026-renda.py`. P. 30 (anexo p. 8) tem bases ponderadas 1.172/918/335, voto F/L/BN/I 38/53/6/2, 55/40/4/1, 59/34/6/1. Ajuste limitado a 2.425/2.520; 95 sem renda conservam o publicado. Entra nas duas centrais, mantém id/campo/divulgação. Não duplicar onda nem reescrever inventário inicial de 15/10. A comparação temporal Datafolha agora usa PNAD nas duas ondas, removendo a troca ajustado→publicado.
- As novas ondas ativaram a tendência pelo critério já existente do motor. A Projeção extrapola inclinação pós-urna até 25/10 e pode absorver mudanças metodológicas; explicitar a distinção da Média. Contratos históricos dos testes usam data explícita ou snapshot congelado: Vox e Datafolha DF de 09/10 saem naturalmente da janela em 16/10.
## Veritá de 17/10/2026
- `python3 scripts/verita-171026-renda.py`, `reponderacao-pnad.py calcular --hoje 2026-10-17` e `reponderacao-build.py` integram a onda BR-01107/2026, campo 12–16/10, n = 15.554. Relatório fornecido em Downloads, preservado com SHA-256 em `data/originals/verita_102026_17/` e cópia pública em `docs/fontes/verita_17102026.pdf`.
- Arquivo de 13 páginas com saltos na numeração impressa: perfil p. 4; topline p. 9 (impressa 13); renda e sexo p. 10 (impressa 14). Totais F/L/BN/NS: 49,7/47,7/1,5/1,1; válidos publicados 51,1/48,9 separados. “Ausente” 2,6% é subtotal BN + NS, não abstenção. Frequências dos candidatos somam 15.151 contra subtotal 15.152; preservar percentuais publicados, sem extrair falsa precisão das contagens.
- Perfil 42,7/38,6/18,7; frequências 6.635/6.010/2.909, sem não resposta publicada. `perfil_tipo=perfil_publicado`: estágio antes/depois da ponderação não explicitado. Cruzamentos totais por renda 43,3/53,4/1,6/1,7; 55,4/43/1,2/0,4; 52,8/44,4/1,6/1,2. Recompor por renda e sexo; não confundir voto lembrado ou expectativa de vitória com intenção atual. Entram as duas centrais sob essa hipótese de perfil; preservar snapshots anteriores e arquivo do primeiro turno.
## Coding Style & Naming
- Prefer Python (PEP 8, 4 spaces).
- Script naming: `kebab-case` (new files), keep existing names for compatibility.
- Keep scripts stream-first for large data; avoid loading full files in memory when not needed.
## Testing Guidelines
- Tests in `tests/`, names `test_*.py`.
- Cover parsing, type conversion, schema checks, and CLI behavior.
- Run `pytest -q` before merging.
- CI precisa de `fetch-depth: 0` para conferir as datas do sitemap. As malhas compactas de `apuracao/public/geo/` e `data/originals/ibge_malhas/br_uf/br_uf_minima.geojson` são dependências versionadas da renderização, não caches descartáveis.
- Comparações com `apuracao/data/secoes_2026.sqlite` exigem o banco local pesado e são condicionais; os contratos dos fragmentos públicos continuam testados sem ele. A exportação Excel exige `openpyxl` em `requirements.txt`.
## Commit & PR Guidelines
- Commit style: imperative + scoped (example: `add brasil pipeline-run sqlite refresh`).
- PR should include:
- purpose and change summary
- commands used for validation
- backward-compat notes (schema/column changes)
## Security & Data Handling
- Avoid committing sensitive or proprietary data.
- Prefer lightweight samples in `samples/` for tests.
- Normalize line endings to LF.
- Use Git LFS for large binaries when needed.
## Lessons Learned
- Safe filtering uses restricted AST compilation (`pnadc_cli.RowExpr`).
- Delimiter/header detection uses `parse_pnadc.sniff_delimiter` with fallbacks.
- SAS layout parser (`layout_sas.parse_layout`) supports labels/slugs and stable ordering.
- Official IBGE layout files (`data/originals/input_PNADC_trimestral.sas` and `.txt`) are `ISO-8859-1` (`latin-1`), not UTF-8.
- Reading layout in wrong encoding introduces mojibake in labels/slugs (example: `federacao`/`primria` artifacts); keep layout parsing encoding-aware and keep generated CSV/JSON output in UTF-8.
- If mojibake appears in derived headers/labels, rerun extraction pipeline after fixing layout encoding handling.
- `fwf-extract` can derive `data_nascimento` and `dom_id`.
- `household-agg` streams rows and aggregates by `dom_id`.
- `npv_deflators.py` applies deflators and minimum-wage conversion in streaming mode.
- `brasil ibge-sync` refreshes monthly minimum wage from BCB SGS series `1619`.
- `brasil pipeline-run --raw latest` auto-resolves `target` (latest IPCA month) and `min_wage` from `salario_minimo.csv`.
- `brasil renda-por-faixa-sm` and `brasil dashboard` default to weighted population estimates (`V1028`, fallback `V1027`).
- `brasil renda-por-faixa-sm` and `brasil dashboard` now compute sampling margin of error/CI by default (bootstrap replicate weights, `V1028001..V1028200`) when replicate columns are present.
- CI controls: `--no-ci` to disable, `--ci-level` to change confidence level.
- If legacy CSVs were generated before replicate columns were included, CI falls back to disabled until pipeline is rerun.
- `brasil dashboard` default `--sm-mode` is `alvo`; use `--sm-mode both` for period-vs-target comparison.
- `DEFAULT_KEEP` in `fwf-extract` now includes additional high-value modeling fields (sampling, schooling, labor-force and job-formality variables) with good observed coverage in PNADC 2025Q3 profiling.
- `DEFAULT_KEEP` also includes all 200 replicate weights to support uncertainty estimation end-to-end in open workflows.
- Terminal output now has high-contrast Brazilian palette by faixa:
- green (mais pobre), yellow (media baixa), blue (media alta), white (mais rica).
- `--group-by uf` default ordering is `renda_desc` (richer to poorer by average household SM).
- Dashboard sections now include:
- top 10 UFs by income and by population,
- macro-region panel,
- socioeconomic "thermometer" insights (richest/poorest UF and concentration in lowest/highest faixa).
- Pretty outputs now map faixa de SM to BRL ranges (`R$`) for direct interpretation.
- Dashboard now includes an age pyramid (sexo x idade) and age recuts ordered by age buckets.
- For restricted-universe variables, dashboard labels non-response explicitly:
- `Nao se aplica (fora da ocupacao)` for occupation-only variables,
- `Fora de RM/RIDE` for metro-region variable,
avoiding false inflation of `Sem informacao`.
- `brasil query` is optimized for LLM workflows:
- default output is JSON,
- read-only SQL is enforced by default,
- supports SQL via `--sql`, `--sql-file`, or stdin pipe,
- table rendering is available via `--format table`,
- JSON includes `sampling` metadata; CI is not auto-derived for arbitrary SQL.
- In PNADC layout, `var. auxil.` means `variavel auxiliar` (roteamento do questionario), not necessarily `auxilio social`.
- For labor income decomposition, keep `V4033/V4034*` (trabalho principal) together with `V405*` (trabalho secundario/outros); omitting `V403*` undercounts detailed components.
- `brasil ibge-sync --full` sincroniza escopos eleitorais completos: PNADC trimestral + PNADC anual visita 5 + Censo 2022 (renda do responsavel) + TSE (perfil do eleitorado).
- TSE electorate profile now complements PNAD for polling reports:
- `data/raw/tse_eleitorado/perfil_eleitorado_ATUAL.zip` stores the official current TSE profile package.
- `data/outputs/tse_eleitorado_perfil.sqlite` stores compact national summaries for future audits.
- `data/outputs/tse_eleitorado_perfil_summary.csv` is the lightweight CSV companion.
- `data/outputs/tse_eleitorado_perfil_benchmark.json` preserves exact gender/age totals both for the dashboard filter “País: Todos” and for Brazil excluding exterior.
- Current profile was generated by TSE on 2026-07-01 at 12:44:02 (June competence) and totals 157,846,602 Brazil-resident voters after excluding exterior. The 2026-05-01 ZIP is archived for historical dossiers.
- For Censo 2022 sector audits, use the definitive mesh and definitive sector aggregates. The preliminary mesh PDF and FTP tree are historical evidence only; IBGE states the definitive mesh replaces the preliminary version.
- A neighborhood label is not a sampling unit. Compare polling rounds by the 15-digit IBGE census-sector geocode; the same neighborhood may contain many different sectors.
- Rebuild the July 2026 Datafolha campaign layer with `python3 scripts/datafolha-072026-campanha.py` (run `scripts/datafolha-072026-audit.py` first: it produces the territorial CSV the campaign script consumes). It measures the fixed municipal panel (118 of 139 municipalities in all three waves with identical quotas), aggregates TSE electorate coverage in streaming mode, transcribes the report crosstabs from pages 24–33 and cross-checks the panel against the official 2022 runoff.
- Rebuild the May–August 2026 Datafolha income-standardized runoff series with `python3 scripts/datafolha-082026-historico-renda.py`. It anchors each wave to its published topline and adds only the delta between the reported income bases and the same PNADC annual 2025 benchmark. The published Lula gaps are +4, +4, +5 and +4; the standardized gaps are -2.81, -0.16, approximately zero and -1.78. Publish this as a one-margin sensitivity under a common rule, never as the real election result.
- The Datafolha municipal panel is not politically skewed: its 139 municipalities voted 50.88% Bolsonaro in the 2022 runoff against 49.10% nationally, and 49.33% when weighted by interviews. Test that hypothesis before repeating it.
- Rebuild the August 2026 Datafolha second layer with `python3 scripts/datafolha-082026-cruzamentos.py`, then `python3 scripts/datafolha-082026-aprofundamento.py`, `python3 scripts/datafolha-082026-figuras-fundo.py` and `python3 scripts/datafolha-082026-prints.py`. The first extracts the 14 crosstabs from the PDF text with no manual typing; the second computes open market, field-versus-weight, noise floor, gap, substitution, conversion and segment coverage; the third draws eleven figures; the fourth crops the original pages cited in the dossier.
- Rebuild the August 2026 Datafolha audit with `python3 scripts/datafolha-082026-audit.py`, `python3 scripts/datafolha-082026-figuras.py` and `python3 scripts/datafolha-082026-graficos.py`. The registered income target uses PNADC-A 2024; replacing only that margin with PNADC annual 2025 takes the published Lula 47 × 43 Flávio runoff to Lula 44.19 × 45.97 Flávio. Label it as sensitivity, never as corrected vote.
- For Datafolha 08/2026, the published four-point runoff gap has a 95% difference margin of 4.095 points even under simple random sampling. A headline that turns 47 × 43 into an identified lead states more than the sample supports. A numeric headline is faithful but materially incomplete unless the uncertainty of the difference is supplied nearby.
- The Datafolha 08/2026 report and registry declare 128 municipalities, while the territorial annex contains 129 distinct seven-digit municipality codes. The 2,058 interviews close and there are no duplicate sectors. Publish this as a documentary discrepancy requiring reconciliation, not as evidence of fraud.
- The territorial annex is **not** public before fieldwork. Res. TSE 23.600, art. 2º, §7º lets the institute file the municipality and neighbourhood list from the divulgation day up to the next day, and the July 2026 Datafolha registration says so in its own words. What is public at registration time is metadata: field dates, sample size, contractor, value, questionnaire and a generic sampling plan. Do not claim the map leaks before the field; that claim was published once and corrected.
- The predictability comes from repetition, not from the filing deadline: June's annex, public since 19/06, already contained 137 of July's 139 municipalities. The auditable consequence of the current rule is different and sharper: because the annex only arrives after divulgation, **there is no public proof that the sample was defined before the field**. That is what the hashed prior deposit (Res. § 7º-X, PL § 12-A) fixes.
- Rebuild the June–July 2026 Quaest territorial comparison with `python3 scripts/quaest-territory-audit.py --refresh-ibge`. It validates selected sectors against the Panorama service and writes auditable CSV/JSON without imputing vote from Census demographics.
- Rebuild the Atlas July/2026 numbers with `python3 scripts/atlas-072026-audit.py` (writes `docs/assets/atlas_072026_audit.json`) and the Datafolha territorial concentration with `python3 scripts/datafolha-072026-cidades.py` (writes `docs/assets/datafolha_072026_territorio.json`). The second reads the CSV produced by `datafolha-072026-audit.py`, so it needs no `pdfplumber`.
- Atlas crossbreaks are published as images inside the PDF; `pdftotext` and PyMuPDF return only titles. Render the crossbreak pages (`fitz` at ~115 dpi) and transcribe them into the audit script's constant tables, citing the page number.
- When a poll asks both the current-year vote and a "repeat the last election" scenario, the difference between the two isolates the succession cost inside one sample — same respondents, same weights, same recruitment bias. In Atlas 07/2026 it yields Jair 42.3 × Flávio 35.8, with the loss concentrated in the non-bolsonarista right (−20.3) and the unaligned (−19.7), not in the hard base (−2.5). Publish it as descriptive: Atlas gives no unweighted bases, so the gap gets no confidence interval.
- Cross the fear question with the vote question per segment to get the conversion gap — how much emotional advantage a candidate holds and has not converted. Positive gaps mark a trust deficit, not an opinion deficit.
- Datafolha's national design is a fixed master sample: 139 municipalities, 118 identical across May–July 2026, 87.4% of July interviews inside them, only two city swaps between June and July, and AP/RR absent in all waves. Sector rotation, by contrast, jumped from 23% to 79% new between the two intervals. Fixed PSUs are legitimate and reduce the variance of change; the auditable problem is the unpublished selection probability, strata, rotation rule and design effect.
- With ~6 interviews per census sector, Kish's `deff = 1 + (m − 1)ρ` means `ρ = 0.088` erases the 5-point second-round lead and `ρ = 0.736` would be needed to erase the 8-point first-round lead. Report both directions: the first round survives, the second does not.
- Web illustrations for dossiers must come from free-licensed sources (Wikimedia Commons) with author and licence credited in the sources section. Wikimedia rejects arbitrary thumbnail widths — request 800/1280/2560 px or fetch the original via the API.
- Reveal-on-scroll must be gated behind a `js` class added inline in `<head>`, so a page whose script fails still renders every section.
- Rebuild the Atlas income re-weighting with `python3 scripts/atlas-072026-renda.py` (writes `docs/assets/atlas_072026_renda.json`). It streams `base_anual_labeled_npv.csv` (PNADC anual 2024, visita 5) and `base_anual_visita1_labeled_npv.csv` (PNADC anual 2025, visita 1), both already present in `data/outputs/`.
- Poll income quotas are stated in **nominal** reais, so the vintage of the reference PNAD is itself an auditable choice. Atlas 07/2026 declares PNADC 2024 while PNADC anual 2025 had been published in May/2026. Expressing the *same* 2024 microdata at April/2026 prices already moves the R$2.000–3.000 band from 17.3% to 11.9%, because two minimum wages crossed the R$3.000 ceiling (R$2,824 in 2024, R$3,036 in 2025, R$3,242 in 2026) and 42% of that band sat between R$2,700 and R$3,000.
- Re-weighting a published topline on a single margin is legitimate as sensitivity analysis when the published margin reproduces the topline (Atlas 07/2026 does, to 0.1 pp). Always label it as such: the institute's weighting is joint and unpublished. Prefer the same-vintage/price-corrected line as the headline claim, because it is immune to the visita 1 × visita 5 composition objection.
- Never compare two polls on raw percentages when their non-choice shares differ: Atlas 07/2026 has 1.6% blank+null+don't-know against Datafolha's 11%, and those 9.4 points mechanically compress every candidate share in one of them. On **valid votes** the same two polls agree to 0.99 on both Lula and Flávio, and diverge only on movement candidacies — Renan Santos 2.30x, Samara Martins (UP) 1.86x, against Caiado 0.69x, Cury 0.71x and Zema 0.83x. The right/left symmetry is what makes the finding immune to a partisanship objection: it describes the method, not the institute. Reproduce with `intensity_premium` in `scripts/atlas-072026-audit.py`.
- Ad platforms optimize delivery by estimated action rate and let advertisers build audiences from people who engaged with the page. That is enough to explain how a militant group raises its own odds of receiving a pollster's recruitment ad — no coordination needed. Keep the documented mechanism strictly separate from any claim that it was done on purpose.
- Source reports without artifacts (no screenshots, no logs) publish only on the `relato`/hypothesis rung, with the absence of evidence stated in the same breath as the claim, and with an explicit sentence clearing any party the report does not implicate. State what document would settle it — for Atlas, the funnel by origin, creative, campaign and hour with the candidate's vote inside each.
- When auditing an inflated number, close on who it actually costs: it buys short-term debate invitations and screen time, but destroys the diagnosis, the alliance timing and the expectation management of the campaign that celebrates it. That framing is sharper than an accusation and cannot be answered with outrage.
- **Social cards têm uma convenção só, desde 04/08/2026.** Todos saem de `python3 scripts/social-cards.py`, que lê um manifesto único no próprio script, escreve a fonte em `docs/assets/og/<slug>.html` e renderiza `docs/img/og/<slug>.png` em 1200×630 com Chrome headless. Para mudar um texto, edite o manifesto e rode de novo (`--only <slug>` regera um card; `--html` só reescreve as fontes). Nunca edite o HTML gerado nem a imagem à mão.
- Toda página pública tem card próprio, e dossiê e thread têm cards distintos: a thread leva a tarja `Thread` e o acento azul. `docs/social.html` é a galeria de conferência de todos eles, com `noindex`, e não precisa de card.
- Ao criar um dossiê novo: acrescente o card ao manifesto de `scripts/social-cards.py`, rode o script, e ponha nas metatags `og:image` e `twitter:image` apontando para `https://brasil.arvor.co/img/og/<slug>.png`, com `og:image:width` 1200 e `og:image:height` 630.
- Páginas geradas por script (`docs/pnad.html` via `docs/index.template.html` e `docs/build_index.py`; `docs/artigo_*.html` via `docs/build_articles.py`) precisam da metatag na FONTE, não no HTML gerado, senão o próximo build apaga.
## Google Analytics em toda página navegável (07/10/2026)
Toda página HTML em `docs/` que um leitor abre no navegador carrega a tag gtag.js da propriedade `G-ZPYEE8P9YC`, uma vez só, logo depois do `<meta charset>`. A fonte única é `scripts/ga_tag.py` (`GA_ID`, `GA_TAG`, `injetar()`); nunca cole o snippet à mão nem com outro id.
- **Página nova gerada por script**: o gerador grava `injetar(html)` no ponto de gravação (`SAIDA.write_text(injetar(html), ...)`), ou dentro da função `pagina()` quando um teste compara a saída dela com o arquivo publicado (padrão de `scripts/apuracao_2026/thread_pagina.py`). Em `docs/build_*.py` o import precisa de `sys.path.insert(0, ROOT / "scripts")` antes, com `# noqa: E402`.
- **Página nova escrita à mão ou template** (`docs/*.template.html`, `index.html`, `politizesuavizinhanca.html`): rode `python3 scripts/ga_tag.py`, que acrescenta a tag onde falta e não duplica. `--check` só lista.
- `tests/test_ga_tag.py` reprova no CI qualquer `docs/*.html` sem a tag, com ela duplicada ou fora do `<head>`. Os cards de `docs/assets/og/*.html` ficam de fora: são fonte de imagem, não página.
- Para trocar a propriedade, mude `GA_ID` em um lugar e rode o CLI; a tag antiga é detectada pelo id, então uma troca exige remover a anterior antes.
## Transferência de voto 1º → 2º turno (método fixo da casa)
Toda pesquisa de primeiro turno auditada recebe o diagrama de transferência estimada, sempre com os mesmos cinco passos e a mesma blindagem. Reprodução de referência: `scripts/datafolha-072026-graficos.py` (Datafolha 07/2026).
1. **Antes de tudo, procure a matriz publicada.** A afirmação de que nenhum instituto brasileiro publica matriz de transição é falsa e foi corrigida em 04/08/2026: a Nexus publica o cruzamento do voto de 1º com o de 2º turno para o eleitorado de cada candidato menor (relatório de 03/08/2026, p. 51), ou seja, seis das dez linhas. Procure no relatório por `cruzamento`, `migração` e `vs. 2º turno` antes de escrever qualquer coisa. As linhas publicadas entram **fixas, como medição**; só o resíduo é estimado. O que o instituto costuma omitir é a **fidelidade de base**, que é justamente o número que decide um segundo turno.
2. **Cenários alternativos de 2º turno são restrição observada, não decoração.** Quando o relatório traz Lula × A, Lula × B e Lula × C sobre a mesma amostra, a comparação mede quanto o bloco perde ao trocar de líder e para onde vai a perda. Em julho/2026: Lula fica em 47, 48 e 48 — não se move —, enquanto o bloco adversário rende 43 com Flávio e 40 com Caiado ou Zema, e a diferença aparece em branco/nulo (9 → 11 e 10). Isso limita empiricamente o cruzamento de base para o campo oposto a algo próximo de zero.
3. **A prior é ideológica e explícita.** Base própria fiel; candidatura do mesmo campo migra majoritariamente para o líder do campo; cruzamento para o campo oposto próximo de zero; branco/nulo do 2º turno alimentado sobretudo por quem perdeu o líder; indeciso do 1º turno reparte-se com leve vantagem para quem tem menos rejeição no recorte. Zeros são estruturais e o IPF os preserva.
4. **IPF/RAS fecha a aritmética.** Ajuste proporcional iterativo por mínima entropia cruzada contra a prior, até bater exatamente as margens publicadas, reescalando as origens do 1º turno para o total do 2º.
5. **Publicação com blindagem.** Fita sólida = elo medido pelo instituto, fita hachurada = elo estimado por nós, com a legenda declarando quantas origens são de cada tipo. Nunca escrever que nenhum elo foi medido sem antes conferir a página de cruzamento. Mantenha a distinção de robustez: **a razão de consolidação fora das bases é imposta pelas margens e sobrevive à troca da prior; o corte candidato a candidato depende da prior e não deve ser tratado como medição.**
- Reportar sempre a razão de consolidação (ganho de cada finalista fora da própria base) e compará-la com a onda anterior. Datafolha 07/2026: Flávio +10,1 × Lula +6,8, razão 1,48:1, contra 2:1 em junho.
- A leitura é agregada. Nunca descrever o diagrama como o percurso de eleitores individuais, e nunca somar eixos de recortes que se sobrepõem.
## Método de leitura estratégica (Quaest 08/2026 em diante)
Quando o relatório do instituto é imagem sem camada de texto, a transcrição página a página vira parte do produto: grave cada bloco no script de auditoria com a página de origem ao lado, e prove a transcrição recompondo o placar publicado a partir de um cruzamento independente. Na Quaest 08/2026, o cruzamento por posicionamento devolve Lula 38,3 e Flávio 29,6 contra 39 e 30 publicados, com resíduo igual ao bloco de 2% sem posição declarada. Sem esse controle, nenhuma conta derivada é publicável.
- **O vão**: desaprovação do governo menos voto no adversário, dentro do mesmo recorte, com as duas metades vindas do mesmo relatório. Só vira número nacional quando os recortes formam partição fechada (as três faixas de renda somam 100%). Rótulo obrigatório: teto endereçável, não previsão, porque desaprovar não é estar disponível. Complete sempre com a não escolha do recorte, que diz se o voto ausente está com o incumbente ou fora da urna.
- **Substituição medida**: quando o instituto roda vários segundos turnos na mesma amostra, a comparação é experimento, não especulação. Reporte que o incumbente quase não se move e que a variação inteira fica no desafiante e na não escolha. É a prova mais forte de voto útil que existe em pesquisa brasileira publicada, e é rara.
- **Contraponto obrigatório**: procure o recorte em que o substituto bate o candidato preferido e publique com o mesmo destaque. Na Quaest 08/2026, Caiado vence Flávio em renda alta, homens, Centro-Oeste/Norte e superior, exatamente onde o vão é maior.
- **Alcance efetivo de programa de governo**: multiplique alcance declarado por efeito sentido. IRPF chega a 6,3% do eleitorado e Desenrola 2.0 a 2,6%. Diga junto que alcance baixo não é efeito eleitoral nulo, porque política pública produz símbolo além de dinheiro.
- **Canal contra déficit**: cruze fonte de informação por recorte com a margem do candidato no mesmo recorte. Quando o canal forte da campanha alcança melhor quem já vota nela, o problema é de distribuição, não de mensagem.
## Métodos novos da casa (Datafolha 08/2026, segunda camada)
**A estrela do dossiê de pesquisa continua sendo a reponderação por renda.** Os métodos abaixo são camadas de apoio e nunca devem deslocar a manchete do laudo. Erro cometido e corrigido em 25/08/2026: a linha de bases das páginas 12 e 13 da divulgação do Datafolha foi lida como contagem de campo e virou a tese principal do dossiê. A página 13 é a base de uma pergunta de **motivação do voto**, não de intenção de voto; construir sobre ela uma afirmação sobre a diferença entre candidatos mistura dois universos. Removido. Antes de promover qualquer achado a manchete, pergunte de qual pergunta a base veio.
Antes de auditar qualquer relatório, extraia o **anexo inteiro de tabelas cruzadas** por programa, não à mão. `scripts/datafolha-082026-cruzamentos.py` é a referência: lê o texto nativo do PDF, agrupa as sequências numéricas em blocos terminados pela linha de base ponderada, casa cada bloco com uma lista de rótulos declarada, e prova a leitura recompondo o placar publicado a partir de dois cruzamentos independentes. Na onda de agosto o cruzamento por identificação política devolve Lula 46,98 e Flávio 43,29 contra 47 e 43 publicados, com resíduo igual à base sem posição na escala. Sem essa prova, nenhuma conta derivada é publicável.
- **Mercado aberto.** Some a resposta de "o voto ainda pode mudar" com os indecisos. Em agosto dá 30 pontos contra 6 de diferença publicada. Reporte sempre com a ressalva de que poder mudar não é migrar de lado: boa parte termina em branco, nulo ou abstenção. O achado é sobre o tamanho da disputa, não sobre a direção dela.
- **Piso de ruído da rejeição.** Pergunta múltipla, com cartão e com insistência produz recusa contra nomes desconhecidos. Calcule a rejeição média das candidaturas com 1% ou menos de voto: em agosto, 9,67%. Seis dos treze nomes do ranking ficam dentro dele e Cury fica abaixo. O piso varia 2,4 vezes entre recortes (5,7% entre 16 e 24 anos, 13,7% no ensino fundamental), então **comparar rejeição entre recortes sem descontar o piso mistura opinião com estilo de resposta**, e a ordem chega a inverter: descontado o piso, a rejeição a Flávio é maior entre jovens que entre idosos, o oposto da tabela publicada.
- **Cobertura dos recortes.** Some as bases de cada dimensão e compare com o total. Só 6 das 11 dimensões do anexo de agosto são partição fechada. Religião cobre 76,1%: 491 entrevistados, entre eles os 11% sem religião, nunca aparecem cruzados, enquanto o Sul, que pesa 15%, tem coluna. Cor perde 72 (amarela e indígena). Use apenas partições fechadas para agregar qualquer indicador ao nacional.
- **Coletado e não publicado.** Compare o questionário registrado com o relatório, pergunta por pergunta. Em agosto sobraram oito, entre elas o **voto no 2º turno de 2022**, a única variável conferível contra um resultado real, e a **escala de esquerda a direita de 1 a 7**, coletada na mesma entrevista em que se publicou apenas a escala de 1 a 5 entre bolsonarista e petista. É o achado mais forte sobre enquadramento: o instrumento comprime o espaço político em dois nomes próprios e depois chama de "não alinhado" um quarto do eleitorado.
- **Cartão de renda contra a cota de renda.** O cartão mostrado ao entrevistado usa reais do ano corrente (faixa de R$ 1.622 a R$ 3.242, dois salários de R$ 1.621 em 2026). A distribuição alvo declarada no registro vem da PNADC-A 2024, quando dois salários eram R$ 2.824. Régua da pergunta e régua da cota em anos diferentes. Confira também os códigos que existem no cartão e somem do perfil publicado, como "não tem renda".
- **Série congelada.** Antes de aceitar narrativa de tendência, ponha 1º e 2º turno lado a lado. Em agosto a diferença do 1º turno caiu de dez para seis pontos enquanto o 2º turno marcou 43 em quatro ondas seguidas: a convergência é voto útil que o 2º turno já contava. E o desafiante marcava 33 em março e marca 33 agora; a queda é do incumbente.
- **Capítulo estratégico com o mesmo rigor.** O dossiê pode ter lado. Cada movimento recomendado precisa de número com página ao lado, o juízo editorial precisa estar rotulado como juízo editorial, e o capítulo precisa conter o achado que contraria o próprio autor. Em agosto: Flávio é o adversário mais forte no agregado por 3,4 pontos sobre Caiado **e** perde para os próprios substitutos entre os não alinhados, 38 contra 46, 45 e 44.
## Comparação de pauta entre ondas (método da casa, 25/08/2026)
Uma onda isolada não mostra o que o instituto escolheu não perguntar. Quatro ondas lado a lado mostram. Reprodução: `python3 scripts/datafolha-082026-pauta.py`, que extrai os blocos `P.n` do texto nativo dos questionários registrados e classifica cada um em caso, tema político ou consumo, com a classificação declarada no próprio script e os enunciados no JSON.
- **A métrica que decide é "pergunta de caso"**: a que mede o efeito eleitoral de um fato concreto e nomeia pessoas dentro do enunciado. Datafolha 2026: maio 7, junho 3, julho 9, agosto 0. Perguntas temáticas totais: 16, 25, 23, 3. Palavras no questionário: 2.762, 3.461, 2.958, 1.764.
- **Conte os agentes nomeados dentro dos blocos `P.n`, não no arquivo inteiro.** Fora dos enunciados os nomes aparecem no cartão de candidatos e na pergunta de memória de 2022, o que não caracteriza pergunta de caso. Sem esse recorte, agosto aparece falsamente com dois agentes citados.
- **A bateria de custo eleitoral tem quatro degraus**: informar o fato ao entrevistado, pedir juízo moral, medir a mudança de confiança no voto e perguntar se o político deveria desistir. Em maio de 2026 ela foi aplicada com sete perguntas a um só político, incluindo cartão com quatro substitutos possíveis. Em quatro ondas, foi usada uma vez.
- **Publique as duas ressalvas junto com o achado, ou ele não sobrevive a citação hostil.** Primeira: a bateria vem depois das perguntas de voto, então não contamina o topline daquela onda, e isso é bom desenho. Segunda: julho não é unilateral, porque a bateria das tarifas nomeia Lula, pergunta se o governo fez menos do que deveria e oferece o próprio presidente como principal culpado.
- **Não afirme intenção.** Afirme o que os documentos mostram e diga o que resolveria: o instituto publicar o critério pelo qual um fato entra no questionário, e divulgar as perguntas que aplicou e guardou.
- Não nomeie caso, pessoa ou escândalo que não esteja em documento no repositório. Sem fonte, o parágrafo não é publicável, por mais evidente que pareça.
## Cobertura do contratante contra pauta da pesquisa (método da casa)
A comparação de pauta entre ondas fica muito mais forte quando cruzada com o que os **próprios contratantes** publicaram nos dias anteriores ao campo. Reprodução: `scripts/datafolha-082026-cobertura.py`, que guarda a linha do tempo com data, hora, veículo e título, mais as consultas de busca que qualquer leitor refaz.
- **Ferramenta.** `WebSearch` e `WebFetch` não alcançam g1.globo.com, folha.uol.com.br nem uol.com.br: a busca restrita por domínio devolve zero mesmo para matérias cuja URL você já tem, e o fetch é bloqueado. **Resultado nulo de buscador não é prova de ausência de cobertura**, e afirmar o contrário repetiria o erro mais caro da casa. O que funciona: o navegador embutido (`mcp__Claude_Browser__`) nas buscas dos próprios veículos, `search.folha.uol.com.br` e `g1.globo.com/busca`, ambas com filtro de período. O Bing via `WebFetch` também devolve URLs do G1 com a data embutida no caminho.
- **Cite pelo carimbo do veículo.** URL do G1 traz a data no caminho (`/2026/07/31/`) e a Folha imprime data e hora no resultado da busca. Isso torna cada item verificável sem depender de nós.
- **A defesa do instituto entra no nosso texto, não na resposta dele.** Em agosto/2026: as mensagens da PF que citam nominalmente o filho do presidente só vieram a público em 20/08, depois de o campo fechar. Registramos isso antes de qualquer conclusão, e mostramos o que ela não explica: o primeiro inquérito era notícia desde 31/07 e em maio o instituto transformou um fato da semana anterior em sete perguntas.
- **Nunca diga que o veículo escondeu o caso.** A busca da própria Folha devolve 377 resultados para o caso que atinge a oposição e 79 para o que atinge o governo. Os dois aparecem. O desequilíbrio está no questionário que a cobertura contratou, e essa distinção é o que torna a crítica irrespondível.
## Data de produção dos documentos (método da casa, 25/08/2026)
Todo PDF guarda no campo `creationDate` o instante em que foi produzido. Reprodução: `python3 scripts/datafolha-082026-documentos.py`, que lê esse metadado nos questionários, anexos territoriais e relatórios completos e compara com campo e divulgação.
- **Achado do Datafolha 2026, quatro ondas em quatro:** o relatório completo é gerado **exatamente três dias depois da divulgação** (25/05, 22/06, 27/07 e 24/08). O questionário fica pronto de seis a sete dias antes do campo e o anexo territorial no dia da divulgação ou no seguinte, o que é compatível com a Res. TSE 23.600 art. 2º §7º. Durante os três dias entre a manchete e o arquivo, a discussão pública corre sem que exista o documento que permite conferi-la.
- **O que o metadado prova:** um arquivo criado no dia 24 não podia estar disponível no dia 21. **O que não prova:** a data de publicação efetiva, nem irregularidade. Prazo de depósito é matéria de resolução e exige ler o dispositivo, não o arquivo. Escreva as duas coisas juntas.
- Rode esse teste em toda auditoria nova. É barato, é interno ao arquivo do próprio instituto e não depende de nenhuma fonte externa.
## Como criticar uma manchete de pesquisa (regra fixa)
Uma manchete que diz "lidera" afirma liderança identificada, e a afirmação precisa passar em **dois testes independentes**, nomeados assim no texto:
1. **Amostragem**: o intervalo de 95% da diferença não pode conter o zero. Em agosto/2026, 47 × 43 dá de −0,10 a +8,10 e contém.
2. **Composição**: o sinal precisa sobreviver à troca da margem dominante pela régua oficial. Em agosto vira Flávio +1,78, e nas quatro ondas.
- **Publique a versão correta da frase**, para que a crítica seja construtiva e barata de aceitar: "Lula tem 47%, Flávio tem 43%, e a diferença não separa os dois com 95% de confiança."
- **Diga onde a manchete acerta.** No 1º turno "lidera" é correto (+2,34 a +9,66). O erro é usar a mesma palavra para duas situações estatisticamente diferentes. Crítica precisa vale mais que crítica geral e é irrespondível.
- **O gráfico que comunica isso** é de barras divergentes de um zero central, uma linha por onda, publicado acima e reponderado abaixo: `fundo_manchete_versus_renda.png`. O espelho é imediato e dispensa legenda técnica.
## Thread educativa (padrão a partir do Datafolha 08/2026)
A thread deixou de ser resumo do dossiê e virou aula. Referência: `scripts/datafolha-082026-thread.py`, que gera `docs/datafolha_082026_thread.html` com dezoito cards 16:9 e o texto copiável embaixo de cada um.
- **Arco fixo**: tese, ficha do documento, quatro aulas (o que é amostra, margem da diferença, estratificação e cota, ponderação), a régua, a conta em quatro passos, a série, os limites, a robustez, conheça o país, checklist de leitura, o que exigir de transparência, fecho.
- **A conta aparece na tela.** O card do tipo `calc` mostra faixa, peso, voto e contribuição, linha a linha, e a soma no rodapé. O passo 2 é obrigatório: recompor o placar com os pesos do próprio instituto para provar que a leitura está certa antes de trocar qualquer coisa. Em agosto/2026 devolve 46,89 contra 47 publicado.
- **Analogia doméstica em toda aula.** A colher e a panela para amostra, a média do boletim para média ponderada, o restaurante para o vão. Sem analogia o leitor abandona no terceiro post.
- **Nada digitado à mão.** Pesos, votos, bases, série e placar saem de `analysis/datafolha_082026/*.json`. O gerador só carrega texto.
- **Contraste medido no SVG também.** O `scripts/contrast-audit.py` lê texto dentro de `<svg>`. Cores de gráfico costumam reprovar sobre o painel do card: em agosto foi preciso clarear `FAINT` para `#8f8c7f`, `GREY` para `#939cae`, criar `LULA_TXT` `#ea6a5c` para texto pequeno e remover a opacidade das barras. Rode a auditoria antes de publicar.
- **No celular o card empilha.** Abaixo de 720px o `aspect-ratio` sai e a tipografia passa de `cqw` para pixel, senão o card fica ilegível. O 16:9 exato continua valendo na largura de trabalho, que é o que se anexa no X.
- **Posts de 950 a 1.400 caracteres.** Menos que isso vira legenda, mais que isso não cabe.
- **Declarar o limite antes da conclusão**, num post próprio, e fechar convidando o leitor a refazer a conta.
## Auditoria de renderização (método da casa, 01/09/2026)
Contraste mede a cor. Renderização mede se o desenho chegou à tela. São defeitos diferentes e o segundo passa por revisão de código sem ser visto. Reprodução: `python3 scripts/render-audit.py http://localhost:4173/<pagina>.html`.
- **O caso que originou a regra:** as barras dos gráficos são marcadas como `<i>` ou `<span>`, que são `display: inline` por padrão, e elemento inline ignora `width` e `height`. A porcentagem estava certa no atributo, a cor certa no CSS, e a barra não pintava nada. Atingia os cinco gráficos do atlas de MG e mais seis barras do dossiê Quaest de julho. Correção: `display: block` na regra `.bar-fill`.
- O script falha quando um elemento dimensionado tem área zero, quando um container cujo `id` termina em `chart`, `map`, `scatter`, `table-body`, `legend` ou `readout` fica vazio, e quando o console acusa erro. Ignora `<defs>`, `<pattern>` e demais elementos de definição de SVG, que não ocupam área por desenho.
- **Rode nas páginas antigas também, não só na nova.** A varredura das 25 páginas publicadas encontrou o defeito em duas, uma delas no ar desde julho.
- Valide o guarda revertendo a correção: se o script não acusar, o guarda não serve.
## Portão de lint declarado, não herdado (01/09/2026)
O CI instalava `ruff` e `black` sem versão fixa e o projeto não declarava conjunto de regras. Resultado: toda release nova do ruff mudava o portão sem que uma linha de código mudasse, e a main ficou vermelha com 638 achados que não existiam no dia anterior.
- `pyproject.toml` agora declara `[tool.ruff.lint] select`. O CI fixa `ruff~=0.16.5` e `black~=26.3.1`.
- **`N999` fica de fora por decisão consciente**, e não por conveniência: a regra exigiria renomear todo script, e o projeto adota `kebab-case` por convenção documentada neste arquivo. Regra que contraria convenção declarada do projeto sai do conjunto, com o motivo escrito ao lado.
- Os 638 achados foram corrigidos, não silenciados: 601 por `ruff --fix` e `--unsafe-fixes`, 9 à mão. `enumerate` com índice descartado virou laço simples, e os três `B023` passaram a fixar a variável de laço no argumento padrão.
- **Prova de que o fix automático não mudou comportamento:** regenerar `mg_082026_camada2.json` antes e depois devolve JSON idêntico, e os 111 testes seguem passando. Faça essa comparação sempre que aplicar `--unsafe-fixes`.
- `docs/pnad.html` estava fora de sincronia com `docs/index.template.html`, com metatags OG editadas direto no HTML gerado. Regenerar recuperou seis metatags e não perdeu nenhuma. Reforça a regra: página gerada por script se edita no template.
## Índice dos carregadores (método da casa, atlas estaduais, 01/09/2026)
Comparar 41% de um senador com 6% de um deputado estadual não diz nada, e comparar volume bruto leva à conclusão errada. A régua correta normaliza cada nome pela própria média estadual e compara com o topo da chapa na mesma cédula. Reprodução: `python3 scripts/mg-082026-camada2.py`, que escreve `docs/assets/mg_082026_camada2.json` e `derivados/carregadores-municipais.csv`.
- **Fórmula.** `indice = 100 * (cand_municipio / cand_estado) / (presidencial_1T_municipio / presidencial_1T_estado)`, sobre votos válidos do próprio cargo. Cem significa render o mesmo que o topo da chapa rendeu ali.
- **Use o 1º turno presidencial como denominador**, não o 2º. O 2º turno já consolidou voto útil e infla artificialmente a base de comparação. Em MG a escolha muda o resultado do Cleitinho de 8,17 para 2,03 pontos abaixo de Bolsonaro.
- **Achado que derruba o lugar-comum de MG 2026:** Cleitinho fez 41,33% e Bolsonaro 43,36% no mesmo dia e na mesma urna. Ele não é um puxador maior; é um puxador **complementar**. Rende acima no Oeste (índice 130), Central Mineira, Jequitinhonha, Mucuri e no cinturão do minério, e abaixo no Triângulo, Sul e região metropolitana, que já eram de Bolsonaro. Nikolas é o inverso: amplifica base (pico em Nova Serrana, onde Bolsonaro fez 66,8%) e só abre fronteira na periferia metropolitana.
- **Sempre publicar os três limites junto:** não é transferência, não é pessoa, não é previsão. Cargos, cédulas e incentivos são diferentes.
- **Engler é fenômeno intramunicipal.** No município a leitura satura; dentro de BH a zona eleitoral ainda é grossa demais (índice de 67 a 115 em 18 zonas). Bairro exige `votacao_secao_<ano>_MG.zip` cruzado com `eleitorado_local_votacao_<ano>.zip`.
## Corredores de campanha (método da casa)
Agrupar municípios por base econômica, imprensa e formato de encontro possível, e não por mesorregião do IBGE. Sete corredores em MG. Para cada um: pauta extraída da imprensa local com link, quem tem base eleitoral medida em 2022, quem sobe no palanque, formato de evento e o que não dizer.
- **A convergência que decide o alvo:** procure o corredor onde (a) o topo da chapa ficou abaixo da média, (b) os carregadores ficam acima, e (c) existe pauta material com valor, devedor e destinatário. Em MG isso é o Quadrilátero Ferrífero, com a cobrança de R$ 17,7 bilhões de CFEM à Vale, R$ 3,2 bilhões destinados a municípios mineiros, e seis das doze cidades tendo trocado de lado em 2022.
- **Âncora regional é medida, não suposta:** parlamentar eleito cuja votação nominal de 2022 se concentra na mesorregião. Onde não existe âncora, diga: no Jequitinhonha o único com domínio é do PT, e no Mucuri e na Central Mineira nenhum eleito tem base concentrada.
- **Publique o corredor que contraria a própria tese.** Em MG é o Corredor da Produção, 13,85% do eleitorado, onde os três carregadores rendem abaixo do topo da chapa.
## Atlas de São Paulo (método da casa, 05/09/2026)
Reprodução: `python3 scripts/sp-092026-camada2.py` depois dos quatro scripts `sp-092026-*` já existentes, e `python3 scripts/sp-092026-build.py`. A camada 2 escreve `docs/assets/sp_092026_camada2.json` e `derivados/carregadores-municipais.csv`; toda figura é SVG gerado em Python com os dados embutidos na página.
- **Prior empírica em vez de prior ideológica.** Quando um instituto cruza o voto anterior com a intenção atual (Atlas p. 19 e 23: voto de 2022 para governador contra a Presidência de 2026), esse cruzamento vira a prior do IPF de todos os institutos. Tarcísio 2022 dá Flávio 90,7, Lula 2,3 e não escolha 7,0; Haddad 2022 dá Lula 96,8. Só o vazamento agregado sobrevive à troca da prior: Datafolha 14,0% e Atlas 13,2% do eleitor de Tarcísio no 2º turno não votam Flávio. O destino diverge por método: presencial vira voto em Lula (+7 sobre Haddad), digital vira branco e nulo (+5,7).
- **O vão por recorte.** Mesma amostra, duas perguntas de 2º turno (estadual e presidencial): a diferença Tarcísio menos Flávio dentro de cada recorte é teto endereçável, não previsão. Em SP os maiores vãos são ensino superior (10,9), 25 a 44 anos (11,1 e 10,7), RM e Santos (9,9) e homens (9,5). O recorte que decide é o antipetista e antibolsonarista: Tarcísio 51,9, Flávio 8,6, não escolha 54,9. O eleitor de Rodrigo Garcia em 2022 (4,3 milhões, 18,4%) dá 36,5 a Tarcísio, 25,0 a Flávio e 31,9 a Cury no 1º turno.
- **Reponderação por renda com sinal oposto entre métodos.** O Datafolha é 14,7 pontos mais pobre que a PNAD na faixa até 2 SM e quase não se move (54 × 35 vira 55,3 × 35,6), porque a não escolha dos pobres é 20% contra 6% dos ricos. A Atlas, também mais pobre que a PNAD, perde a liderança de Flávio (46,8 × 43,3 vira 45,1 × 44,5) porque nela a direita é mais forte entre os pobres, o inverso de Quaest e Datafolha. Publicar o achado contrário à tese com o mesmo destaque. Controle reprovado e declarado: Quaest p. 79, Flávio recompõe 32,3 contra 30 publicado.
- **Índice dos carregadores em SP.** Tarcísio fez 42,32% e Bolsonaro 47,71% no 1º turno de 2022 porque Garcia levou 18,4%; o governador rende acima do topo no Porto (107), Aeroespacial (105) e Tecnologia (104), e abaixo na capital e no ABC (97). Marcos Pontes (49,68%) é o único nome da direita acima do topo em todo o estado. Derrite (1,05% como deputado) tem índice 434 em Sorocaba e 37 no Porto: geografia de base, não teto.
- **Nove corredores**, declarados no script com lista de municípios; âncoras são eleitos de direita com ao menos 40% da votação dentro do corredor. A regra de convergência aponta metrópole (trem, PCC, tarifa) e Baixada (Tecon 10 adiado nove vezes). Toda notícia tem veículo, data e link conferidos no próprio veículo; Correio Popular, A Tribuna, DGABC e InvestNews bloqueiam o fetch e ficam fora quando a data não pode ser confirmada.
- **A urna de 2022 não separa Tarcísio de Bolsonaro.** No 2º turno, mesmo universo, 55,27 × 55,24 no estado e menos de um ponto em toda cidade: Tarcísio ficou à frente em 597 municípios por 84.771 votos somados. Comparar 1º turno de governador com 1º turno de presidente é erro de universo (Garcia levou 18,4%). O eleitor de Tarcísio que não é de Flávio é fenômeno do mandato, e só as pesquisas de 2026 o medem.
- **Estoque localizado.** Fatia de cada eleitorado de 2022 que vota Tarcísio e não vota Flávio, medida pela Atlas (p. 14 e 23) e aplicada ao voto municipal do TSE: 4,7% dos eleitores de Tarcísio no 1º turno, 1,8% dos de Haddad, 11,5% dos de Rodrigo Garcia; pelo 2º turno, 6,3% e 2,6%. Dá 1,11 e 1,13 milhão de votos, consistentes, metade do vão da Atlas. A densidade segue o voto de Garcia (Olímpia 6,8%, Cruzeiro 6,5%). Publicar como estimativa e dizer que branco, nulo e abstenção de 2022 ficam sem endereço.
- **Real Time entra com dois laudos** (governo SP-01347 e Presidência BR-06537, o segundo hospedado pelo Poder360): 54 × 36 e 44 × 49 na mesma amostra, vão de 10 pontos, o maior dos quatro; 19,6% do eleitor de Tarcísio não vota Flávio, 11,9% com Lula pelo IPF. Renda 31/39/30: reponderada, a direita ganha (17 para 19,7 no governo).
- **Série reponderada só onde há cruzamento por onda.** Quaest publica renda do 2º turno em três ondas: efeito de −0,9, −1,1 e −1,3 ponto, estável. O Datafolha só tem anexo em agosto; o PDF de julho no Poder360 é a matéria. Não inventar série com pesos de outra onda sem declarar (as bases de agosto recompõem abril e julho da Quaest com resíduo de 0,3).
- **Sankey de três níveis (governador 1º turno, presidente 1º turno, presidente 2º turno).** Estágio 1 com prior composta pela origem de 2022 (Atlas p. 10 e 19, pesos do TSE); estágio 2 como cubo origem × via × destino com prior condicionada à origem (eleitor de Tarcísio 2022 na terceira via: 67% Flávio, 0% Lula; eleitor de Garcia: 47% Lula), ajustado às células do estágio 1 e à margem do 2º turno. Nunca usar Markov (independência dentro do intermediário): infla o caminho para Lula. Resultado em SP: o voto de Tarcísio que chega a Lula é direto (já vota Lula no 1º turno: 5,7 de 6,5 na Atlas); a terceira via devolve dois terços a Flávio e manda um terço ao nulo. A hipótese "Renan leva voto de Tarcísio a Lula" não passou.
- **Lembrança de voto não é pesquisa antiga.** A Atlas de agosto de 2026 pergunta o voto de 2022 e cruza com 2026; Garcia aparece só como origem. Escrever sempre "voto declarado de 2022 na pesquisa de 2026", senão o leitor entende que há uma pesquisa de 2022.
- **Prior do estágio 1 no Sankey de três níveis: linha própria, não composição.** Misturar origens pela composição do eleitorado de 2026 (Atlas p. 10) tratava o não votante de 2022 que hoje vota Haddad como o não votante médio (23% Flávio) e criava fluxo Haddad-Flávio. Regra: Haddad para Flávio é zero estrutural (medido: 0,0 na p. 19); Tarcísio para Lula existe e é pequeno (0,5% no 1º turno, 2,3% no 2º, p. 19 e 23). Com isso a retenção dos três níveis (88%) fecha com a dos dois níveis (87%).
- **Pontes é carregador do centro-oeste paulista**, não da metrópole: +12,3 pontos sobre Bolsonaro em Bauru (cidade natal), +7,5 na região, acima em Jaú, Ourinhos, Botucatu, Marília, Sorocaba, Itu, Guaratinguetá e Caçapava; igual ou abaixo na capital, Santana de Parnaíba e Baixada. Cruzar excedente de Pontes (≥ 4 pp) com estoque (≥ 4,9%) dá a lista curta de agendas conjuntas. Biografia (ITA, DCTA, MCTI) só vira pauta nos corredores Aeroespacial e da Tecnologia.
- **Companhia de jornada por corredor** é campo obrigatório da pauta (`companhia`): quem sobe com Flávio, com o índice ao lado, e quem não deve subir porque rende abaixo do topo ali.
- **Thread em cards 1:1 (SP, 05/09/2026).** `scripts/sp-092026-thread.py` gera nove cards quadrados (`aspect-ratio:1/1`, largura de trabalho 1080 px, tipografia em `cqw`, empilha abaixo de 720 px) com o gráfico ocupando a metade inferior e o post copiável embaixo, de 950 a 1.500 caracteres. Todo número vem do JSON da camada 2; o script falha se algum post sair da faixa ou se houver travessão. Arco: tese, cinco pontos, limites (com o achado contrário), o que fazer, fecho. Rótulo de SVG sobre fita colorida precisa de retângulo escuro atrás: halo por `paint-order` não basta para o auditor de contraste.
- **Página pesada engana o painel de preview.** Prints com rolagem por `scrollIntoView` saem em branco em página de 860 KB; capturar por elemento com Playwright, como faz a auditoria de contraste.
## Agregador Arvor de reponderação por renda (método da casa, 10/09/2026)
**Rotas desde 09/10/2026.** O build gera em conjunto `reponderacao_pnad.html` (app do 2º turno), `reponderacao_pnad_1o_turno_2026.html` (arquivo do 1º turno e urna) e `reponderacao_pnad_log.html` (diário). Fontes em `reponderacao-paginas.py`, `reponderacao-simulador{,-view}.py` e espelho JS `reponderacao_simulador_motor.js`. Central de válidos: uma onda por casa na janela de sete dias, campo iniciado depois de 04/10, PNAD + propensão Nexus + hipótese de presença relativa F +5%; escolha posterior à urna, sem probabilidade de vitória validada. A série descritiva antiga permanece separada e pode incluir campo pré-eleição.
- Exibição na ordem Flávio × Lula e diferença F−L; os campos legados `gap_*` do JSON/CSV preservam L−F. Links `#sim=` guardam todos os controles e a versão; conservar snapshots publicados de dados e motores em `docs/assets/reponderacao_cenarios/`. O diário `analysis/reponderacao/log.json` mantém primeira incorporação no Git (sem confundir com divulgação/campo); `reponderacao-diario.py` acrescenta ondas e registra revisões por hashes nos próximos builds.
- Vox de 09/10, BR-09623/2026: relatório de 16 páginas em `data/originals/vox_102026_09/`, perfil 83,9/12,4/2,8/0,9 e nenhum voto por renda. Registro cita Censo 2022 sem tabela/variável/universo; pergunta 4 só diz “RENDA”. Não afirmar qual conceito gerou 83,89% nem reponderar sem as células. Conferência visual do PesqEle em `docs/fontes/vox_09102026/registro-conferencia.txt`; não é exportação original do questionário. Cards das três rotas em `social-card-reponderacao.py`, invocado pelo manifesto único.
A página `docs/reponderacao_pnad.html` reúne toda pesquisa nacional que publica o voto por faixa de renda e mostra o placar publicado ao lado do placar com a renda trocada pela régua da PNAD. É a estrela da casa em escala de série, e a home traz o gráfico resumido entre os marcadores `<!--FIG:reponderacao_home-->` e `<!--FIG:reponderacao_home_placar-->`.
- **Régua.** `python3 scripts/reponderacao-benchmark.py` lê uma vez `base_anual_visita1_labeled_npv.csv` (PNADC anual 2025, visita 1) e grava `analysis/reponderacao/pnad_2025v1_histograma.json`: histograma ponderado em caixas de R$ 10 do rendimento domiciliar (VD5001 efetivo e VD5007 habitual) a preços de abril de 2026, para pessoas de 16+ (peso V1032) e para domicílios (pessoa responsável). Qualquer corte de cartão de renda vira soma de caixas com interpolação linear; a régua de 2, 5 e 10 salários de 2026 devolve 35,4 / 39,2 / 16,9 / 8,4, igual ao já publicado.
- **Uma pesquisa, um JSON** em `analysis/reponderacao/pesquisas/<instituto>_<fim-do-campo>.json`: instituto, registro TSE, campo, n, método, fonte (PDF e páginas), `renda` (unidade `salarios_minimos` ou `reais_nominais`, `ano_referencia` do cartão, faixas com `max` e a última aberta, `bases` ou `amostra_pct`), `publicado` e `cruzamentos` por turno (`opcoes` e `linhas`, uma linha por faixa). Esqueleto: `python3 scripts/reponderacao-pnad.py modelo <Instituto> <AAAA-MM-DD>`; para achar as páginas de renda de um PDF, `python3 scripts/reponderacao-pnad.py paginas <arquivo.pdf>`.
- **Motor.** `python3 scripts/reponderacao-pnad.py calcular` recompõe o placar pelas bases do instituto (resíduo impresso; o teste falha acima de 1,5 pp), converte os cortes para reais de 2026-04 pelo salário mínimo do ano do cartão e pelo IPCA, lê a régua em três cenários (pessoas 16+ efetivo, principal; pessoas 16+ habitual; domicílios) e aplica `ajustado = publicado + (contrafactual - recomposto)`. Grava `docs/assets/reponderacao_pnad.json`.
- **Média Arvor (atualizada em 21/09/2026).** Média móvel retrospectiva de 7 dias, D-6 até D pela divulgação, publicada e reponderada: última onda elegível de cada instituto dentro da janela, peso igual entre casas. Sem divulgação conhecida ou sem pesquisa na janela, não imputar zero nem prolongar a média anterior. A média simples sem janela da última onda de cada instituto aparece separada. Nunca chamar de previsão: é sensibilidade sob régua comum.
- **Página.** `python3 scripts/reponderacao-build.py` gera o HTML a partir do JSON e injeta o gráfico e o placar na home. Fluxo completo para uma pesquisa nova: baixar o PDF em `data/originals/<instituto>_<MMAAAA>/`, criar o JSON, rodar `calcular`, rodar o build, rodar `pytest -q tests/test_reponderacao_pnad.py`, regenerar o card social e commitar.
- **Onde as íntegras estão (10/09/2026).** Quaest: `quaest.com.br/wp-json/wp/v2/media?mime_type=application/pdf`. Gerp: `gerp.com.br/relatorios/manifest.json` lista todos os PDFs, que baixam direto de `gerp.com.br/relatorios/<arquivo>`. Datafolha: `curl` funciona em `datafolha.folha.uol.com.br` (só o WebFetch é bloqueado); o PDF fica em `media.folha.uol.com.br`. Atlas nacional: aba "Exclusive Polls", host `cdn1.atlasintel.org`. PoderData e Nexus: Poder360. O registro do TSE mudou para o PesqEle Público (`pesqele-divulgacao.tse.jus.br/app/pesquisa/listar.xhtml`, JSF sem API); `divulgacandcontas` não tem mais a rota de pesquisas. Número `BR-` significa cargo federal, não amostra nacional: Paraná Pesquisas, Ipespe e Ipec só registraram amostras estaduais da corrida presidencial no período.
- **Quem cruza renda e quem não cruza.** Atlas e Real Time só cruzam o 1º turno nos relatórios arquivados; PoderData só cruza o 1º turno no PDF, mas também publicou o 2º por renda no gráfico da matéria de 17/09/2026; Gerp cruza o 1º em toda onda e o 2º em algumas; Futura nunca cruza; Vox Brasil cruza em duas ondas e o cruzamento não recompõe o placar (fica `ignorar` com a conta no `motivo`); MDA/CNT cruza os dois turnos em três faixas.
- **Perfil de renda do instituto é série, não constante.** A Atlas manteve o perfil de renda quase parado em quatro ondas (faixa até R$ 2.000 em 22,8 / 22,4 / 22,1 / 22,0) e mudou na de setembro, para 20,0, com a faixa acima de R$ 10.000 subindo de 13,6 para 16,2. Isso aproximou a amostra da PNAD e derrubou o desvio da primeira faixa de 5,10 para 3,08 pontos. Antes de atribuir movimento de voto a uma mudança de composição, faça a decomposição: aplique o perfil da onda anterior ao cruzamento da onda nova. Em setembro de 2026 a troca de composição alargou a diferença a favor de Lula em 1,09 ponto, ou seja, andou contra o candidato que subiu. O movimento estava dentro das faixas.
- **Camada interativa por cima do SVG, nunca no lugar dele (10/09/2026).** Os gráficos continuam desenhados em Python e completos no HTML; o JavaScript só acrescenta a ficha ao passar o ponteiro. Cada onda vira um `<g class="hit">` com área transparente de toque em volta de cada marcador, um halo que só aparece no hover e uma linha vertical de leitura. As fichas vão embutidas na página num `<script type="application/json" class="tips">`, então funcionam abrindo o arquivo do disco, sem rede. A folha e o script ficam em `docs/assets/reponderacao_tip.css` e `.js`, gerados pelo build e usados também pela capa. Se o script falhar, a página perde a ficha e não perde nenhum gráfico. Custo medido: 27 KB comprimidos.
- **Poder360 publica as íntegras.** Quando o relatório do instituto não traz o cruzamento por renda, a pesquisa entra no manifesto com `ignorar: true` e o motivo, e fica listada na página como não reponderável, sem número reponderado. Confira também gráficos publicados pelo instituto fora do PDF antes de concluir que o cruzamento não existe.
### Rodada de 08/10/2026
- Reproduzir com `python3 scripts/pesquisas-081026-renda.py`, `python3 scripts/reponderacao-pnad.py calcular --hoje 2026-10-08`, `python3 scripts/reponderacao-build.py --skip-home` e `python3 scripts/social-cards.py --only reponderacao_pnad`. Inventário e limites em `analysis/reponderacao/auditoria_20261008.json`.
- O novo painel presidencial de 2º turno do Datafolha usa `paginaId=216`, `ESTIMULADA-PRE-001` e barras com `date/value/option`, não `values`. O antigo `paginaId=100` continua devolvendo a onda de 03/10; não reutilizar sua resposta como atual. Os cruzamentos entram como `2t`, apesar do nome do código. Sem bases atuais, o perfil de 01/10 é hipótese explícita, inclusive nos rótulos e tooltips; a boa recomposição não confirma o perfil. O painel diz campo 6–7/10, a notícia e a agenda dizem 6–8/10; preservar a divergência até a íntegra.
- PoderData (BR-08134/2026): perfil atual 46/33/21 na p. 4, votos totais por renda na p. 9, controle por sexo na p. 7. Veritá divulgado em 05/10 tem campo anterior ao 1º turno e somente válidos confirmados; `publicado_validos` não vira `publicado` nem entra nas médias sem ajuste. A janela de sete dias ainda atravessa a eleição e inclui campos anteriores: não descrevê-la como média exclusivamente pós-1º turno.
## Atlas estadual e o vão estadual (método da casa, 16/09/2026)
Reprodução: `python3 scripts/estaduais-092026-tse.py`, depois `estaduais-092026-extract.py`, `estaduais-092026-data.py` e `estaduais-092026-build.py`. A thread sai de `superthread-092026.py` e a camada que entra nos dossiês nacionais, de `campanha-092026-camada.py`.
- **O vão estadual** é o método novo: melhor candidatura de direita ao governo do estado menos o voto do presidenciável, na mesma entrevista e no mesmo relatório. Não há reponderação nem modelo; os dois números saem da mesma tabela de campo. Em setembro de 2026 dá CE +33, BA +28, PE +25, PB +25, MA +24. Rótulo obrigatório: **teto endereçável, não previsão**, porque ACM Neto, Raquel Lyra e Ciro Gomes não são bolsonaristas.
- **O sinal precisa inverter em algum lugar, senão a medida é viés.** No Acre (−2) e em Rondônia (−6) o presidenciável tem mais voto que o candidato ao governo. Publicar isso com o mesmo destaque: o déficit é do Nordeste, não do candidato.
- Onde o instituto mede os dois segundos turnos na mesma amostra, use a régua turno contra turno, que é a mais limpa: PE +19, MG +9, RJ +9, SP +7, DF +2.
- **Os relatórios estaduais da Quaest são imagem.** O texto nativo traz só título e enunciado. A extração usa duas passagens de tesseract na mesma página, uma livre para os rótulos e outra restrita a dígitos, e **prefere o número que o próprio rótulo carrega** (`Lula (PT) 25 o`), porque a coluna isolada captura ruído de eixo. Mesmo assim a leitura de máquina é localizador de evidência: a transcrição publicada é feita página a página, e o teste compara as duas.
- Baixe os PDFs pelo `wp-json` do instituto (`quaest.com.br/wp-json/wp/v2/media?mime_type=application/pdf&per_page=100`). Em agosto e setembro de 2026 saíram quinze estaduais; **Piauí e Sergipe não têm pesquisa publicada** e entram no dossiê só com dado do TSE.
- **Onde está o voto é pergunta de TSE, não de pesquisa.** 54 municípios de 1.794 concentram metade do voto bolsonarista do Nordeste, e os nove maiores estoques das duas regiões são capitais. Manaus tem 692.580 votos de Bolsonaro de 2022, mais que Fortaleza (633.009) e uma vez e meia Salvador (451.131).
- **O achado que contraria a tese e que precisa continuar publicado:** o MATOPIBA soma 38 municípios, 344.366 votos e 1,1 milhão de eleitores, metade do que Manaus entrega sozinha. O cerrado rende doação, estrutura e pauta; não rende volume.
- Agenda de campanha entra com veículo, data e link conferidos no próprio veículo, e a comparação é com estoque de 2022: Salvador tem 5,4 vezes o voto de Vitória da Conquista; Santa Cruz do Capibaribe, único município de PE que Bolsonaro venceu, tem 27 mil contra 433 mil do Recife.
- O capítulo de rota é **juízo editorial declarado**, sem datas, com o número e a página ao lado de cada movimento.
## Auditoria de contraste: quatro defeitos do próprio guarda (16/09/2026)
A varredura de uma página de 32 mil pixels expôs quatro erros no `scripts/contrast-audit.py` que inventavam reprovação. Todos corrigidos, e o guarda foi validado numa página de teste com um caso que passa, um que reprova por pouco e um invisível.
1. `bounding_box()` do Playwright é relativo à janela. Depois da captura em faixas a página fica rolada e todo recorte sai deslocado. Agora a caixa vem de `getBoundingClientRect() + scrollY` em JavaScript.
2. `full_page=True` com `clip` não escapa do limite de 16.384 px do Chromium: o recorte incide sobre uma captura já truncada. Agora a janela é encolhida para a altura da faixa e cada faixa é fotografada rolando.
3. `scroll-behavior: smooth` transforma cada rolagem em animação e a faixa seguinte era fotografada no meio do caminho. Solte o `scroll-behavior`, o `position: sticky` e o `loading="lazy"` antes de fotografar.
4. Texto dentro de `<details>` fechado tem caixa de layout no Chromium e não é pintado. Medir o pixel ali lê o que estiver desenhado por baixo. Agora esses elementos saem da medição.
- O que reprova na varredura volta para uma **medida exata**, rolando até o elemento e fotografando só a caixa dele, dentro da janela. A costura é só o filtro.
- Paleta corrigida nesta rodada: verde-petróleo de texto e de barra passou de `#0f8f86` para `#0c7a72`; vermelho de barra na thread, de `#e0483a` para `#d13c2e`; vermelho de texto pequeno sobre papel, `#b02f21`; cinza, `#5f6773`; roxo, `#6b4a92`.
## Super thread (16/09/2026)
Sete cards 1:1 com cerca de **2.000 caracteres por post**, acima do padrão de 950 a 1.500 das threads anteriores, por pedido explícito: cada card carrega um dossiê inteiro. Arco: abertura com as quatro pesquisas sob a mesma régua, um card por instituto (Datafolha, BTG/Nexus, Quaest, CNT/MDA), um para o atlas estadual e um de fecho com a rota. O card do instituto que contraria a tese (Quaest, amostra mais rica que o país) é obrigatório e vem com o rótulo `contraprova`.
## Materiais recebidos de terceiros
Relatório de terceiro, mapa recebido e anexo sigiloso não ficam no repositório público, nem mesmo em pasta ignorada dentro dele. Vão para o cofre da campanha correspondente, em `~/arvor/campanhas/<candidato>/data/raw/`, que é ignorado pelo git daquele repositório.
- O manifesto público continua registrando **nome, tamanho e SHA-256** com o caminho `cofre-externo/<arquivo>` e a nota de que o arquivo não é redistribuído. Isso preserva a conferência de integridade sem publicar documento alheio.
- `scripts/mg-082026-data.py` lê esse cofre por `MG_FONTES_RECEBIDAS` e segue funcionando se o arquivo não estiver presente, apenas avisando.
## Auditoria de contraste em página longa (correção de 01/09/2026)
`page.screenshot(full_page=True)` no Chromium não devolve captura acima de aproximadamente 16.384 pixels de altura: o excedente volta branco. Em dossiê longo isso fazia `scripts/contrast-audit.py` acusar dezenas de reprovações falsas no rodapé, com texto claro sobre fundo "branco" que na verdade é escuro. O script agora fotografa em faixas de 8.000 pixels e costura. Antes da correção o atlas de MG acusava 441 reprovações; depois, 69 reais, e zero após a correção da paleta.
- Paleta que passa em WCAG AA sobre papel da casa: `--muted` em `#535b54`, dourado de texto pequeno em `#7d5b00`, vermelho sobre fundo escuro em `#f0a79c`, rótulo de barra com chip de fundo claro e texto `--ink`.
- Rode a auditoria em toda página publicada, não só nas novas, e trate reprovação herdada como dívida a pagar.
## Regras de escrita (valem para todo texto público da casa)
- **Travessão é proibido.** O caractere `—` não entra em dossiê, thread, card, home, minuta ou legenda. Não trocar por `–` nem por ` - `: reescrever a frase com vírgula, dois-pontos, ponto e vírgula, parênteses ou ponto final. Aposto duplo entre travessões vira oração à parte. O hífen de palavra composta (`pós-estímulo`) e o `–` de intervalo numérico (`22–24/07`, `45–59 anos`) continuam válidos.
- Verificar antes de publicar: `grep -c "—" docs/*.html` precisa devolver zero.
- Frase curta, verbo forte, zero adjetivo decorativo. O número carrega a força; a indignação, não.
- Abrir cada bloco pela informação mais forte, sem preâmbulo. Cortar muleta (`é importante notar`, `vale dizer`, `ou seja` repetido).
- Nada de hashtag, emoji ou linguagem de engajamento em thread.
## Editorial Position & Evidence Discipline
- Internal collaboration may be frank, politically explicit and use strong language. Public work must remain fully professional, precise, reproducible and legally defensible.
- The project owner's political framing is that the Lula government represents a communist/authoritarian project, that censorship and institutional overreach are central risks, and that Lula's relationship with Daniel Ortega and the Nicaraguan regime deserves sustained scrutiny. Preserve this as the author's editorial position and research agenda, not as an automatically established empirical fact.
- The project owner also regards orders and conduct attributed to Supreme Federal Court Justice Alexandre de Moraes as censorship and institutional overreach. Preserve this as an explicit editorial position and priority for documentary investigation, not as a substitute for proving the scope and effect of each specific act.
- When covering Moraes, the STF or alleged censorship, identify the exact decision, case or inquiry, date, legal basis, target, measure imposed, duration, secrecy status, practical effect, available appeal or review, and the strongest primary and international sources. Distinguish removal orders, account blocking, prior restraint, confidentiality, criminal investigation and platform regulation instead of collapsing legally different acts into one label.
- Public writing may be opinionated and morally clear, but it must remain calm, accurate and professional. Prefer quotations from decisions, verifiable timelines and explicit legal reasoning over adjectives or personal attacks. State worldwide criticism or recognition only with attributable sources.
- Treat legal and reputational resilience as part of the strategy: every contentious sentence should preserve its meaning under hostile quotation, identify whose conclusion it is, and avoid claiming more than the underlying record proves.
- Do not minimize documented authoritarian conduct, censorship, electoral interference, foreign-regime alignment or institutional abuse. Investigate concrete acts, dates, decisions, legal instruments, public statements, financial ties and consequences.
- For publication, replace broad labels with the strongest provable formulation supported by primary sources. Clearly separate:
- verified fact;
- inference supported by evidence;
- editorial judgment;
- hypothesis or allegation still requiring proof.
- Claims such as “regime”, “censorship”, “terrorism”, “cancellation of elections”, “dictatorship” or “fraud” require exact attribution and documentary support. Never weaken a serious case by publishing a broader accusation than the evidence sustains.
- Spiritual language such as “principados e potestades” may express the owner's internal moral motivation. Public analytical products should translate that motivation into truth-seeking, courage, due process, human dignity, constitutional limits and verifiable evidence.
- The project is not neutral between truth and falsehood, but it is methodologically impartial: use the same evidentiary standard for allies, adversaries and favorable or unfavorable polls.
- Core maxim: the truth must be exposed without euphemism, and every public claim must be strong enough to survive hostile factual, statistical and legal review.
## Atualização do agregador de 17/09/2026
- Reproduzir com `python3 scripts/pesquisas-170926-renda.py`, `python3 scripts/reponderacao-pnad.py calcular` e `python3 scripts/reponderacao-build.py`. Os quatro PDFs ficam em `data/originals/{atlas,poderdata,gerp,futura}_092026_17/`; URLs, páginas, tamanhos e SHA-256 ficam nas fichas e em `analysis/reponderacao/auditoria_20260917.json`.
- Não limitar a busca ao PDF: o PoderData publica o cruzamento Lula × Flávio por renda na imagem `pd-pesquisa-eleitoral-intencao-presidente-16-set-2026-05-scaled.png` da matéria. Linhas Lula/Flávio: 50/39, 35/52, 42/50; perfil 46/33/21 confirmado no PDF e no gráfico de perfil. Recomposição por renda 43,37/45,60; por sexo 44,42/45,52; placar 44/46. Só os dois candidatos são ajustados, sem inventar não escolha por faixa.
- Atlas desta onda usa perfil 17,8/12,4/27,0/26,3/16,5 (p. 5), cruzamentos pp. 17–18 e nenhum cruzamento de 2º turno. Gerp cruza os dois turnos nas pp. 15 e 23, com perfil ponderado da p. 8; as contagens n das tabelas não são os pesos. Futura tem perfil na p. 7, mas nenhum voto por renda.
- A página mostra as quatro publicações, inclusive as não reponderáveis, e mantém a média publicada e ajustada sobre o mesmo conjunto de pesquisas em cada turno. A cobertura é gerada em `scripts/reponderacao-cobertura.py`.
## Atualização do agregador de 21/09/2026
- Reproduzir com `python3 scripts/pesquisas-210926-renda.py`, `python3 scripts/reponderacao-pnad.py calcular` e `python3 scripts/reponderacao-build.py --skip-home`. O último parâmetro preserva `docs/index.html` e `docs/assets/reponderacao_home.svg`. O gerador visual foi dividido em `scripts/reponderacao_vista/`, com módulos abaixo de 1.000 linhas.
- Fontes, tamanhos e SHA-256: `analysis/reponderacao/fontes_20260921.json`. Auditoria e controles independentes por renda e sexo: `analysis/reponderacao/auditoria_20260921.json`. Nexus nacional: campo 18–20/09, BR-00485/2026, renda nas pp. 34/81 e perfil na p. 137. Real Time SP, PR, AC e MG são amostras estaduais, fora da média nacional; o PDF do Paraná indica divulgação em 16/09, embora a matéria seja de 21/09.
- Palver onda 3: campo 15–18/09 conforme PDF pp. 16/22, BR-00860/2026. Continua usando PNADC 2024 visita 5 (VD5007), região × voto de 2022 e, no método v2, filiação partidária. Os alvos de renda da p. 18 são metas, não perfil observado. Cruzamentos visuais pp. 32/40; publicar o ajuste como sensibilidade marginal condicionada à aderência a essas metas.
- O GitHub Palver publica código e alvos, não microdados com pesos. O PDF da onda 3, p. 6, promete a base individual depois do segundo turno. O snapshot `7523cf14f0095f088ac9680e9c64a9923289fdb1` só contém configurações v1 das ondas 1/2; foi arquivado em `data/originals/palver_092026_21/.repositorio/` (oculto para não coletar testes de terceiros).
- A Palver substituiu a onda 2 v1 pela v2, BR-06100/2026. O PDF novo traz os placares revisados nas pp. 30/37, mas não o cruzamento de renda revisado. Preservar o manifesto original com `ignorar: true`; não reaplicar suas linhas antigas ao topline novo nem contar a mesma amostra duas vezes.
- O comparativo de metodologia em `reponderacao_pnad.html#comparar-metodos` é gerado por `scripts/reponderacao-metodos.py`, a partir de uma ficha por onda em `analysis/reponderacao/metodologias/`. Fontes e questionários do TSE ficam em `docs/fontes/reponderacao_metodologias/`; `scripts/reponderacao-registros.py --export-only` reproduz os excertos locais com conferência de hashes. A nota é de qualidade documental, não certificação AAPOR nem precisão eleitoral. O sinal relativo de `scripts/reponderacao-efeito-casa.py` usa votos válidos, datas centrais próximas e uma onda por outro instituto; não prova alinhamento partidário.
- Registros consultados em 21/09/2026: Atlas já declara renda PNADC 2025 e escolaridade PNADC 2026, sem visita/trimestre; Futura declara escolaridade PNADC 2º tri/2026, mas renda Censo 2010; PoderData e Real Time também citam Censo 2010 para renda. Real Time registra abordagem mista, mas o relatório nacional descreve entrevistas telefônicas humanas. Não transportar métodos antigos nem confundir plano registrado com execução comprovada. Palver continua na PNADC 2024 visita 5; o questionário atual separa elegibilidade e comparecimento em 2022, portanto a recodificação do código público v1 não pode ser atribuída automaticamente à onda 3.
## Datafolha completo de 21/09/2026
- Reproduzir com `scripts/datafolha-21092026-extract.py`, `scripts/datafolha-21092026-audit.py` e `scripts/datafolha-21092026-build.py`. BR-04029/2026: campo 15–17/09, divulgação 17/09, PDF completo publicado em 21/09. A chegada do PDF encerrou a espera da capa; `reponderacao-build.py` pode atualizar a home nesta rodada. `fonte.relatorio_completo` marca a chegada documental sem alterar a data da pesquisa.
- São 13 tabelas com três blocos; o terceiro agora inclui preferência partidária. A ordem das candidaturas menores mudou: mapear os nomes antes de associar colunas. Bases de renda 992/655/266; segundo turno por faixa Lula 53/41/32 e Flávio 37/50/60. Sensibilidade principal 42,951 × 47,332. O delta ancorado pode gerar resíduo negativo para candidatura arredondada a zero; não apresentar esse resíduo como intenção de voto.
- O Sudeste nacional é Lula 42 × Flávio 46, não liderança de Lula. Estaduais do mesmo instituto, campo 8–10/09: SP 42 × 47, RJ 41 × 49, MG 46 × 45; PDF conjunto pp. 58/76/94. ES não localizado. Os três estados cobrem 95,49% do eleitorado regional no snapshot TSE de julho; média condicionada 42,83 × 46,89. Comparar primeiro com o Sudeste nacional do mesmo campo (42 × 47), sem deduzir o voto capixaba da diferença entre amostras.
- A projeção conjunta voto × renda × região × sexo tem 128 células e posto linear 32. Dois certificados contínuos preservam as mesmas margens não arredondadas compatíveis com a p. 42, mas divergem na associação oculta. São exemplos de não identificação dessa projeção, não microdados individuais recuperados nem reconstrução de todas as perguntas. Código em `datafolha-21092026-identificacao.py`.
- O anexo territorial soma 2.001 entrevistas em 302 setores e 126 códigos municipais; relatório declara 125 municípios. Rodapé territorial: 14–16/09; registro/relatório: 15–17/09. Registrar como discrepâncias documentais. No parser, `SE` pode significar região Sudeste ou UF Sergipe: validar também a posição da sigla da UF para não atribuir Sergipe ao Sudeste.
- Comparação entre governador e presidente em SP/MG (campo 8–10/09): reproduzir com `scripts/datafolha-21092026-governadores.py` antes do gerador do dossiê. Os PDFs oficiais de governador têm 13 tabelas em SP e 14 em MG; todas foram extraídas. Segundo turno: Tarcísio 56 × Haddad 35, Lula 42 × Flávio 47; Cleitinho 59 × Patrus 24, Lula 46 × Flávio 45. Diferença entre cargos não prova inconsistência. Dentro da preferência pelo PT, Lula/Cleitinho = 97/34 e Lula/Tarcísio = 95/19: limites de Fréchet exigem interseções mínimas de 31%/14% do recorte, ou 30%/13% admitindo arredondamento, **condicionadas aos mesmos respondentes e pesos finais**. Não confundir preferência partidária com voto presidencial ou escala petista/bolsonarista. Cobrar a matriz governador × presidente, bases e pesos; não inventar o cruzamento.
## Camada Sudeste do Datafolha de 21/09/2026 (método da casa)
- Reproduzir com `scripts/datafolha-21092026-sudeste.py`, `datafolha-21092026-cobertura-sudeste.py`, `datafolha-21092026-governadores.py`, `datafolha-21092026-build.py` e `datafolha-21092026-thread.py`. O capítulo vive em `datafolha-21092026-sudeste-view.py` e `-sudeste-figuras.py`; os dois scripts maiores passaram de 1.000 linhas e o próximo acréscimo pede divisão.
- **O Datafolha publica a transferência governador × presidente em texto corrido** do relatório presidencial estadual (SP p. 4, RJ pp. 12–13, MG pp. 20–21): 13 linhas medidas. Os anexos de tabelas não trazem voto de outro cargo como coluna, então a varredura precisa ler a prosa, não só as tabelas. Linhas publicadas entram fixas no IPF; o resto leva a faixa de Fréchet ao lado. SP não tem linha medida no par 2º turno × 2º turno.
- **Piso medido: estimativa de 2º turno nunca fica abaixo de medição de 1º turno na mesma amostra.** Erro corrigido em 21/09/2026: o IPF ideológico dava Tarcísio para Lula 2,23 pp no 2º turno enquanto a p. 4 mede 12% de 49, ou 5,88 pp, já no 1º. Onde o par alvo não tem linha publicada mas existe linha `gov × presidente 1T`, a célula sai de cadeia de três níveis (`scripts/datafolha-21092026-cadeia.py`): estágio 1 com as linhas medidas fixas, estágio 2 como cubo origem × via × destino com prior condicionada à origem e termo de interação declarado, ajustado às células do estágio 1 e à margem publicada. Nunca Markov. Retenção de quem já escolheu um finalista no 1º turno: 0,98, sensibilidade de 0,93 a 0,99, e ela entra fixa no cubo, então o piso de cada célula é exato. O par `gov2_pres2` usa a cadeia `gov1 → gov2 × pres2`, com a fidelidade de base do 2º turno estadual (0,98) e a condição necessária conferida: as duas candidaturas crescem do 1º para o 2º turno nos três estados. Quarto estado de célula, além de medida, limitada e estimada: **`ancorada`**, com `piso_medido_pp`, página de origem e retenção gravados, e a fita do Sankey em textura pontilhada.
- Efeito medido: SP Tarcísio para Lula 2,23 vira 7,00 pp no par 1º × 2º e 4,02 vira 7,20 no 2º × 2º; MG Cleitinho 2T para Lula 10,18 vira 13,92 pp, 30% de todo o voto de Lula no estado; RJ Ruas 2T para Lula tinha amplitude de 0,80 a 5,46 pp conforme a prior e fica em 1,77 a 2,98. Vazamento total de SP no 2º × 2º passa de 17,11–23,53% para 19,15–22,96%.
- **Linha medida em subamostra pequena também tem intervalo, e o dossiê publica.** Base ponderada, IC95 sob amostragem simples e com efeito de desenho plausível de 1,5 (Kish com ~6 entrevistas por setor e ρ=0,10), e o valor em pontos do eleitorado. Ruas para Lula no 2º turno é 7% de 304 entrevistas, 3,5 a 10,5 com deff, zero fora, e vale 1,77 ponto: medição não se sobrescreve por prior, por mais óbvia que a prior pareça. Patrus para Flávio, 3% de 157, tem o zero dentro do intervalo, e isso é publicado com o mesmo destaque. Confira também a coerência entre turnos: onde o instituto mede os dois, o valor de 2º turno não pode ficar abaixo do de 1º vezes a retenção. Nas 10 linhas do Sudeste todas passam, e a mais apertada é Patrus para Flávio, com folga de 0,06 pp.
- **A fita do Sankey não tem espessura mínima**, e há teste que reprova se alguém criar uma: fluxo de 1,77 ponto precisa aparecer pequeno, senão o desenho sugere transferência grande onde não há.
- **A conta na tela em cada estado**: Lula 46 em MG exige voto de Cleitinho? Pela aritmética não, fora dele há 63 pontos; pelo medido sim, 25% de 37 = 9,25, um em cada cinco votos de Lula. Com Cleitinho, Lula precisa de 44% do que resta; sem ele, de 68%. Em SP a mesma conta usa o piso do 1º turno: 5,76 pontos medidos, 7,00 ancorados, um em cada seis ou sete votos de Lula, e sem Tarcísio a exigência sobe para 90% do resto.
- O capítulo da transferência saiu de `datafolha-21092026-sudeste-view.py` para `datafolha-21092026-sudeste-view-transferencia.py` quando o arquivo passou de mil linhas.
- Sudeste são três problemas: SP Tarcísio 56 × Flávio 47 (vão +9), MG Cleitinho 59 × Flávio 45 (+14, com 25% do eleitor de Cleitinho em Lula), RJ invertido, Flávio 49 × Ruas 34. Senado tem duas vagas nos três estados e o melhor nome de direita fica 22, 25 e 27 pontos atrás de Flávio.
- Recorte Sudeste do nacional (42 × 46, n=838) e média estadual ponderada pelo TSE (42,83 × 46,89) não se separam: IC95 da diferença de −6,98 a +7,09. O ES implicado por subtração não é publicável. ES entra pela Real Time Big Data (ES-01967/2026), em bloco separado, sem republicar o PDF.
- No anexo presidencial estadual, Situação A é o cenário COM Marçal e B o SEM. A casa usa a B; a A fica guardada em `first_president_com_marcal`.
- Figura larga ganha variante empilhada para telas abaixo de 720 px, as duas embutidas e trocadas por CSS, sem JS. Arquivo PDF novo em `docs/fontes/` exige `git lfs push origin main` antes do `git push`.
- A busca do UOL devolve vazio no navegador embutido; a da Folha funciona com filtro de período e forneceu 72 dos 76 itens.
## Integração do Palver Explorer
- `python3 scripts/palver-explorer-integrate.py` integra as tabelas arquivadas ao agregador; depois execute `reponderacao-pnad.py calcular --hoje 2026-09-21` e `reponderacao-build.py`. O gerador antigo `pesquisas-210926-renda.py` reaplica essa integração ao final para não restaurar transcrições superadas.
- Os painéis Palver mostram três ondas e quatro versões: 09/08, 07/09 v1, 07/09 v2 e 18/09. A v1 substituída é só histórico; os cenários principais do Explorer de 07/09 contêm Marçal e ficam fora da média do primeiro turno. A alternativa sem Marçal do PDF antigo permanece no manifesto arquivado, sem ser confundida com o cenário do Explorer.
- O perfil ponderado de renda é recuperado por sistema linear de posto completo e validado pelo n efetivo. Usar os percentuais exatos do Explorer como âncora; preservar os placares inteiros do PDF em `publicado_pdf`. Histórico completo em `docs/assets/palver_explorer_historico.json`; os n de grupo são contagens brutas e não podem ser usados como pesos de composição.
## Fontes interativas recorrentes para reponderação
- **Palver Explorer:** https://www.palver.com.br/survey/explore . Publica versões de ondas, cruzamentos por renda e outras estratificações, percentuais com precisão, contagens brutas e n efetivo. Consultar primeiro o acervo e os scripts `palver-explorer-*`; diferenciar contagens brutas de composição ponderada e versões de uma mesma amostra.
- **G1, Quaest presidencial, 1º turno:** https://g1.globo.com/politica/eleicoes/2026/pesquisa-eleitoral/presidente-1-turno-quaest/ . URL fornecida pelo usuário em 21/09/2026 para antecipar a leitura dos cruzamentos enquanto o PDF não sai. Guardar um snapshot com data, instituto, campo, registro e cenário; uma página dinâmica pode passar a outra onda. Confirmar o perfil de renda no registro atual ou no relatório, sem transportar automaticamente o da pesquisa anterior.
- O usuário indicou os painéis do G1 como fontes úteis também para Datafolha. Descobrir e confirmar os links próprios do instituto e do turno; não inventar URLs trocando segmentos. A URL acima é específica do primeiro turno Quaest e não documenta o segundo turno. O acervo de 14/09 já contém uma fonte G1 de segmentos do segundo turno Quaest, que é de outra onda.
- Falha de busca não prova ausência de dados. Bloqueio explícito de segurança da ferramenta é diferente de falha técnica: não contorná-lo com outro navegador, HTTP, proxy ou cópia indireta. Usar fonte independente autorizada ou conteúdo fornecido pelo usuário. Nesta consulta de 21/09 o navegador bloqueou a URL G1 acima, antes de exibir a página.
- Quaest de 21/09/2026 (BR-06004/2026): `scripts/quaest-210926-g1.py` integra quatro prints fornecidos pelo usuário, preservados em `docs/fontes/quaest_21092026/`. Primeiro turno: Lula 49/34/29 e Flávio 23/33/41 por renda. Usar cotas **atuais** 31/42/27 como hipótese explícita até conferir o perfil final. Recomposição 37,30/32,06 versus publicado 37/33: ancorar no publicado, não renormalizar as quatro candidaturas legíveis. Nomes menores sobrepostos não são zeros; essa onda fica fora da decomposição em grupos. Segundo turno pendente, sem reutilização dos cruzamentos anteriores. Regerar agregador e página com `--skip-home` quando a capa não fizer parte do pedido.
- Séries de indecisos e branco/nulo/não vai votar nos dois turnos: `scripts/reponderacao-nao-escolha.py` exige as duas categorias identificadas por renda na mesma onda; ausência não vira zero nem resíduo. Mesma janela retrospectiva de 7 dias pela divulgação da média dos candidatos, com última onda elegível por casa e peso igual. A categoria padronizada branco_nulo já inclui não vai votar quando agregado na fonte; parcelas separadas são somadas antes da média. Cobertura pareada por turno, publicada na página e em `docs/assets/reponderacao_nao_escolha.csv`. As linhas podem usar menos ondas que os candidatos e não somam uma partição de 100%.
- Implementação única da janela em `scripts/reponderacao-janela.py`, usada nos dois turnos por candidatos, grupos e não escolha. Não usar novamente o alisador simétrico nem pesquisas futuras. Conferir a cobertura de cada dia em `docs/assets/reponderacao_medias_7d.csv`; dias sem dados continuam ausentes no CSV; o gráfico liga extremos disponíveis com pontilhado apenas visual. O histórico é recalculado com os documentos atuais e suas datas de divulgação; não é um snapshot das versões disponíveis à época.
- Ligações visuais de lacunas: `scripts/reponderacao_vista/gaps.py` desenha interpolação linear pontilhada somente entre extremos válidos, com intervalo e ressalva no tooltip. Não preenche JSON/CSV, não altera a janela de sete dias, não extrapola antes/depois dos dados e não é previsão. Pontilhado é distinto do tracejado de médias publicadas.
## Reponderação após a urna (08/10/2026)
- A seleção inicial da projeção é `PNAD + comparecimento` / presença relativa de Flávio `+5%` (`display_defaults` em `reponderacao-validos.py`), aplicada também aos gráficos e placares sem JS. Foi escolhida após a urna; não muda os parâmetros centrais da Nexus nem demonstra presença observada por candidato. O cenário central continua acessível e os diagnósticos centrais permanecem rotulados.
- A comparação do agregador com a urna usa `analysis/apuracao_2026/dados/pesquisas_vs_urna.json` e confere os totais com `presidente.json`; módulos `scripts/reponderacao_vista/urna_*.py`. Reproduzir com `python3 scripts/reponderacao-build.py --skip-home`. Exporta `docs/assets/reponderacao_urna_1t.{json,csv}`, com hashes e os mesmos erros do relatório `apuracao_1o_turno_2026.html#pesquisas`.
- A projeção de válidos congela a referência do 1º turno em 04/10/2026; o 2º acompanha a atualização. Parâmetros Nexus continuam de 28/09, sem recalibrar pela urna. CSV de válidos acrescenta `urna_validos`, `erro_pp` e `erro_diferenca_lula_flavio_pp`, vazios no segundo turno. Sempre normalizar pelo vetor completo de candidaturas; não escolha fica fora.
- O balanço final usa uma última onda por casa com campo encerrado desde 25/09: 13 publicadas, dez reponderáveis. O ajuste parcial da apuração mantém a parcela publicada das opções sem voto por renda (Atlas, MDA e Real Time); isso é declarado e não vira zero. A projeção de comparecimento exige vetor completo e usa sete casas. Comparar efeito da PNAD nas mesmas dez casas; ondas antigas são histórico, não ranking de erro final. Institutos são separados por turno, e as versões originais da Palver continuam nos detalhes documentais. Os filtros das fichas preservam o arquivo sem JS e revelam ondas antigas por âncora.
## Mapa do voto útil (método da casa, 26/09/2026)
Reprodução: `python3 scripts/voto-util-092026-tse.py`, `python3 scripts/voto-util-092026-data.py`, `python3 scripts/voto-util-092026-build.py` e `pytest -q tests/test_voto_util_092026.py`. Gera `docs/mapa_do_voto_util.html` e `docs/assets/voto_util_092026.json`. Módulos: `voto_util_base.py` (leitura das transcrições), `voto_util_modelo.py` (motor puro), `voto_util_mapa.py` (malha IBGE em SVG), `voto_util_figuras.py`, `voto_util_capitulos.py` e `voto_util_campanha.py`.
- **Reserva de 2º turno** é a medida central: Flávio no 2º turno menos Flávio no 1º, **na mesma amostra**. Não é suposição sobre a terceira via; é gente que o instituto mediu escolhendo Flávio contra Lula e outro nome no 1º turno. Soma 9,6 milhões de votantes esperados nas 27 UFs na média das três casas (a AtlasIntel, painel digital com pouca terceira via e pouco indeciso, mede reserva menor).
- **As ondas estaduais da Quaest de 19 a 24/09** (BA, CE, DF, GO, MG, PE, PR, RJ, RS, SC, SP, TO) trazem páginas que nenhum outro instituto publica: presidente × governador, presidente × comparecimento às urnas ("sempre vota" contra "já deixou de votar ou não vai votar"), voto definitivo por candidato, quem vai ganhar e medo. Localize pelo título na camada de texto e leia o número na imagem a 240 dpi. As ondas de agosto têm dois cenários de 1º turno; use o Cenário II, sem Marçal, que o PRTB trocou por Leonardo Avalanche.
- **Real Time Big Data publica estaduais com presidente em 23 UFs** (íntegras no Poder360, texto nativo) e **a AtlasIntel em 19** (PDFs em imagem, ondas de 22/09 em SP, RJ, MG, RS, CE e PE). São a segunda e a terceira bases; a AtlasIntel só vira base própria com 15 UFs ou mais. A média das três casas é o número central, e cada uma aparece separada. A Atlas junta branco, nulo e não sei numa barra só e cruza o voto de 2026 com o voto presidencial e para governador de 2022 em cada estado.
- **Eleitor provável**: mistura as duas colunas do cruzamento por comparecimento com peso igual à parcela do grupo que diz que vai votar. O efeito nacional é quase nulo e isso se publica sem enfeite. No Nordeste o eleitor que costuma faltar é menos lulista que o fiel; no PR e no RS, mais. A Nexus nacional (p. 22) mostra o contrário no agregado: quem se absteve nas duas últimas eleições é mais lulista.
- **Calibração nacional**: pesquisas estaduais são mais antigas e, na média, mais à esquerda que as nacionais. O modelo multiplica F, L e terceira via de todas as UFs pelos mesmos fatores até reproduzir a média das ondas nacionais divulgadas na última semana, e reaplica o eleitor provável depois. Publique sempre a versão sem calibração ao lado.
- **Matriz de transferência**: só a Nexus publica o 2º turno de cada eleitorado de terceira via (21/09, p. 79): Renan 56% Flávio, Zema 59%, Cury 44 × 30, Caiado 30 × 36 (o Datafolha, no texto da p. 7, dá Caiado 42 × 27). Nenhum instituto publica o destino de indecisos e brancos; a divisão deles é hipótese declarada e só afeta quanto da reserva sai de voto válido.
- **Números de 26/09 (três casas)**: hoje, eleitor provável e calibrado, Lula 44,2 × Flávio 41,3 dos válidos. Flávio termina o 1º turno na frente com 32 a 40% da reserva antecipada, conforme a base; voto útil completo da direita dá 48,6% (faixa até 49,8%). Se só a esquerda consolidar, Lula vai a 48,2% (sem calibração, 49,9%). Se os dois consolidarem, 48,0 × 47,3. O risco é unilateral e é o argumento de "voto necessário".
- **Achados de campanha que o dado sustenta**: 71% de tudo o que Flávio e Lula ganharam desde 26/08, em oito institutos, foi para Flávio; 24% dos eleitores de Bolsonaro em 2022 ainda não votam em Flávio (17% na terceira via, Nexus p. 23); em 6 dos 7 estados onde Flávio lidera o 2º turno, mais gente aposta na vitória de Lula; o voto definitivo de Flávio subiu em 10 de 10 UFs medidas duas vezes; Caiado caiu de 32% para 23% em Goiás.
- **Classificação de campo com exceção declarada** (`PARTIDO_CAMPO` em `voto_util_base.py` e `CAMPO_EXCECAO` no script de dados). Por decisão do Leonardo (26/09/2026), **tucano é centro-esquerda**: PSDB e Cidadania nunca entram como direita (Aécio Neves, Plínio Valério, Ciro Gomes). PSD é centro; União, PP e Podemos, centro-direita; PL, Novo e Republicanos, direita. Além do campo, cada nome tem `alinhado_lula` (esquerda ou aliança local declarada: Paes, Renan Filho, Omar Aziz, Ferraço, Lucas Ribeiro, Clécio, Zenaide Maia, Fufuca). O alvo de governador é "fora do campo de Lula", com o campo impresso ao lado do nome; a lista de Senado é só direita e centro-direita não alinhadas. Escreva "eleitorado de {nome}" ou "candidatura", nunca "eleitores dele": há muitas candidatas (Raquel Lyra, Celina Leão, Professora Dorinha, Paula Belmonte).
- **Frases por estado são geradas do número do próprio estado**; a regra fixa é atacar a inutilidade do voto que não chega ao 2º turno, nunca o candidato de terceira via. O kit da última semana ensina a pedir documento, não a ignorar fato provado.
- **Teal de terceira via é `#0f7f5f`**: o `#0f8a6e` reprova com texto branco dentro da barra (4,3:1). Rótulo de estado pequeno fora do contorno leva caixa branca, e rótulo sobre azul escuro vira branco com halo escuro.
- Toda figura larga rola na horizontal abaixo de 720 px (`min-width:680px`), menos o mapa, para a página nunca rolar de lado.
- **Reencontro com 2022 por estado**: a AtlasIntel cruza, em 19 estados, o voto de 2026 com a lembrança declarada do voto no 2º turno de 2022. `reencontro_2022` multiplica a parte do eleitor de Bolsonaro que hoje está na terceira via, indecisa ou em branco pelos votos de Bolsonaro no estado (TSE): 5,8 milhões, com SP, GO, SC e RJ à frente. Escrever sempre "lembrança declarada numa pesquisa de 2026" e datar o campo, porque metade dos relatórios é de antes de 10/09.
- **Desistência depois do prazo (26/09/2026)**: o prazo de substituição do 1º turno acabou em 14/09 (TSE, 20 dias antes do pleito; só falecimento abre exceção), e o TSE considera nulos os votos em candidato que desiste antes do pleito, com o nome ainda na urna (Temas Selecionados, AAg 1979/1999). Logo, desistência só ajuda o beneficiado se o eleitor mudar o número. `desistencias()` no script de dados mede isso: Zema (cerca de 1% dos válidos, 59% do eleitor para Flávio pela Nexus) move a diferença de −2,9 para −2,5; Caiado (2,7%, eleitor dividido: 30 × 36 na Nexus, 42 × 27 no Datafolha) quase não move e aumenta a parcela de Lula nos válidos, porque parte do eleitor vira nulo. A linha do tempo com fonte e tipo de evidência fica em `analysis/voto_util/movimentos_092026.json`; relato com fonte anônima (PlatôBR, Revista Oeste) nunca vira fato no texto. Kassab é o vice de Caiado: retirada seria da chapa inteira.
- **O que dói e notícias nas fichas estaduais (28/09/2026).** A Quaest publica em todo relatório estadual "qual é o problema mais grave que o seu estado enfrenta hoje?" como imagem; as 25 páginas foram transcritas em `analysis/voto_util/problemas_quaest_092026.json`, com arquivo, página e onda, e cada leitura precisa fechar 100 (o script de dados falha se não fechar). Saúde lidera em 19 estados, violência em 5 (SP, RJ, BA, CE, ES) e no RS enchente e saúde empatam em 25%. Piauí e Sergipe não têm a pergunta. As notícias de 1º a 26/09 ficam em `analysis/voto_util/noticias/<UF>.json` (194 itens com veículo, data conferida, link e tipo de evidência); a página publica título, veículo, data, o resumo só dos itens de ataque (que traz a versão de cada lado) e o campo `cuidado` como "O que não dizer". A `leitura` da coleta fica fora da página, porque cita placares tirados de matéria sem o PDF do instituto. O roteiro de leitura estado por estado para o X está em `derivados/voto-util-092026-roteiro-estados.md`.
- **Frase do comparecimento compara vantagem, não parcela.** A regra dispara quando a diferença Flávio menos Lula é maior entre quem costuma faltar do que entre quem sempre vota; no RJ e em SC Flávio tem menos voto entre quem falta (30 contra 39 no RJ), com vantagem maior. Escreva "a vantagem de Flávio sobre Lula é maior entre quem costuma faltar", nunca "quem costuma faltar vota mais em Flávio". E "mil" não pede "de": `eleitores()` em `voto_util_figuras.py` escreve "660 mil eleitores" e "2,01 mi de eleitores".
- **Ficha aberta rolava de lado no celular** (1.064 px numa tela de 390): a ficha é item de grid e a tabela de pesquisas impunha a largura mínima. `min-width:0` na `.ficha` resolve. Meça a rolagem lateral com todos os `<details>` abertos, porque a auditoria de contraste pula `<details>` fechado.
## Camada de UX da página de predição (03/10/2026)
- `docs/assets/predicao_2026_ux.css` (carrega por último) e `docs/assets/predicao_2026_ui.js` (defer) cuidam de navegação, leitura e tabelas; o motor (`predicao_2026.js`) e o mapa não foram tocados. Sem JS a página continua completa: o script só destaca o capítulo atual (`aria-current`), mede a barra (`--nav-h`, usado por `scroll-padding-top` e pelo topo do simulador), monta o sumário interno por `h3` (fora de `<details>`), ordena tabelas com `data-sortable`, abre `<details>` alvo de âncora (`#estado-UF`), dá foco de teclado a regiões roláveis e abre os detalhes na impressão.
- Caixas de leitura vêm de classes na FONTE (`.io`, `.hyp` com `strong.iffail`, `.analogy`, `.plain`, `.example`, `.glossary`), nunca do JS. Colunas numéricas recebem `class="num"` em `view.table()` (80% de células numéricas); `sortable=True` marca a tabela das 27 UFs.
- Barra do placar do hero (`view.percent_bar`): `div` com `display:block`, mesma escala 0 a N% nos três cartões, faixa de 90% como caixa hachurada. Nunca `span` inline com `width`.
- Tabela com cabeçalho `sticky` precisa de `max-height` no `.table-scroll`; por isso o `scripts/contrast-audit.py` agora solta o `max-height` de contêineres com rolagem vertical antes de medir (linhas escondidas liam o fundo do hero e acusavam 1,02:1).
- QA: `python3 analysis/predicao_2026/qa-ux.py` (servidor em 4173) mede nav, âncoras, ordenação, largura com `<details>` abertos, skip link, file:// e impressão, e grava `qa-ux-*.png`.
## Predição do Senado 2027 (03/10/2026)
Reprodução, nesta ordem: `python3 scripts/senado-2026-g1.py` (painel do G1), `python3 scripts/senado-2026-outros.py` (valida as fichas transcritas de Real Time, Paraná Pesquisas, AtlasIntel, França e Futura), `python3 scripts/senado-2026-tse.py` (candidaturas, fotos, eleitos de 2022, casamento de nomes), `python3 scripts/senado-2026-motor.py` (grava `docs/assets/predicao_senado.json`), `python3 scripts/senado-2026-build.py` (gera `docs/predicao_senado.html` de `docs/predicao_senado.template.html`) e `python3 scripts/social-cards.py --only predicao_senado`. Contrato entre as partes em `analysis/senado_2026/CONTRATO.md`; método em `analysis/senado_2026/metodo.md`.
- **O painel do G1 tem API aberta** (`especiaisg1.globo/api/pesquisas-eleitorais/graficos/<paginaId>/?tipo_pergunta=<codigo>&instituto=<Instituto>`): séries completas por estado, cargo e instituto, com partido e foto, em fração; a data da série é a divulgação, e a metodologia da página vale só para a onda mais recente. Só Quaest e Datafolha estão lá. Ondas com campo nulo e divulgação em 30/09 ou depois têm o campo inferido (divulgação menos 1 a 3 dias) e marcado `campo_inferido`.
- **Uma pesquisa, um JSON** em `analysis/senado_2026/pesquisas/<instituto>_<UF>_<fim do campo>.json`, com `votos_por_eleitor` (1 quando a soma fica em 100, 2 quando a pergunta pede dois nomes e a soma passa de 150; Paraná Pesquisas e Futura são 2) e `soma_total`. O motor divide por 2 antes de combinar. Fichas da França e da Paraná vêm sem partido; o partido e o campo saem do casamento com o TSE.
- **Fotos oficiais**: `cdn.tse.jus.br/estatistica/sead/eleicoes/eleicoes2026/fotos/foto_cand2026_<UF>_div.zip`, lidas direto do zip e gravadas em `docs/img/senado/<UF>_<SQ>.jpg` (240×240). `DS_SITUACAO_CANDIDATURA` veio `#NE` para todas as 319 candidaturas no `consulta_cand` de 03/10: não dá para filtrar aptas. Casamento de nomes sem adivinhação: `APELIDOS` e `DESEMPATE` declarados em `scripts/senado_2026/tse.py`.
- **Modelo**: duas vagas por UF, os dois mais votados. Média por recência (meia-vida 5 dias), uma onda por casa, peso igual entre casas; central só com campo em 28/09 ou depois, o resto vira prior fraca (`cobertura: "antiga"`). Monte Carlo logístico-normal com erro comum ao campo (nacional e estadual), erro próprio da candidatura e deriva por dia até a urna; indecisos 70% proporcional, 30% uniforme; branco e nulo nunca viram voto. `p_eleito` soma 2,0 por estado.
- **Calibração com 2022**: 26 pesquisas finais de Datafolha, Ipec e Quaest em 19 estados (índice da Wikipédia, texto bruto com SHA-256 em `data/originals/senado_102026/wikipedia_2022/`) contra a urna do TSE: erro absoluto médio por candidatura 3,91 pp dos válidos; nas candidaturas de 20% a 40%, 7,70 (RMSE 9,09); diferença entre 2º e 3º com desvio 12,0. Candidaturas de direita ficaram 3,15 pp abaixo da urna em 2022; o viés entra só como tamanho do erro, nas duas direções. Resultado: desvio de 9,1 pontos para quem tem 30%. Pesquisa de Senado erra o dobro da presidencial; a página diz isso em "Como lemos".
- **Senado de 2027** = 27 eleitos em 2022 (eleito da urna, não o titular atual; Cleitinho eleito pelo PSC entra como direita por exceção declarada) + 54 simulados. Campo é classificação editorial (`PARTIDO_CAMPO`; tucano é centro-esquerda). Suplência, migração partidária e coligação ficam fora do modelo.
- Candidaturas retiradas no meio do campo (Salles em SP, Ronaldo Fonseca no DF, 28/09) continuam em algumas fichas: `RETIRADAS` em `scripts/senado_2026/base.py` troca o voto por indeciso em toda onda usada, com registro em `validacao.retiradas`.
- **Registro indeferido (03/10/2026, Deltan Dallagnol, PR)**: `REGISTRO_INDEFERIDO` em `scripts/senado_2026/base.py` e o módulo `indeferido.py` geram, por estado, `alertas` (texto e matérias arquivadas com SHA-256 em `data/originals/senado_102026/deltan_tse/`) e `cenarios` (votos anulados; voto migrando para o mesmo bloco), reaproveitando os sorteios da central; a central mantém a candidatura enquanto a decisão monocrática puder ser revertida pelo plenário, e isso é hipótese declarada na página. `senado_2027.cenarios` traz o efeito nacional. O clique no mapa troca a ficha no lugar, sem âncora e sem rolar; o build carimba `?v=<hash>` no JS e no CSS próprios.
## Predição de governador 2026 (03/10/2026)
Reprodução, nesta ordem: `python3 scripts/senado-2026-g1.py --cargo governador` (painel do G1, 1º turno e `SEGTURNO-GOV-*`), `python3 scripts/governador-2026-acervo.py` (converte as transcrições de governador já feitas em `analysis/voto_util/outros/` para o esquema do contrato; Quaest e Datafolha ficam de fora porque o G1 traz a série), transcrições diretas dos PDFs em `analysis/governador_2026/pesquisas/` (Real Time, Paraná, Atlas, Futura, França de `data/originals/senado_102026/`, com `governador_p<N>.png` ao lado do PDF), `python3 scripts/governador-2026-tse.py` (cargo 3, fotos em `docs/img/governador/`, apelidos declarados em `scripts/governador_2026/tse.py`), `python3 scripts/governador-2026-calibracao.py`, `python3 scripts/governador-2026-motor.py` (grava `docs/assets/predicao_governador.json`), `python3 scripts/governador-2026-build.py` (gera `docs/predicao_governador.html` de `docs/predicao_governador.template.html`) e `python3 scripts/social-cards.py --only predicao_governador`. Contrato em `analysis/governador_2026/CONTRATO.md`.
- **O coletor do G1 é um só para os dois cargos**: `configurar(cargo)` troca prefixo (`SEN`/`GOV`), pastas e regex; para governador o painel tem `SEGTURNO-GOV-00n`, um código por par medido, que vira a lista `segundo_turno` da onda. A base lê `segundo_turno` de qualquer fonte (G1 ou PDF) e `pares_medidos()` faz a média por recência de cada par, uma onda por casa.
- **Motor** (`scripts/governador_2026/motor.py`): o 1º turno é o mesmo sorteio logístico-normal do Senado; a candidatura mais votada com mais de 50% dos válidos (candidaturas e "outros"; branco, nulo e indecisos fora) decide; senão as duas mais votadas vão ao 2º turno. Par medido: fração publicada do primeiro nome entre os dois, com ruído amostral do par, deriva até a urna e a diferença de choques do 1º turno com correlação `RHO_TURNOS = 0,5` (hipótese declarada). Par não medido: transferência por proximidade de campo (70% do voto eliminado vota, dividido por softmax de menos a distância na reta esquerda-direita, temperatura 1; ruído extra 0,25 no logit). `p_eleito` soma 1,0 por estado e `p_vence_1t + p_vence_2t = p_eleito`; teste obrigatório.
- **Calibração própria**: as mesmas páginas da Wikipédia de 2022 têm a seção de governador (SP usa a predefinição "Governador - 1º turno", em `data/originals/governador_102026/wikipedia_2022/SP.wiki`). O calibrador do Senado ganhou `padrao` e `cargo`; o bloco de governador atravessa os subtítulos "Primeiro turno". Resultado: 19 estados, 26 pesquisas finais, RMSE 6,76 pp para candidaturas de 20% a 40% (Senado: 9,09), escala 7,06 pp para candidatura em 30%. O viés de 2022 (direita 3,8 pp abaixo da urna) entra só como tamanho do erro.
- **Cenário com dois nomes sem o rótulo "2º turno"** (Paraná Pesquisas "Cenário 2") fica em `cenarios_alternativos`, fora da média e fora dos pares medidos; a página declara isso nos limites. Candidatura chamada "Outros" no painel vira a categoria `outros`.
- **A projeção condicional é diferente da medição.** Quando o 2º turno é improvável, o par só ocorre nos sorteios em que a favorita despencou, e a projeção condicional fica perto de 50 × 50 mesmo com medição folgada. A página mostra as duas coisas: a medição dos institutos ("medido por ...") e a chance condicional de cada nome.
- `pytest -q tests/test_predicao_governador.py`; `render-audit.py` e `contrast-audit.py` zerados em 03/10. A página reaproveita `predicao_senado.css` e `predicao_senado.js` (ids `sn-map`, `sn-painel`, `estado-UF`) e acrescenta `predicao_governador.css` (quadro das corridas `gv-board`, cartões `gv-pares`).
- **Camada visual em português corrente (04/10/2026, depois do feedback no X: "gráficos para especialistas em estatística", "textos pequenos").** A página de governador passou a ter: azulejos dos 27 estados no hero (cor do campo, foto, chance, listras para 2º turno), capítulo "Em 30 segundos" com três listas de estados, um cartão por estado com uma frase gerada (`view.frase`: "Empate: X tem 50% e Y tem 50%. É cara ou coroa."), selo de veredito ("Termina no 1º turno" / "Deve ir ao 2º turno"), placar de 2º turno medido em números grandes, corpo em 18 px e `.sn-meta` em 15 px. Parâmetros, calibração e sensibilidades ficam dentro de `<details class="gv-tec">`. Probabilidade em palavras: `_chances()` (9 em 10, 3 em 4, 2 em 3, cara ou coroa). **Concordância de gênero vem do `DS_GENERO` do TSE** (`genero` no JSON, `view.lidera`: "é o favorito" / "é a favorita"); sem casamento com o TSE, "tem a candidatura favorita". Nunca escrever "X é a favorita" com X sendo pessoa: "a favorita" só concorda com "candidatura", e leitor leu como erro. Vale como padrão para toda página de predição nova: a frase antes do gráfico, o gráfico antes do parâmetro.
## Sitemap e robots (07/10/2026)
- `python3 scripts/sitemap-build.py` gera `docs/sitemap.xml` e `docs/robots.txt`: entram as páginas HTML de primeiro nível de `docs/` rastreadas pelo git, menos `*.template.html`, páginas com `noindex` (`social.html`) e as fontes de card em `docs/assets/og/`; `lastmod` é a data do último commit do arquivo. Rode depois de criar ou regenerar qualquer página; `tests/test_sitemap.py` reprova se o sitemap publicado estiver desatualizado (`--check`). Enviado ao Google Search Console como `https://brasil.arvor.co/sitemap.xml`.
## Politize sua vizinhança (aplicativo, 07/10/2026)
Clone "do nosso lado" do site ondedapraconversar.com.br (lado Lula; React + Leaflet, grade de células, raio de 1 km, contador por API). O nosso é 100% estático: `docs/politizesuavizinhanca.html` (escrito à mão) + `docs/assets/politize/{app.js,app.css,carta.js,card.js}` + JSON fixos em `docs/assets/politize/dados/`, servidos pelo GitHub Pages para muito tráfego. Contrato entre motor, textos e app em `analysis/politize/CONTRATO.md`; decisões em `analysis/politize/DECISOES.md`; relatório do build em `analysis/politize/relatorio_build.md`.
- Reprodução: `python3 scripts/politize-build.py` (módulos `scripts/politize/`; `--uf AC` para amostra, `--so-pnad`, `--sem-setor`), 3 minutos para o país; `pytest -q tests/test_politize.py`; `python3 scripts/social-cards.py --only politizesuavizinhanca`; textos em `docs/assets/politize/textos.json` (redator) e citações do programa de governo em `docs/assets/politize/propostas.json` (`scripts/politize-propostas.py`).
- **Entrada principal é UF + zona + seção** (decisão do Leonardo: "as pessoas acham mais fácil", é o que está no título e no e-Título); CEP, cidade/bairro e geolocalização são alternativas. Duas camadas: seção (`dados/zona/<UF>/<zona>.json`, uma linha por seção principal; seção agregada resolve para a principal; seções com menos de 30 aptos não mostram voto) e local de votação = vizinhança (`dados/mun/<UF>/<mun_tse>.json`). Exterior entra como UF `ZZ`, zona 1, 186 cidades, com a coordenada da cidade do consulado (`apuracao/public/geo/exterior_cidades.json`) e o planisfério como mapa; a PNAD não cobre o exterior, então renda e c_perfil ficam nulos lá.
- **Renda é estimativa, porque o Censo 2022 não publica renda por setor** (só básico, alfabetização, domicílios, cor/raça, demografia). A renda da vizinhança sai da PNADC anual 2025 (visita 1, pessoas 16+, VD5001 a preços correntes) por UF × escolaridade do eleitorado (TSE) × situação urbana/rural do setor censitário do ponto; o voto esperado pelo perfil usa o voto por faixa de renda de Datafolha e Quaest de 03/10, recentrado por UF para que a média do esperado em cada estado seja a urna do estado (a recentragem nacional única virava geografia regional: Nordeste +13 pp, Sul −11). O vão positivo entra no índice como `c_perfil`.
- **Índice de conversa** (0 a 100) = (terceira via + brancos/nulos) + metade da abstenção + reencontro (Bolsonaro 2022 menos Flávio 2026, na mesma seção e mesmo local) + vão de perfil, em votos por 100 aptos, dividido por 40; `percentil` nacional e `percentil_uf` do potencial acompanham. Nove arquétipos em ordem fixa (fortaleza ≥ 60% Flávio; muro ≥ 65% Lula; pêndulo |margem| ≤ 6; reencontro ≥ 5; fértil terceira+bn ≥ 12; dormindo abstenção ≥ 28; abaixo_do_perfil vão ≥ 5; frente; atrás). `viravel` usa só branco + nulo + abstenção ≥ diferença, como a manchete da referência, e é publicado nos dois sentidos.
- **Conta do 2º turno**: 30% da terceira via sem escolha (Nexus 21/09 p. 79, agregado) e o resto 61/39 Flávio/Lula (síntese de três fontes em `analysis/predicao_2026`); uma em cada três conversas convence (hipótese declarada). Nunca chamar de previsão.
- Perfil por seção do TSE (`perfil_eleitor_secao_2026_<UF>.zip`) só existia para AC; o CDN `cdn.tse.jus.br` devolveu 429 por horas em 07/10 (também para a API do DivulgaCandContas). Fallback por zona (`perfil_eleitorado_2026.zip`); o build registra a fonte por UF. Quando os arquivos chegarem em `data/raw/tse_eleitorado/perfil_eleitor_secao/`, basta rodar o build de novo. O programa de governo veio do espelho do Poder360 com o rótulo "não conferido contra o original"; `scripts/politize-propostas.py --conferir-tse` compara o hash quando o TSE voltar.
- Regras de texto do app: lado declarado, voto secreto e leitura agregada por seção em todo bloco, "eleitorado de X" (nunca "eleitores dele"), nunca sugerir boca de urna, carona, favor ou abordagem a desconhecido; a lei do dia da eleição é citada com artigo (Lei 9.504/1997, art. 39, § 5º e art. 39-A). Sem rastreador; a geolocalização e a seção digitada não saem do aparelho.
## Senado de 2027 diante do STF (07/10/2026)
Reprodução: `python3 scripts/senado-2027-motor.py` (valida os JSON, aplica a régua, simula e grava `docs/assets/senado_2027.json` e `.csv`), `python3 scripts/senado-2027-build.py` (gera `docs/senado_2027.html` de `docs/senado_2027.template.html`), `python3 scripts/social-cards.py --only senado_2027`. Contrato em `analysis/senado_2027/CONTRATO.md`; instruções dos agentes de pesquisa em `INSTRUCOES_PESQUISA.md`; contexto (composição, PEC 8, listas da imprensa, rito, pós-eleição) em `contexto.json` e `contexto.md`; decisões de arbitragem em `arbitragem.json`. Testes: `pytest -q tests/test_senado_2027_*.py`.
- **Um JSON por senador** em `analysis/senado_2027/senadores/<slug>.json`: casos com estágio, foro, relator, datas, resumo, **defesa obrigatória**, fontes com `acesso` (página lida, trecho de busca, relatório anterior) e `nos_relatorios`; sinais de contrapeso com fonte; `scores_anteriores` dos quatro relatórios de IA (Claude, Gemini, ChatGPT, Perplexity, arquivados em `relatorios_origem/`) só para a figura de dispersão. Suplentes que saíram do elenco ficam em `senadores_arquivo/`.
- **Nenhum score é copiado de relatório de IA.** A régua única (`scripts/senado_2027/scores.py`, dicionário `REGUA`, impresso na página a partir do código) aplica-se aos fatos. K por estágio com bônus de foro, relator alvo e recência só em caso ativo; `C_imp` e `C_pec` separados, base por bloco mais ajustes por sinal observado, piso de autoria, redutor só sobre K patrimonial ativo. Casos de opinião e 8 de janeiro não reduzem C: a evidência mostra que radicalizam.
- **Arbitragem declarada**: estágios criados pelos fatos (`suspenso`, `condenacao_civel`, `reu_civel`, `antigo_sem_desfecho`, `arquivamento_pedido`); regra geral: última decisão anterior a 2024 sem desfecho localizado e confiança não alta vira `antigo_sem_desfecho`. `sem_posicao_localizada` só pesa quando não há nenhum sinal com posição (lista da imprensa que omite o nome não apaga declaração localizada).
- **Simulação**: 20.000 sorteios, correlação latente intrabloco 0,35 e nacional 0,15 (desvios 1,01 e 0,87 no logit); sem correlação a chance de 54 cairia de 19% para 1%. Variantes: base, suplentes do 2º turno, cadeira sub judice vaga. Cenário Flávio e cenário Lula sempre lado a lado.
- **Números de 07/10**: 59 dos 81 com algum registro; K médio 21,0, mediana 9,8; PEC 57,9 votos esperados e 91% para 49; impeachment 47,2 e 19% para 54 (governo Lula: 56,0 e 84%; 42,9 e 5%). Teste da PEC 8: entre os 39 de 2027 que a votaram em 2023, expostos votaram sim em 75% e sem caso em 87,5%, Fisher p = 0,65; nenhum "não" tinha caso patrimonial ativo.
- **Premissas de relatório que caíram na verificação**: não existe lei nova do impeachment de 2025 (a liminar de Gilmar, ADPFs 1.259 e 1.260, suspende trechos da Lei 1.079/1950); a Folha conta 49, não 51; Camilo Santana e Ana Paula Lobato já reassumiram as cadeiras; Lira não figura como investigado formal na petição das emendas; Braga teve o inquérito arquivado por Fachin em 2024; Otto Alencar declarou voto contra o impeachment de Moraes em 2024.
- **Fontes**: WebSearch tem limite de 200 buscas por sessão, compartilhado entre agentes; esgotou no fim da rodada. `noticias.stf.jus.br` devolve 403 ao WebFetch, mas `curl` com user-agent comum lê. A votação de 2026 ao Senado está no banco local da apuração (`analysis/apuracao_2026/dados/senado.json`), não precisa de agregador. A coluna de Bela Megale só foi lida em reproduções (Política Livre, Brasil 247); o post de Andreza Matais, só pelo trecho indexado.
## Vídeo dos fiscais em Remotion (09/10/2026)
Reprodução: `python3 scripts/video-fiscais-dados.py`, `python3 scripts/video-fiscais-voz.py`, depois em `video/fiscais/` `npm install`, `node navegador.mjs`, `npm run typecheck && npm run lint` e `npm run render` (saídas em `out/`, ignoradas pelo git). Detalhes em `video/fiscais/README.md`; teste em `tests/test_video_fiscais.py`.
- **Roteiro é fonte** (`video/fiscais/roteiro/roteiro.md`, um bloco `## id` por cena, tags de áudio do `ESTILO.md`). A voz sai do endpoint `with-timestamps` do ElevenLabs v4, e o alinhamento por caractere vira palavras com tempo em `src/dados/voz.json`: a duração de cada cena é a do áudio, e os elementos entram na palavra certa (`quadro()` em `src/plano.ts`, gatilhos por critério em `src/destaques.ts`). O v4 fala pausado: 20 cenas deram 594 s de narração (cerca de 10 min); para versão curta, cortar cenas do roteiro, não acelerar o áudio.
- **Uma seção real por critério**, escolhida por regra declarada em `scripts/video-fiscais-dados.py` (nível mais alto, pontuação, votantes, sem repetir seção). O JSON compacto (`src/dados/dados.json`) carrega as três frases do rótulo, os critérios com exemplo, o mapa projetado (caminhos SVG por UF e pontos alta/média) e os totais; o teste confere contra `fiscais.json` e exige que o bloco de cada critério no roteiro cite o município do exemplo.
- **Remotion nesta máquina**: a extração automática do Chrome Headless Shell deixa só `ABOUT` e `LICENSE` no zip e o render termina com exit 0 sem gerar nada. `navegador.mjs` extrai o zip à mão e `remotion.config.ts` fixa `setBrowserExecutable` (com o Chrome instalado como reserva). `@remotion/google-fonts` carrega Space Grotesk e JetBrains Mono em tempo de render (precisa de rede). `stills.mjs` empacota uma vez e grava vários quadros de conferência.
- **Atalho `brasil.arvor.co/politize/`**: `docs/politize/index.html` redireciona por `meta refresh` e `location.replace` para `politizesuavizinhanca.html`, preservando `?` e `#`, com `noindex` e canônica; fica fora do sitemap (só primeiro nível) e do teste de GA (idem).
## Totalização paralela por QR do BU (15/10/2026)
Sistema crowdsourced para o 2º turno de 25/10/2026: a pessoa lê os QR do BU impresso na PWA `docs/totalizacao.html`, a Edge Function `receber-bu` verifica e grava no Supabase (projeto `brvjvizqbyfamtxogvqf`, "PNAD"), `scripts/totalizacao-exportar.py` exporta agregados e CSV para `docs/assets/totalizacao_dados/` (workflow `totalizacao.yml`, a cada 10 min nos dias 25 a 28/10, commit de snapshot e deploy do Pages) e `docs/totalizacao_painel.html` mostra cobertura, placar e integridade. Biblioteca de parse e criptografia em `totalizacao/` (Bun; `bun test`, `bun run typecheck`, `bun run lint`), migrações em `totalizacao/supabase/migrations/`, função em `totalizacao/supabase/functions/receber-bu/`.
- **Formato (manual TSE 2026, `data/originals/tse_qrbu_2026/`, SHA-256 em `fonte.json`):** `QRBU:i:n VRQR:6.0 ... HASH:` por QR e `ASSI:` no último; hash encadeado SHA-512 com o espaço de quebra reposto; assinatura sobre sha512 do último hash. A chave não é por UF: é o certificado da própria urna nos dois QR `QRCE` (DER nas UE2013/2015, PEM nas UE2020/2022). UE2013/2015 assinam ECDSA P-521; UE2020/2022 EdDSA na curva E-521 (SHAKE256, 132 bytes, OID `1.3.6.1.4.1.44588.2.1`), sem biblioteca padrão: referência ECPy dev (`cslashm/ECPy@8143d9ac`). Os dez exemplos oficiais (`totalizacao/tests/fixtures/exemplos_tse_2026.json`) verificam. 2º turno: `PROC:1219 PLEI:3221 TURN:2 DTPL:20261025 FASE:O`, `IDEL:6258` presidente (`CARG:1`) e `IDEL:6260` governador em AM, RN, DF, ES e AC.
- **Cadeia de confiança.** `dpc.acue2020.tse.jus.br` e os hosts de LCR respondem 403 a tudo e o Wayback só tem o índice de 2022. AC URNA, AC UE2020 e AC UE2022 vieram de `mr_util.py` em dois repositórios independentes (doccaz/urnas-br e fernandysson/resultados-eleicoes-2026), byte a byte iguais, e ficam em `data/originals/tse_qrbu_2026/ac_certs/*.pem`. A prova é criptográfica: cada AC valida os certificados das urnas dos exemplos oficiais e o certificado de hardware embutido no `-vota.vsc` real do 1º turno, e um byte alterado reprova. Assinatura de certificado: SHA-512 do `tbsCertificate` para ECDSA, `tbsCertificate` cru para Ed521. A AC URNA expirou em 18/07/2026 e os certificados das urnas 2013/2015 continuam válidos: a validade da AC é informação, não critério. Um BU só conta com assinatura válida **e** cadeia válida.
- **Zero `.env` em repo público.** URL e chave publicável vão no código; `service_role` só existe dentro da Edge Function; `MODO`, `SAL_IP` e `TURNSTILE_SECRET` em `supabase secrets set`. RLS ligado sem policy para `anon` (tudo negado), leitura pública só pelas views `v_*`, tabelas `envio`, `bu`, `bu_cargo`, `bu_voto` imutáveis por trigger, `bu` com cadeia de hashes (`cadeia`) reconferida a cada exportação, `registrar_envio(jsonb)` atômica com dedup (`repetido`), `conflito` (segundo hash na mesma seção, fora dos totais) e `set constraints ... immediate` para a soma falhar na chamada. O MCP do Supabase está sem token; o que funciona é o token do CLI no keychain, decodificado dentro do shell e enviado a `api.supabase.com/v1/projects/<ref>/database/query`, sem passar pelo contexto.
- **Rede do TSE:** `tse.jus.br`, `qrcodenobu.tse.jus.br` e `resultados.tse.jus.br` exigem cabeçalhos completos de Chrome no `curl` (ver `fonte.json`); o servidor ignora `Range`. O `.vsc` oficial por seção traz o certificado de hardware da urna em PEM no fim do arquivo: serve para fixar urna por seção (pinning) como segunda camada.
- **Conferência com o TSE** (`scripts/totalizacao-conferir-tse.py`, antes da exportação no workflow): cada BU aceito em fase O é comparado voto a voto com o `-bu.dat`/`-busa.dat` publicado pelo TSE para a seção (decodificação ASN.1 com `apuracao/scripts/secoes/bu.asn1`, dependência `asn1tools`); situações `igual`, `divergente`, `tse_ainda_nao_publicou`, `erro` e `fora_do_oficial` em `conferencia_tse.json`/`.csv`, bloco próprio no painel. Lógica compartilhada de leitura das views em `scripts/totalizacao_comum.py`.
- **Rótulo obrigatório:** soma dos BUs recebidos, não projeção; a amostra é de quem enviou; a conta prova transmissão e totalização, nunca o interior da urna. `MODO=teste` aceita `FASE:S`; trocar para `oficial` antes de 25/10.
## Fiscalização por seção e mapa de fiscais (15/10/2026)
- `python3 scripts/politize-fiscal.py` grava `docs/assets/politize/dados/fiscal/` (regras e um arquivo por zona): toda seção do país recebe nível de atenção (máxima, alta, reforçada, padrão) somando os 12 critérios do capítulo 13, sinais novos do boletim de urna de todas as seções (liberação pelo ano de nascimento, troca de urna, UE2013, abertura atrasada, fila no fechamento, comparecimento atípico, tamanho, trânsito, disputa, eleitorado que pede ajuda), sinais do local e da zona e o risco do território. O app mostra "A seção N precisa de fiscal" com o que conferir e o botão para `https://fiscaisdopl.com.br`. Regras em `scripts/politize/fiscal.py`, textos em `fiscal_textos.py`, contrato na seção Fiscalização de `analysis/politize/CONTRATO.md`. Toda seção precisa de fiscal: o nível diz quantos motivos a mais, nunca dispensa.
- `docs/fiscais_mapa.html` (à mão; app em `docs/assets/fiscais_mapa/`, dados por `python3 scripts/fiscais-mapa-build.py`) atende o feedback de usuárias: busca por CEP, zona (exige UF), município, nome e localização do aparelho; raio 1, 2, 5, 10, 15, 20, 30 ou 50 km (padrão 10) em linha reta por Vincenty/WGS84, nunca por estrada; Leaflet 1.9.4 + markercluster 1.5.3 do cdnjs com SRI; marcadores nas cores originais do capítulo 13; ficha com Google Maps; modo lista sem raio, com ordenação, paginação, busca e CSV; coordenada ausente ou fora do território não vira ponto, só linha da lista. O estado vai no `#` (`uf`, `zona`, `mun` com o código TSE, `q`, `nivel`, `raio`, `modo`, `l` abre a ficha de um local, `s` destaca a seção); o CEP nunca vai para a URL.
- **Versão 1.1 (27/10/2026), decisão do Leonardo em 27/10/2026:** critério `ml_atipico` ("Grupo atípico nos dois turnos", 1 ponto em `fiscal.PESOS`), para a seção no grupo mais atípico da mistura gaussiana dos dois turnos; fonte `data/outputs/apuracao_2t_2026/anomalia_secoes.json.gz` lida por `politize_se.fontes.anomalia_ml`, com SHA-256 conferido contra `analysis/apuracao_2t_2026/dados/anomalia_ml.json` (SHA-256 e `gerado_em` em `regras.json`, que ganha `historico` e o bloco `anomalia_ml`); seção sem linha na mistura (exterior, menos de 30 aptos) não recebe o critério, e o script para se o arquivo faltar ou não conferir.
- Efeito medido com as mesmas entradas da 1.0: 10.850 seções com o critério, 4.353 sobem um nível (padrão para reforçada 2.451, reforçada para alta 1.556, alta para máxima 346); depois, `politize-se-build.py` (só os campos `fiscal_*` mudam); `fiscais-mapa-build.py` não lê o nível, o app do mapa o carrega em tempo de execução.
## Mapa de fiscais, formato 2 (16/10/2026)
- Dados normalizados: `indice.json` (critérios, `logs.familias`, `logs.niveis_atencao`, `logs.sem_ocorrencia`, `partes` por UF com `municipios` como pares `[código TSE, nome do cadastro]`, `resumo.atencao`), `uf/<UF>.json`, `originais.json` (só capítulo 13), `destaque.json` (capítulo 13 mais logs com atenção 2 ou 3, usado só quando os níveis de rotina e de um sinal estão desligados) e `dados.json` (tudo, 31 MB; é a abertura nacional, por decisão do Leonardo em 16/10: o mapa não esconde sinal nenhum, só os critérios zerados saem do seletor). Cada arquivo tem `locais` (uma linha por prédio, com `risco_motivos`, `secoes_total` e `aptos_total` do Politize) e `secoes` (apontando o local por `li`). O app recusa `formato` diferente de 2.
- Nome de município vem sempre do cadastro do Politize (`mun/<UF>/<código>.json`), nunca do capítulo 13 em maiúsculas: a duplicidade de grafia quebrava o filtro de cidade (3.208 municípios dobrados até 15/10). Toda seção leva `comparecimento`, `flavio_pct` e `lula_pct` (válidos do 1º turno, do Politize); seção com menos de 30 aptos não mostra voto, como no Politize.
- `scripts/apuracao_logs/familias.py` agrupa os 25 diagnósticos em cinco famílias pela co-ocorrência medida (energia e reinícios, com ciclo não reconstruído, que acompanha reinício em 96%; identificação do eleitor; ritmo da votação, com retomadas e suspensões, que andam com votação lenta; pausas e inspeções, inspeção longa e meia hora sem voto, que dependem do tamanho da seção; conferência do arquivo, só integridade), dá nome curto a cada um (`NOME_CURTO`) e calcula `atencao` 0 a 3 por seção: 0 só bateria ou inspeção longa, 1 um tipo de sinal, 2 dois tipos, 3 conferência do arquivo ou três tipos (contagens em `indice.json`, `resumo.atencao`). É ordenação para fiscalização por regra declarada, não probabilidade de irregularidade; os logs continuam sem alterar a pontuação histórica. Bateria em qualquer momento é ruído de massa (23% das urnas, 27% delas só antes da zerésima, lift de 0,8 a 2,1 com os demais sinais) e continua como contexto, nível 0.
- Os quatro diagnósticos de rapidez (`processo_rapido`, `cadencia_rapida`, `rajada_rapida`, `tempo_rapido`) têm zero seções de verdade, não por defeito de identificação: referências e escalas recalculadas batem com as publicadas, uma seção fictícia a 45% da referência dispara, e o corte de 4 escalas sozinho já não marca ninguém (z robusto mínimo −4,00 na votação, −2,77 na cadência, −3,92 na rajada, −3,37 no processo). Tempos têm piso físico e cauda à direita; escala simétrica pelo MAD torna −4 escalas inalcançável pela esquerda. Alternativa coerente (z em escala log, corte −4) marca 1, 0, 14 e 1 seções; percentil 0,1% por grupo marca 328/414/655/508, mas é fila de tamanho fixo, não teste. Ficam declarados em `logs.sem_ocorrencia`, fora do seletor; a página explica por quê. Não afrouxar a regra publicada sem registrar nova versão no relatório dos logs.
- **Bateria durante a votação (parser versão 12, 16/10/2026).** `parser.fases_da_bateria` classifica cada mensagem contada de operação com bateria interna em pré-zerésima, pré-votação, votação (do primeiro ao último cômputo) e pós-votação, e devolve os instantes da fase de votação; `publicacao.simultaneidade_bateria` conta, por seção, quantas outras seções do mesmo município registraram o mesmo a ±60 s (máximo entre os instantes; os instantes não são publicados). Dois critérios novos na família energia, nível 1: `bateria_votacao_local` (cinco ou mais outras seções coincidentes; assinatura de fornecimento compartilhado do prédio ou da rede) com 41.811 seções e `bateria_votacao_isolada` (nenhuma) com 12.668; de uma a quatro coincidentes fica só no registro geral. Colunas públicas `bateria_eventos`, `bateria_fase`, `bateria_votacao`, `bateria_simultaneas`. Exigem relógio válido; não medem duração. Atenção após a mudança: 0 = 72.082, 1 = 87.896, 2 = 8.250, 3 = 1.918; destaque nacional com 22.211 seções. Reprocessar leva 21 minutos com 10 processos (gargalo é a leitura dos blobs, 240 logs/s); republicar depois e descartar as mudanças só de carimbo nos SVGs.
- Interface em português corrente: níveis "Prioridade alta/média/baixa" (capítulo 13) e "Conferir o arquivo / Sinais combinados / Um sinal no log / Registro de rotina" (logs); seletor de critério com históricos, famílias e diagnósticos; ficha do prédio com uma carta por seção (aptos, votaram, Flávio × Lula com barra, motivos por família, explicação provável, nível do Politize carregado de `fiscal/<UF>/<zona>.json`, e as demais seções do prédio de `zona/<UF>/<zona>.json`). Os números das seções aparecem escritos no mapa a partir do zoom 15 (`rotulo-secoes`). A ficha do prédio no Politize (`fiscal.js`, bloco "Neste prédio") linka de volta com `#uf=&l=&s=`. Com `l=` o mapa vai direto ao zoom 17 sem animação: `zoomToShowLayer` perdia a corrida com o `fitBounds` e a ficha não abria.
- `window.fiscaisMapa` expõe estado e funções só para QA; `hashchange` aplica o filtro sem recarregar; `modo=lista` não monta o mapa antes. Jargão (Vincenty, WGS84, cômputos) fica no comentário do código e no rodapé; `tests/test_politize_fiscal.py` reprova se voltar à interface. Republicar os logs (`apuracao-2026-logs-build.py`, gzip com `mtime=0`) sempre que `scripts/apuracao_logs/*.py` mudar, porque `integridade_codigo` do índice precisa bater com o código.
- O link para o mapa entrou na fonte do capítulo 13 (`pagina_fig_fiscais.bloco_download`). O rebuild do dossiê mexeria em outros capítulos (dados mudaram desde 07/10), então o fragmento gerado foi aplicado no HTML publicado; no próximo rebuild ele sai igual.
## Logs das urnas (15/10/2026)
- Pipeline: `scripts/apuracao-2026-logs-{coletar,processar,build}.py`, módulos `scripts/apuracao_logs/`, contrato em `analysis/apuracao_2026/logs_urnas/CONTRATO.md`. O coletor recupera os ZIPs do mesmo hash de transmissão do BU e compara SHA-256 anterior quando disponível; preserva originais em `data/raw/tse_logs_2026/logs.sqlite` e métricas em `data/outputs/logs_urnas_2026.sqlite`. Não apagar os originais nem confundir hash conferido com validação da assinatura eleitoral.
- `docs/logs_urnas_2026.html` é gerada; blocos da apuração e thread vêm de `view.bloco`. Aplicação cirúrgica preserva outros capítulos históricos. JSON por zona, cobertura e CSV comprimido em `docs/assets/logs_urnas_2026/`; nenhum identificador pessoal ou sequência individual é exportado.
- 18 diagnósticos operacionais adicionais, sem pontos automáticos ou preferências de candidatos. Regras, denominadores, sensibilidades e limites em `criterios.py`. Preservar as 13.045 seções e pontuações históricas. Bateria não é defeito; ALERTA não é ERRO; falta de evento no pacote não prova ausência do procedimento.
- Tempos separam habilitação, votação e intervalo; não são tempo de fila. Suspensão parcial fica fora do tempo completo. Recuos de carimbo são verificados antes de ordenar e invalidam durações por cautela. Biográficas/(biométricas+biográficas) difere de sem biometria/comparecimento. BU sem essas categorias vira indisponível, nunca divergência ou zero.
- Mudança semântica no leitor ou reconciliação exige nova `parser.VERSAO` e reinício do processador observador. A leitura final deve alcançar a coleta antes da publicação; pendências e erros são estados explícitos, não resultados limpos.
- `apuracao-2026-logs-lacunas.py` preserva a reconsulta das 92 lacunas; `--preparar-bus` arquiva os 20 BUs antes indisponíveis, e `--aplicar` complementa só chaves sem hash/log, com o coletor parado. Os 31 BUs do sistema de apuração têm logSA listado, distinto do log VOTA: linkar a fonte, não dizer que não há registro algum. Depois, repetir coleta e processamento. `complementos.json` e originais documentam a fonte suplementar sem alterar `secoes_2026.sqlite`. Reconsulta e preparo retomam o manifesto existente, sem sobrescrever evidência.
- `fiscais-mapa-build.py` gera índice, histórico e recortes por UF além do acervo completo. O mapa abre o histórico; filtros de logs carregam o recorte pedido. Exterior (`ZZ`) admite visão mundial, zona 1 sem centro geográfico; cidades aproximadas rotuladas. `docs/assets/politize/logs.js` mostra métricas, referências, motivo de ausência, URL oficial e SHA por seção, sem mudar a pontuação do Politize.
- `scripts/contrast-audit.py` com várias URLs da mesma página que só mudam o `#` não recarrega a página e mede no meio da renderização (431 falsos positivos com cor transparente). Rode uma URL por vez nessas páginas.
## Masterclass em vídeo: do 1º turno à fiscalização do 2º (17/10/2026)
Vídeo de 14:41 em 16:9 e 9:16 (`video/masterclass/`, Remotion 4, cópia generalizada de `video/fiscais/`, que segue intacto). Contrato entre as peças em `video/masterclass/CONTRATO.md`; sete capítulos e 37 cenas em `src/ordem.ts`; registro de cenas em `src/cenas/registro.ts` (capítulos 0 a 2) e `registro_b.ts` (3 a 6), com `satisfies Record<CenaId, CenaDef>` para o typecheck reprovar cena sem componente. Reprodução, nesta ordem: `python3 scripts/video-masterclass-dados.py` (grava `src/dados/masterclass.json`, nada digitado à mão), roteiro em `roteiro/roteiro.md` (fontes em `roteiro/fontes.md`), `python3 scripts/video-masterclass-voz.py` (narração v4 e efeitos; sem `--sem-musica` gera uma faixa por capítulo pelo `/v1/music`, com duração igual à extensão do capítulo + 12 s), `python3 scripts/video-masterclass-midia.py` (clipes e stills), `python3 scripts/video-masterclass-capturas.py` (gravações Playwright das páginas), `npm run verificar` (portão 840 a 930 s; 13 minutos é proibido), `node stills.mjs`, `npm run render`. Teste: `pytest -q tests/test_video_masterclass.py`.
- **Roteiro é fonte e é testado.** Cada número narrado leva `<!-- dado: caminho = valor -->` resolvido em `masterclass.json` (seletor `[campo=valor]` e `.length` aceitos) e precisa aparecer por extenso no bloco; nenhum algarismo nas linhas narradas; sem travessão; sem "fraude"; fatos externos só com `<!-- fonte: id -->` presente em `fontes.md`. O núcleo de voz vive em `scripts/video_voz.py` e tira os comentários HTML antes de mandar ao ElevenLabs; `video-fiscais-voz.py` virou wrapper com saída byte a byte igual.
- **Fontes que derrubaram premissas (17/10):** a resolução vigente é a TSE 23.751/2026 (a 23.611 é de 2020); não há vedação literal a retirar fiscal da seção, o presidente pode retirar quem perturba a ordem e todo protesto vai para a ata; a zerésima sai depois da conferência das 7h e a votação começa às 8h; a via do BU é entregue no encerramento a quem pediu; as duas últimas pessoas que votam podem acompanhar o fechamento e levar uma via (art. 127); o art. 211 § 2º autoriza ferramentas de terceiros para ler o BU; a AAPOR não define "house effect" (definição da literatura, atribuída assim); o cadastro de fiscais do PL não tem contador público e a credencial é expedida pelo partido, não pela Justiça Eleitoral.
- **Geradores de mídia.** `openclaw infer image|video generate` tinha Sora 2, Veo 3.1, gpt-image-2 e Gemini Image configurados, mas todos recusaram em 17/10 (404 na rota de vídeo da assinatura, 429 na cota Gemini, 402 no OpenRouter): o script marca `manual` e `--faltando` imprime os prompts. O que funcionou: CapCut Seedance 2.0 Mini no navegador do Leonardo (140 créditos por clipe de 5 s a 720p, dez clipes), Grok Imagine (um clipe grátis por dia, 480p), e mflux FLUX2 Klein local para stills e clipes de câmera lenta por `zoompan` (ffmpeg e mflux leem stdin: `</dev/null` e `-nostdin` dentro de laços `while read`). Gemini web falhou três vezes no vídeo. Arquivos do navegador caem em `midia/entrada/<id>_<fmt>.mp4` e `--absorver` normaliza, recortando o 9:16 do 16:9 quando só há um. `midia/entrada/` guarda os únicos originais dos clipes de IA e está no LFS (`.gitattributes`: `*.mp4` e `*.png` dessa pasta); `midia/brutos/` e `public/midia/` continuam ignorados.
- **Capturas.** 9:16 exige `--force-device-scale-factor=2 --window-size=540,960` no Chromium (o `record_video_size` sozinho deixa a página num canto). O app da totalização lê QR pela câmera falsa (`--use-fake-device-for-media-stream` com um mjpeg dos QR dos exemplos oficiais) e pela galeria; o exemplo 6 (2º turno, só presidente) tem os dois QR de certificado e habilita "Conferir"; `#btn-enviar` nunca é clicado. Cada still tem o segundo em que aparece na gravação (`src/dados/capturas.json`, `por_formato`), casado contra os quadros do vídeo.
- **9:16 polido (17/10, tarde).** Ficha do prédio nas cenas do mapa vira folha de app (`componentes/FolhaPredio.tsx`): stills `ficha` e `cartas` costurados por pixel, sem o botão "Fechar ficha", rolagem casada com a narração e anel na seção citada; `LayoutCaptura` ganhou `inicioPainel` e `useJanelaTelaCheia`. Cenas esparsas no vertical (`tese`, `sopa-regua`, `urna-resultado` empilhado, `depois-fiscais`, `risco-conferir-arquivo`, fechos) ocupam de 64% a 98% da altura útil, sempre acima da faixa de legenda. Conferência de leitura do v4: transcrever as cenas com `mlx_whisper` (large-v3-turbo) e fazer diff por palavra contra o roteiro; o v4 leu "aptos" como "apartamentos", trocado por "eleitores" (evitar abreviações no roteiro). Alucinação de 0,1 s no fim do áudio é do Whisper, não da voz.
- Capas (thumbnails): `python3 scripts/video-masterclass-capa.py` compõe HTML com a marca sobre `public/midia/sopa_still_hero_<fmt>.png` (fonte em `video/masterclass/capa/`) e renderiza `out/capa_16x9.png` e `out/capa_9x16.png` com Playwright; título "A sopa, a concha e a urna", chips de duração e data.
- Música: o `/v1/music` devolve 429 em rajada; o laço com pausa de 90 s resolve. Trilhas em `public/musica/<capitulo>.mp3`, ducking de 0,22 a 0,10 sob a narração em `componentes/Trilha.tsx`. Nada em `public/` é versionado; os cards OG do vídeo saem do manifesto único de `social-cards.py` quando a página pública existir.
## Mudanças de local de votação entre os turnos (19/10/2026)
Reprodução, nesta ordem: baixar `cdn.tse.jus.br/estatistica/sead/odsele/eleitorado_locais_votacao/eleitorado_local_votacao_2026.zip` para `data/raw/tse_eleitorado/locais_2t/` (o TSE regrava o mesmo nome todo dia às 6h30; a versão de 18/10 traz `NR_TURNO` 1 e 2 e as colunas `*_ORIGINAL`; a de 02/10, só o 1º turno, fica como base), `python3 scripts/mudancas-secoes-2t-clima.py` (Open-Meteo ERA5 em 533 locais de origem e 1.500 controles; INMET devolve 204/404), `python3 scripts/mudancas-secoes-2t.py` (motor, 2,5 min; `--reps 200` para rascunho), `python3 scripts/mudancas-secoes-2t-build.py` (laudo `docs/mudancas_secoes_abstencoes.html`), `python3 scripts/mudancas-secoes-2t-thread.py --png` (três cards 1:1) e `python3 scripts/social-cards.py --only mudancas_secoes_abstencoes` e `--only mudancas_secoes_thread`. Contrato em `analysis/mudancas_secoes_2t/CONTRATO.md`; relatório com todos os ICs em `relatorio.md`; testes `tests/test_mudancas_secoes_2t*.py`.
- **Quatro números oficiais que não batem, sempre com data:** TSE via Agência Brasil 16/10, 4.352 seções; relatório da coligação de Lula (TSE 0603126-92.2026.6.00.0000, 17/10), 4.864 seções e 1.795.241 eleitores; consulta da Fórum ao sistema do TSE 18/10, 2.033 e 592.870; painel do Portal de Estatísticas (Capilaridade, Seções alteradas, 18/10 20:27), 1.106 e 321.382. Nenhum recorte do arquivo reproduz 4.352 (RJ 431 não existe no arquivo; máximo 47). Os 1.795.241 ficam a 1,6% dos 1.767.261 eleitores das 6.036 seções que no 2º turno votam fora do local original (hipótese de reconciliação, rotulada).
- **Classificação da casa** pela chave (UF, município, zona, seção): A retorno ao original 754, B nova realocação 255, C 26, D e E mesmo número com prédio trocado 306, F só nome 208, G e H só coordenada; mudança real = 1.211 seções, 348.568 eleitores, 334 pares, 212 municípios. G nunca conta (nome e endereço iguais; Maringá tinha 14 locais com a mesma coordenada). O caso de controle é RJ zona 188 seções 123 a 127 (mesmo número, Rua Muaná para Rua Irapuá), que o painel do TSE omite.
- **Painel × arquivo da mesma hora:** 966 em comum, 140 só no painel (137 são retorno ao original que o arquivo ainda traz como temporário), 69 só no arquivo (68 novas realocações). O Politize usa a união (1.362 seções) com o campo `fonte` e manda conferir no e-Título. Sites `tre-XX.jus.br`, `justicaeleitoral.jus.br` e `sig.tse.jus.br` bloqueiam curl; o navegador embutido lê; a tabela de 1.106 linhas foi paginada por JavaScript, sem download.
- **Distância é variável central:** mediana 382 m nas novas realocações, igual à da categoria A no 1º turno (382) e à do prédio vizinho mais próximo (407); 12,7% acima de 1 km, 4,2% acima de 2 km. Cada par leva `maps_novo` e `maps_rota` (Google Maps).
- **Motivo:** só 36 dos 334 pares casam com nota de TRE que cite o local; 89,9% das seções ficam em "sem motivo publicado", categoria própria do gráfico. TRE-AL e TRE-MT negaram mudanças em 16/10 e o painel de 18/10 lista 22 seções em Craíbas (AL) e 8 em MT. Clima (ERA5): os locais que mudaram tiveram menos chuva que o controle (−7,9 pontos na parcela com dia acima de 20 mm, IC −13,1 a −2,9); 109 origens sem chuva acima de 10 mm nem rajada acima de 50 km/h.
- **Efeito medido no 1º turno (experimento natural):** 6.534 urnas em local temporário tiveram +0,53 ponto de abstenção em diferença em diferenças contra 2022 (IC 0,40 a 0,65); dose e resposta na categoria A de +0,52 até 500 m a +2,43 acima de 5 km; Rio +1,65 na mesma zona (Maré, zona 161, 28,46%, igual ao ConJur). As transferências do TRE-RJ no 1º turno mantiveram o número do local e trocaram nome e endereço: a regra "local != original" não as enxerga; o grupo "troca de prédio desde 2022" enxerga. Rótulo obrigatório: não é efeito causal.
- **Votos em jogo:** as urnas fora do original deram 49,69% a Lula e 43,32% a Flávio; com 0,53 ponto, a diferença muda 568 votos a favor de Flávio; teto do Rio 1.768; cenários +2 a +20 de 711 a 7.110; saldo entre turnos 102 votos a favor de Lula porque 781 seções voltam ao original. Centenas de votos no país, dano local sobre quem anda mais; o problema demonstrável é a transparência. Publicar nas duas direções.
## Nexus e PoderData de 19/10/2026
- `pesquisas-191026-renda.py`, `reponderacao-pnad.py calcular --hoje 2026-10-19` e `reponderacao-build.py` integram ambas, campo 16–18/10. Fontes oficiais e SHA-256 em `data/originals/{nexus,poderdata}_102026_19/`; inventário `analysis/reponderacao/auditoria_20261019.json`. Preservar snapshots anteriores e o arquivo do primeiro turno.
- Nexus 18ª rodada: BR-04499/2026, 2.002 entrevistas CATI, 128 páginas. Publicado F/L/BN/I 46,5/45,9/4,7/2,9 (p. 22), válidos 50,3/49,7 (p. 24), perfil atual 21/16/40/23 (p. 125), renda p. 43 e sexo p. 42. Uma casa decimal desde esta onda; não sobrescrever ondas antigas com a série retrospectiva mais precisa. Presença 92,9% é declarada e não troca a âncora do simulador.
- PoderData: BR-02586/2026, 3.000 entrevistas IVR, 33 páginas. Publicado 49/46/4/2 soma 101; válidos publicados 52/48 separados. Perfil 46/33/21 (p. 4), renda p. 9, sexo p. 7; ponderação pelo voto do primeiro turno declarada na p. 2. Ambas usam `perfil_tipo=perfil_publicado`: etapa antes/depois da ponderação não explícita, sensibilidade condicional.
- `nexus-btg-191026-build.py` e módulos `scripts/nexus_191026/` geram `docs/nexus_btg_18102026.html`: o endereço usa o fim do campo, a divulgação é 19/10. Onze perguntas, 29 linhas incluindo o total, oito dimensões e controles de recomposição. O explorador recebe `profile_page=125`; versões antigas mantêm 99. Não editar a página gerada. Testes em `tests/test_nexus_191026.py`.
## Complemento nacional de 19/10/2026
- `python3 scripts/pesquisas-191026-complemento.py` integra Ipespe (17/10), Atlas (19/10), Futura (19/10), Vox (18/10) e DataTrends (19/10). Inventário em `analysis/reponderacao/auditoria_20261019_complemento.json`; quatro íntegras arquivadas, DataTrends com divulgação arquivada e íntegra pendente. Preservar snapshot anterior `dabd2571f6bf78c3`.
- Atlas: campo 13–18/10 integralmente pós-urna, 4.998 entrevistas, perfil atual 18/12,2/25,9/26,6/17,2 em cortes nominais de R$ 2/3/5/10 mil. Branco/nulo/não sei agregado em 2,6%; nunca inventar indecisos separados. Ipespe: perfil familiar 41/38/22, cruzamentos p. 6, total 48/46/3/3. Os 89% com máxima chance declarada de comparecer não substituem o topline. Ambas recebem sensibilidade condicional ao perfil publicado.
- Futura continua sem voto por renda. Vox agora tem cruzamento na p. 18 (íntegra de 53 páginas), mas o conceito de renda não é definido; perfil 84/12,4/2,7/1 não pode ser tratado como renda familiar. Ambas somente pelo publicado na Projeção. DataTrends BR-04454/2026: divulgação do dirigente Edmar Lyra confirma 49/46/4/1, válidos 51,5/48,5; não reutilizar o perfil ambíguo de 11/10. Paraná BR-09051/2026 é Tocantins, não nacional.
## Projeção territorial experimental do 2º turno (19/10/2026)
- `projecao-secoes-2t-validar.py`, `projecao-secoes-2t-dados.py --hoje 2026-10-19` e `projecao-secoes-2t-build.py` geram a nova página `docs/projecao_secoes_2t_2026.html`. Fonte em template e `scripts/projecao_secoes_2t/`; não recalculam as centrais anteriores. Contrato em `analysis/projecao_secoes_2t/CONTRATO.md`.
- Retrospectiva 2018→2022 entre seis métodos escolheu proporcional por seção (RMSE estadual 1,73 pp; erro nacional −1,71 pp). Matrizes ecológicas de UF/contexto perderam (2,20/2,28 pp). No corte 19/10, matrizes 2022→2026 são cenários de 52,53–52,65% F; proporcional 51,28%; combinação experimental com âncora PNAD das pesquisas, 50,90%. Não confundir seleção em uma eleição com validação da fusão completa.
- Conservar aptos = finalistas + BN + ausência. 496.580 BUs auditados cobrem 99,726%; resíduos oficiais municipais de Betim, Uberlândia e Carapicuíba completam 432.714 aptos. Linhas de zona/seção zero são resíduos, não seções fabricadas. Exterior separado. Seções agregadas não contam duas vezes.
- Quaest em seis UFs atualiza distribuição antes da calibração nacional. Não somar estaduais como casas nacionais nem reaplicar o resíduo +3,8% de presença da central antiga. Erro comum de 2 pp e pesos da fusão são hipóteses; ±2 pp é sensibilidade, não IC nem chance de vitória. Matriz de transição não identifica migração individual; limites de terceiros→Bolsonaro em 2022 quase cobrem 0–100%.
- Extratos/cache em `data/outputs/projecao_secoes_2t/`; CSV público gzip no LFS; hashes no JSON. `--refresh` reextrai o banco 2026. Os ZIPs eleitorais usam latin-1 e streaming. Testes em `tests/test_projecao_secoes_2t.py`.
## Clima, bateria e abstenção no 1º turno (20/10/2026)
Reprodução: `python3 scripts/clima-1t.py --coletar` (Open-Meteo ERA5 por célula de 0,25°, 6.539 células, retomável; cota de cerca de 10 mil chamadas por dia, 5 mil por hora: 429 espera), `python3 scripts/clima-1t-previsao.py` (células de 0,5°, 2.239, grava `docs/assets/fiscais_mapa/clima/previsao.json`; o workflow `clima_previsao.yml` roda todo dia às 12h UTC até 26/10 e commita só esse arquivo), `python3 scripts/clima-1t.py --analisar --reps 2000`, `python3 scripts/clima-1t-build.py` (relatório `docs/clima_abstencao_1t_2026.html`) e `python3 scripts/social-cards.py --only clima_abstencao_1t_2026`. Contrato em `analysis/clima_1t_2026/CONTRATO.md`; relatório com ICs em `relatorio.md`; testes `tests/test_clima_1t*.py`.
- **Janela de votação é 7h às 18h de Brasília** (votação das 8h às 17h de Brasília em todo o país; o primeiro voto tem moda às 8h de Brasília em toda UF), não hora local; o fuso só converte a hora de pico para o rótulo.
- **Chuva derruba a rede, não o eleitor.** Bateria durante a votação sobe de 12,90% (seca) para 29,54% (chuva forte nas horas de votação), razão 2,29 (1,44 a 3,29); odds 1,39 por 10 mm, toda na bateria simultânea (1,53) e não na isolada (0,95); rajada não se associa (1,00). Abstenção: +2,11 pp bruta no país, +0,69 dentro da UF, +0,26 dentro do município (IC inclui zero); com efeito fixo de UF a chuva do dia vem com abstenção menor (−0,53 por 10 mm). Bateria × abstenção dentro do prédio +0,06. Cadeia 2×2×2 sem sinal.
- **Confresa (MT)**: 3,1 mm, nenhuma chuva forte, 16,25% das urnas em bateria. As 283 origens das mudanças tiveram menos chuva (4,98 contra 6,91 mm) e mais bateria (18,97% contra 13,59%).
- **Mapa de fiscais** ganhou a camada `mudanca_endereco` (losango no prédio do 2º turno, 1.362 seções, 824 linhas novas de nível `mudanca`; módulo `scripts/apuracao_logs/mapa_mudancas.py`, que lê a pasta `mudancas` do mesmo cadastro do Politize passado por `integrar`), a ficha com "No dia do 1º turno" e "Previsão para 25/10" (`clima/<UF>.json`, `clima/previsao.json`, chave da célula `floor(lat*2)/2,floor(lon*2)/2`) e os filtros de risco previsto e de chuva forte. Mudar qualquer `scripts/apuracao_logs/*.py` exige republicar os logs (`apuracao-2026-logs-build.py`) e descartar os SVGs só de carimbo.
- **Previsão para 25/10 gerada em 20/10 01h12 UTC**: 42,3 milhões de eleitores em células de risco alto (SP 84%, PR 80%, MS 70%); muda todo dia, indicativo de atenção, não previsão do prédio.
- **Previsão horária de 24/10:** `clima_1t/horaria.py` agrega 08h–17h de Brasília pelos endpoints 09–17 da Open-Meteo (chuva/rajada/probabilidade da hora anterior). Períodos 08–12, 12–14, 14–15 e 15–17. O formato 2 de `previsao.json` usa a votação nos campos principais, preserva `diario` e publica `horas`, `periodos`, `resumo_periodos`; nunca substituir hora faltante pelo total diário. Probabilidade é máximo horário, não probabilidade conjunta. Fusos incluem os 11 municípios do AM em UTC−5 e Noronha em UTC−2. Mesmos cortes editoriais, sem ajuste climático da abstenção; histórico 07–18 preservado.
- **Atualização de clima em 24/10:** o build da página sincroniza mapas, texto e JSON público com `previsao.json`, mantendo `analysis/clima_1t_2026/clima.json` como análise histórica; arquiva cada rodada em `analysis/clima_1t_2026/previsoes/`. O workflow diário também roda o build. `territorio.py` cruza a totalização municipal com a exposição climática por UF/código TSE; `cenario_2t.json` publica 5.571 municípios. Referência A₂ = A₁, sem acréscimo por chuva e sem validação preditiva municipal. Atenção conjunta: ≥10 mil aptos, abstenção anterior acima do Brasil sem ZZ, ≥50% do cadastro mapeado em risco alto e clima completo nas células mapeadas; ordenar por expostos, nunca chamar expostos de ausentes. A home mantém clima e o quadro geral de reponderação antes dos dossiês.
## Vídeo "Sete riscos, um fiscal" (21/10/2026)
Vídeo de 10:36 em 16:9 e 9:16 (`video/sete_riscos/`, clone generalizado de `video/masterclass/` que segue intacto): sete riscos ao voto (boca de urna, compra, transporte, medo, mesário, pianista, totalização), cada um com caso real documentado, sinal nos dados e o que o fiscal faz; a hora de fechar (art. 160 e 127 da Res. 23.751), a totalização paralela por QR, o mapa de fiscais e o cadastro do PL. Contrato em `video/sete_riscos/CONTRATO.md`; 20 cenas em 6 capítulos (`src/ordem.ts`); portão de duração 540 a 690 s. Reprodução, nesta ordem: `python3 scripts/video-sete-riscos-dados.py` (lê `analysis/apuracao_2026/fontes_fiscais.json`, o voto por seção do Politize e o mapa de fiscais; grava `src/dados/sete_riscos.json`), roteiro em `roteiro/roteiro.md` com `<!-- dado -->`/`<!-- fonte -->` conferidos por `tests/test_video_sete_riscos.py` (seletor `[campo=valor]` em listas), `python3 scripts/video-sete-riscos-voz.py` (v4 + música por capítulo com espera no 429), `video-sete-riscos-midia.py` (openclaw, senão mflux + `zoompan`), `video-sete-riscos-capturas.py` (prints das matérias com Playwright: esconde `position: fixed`, só fecha ou recusa banner de cookie, aceita página clara com 2% de pixels de conteúdo), `npm run verificar`, `typecheck`, `lint`, `node stills.mjs`, `npm run render`, `python3 scripts/video-sete-riscos-capa.py`. Kit de publicação em `publicacao.md`.
- Casos e lei saem de `fontes_fiscais.json` (tabela risco × casos × `base_legal` na seção 3 do contrato); o script falha se um id faltar. Nada de 2026 entra como caso; Pescaria Brava nunca "mudou o resultado"; Itumbiara, Paulista e Doppelgänger não são condenações; a credencial é expedida pelo partido; 24/10 é prazo do site do PL; totalização é "soma dos BUs recebidos, não projeção". Celular na cabine: art. 137 da Res. 23.751 e Lei 9.504, art. 91-A. Transporte: Lei 6.091, art. 11, III (não o V). Força federal: requisição do TSE (CE, art. 23, XIV).
- Motivação com Lula na frente: `lula_frente` conta no país inteiro (Politize, 499.187 seções) as seções com um candidato acima de 90% e aptos ≥ 100, excluindo aldeia, presídio, trânsito, exterior e locais cujo nome indica escola indígena ou unidade prisional: Lula 2.883, Flávio 156. Exemplo de abertura Barcarena PA (z65 s327, 98,21%, comparecimento 99,13%); no risco do medo usar seção ribeirinha (Bagre PA), nunca aldeia indígena. Rótulo sempre junto: atipicidade não é irregularidade.
- Conferência da leitura v4 por `mlx_whisper` exige `condition_on_previous_text=False` (senão alucina em loop no fim) e um `initial_prompt` com a URL para a transcrição não descartar "brasil ponto arvor ponto co barra totalização"; o alinhamento `palavras.json` do ElevenLabs é a prova de que a palavra foi falada. "QR" lido como "quê erre" é a pronúncia correta.
## Rodada nacional de 22/10/2026
- `pesquisas-221026-renda.py` integra PoderData/Indexa de 22/10, Gerp de 21/10 às 18h e revisa a mesma Quaest de 21/10 com a íntegra oficial publicada em 22/10 (207 páginas). Inventário `analysis/reponderacao/auditoria_20261022.json`, leitura `RODADA_20261022.md`, fontes `data/originals/*_102026_22/`. Preservar arquivo 1T, Score Arvor e snapshots publicados.
- Quaest: perfil atual p. 203 31/42/27, cruzamentos pp. 25/22, total p. 17; etapa dos pesos não explicitada. Não recriar a pendência antiga ao rodar o integrador de 21/10. Gerp BR-03835/2026: ficha p. 9 campo efetivo 19–21/10, perfil ponderado p. 10 13/22/40/17/6/2, cruzamentos p. 18; onda distinta do tracking de 15–19/10.
- PoderData BR-07926/2026: totais 49/48/3/1, válidos oficiais 51/49, perfil 46/33/21, ajuste condicional. Presença certa p. 19 por voto F/L/BN/I 97/95/56/72 entra somente na projeção documental da própria onda; não muda as centrais.
- Indexa BR-02348/2026: caderno digital completo, rodada 8, JSON.gz e duas partes da API arquivados. Fonte de divulgação usa 45,2/44,1/4,3/1,6/4,8 (F/L/BN/I/não votaria), API guarda mais casas e tela mostra inteiros. Válidos oficiais 50,6/49,4. Perfil 42/38/20 recompõe F=43,806: resíduo −1,394 pp incompatível com arredondamento; permanece sem PNAD. Decisão de voto não é presença. Datafolha de 22/10 ainda aguardava divulgação anunciada às 19h no fechamento desta rodada.
## Datafolha de 22/10/2026, após a divulgação
- `python3 scripts/datafolha-221026-renda.py` integra o painel G1 e o registro BR-09709/2026: n=2.520, campo 20–22/10, total F/L/BN/NS 47/46/5/2, válidos oficiais 50/50. Fontes com hashes em `data/originals/datafolha_102026_22/`; auditoria adicional `analysis/reponderacao/auditoria_datafolha_20261022.json`, preservando o inventário da consulta anterior à divulgação.
- A API contém várias datas fora de ordem; selecionar explicitamente 22/10. Renda atual 39/54/5/2, 54/39/6/1, 54/40/5/1, mas bases efetivas ausentes. Não copiar as bases de 15/10 nem usar 49/47/4 do plano TSE como perfil observado. TSE confirmou que a íntegra não foi fornecida na consulta. Publicado entra na Projeção; PNAD pendente. Preservar 50/50 oficial separado da normalização 47/93; a troca de base na tendência fica explicitada.
- Prévia autorizada pelo usuário em 22/10: `datafolha-221026-renda.previa()` usa apenas perfil e cobertura da onda de 15/10 (1.172/918/335, q=2.425/2.520), com votos por renda de 22/10. `perfil_tipo=hipotese_onda_anterior`; não são bases atuais observadas. Entra nas duas centrais e na tendência, com aviso no gráfico, ficha e cobertura. Auditoria inicial preservada; nova em `auditoria_datafolha_20261022_previa.json`. Substituir quando vier a íntegra. A soma direta PNAD aparece como comparação, enquanto a central usa o delta ancorado no publicado. `process_poll` preserva também `publicado_validos` nas ondas ajustadas para não perder o 50/50 oficial.
## Datafolha de 22/10/2026, íntegra conferida em 23/10
- `datafolha-221026-renda.completa()` substitui a prévia na mesma onda; `previa()` e as auditorias antigas continuam reproduzíveis. Íntegra oficial de 36 páginas em `data/originals/datafolha_102026_22_integra/`, com URL e SHA-256, e `docs/fontes/datafolha_22102026.pdf`. Campo 20–22/10, 154 municípios. P. 22 define bases ponderadas; p. 27 (anexo 8) traz renda 1.171/913/341. Ajuste limitado a 2.425/2.520; 95 sem renda conservam o publicado. Sensibilidade PNAD 48,891/44,219 (F/L); não criar outra onda nem alterar snapshots publicados.
- `python3 scripts/datafolha-221026-build.py` gera `docs/datafolha_22102026.html`; fontes em `scripts/datafolha_221026/`. Dez perguntas em onze tabelas, 31 recortes cada. Decisão tem base ponderada 2.482; válidos e motivação, 2.351. A apresentação p. 9 diz 2.347 entrevistas; não tratar essa base como ponderada nem inferir votos exatos pela diferença.
- Arredondamento: 47/93 gera 50,54%, mas não recupera os percentuais antes do arredondamento. Exemplo hipotético 46,80/46,49/5,20/1,51 soma 100, aparece como 47/46/5/2 e produz válidos 50/50. Não é estimativa dos dados internos nem prova de manipulação. Preservar o oficial 50/50 separado da normalização dos inteiros. Recorte dos que declaram ter votado no 1T publica 51/49, sem base suficiente para projetar presença.
- TSE consultado em 22/10: desenho misto, cotas de gênero e idade na seleção em campo; renda 49/47/4 é referência, com fator previsto 1, não cota de renda declarada. Base ponderada masculina 1.239/2.520 = 49,17% contra cota registrada de 47% pede reconciliação, mas não identifica o perfil bruto nem comprova descumprimento no campo. A margem declarada usa AAS; não valida a precisão do desenho misto. Transcrições públicas do registro e plano guardam a data de consulta; íntegra obtida no site Datafolha em 23/10, sem nova conferência do anexo no TSE.
## Rodada nacional de 23/10/2026, integrada em 24/10
- `pesquisas-231026-renda.py` integra Real Time, Alfa e Ipespe com renda atual (perfil publicado, etapa não explícita); Vox, Veritá, DataTrends e Vetor/Arrow somente publicado. Cinco PDFs e duas divulgações com SHA-256 em `data/originals/*_102026_23/`; inventário `analysis/reponderacao/auditoria_20261023.json`.
- Veritá p. 4: três rendas já somam 100%/15.554; NS/NR adicional 4,3%/676 gera 104,3%/16.230. Não ajustar nem reinterpretar como perfil condicional sem reconciliação. Vox não define conceito de renda; DataTrends e Vetor sem íntegra localizada. Não transportar cruzamentos anteriores.
- Ipespe p. 12: presença máxima F/L/NS 94/90/61%, só nas séries documentais. Geral válido 50,5/49,5; subconjunto oficial p. 13 51,5/48,5 separado da conta Arvor. Instituto mantém identidade `Ipespe`, sem criar segunda casa Abrapel.
- Corte 24/10: Média com dez casas; Projeção dezenove, incluindo as sete novas. Veritá e DataTrends saem da Média pela falta de renda elegível na última onda; não conservar ondas antigas como atuais. Preservar revisão Datafolha, arquivo 1T e snapshots publicados.
## Rodada nacional de 24/10/2026, corte da tarde
- `pesquisas-241026-renda.py`, `reponderacao-pnad.py calcular --hoje 2026-10-24` e `reponderacao-build.py` integram CNT/MDA 173ª rodada e Instituto França. Fontes com hashes em `data/originals/*_102026_24/`, inventário `analysis/reponderacao/auditoria_20261024.json`. Rodada de 23/10 já preservada.
- MDA BR-02136/2026: campo 21–23/10, n=2.032, totais 46,3/45/5,8/2,9; renda e sexo p. 7, perfil p. 22 (42,4/36/20,6 e NS/NR 1%). PNAD condicional ao perfil publicado, parcela 99%; válidos oficiais 50,7/49,3. Ponderação socioeconômica e voto declarado 1T na p. 2; decisão não é presença.
- França BR-04863/2026: material de imprensa de sete páginas, n=1.537, 45,6/43,1/7,4/3,9; válidos 51,4/48,6. Campo 21–23/10 na divulgação arquivada. Renda pp. 5/7 sem pesos atuais; somente publicado na Projeção. Não transportar perfil anterior nem cotas do registro como pesos observados.
- Corte: Média onze casas, Projeção vinte. Snapshot `0fe265d14c2bbaf3`; preservar anteriores, revisão Datafolha e arquivo 1T. Outras pesquisas anunciadas para o dia só entram após divulgação confirmada.
## Rodada noturna de 24/10/2026
- `scripts/pesquisas-241026-noite-renda.py` integra Palver onda 9, Gerp, Nexus rodada 19, Datafolha e Colectta; inventário `analysis/reponderacao/auditoria_20261024_noite.json`. Preservar auditoria da tarde e snapshots publicados.
- Palver mantém v3, perfil ponderado 36/41/23. Gerp tem campo efetivo 22–24/10, perfil ponderado 13/22/40/17/6/2, sem recusa publicada; bases brutas não são pesos. Nexus tem perfil atual 21/16/40/23, etapa não explicitada, PNAD condicional.
- Nexus nas centrais usa amostra completa 47/46/5,2/1,8. LVM de 52,4/47,6 e abstenção estimada 21% ficam documentais; não aplicar presença Arvor novamente a esse subconjunto.
- Datafolha 24/10: 48/47/3/2, válidos 51/49, campo 23–24/10, n=4.050, BR-09540/2026. G1 tem voto por renda; por solicitação explícita, prévia nas duas centrais com perfil e cobertura de 22/10: bases de referência 1.171/913/341 e fração 2.425/2.520. Transportar composição e fração, nunca chamar essas contagens de bases das 4.050 entrevistas atuais. `perfil_tipo=hipotese_onda_anterior`; substituir quando sair a íntegra atual. Colectta: 46/46,5/4,4/3,1, válidos 49,7/50,3, campo 23/10, n=3.000, BR-05601/2026; somente publicado até localizar íntegra e renda atual.
## Quaest e Atlas de 24/10 após 19h
- `scripts/pesquisas-241026-final-renda.py` integra Quaest (BR-09158/2026, campo 23–24/10, n=3.702) e AtlasIntel (BR-06380/2026, campo 18–23/10, n=4.990). Fontes e hashes em `data/originals/{quaest,atlas}_102026_24/`; inventário `analysis/reponderacao/auditoria_20261024_final.json`. Atlas: PDF de 18 páginas, perfil p. 5, totais p. 7, válidos p. 8, renda/sexo p. 9. PNAD condicional ao perfil publicado; não separar os 1,7% de BN/NS.
- Quaest conserva amostra completa 46/45/8/1 e `publicado_validos` 51/49. Por decisão do usuário, `eleitor_provavel_oficial.usar_na_projecao` incorpora o 51/49 na Projeção, depois dos ajustes das demais casas; uma onda e o peso usual por recência. Sem perfil atual ou cruzamentos do LV, não transportar pesos de 21/10 nem incluir a onda na Média PNAD. Normalização 46/91 = 50,55% não identifica efeito do LV, devido ao arredondamento.
- `reponderacao-likely.py` separa a contribuição oficial e faz bootstrap conjunto, mantendo choque comum compartilhado e incerteza de inclinação só nas casas de amostra completa. A casa que muda de universo fica fora da regressão de tendência. O espelho Python/JS combina o válido oficial sem reaplicar Nexus, adicional relativo ou indecisos; controles explícitos de erro comum e saída diferencial para nulo continuam cenários. Contabilidade por eleitor assume a mesma fração de válidos entre presentes das demais casas: hipótese, não total observado do LV. Volumes de indecisos são ponderados pela massa das casas de amostra completa.
- Histórico Quaest conserva totais; modo válidos mostra o oficial identificado e interrompe a linha na mudança de universo. A Nexus continua com amostra completa nas centrais, LVM documental. Preservar snapshots anteriores; snapshot publicado desta rodada `7b8ef4f4a3b871ce`, motor `dafbfc3b86546989`.
## Futura de 24/10, 20h32
- `scripts/futura-241026-renda.py` integra BR-09726/2026, campo efetivo 23–24/10 informado por CNN e Exame, n=2.000, CATI, totais F/L/BN/I 48,2/47,9/2,3/1,6 e válidos oficiais 50,1/49,9. Relatório de oito páginas e divulgações arquivados com hashes em `data/originals/futura_102026_24/`; cópia pública `docs/fontes/futura_24102026.pdf`. Perfil de renda na p. 3, totais na p. 4 e válidos na p. 5; não há voto por renda. Entra apenas pelo publicado na Projeção; não alterar o 51,1/48,9 da onda anterior por causa do 51,5% citado por engano na matéria Exame. Auditoria `analysis/reponderacao/auditoria_futura_20261024.json`. Snapshot `1b2c2ca5884932ac`; motor e tratamento do likely voter Quaest preservados.
## Veritá final de 24/10, reponderação solicitada
- `scripts/verita-241026-renda.py` integra BR-03181/2026, campo 19–23/10, n=15.554, 905 municípios, URA. Página oficial `https://eleicoes26.institutoverita.com.br/pesquisa/7b9ce6dd-df07-45b7-aef6-c8d8abc11eba`; PDF de 13 páginas com hash em `data/originals/verita_102026_24/`, cópia pública `docs/fontes/verita_24102026.pdf`. P. 9: totais F/L/BN/I 49,44/46,46/1,43/2,67; válidos oficiais 51,56/48,44. Perfil p. 4 e cruzamentos p. 10 conferidos visualmente. 'Ausente' é subtotal BN+NS, não abstenção; 97,51% de certeza declarada de votar (p. 5) não é likely voter.
- Decisão explícita do usuário: reponderar a onda atual apesar da inconsistência do perfil, como sensibilidade identificada. Três faixas 40,4/40,9/18,7 somam 100% e 6.283/6.362/2.909 somam n; NS/NR adicional 260/1,7% eleva a 101,7% e 15.814. `perfil_tipo=hipotese_perfil_condicional` assume os três percentuais como composição entre declarantes e `parcela_ajustada_pct=100*(15554-260)/15554` (98,3284%). Delta PNAD limitado a essa massa; sem renda conserva publicado. Isso não é perfil identificado nem correção confirmada pelo instituto. A onda anterior permanece arquivada sem reponderação; não revisar snapshots antigos.
- PNAD pessoas16 efetivo F/L 49,953/46,005 no total (52,057/47,943 válidos simples). Média 52,835/47,165 e Projeção 51,969/48,031 após ajustes Arvor; Veritá entra uma vez nas duas. Gráficos e fichas identificam a hipótese. Snapshot `9399acb33c51065d`, motor `dafbfc3b86546989`. Quaest continua 51/49 oficial sem nova presença; auditoria anterior Futura preservada no seu corte.
## Mapa de previsão por estado do 2º turno (25/10/2026)
- `python3 scripts/mapa-previsao-2t.py --hoje 2026-10-24` (rodar de `scripts/` ou com `scripts/` no caminho) grava `docs/assets/mapa_previsao_2t_2026.json`, a fonte `docs/assets/og/mapa_previsao_2t_2026.html` e o PNG 2160×2160 `docs/img/og/mapa_previsao_2t_2026.png` (Playwright, viewport 1080 com escala 2). Módulos em `scripts/mapa_previsao_2t/` (`motor.py`, `figura.py`); testes em `tests/test_mapa_previsao_2t.py`.
- Método: reaproveita o transporte proporcional por seção de `projecao_secoes_2t` (conferido contra `projecao_secoes_2t_ufs.csv`), as estaduais Quaest pós-urna de `analysis/projecao_secoes_2t/estaduais.json` e um deslocamento comum de log-odds por âncora até bater exatamente a Média Arvor e a Projeção Arvor de `reponderacao_simulador.json` (a `reference` do snapshot precisa ser a data de `--hoje`). Comparecimento e branco/nulo ficam os do 1º turno em toda seção; exterior fora.
- Corte de 24/10: Projeção 52,0 × 48,0 (Flávio à frente em 16 UFs, Lula em 11; AM, AP e PA abaixo de 5 pp); Média 52,8 × 47,2 (17 × 10). A cor usa escala de raiz quadrada com domínio 50 pp: claro é disputado. É expectativa pontual; sem probabilidade de vitória nem liderança identificada.
## PoderData final de 25/10/2026
- `scripts/poderdata-251026-renda.py` integra BR-02828/2026, campo 23–24/10, n=4.000 em 914 municípios, IVR. Íntegra oficial de 27 páginas com SHA-256 em `data/originals/poderdata_102026_25/`, cópia pública `docs/fontes/poderdata_25102026.pdf`. Totais F/L/BN/I 49/47/3/1 (p. 6), válidos oficiais 51/49 (p. 11).
- Pp. 3–4 agora identificam expressamente percentuais ponderados; renda 46/33/21, sexo 47/53. `perfil_tipo=perfil_ponderado` nesta onda, sem revisar anteriores. Renda p. 9: 42/54/4/0, 56/40/3/1, 52/44/3/1; sexo p. 7: 56/41/3/1, 42/53/4/0. PNAD por delta F/L 50,332/45,668 no total, 52,429/47,571 válidos simples.
- Presença certa p. 19 F/L/BN/I 96/94/52/56 apenas na série documental da própria onda. Centrais mantêm regras, Quaest LV 51/49 sem nova presença, Datafolha prévia e Veritá condicional. Atualizar com `reponderacao-pnad.py calcular --hoje 2026-10-25`, `reponderacao-build.py`, cards e `mapa-previsao-2t.py --hoje 2026-10-25` (PNG renderizado com Chrome local nesta rodada).
- Corte 25/10: Média 52.880441/47.119559; Projeção 52.065802/47.934198. Snapshot `e1e4524328558a79`; preservados os anteriores e o motor `dafbfc3b86546989`. Auditoria `analysis/reponderacao/auditoria_poderdata_20261025.json`.
## IDs das urnas e logs do 2º turno (26/10/2026)
- `python3 scripts/apuracao-2t-2026-urnas.py` (módulos `scripts/apuracao_2t_2026/urnas_*.py`) lê os bancos de BUs por seção dos dois turnos em modo somente leitura e grava `analysis/apuracao_2t_2026/dados/urnas.json` e `urnas.md`: modelos, IDs repetidos classificados (mesmo BU, sistema de apuração, sobreposição de horário, troca compatível, sem contingência), ID do BU contra o log, código de carga repetido, carga e fase, mesma urna nos dois turnos e diferença em diferenças das trocadas contra vizinhas. Reexecutável na coleta parcial; cache do 1º turno em `data/outputs/apuracao_2t_2026/`. Rótulo: pede explicação, não prova irregularidade. Testes `tests/test_apuracao_2t_urnas.py`.
- Fontes da alegação de 2022 (número 67305985 no log das urnas anteriores à UE2020, PetCiv 0601958-94.2022.6.00.0000, multa de R$ 22.991.544,60) com SHA-256 em `analysis/apuracao_2t_2026/urnas_fontes/fontes.json`. A alegação era de número genérico repetido no log, não de uma urna em várias seções. Em 2026 o número não aparece e o ID do BU escreve linhas no log em praticamente todas as seções; as exceções do 1º turno são votação recuperada (tipo de arquivo 2), e o único ID repetido do 1º turno é o equipamento da junta do exterior (tipo de arquivo 5, 29 seções).
- Logs do 2º turno: `apuracao_logs/pleito.py` parametriza dia e caminhos (padrões do 1º turno intocados, leitor continua 12). A carga de setembro serviu aos dois turnos, então o log do 2º turno contém o do 1º como prefixo; `--guardar compacto` guarda esse prefixo por referência (cerca de 29 GB contra 89 GB dos ZIPs, que não cabem). `GAP: Problema ao desmontar a MR` antes da zerésima aparece em quase toda seção do 2º turno e dispara `erro_tecnico`; contado à parte, regra publicada não alterada. Comandos e ordem no fim de `analysis/apuracao_2026/logs_urnas/CONTRATO.md`.
## Grupos de seções por mistura gaussiana nos dois turnos (26/10/2026)
- `python3 scripts/apuracao-2t-2026-anomalia.py` (módulos `scripts/apuracao_2t_2026/anomalia_*.py`; `--amostra N` rascunho; `--so-texto` refaz leitura e memorando sem reajustar) grava `analysis/apuracao_2t_2026/dados/anomalia_ml.{json,md}` e o arquivo pesado `data/outputs/apuracao_2t_2026/anomalia_secoes.json.gz` (fora do git; `anomalia_linhas.bloco`). Depois: `politize-se-build.py`, `politize-se-mapa-build.py`, `hipoteses`, `video-apuracao-2t-dados`, `build`, `thread`. Contrato em `analysis/apuracao_2t_2026/CONTRATO_ANOMALIA.md`; testes `tests/test_apuracao_2t_2026_anomalia.py` e `caps_e.py`.
- Espaço: nove frações do eleitorado do próprio turno (Lula, Flávio, outros, brancos, nulos no 1T; Lula, Flávio, brancos, nulos no 2T), padronizadas; comparecimento e abstenção implícitos (décima coluna deixaria a covariância singular). **Mistura com covariância completa é invariante a transformações afins: enquadrar por diferenças entre turnos é o mesmo modelo** (ARI 0,975 entre as melhores partidas dos dois enquadramentos); os centros saem também em deltas; só o k-means (contraste) muda com o enquadramento. Exterior fora; aptos ≥ 30 nos dois turnos; 497.796 seções.
- k por regra declarada antes de ver os grupos: joelho do BIC a 5% da queda total de k = 2 a 10, ICL como alternativa, 3 ≤ k ≤ 10. Deu k = 8 (BIC mínimo em 10, ICL mínimo em 2: grupos sobrepostos, nuvem contínua). Convergência obrigatória (tol 1e-6, 2.000 iterações, dobra se preciso); partida degenerada (menor autovalor da covariância < 1e-4, componente colado em zeros de branco/nulo) fica fora da escolha e é contada. 16 de 16 partidas convergidas, 13 no mesmo máximo, ARI médio 0,96.
- Grupo atípico (critério do 1T: postos de menor log-verossimilhança e maior dispersão): 10.850 seções (2,18%), brancos e nulos muito altos nos dois turnos; **não é geografia** (V de Cramér 0,044 com região) nem modelo de urna (0,012); é em boa parte seção pequena (34% das de 30 a 99 aptos). Voto: fatia de Flávio −3,56 pp contra vizinhas (descritivo: o grupo é definido pelo voto) e DiD −0,05 pp (IC inclui zero). Os oito grupos seguem a geografia política (V 0,446 com região). Rótulo em todo lugar: atipicidade estatística não é irregularidade.
- Sinal `anomalia_ml` por seção no Politize-se (`ml_grupo`, `ml_anomalo` 0/1, `ml_p`), `secoes_anomalas` por prédio e município, camada `anomalia` do mapa com `precisa_ml` (nulo pinta cinza). Capítulo `anomalia` ("Grupos") do dossiê entre `secoes` e `logs`, figuras `an_*`.
## Seções com zero voto (27/10/2026)
- `python3 scripts/apuracao-2t-2026-zeros.py` (módulos `scripts/apuracao_2t_2026/zeros_base.py` e `zeros_dados.py`, leitura somente leitura dos bancos por seção dos dois turnos, do arquivo `presidente_secao_2022.csv.gz` e do cadastro do Politize) grava `analysis/apuracao_2t_2026/dados/zeros.json`, com `ESPERADO` que falha se a conta mudar. O bloco entra no capítulo Grupos por `pagina_fig_zeros.py`; testes em `tests/test_apuracao_2t_2026_zeros.py`. Lista de referência em `dados/flavio_zero_2t_2026.csv`.
- Números (Brasil sem exterior): 2º turno de 2026, 106 seções com zero Flávio (Lula 14.860) e 4 com zero Lula (Flávio 296); 2022, 141 com zero Bolsonaro (Lula 16.418) e 2 com zero Lula (118); 1º turno de 2026, 79 e 8; 2022, 160 e 1. Com exterior, 108 e 6 (as duas a mais são seções em que ninguém votou). Candidato sem linha no BU é zero voto; a mediana de aptos das 106 é 161 (a mediana alta é 165).
- Leitura: comunidade fechada e pequena (51 aldeias ou escolas indígenas pelo nome, 2 prisões, 16 comunidades), AM 30, MA 20, PA 16; Flávio já tinha zero em 50 delas no 1º turno e no máximo 5 votos em 105. Achados contrários publicados: 67 das 106 caem no grupo 8 da mistura e só 11 no atípico (ponta de nuvem contínua, não padrão à parte); a regra de nome classifica 103 das 141 de 2022 como "outro" (escolas rurais do MA e da BA), logo a leitura de comunidade fechada vale mais para 2026 do que para 2022; o Norte passou de 25,5% para 61,3% da lista. Tipo de local pelo nome é regra declarada, não cadastro oficial; nomes com apóstrofo casam também sem espaços. Rótulo: atipicidade pede explicação, não prova irregularidade; publicar os dois lados. A coluna Painel da Folha de 27/10 (Carlos Petrocilo, atribuída à Paris Group) está arquivada com SHA-256 em `data/originals/folha_102026_27/`; sua distribuição regional (65/29/6/3/3) coincide com a contagem dos BUs e o bloco publica essa conferência com selo Verificado.
- Cauda (`zeros_cauda.py`, leitores por seção em `zeros_cauda_secao.py`, página em `pagina_fig_zeros_cauda.py`, `ESPERADO_CAUDA` falha se a conta mudar): das 106, 56 tinham voto em Flávio no 1º turno (30 com 1, 10 com 2, 9 com 3, 5 com 4, 1 com 5, 1 com 16). Régua da independência (1 − p)^n ≈ e^−k, com p a fatia de Flávio nos válidos do 1º turno e n = Lula + Flávio no 2º: 37% com 1 voto, 1,8% com 4. Taxa base do país por k: 129/30, 150/10, 201/9, 241/5, 263/1, nenhuma de 6 a 15, 659/1. Até 5 votos é aritmética de número pequeno (81 zeros esperados, 55 observados).
- Cauda propriamente dita, com ao menos 30 nominais no 2º turno: Flávio de 6 ou mais para 1 ou nenhum pega 6 seções e a independência esperaria 7,6 (cabe no acaso); 10 ou mais com queda de 80% pega 6 contra 1,7 esperadas. União de 10 (Ipixuna, Itaubal, Anapu, São Paulo de Olivença, Maués, Icatu e quatro de 6 ou 7 para 1 no MT e no AC); espelho de Lula vazio; nas 10, mesma urna e mesma carga nos dois turnos e RDV confere. Maués 176 (seção nova, 16 → 0, 1 em 16 milhões sob independência) e Ipixuna 63 são lidas por dentro: BU, RDV com hash conferido, métricas do log do 2º turno e o 1º turno relido por `apuracao_logs.parser.analisar` com dia 04/10/2026 sobre o ZIP de `logs.sqlite` (somente leitura, pela chave primária com UF minúscula).
- Leitura: Verificado para contagens; Inferência para o voto de Flávio que some junto com o de governador de direita e centro-direita nas três seções do AM (Maués 129 → 1, Omar Aziz 176 → 328); Achado contrário obrigatório em Marechal Thaumaturgo (AC), onde Mailza Assis foi a 123 e Flávio caiu; Hipótese do voto em bloco por orientação de liderança, compatível com tudo e identificada por nada, porque o voto é secreto. Nomes de governador vêm de `governadores.json` e `analysis/governador_2026/tse_candidatos.json`: o AP não teve 2º turno de governador, e o 44 do AM no 1º turno é Roberto Cidade (UNIÃO).
## Dossiê do 2º turno: municípios com menos votos absolutos (27/10/2026)
- Subparte "Onde Flávio teve menos votos no 2º turno do que no 1º" do capítulo turnos: contas em `scripts/apuracao_2t_2026/turnos_perdas.py`, texto em `pagina_texto_turnos_perdas.py`, figura `tu_perdas_uf` (barras por UF com o total de municípios, losango para UF com 2º turno de governador, versão empilhada no celular) e listas completas ordenáveis (`data-ordena`) em `pagina_fig_turnos_perdas.py`. Números de 26/10: 938 de 5.571 municípios, −133.900 votos de Flávio, Lula +486.922 neles (ganhou em 863), comparecimento caiu em 728 (−274.667); espelho de Lula com 79 municípios (−16.115), comparecimento caiu nos 79. Decomposição por duas réguas declaradas (Inferência): teto, 115.918 cabem na queda do comparecimento e 17.982 não, em 317 municípios, em todos com ganho de Lula de ao menos o tamanho da sobra; proporcional, 92.586 e 41.314 (69,1% contra 97,7% de Lula). As 6 UFs com 2º turno de governador entram como contexto (queda do comparecimento em 52,7% dos municípios contra 17,2% nas outras), sem causa. Rótulo: votos absolutos, não fatia dos válidos; menos votos não identifica eleitor nem motivo.
- `comparacao_1t.json` ganhou `t1_aptos`, `t1_comparecimento` e `t2_comparecimento`; `python3 scripts/apuracao-2t-2026-dados.py --so comparacao_1t.json` regrava só esse arquivo (rodar o script inteiro com o servidor local desligado esvazia `projecao_noite.json`). `python3 scripts/apuracao-2t-2026-dataset.py --municipios` grava `docs/assets/apuracao_2t/dataset/municipios_flavio_menos_votos_2t.csv` e `municipios_lula_menos_votos_2t.csv` (`dataset_municipios.py`, mesmo esquema, maior perda primeiro), registrados em `manifesto.json` (`listas_municipais`) e numa seção própria do `DICIONARIO.md`, sem tocar no CSV por seção; rodar depois de regerar o JSON. Testes `tests/test_apuracao_2t_2026_caps_b.py` (`ESPERADO_PERDAS`) e `tests/test_apuracao_2t_2026_dataset.py` conferem linhas, somas, bytes e hash contra o JSON.
- Thread do dossiê do 2T com 26 cards (`MAX_POSTS` em `thread_build.py`): o 25 traz onde Flávio teve menos votos no 2º turno (contas de `turnos_perdas.py`, figura por UF em parcela dos municípios com o losango do governador, duas réguas, espelho de Lula, achado contrário do 2º turno de governador, link `apuracao_2T_2026.html#tu-menos-votos` e o CSV da lista) e o 26 a pendência documental (série da memória de resultado repetida e urna realocada, com IC95 contra as vizinhas, o que pedir pela Lei de Acesso à Informação citando o pleito lido de `urnas.json`, onde está a lista em `metadados.json`, link `#logs`); valores em `thread_valores_c.py`, figuras em `thread_fig_d.py`, posts em `thread_posts_c.py`. O verificador aceita `#` só como fragmento `.html#âncora`; fora disso é hashtag.