PROJETO · HISTÓRICO DE VERSÕES

Changelog

Todas as mudanças importantes do projeto, em ordem reversa cronológica. Formato segue Keep a Changelog; versões em SemVer.

Histórico de versões

Registro cronológico de tudo que mudou no painel — dados, metodologia e interface —, da versão mais recente para a mais antiga.

Página 9 de 12 · 136 versões no total.

  1. v3.9.2 2026-04-29 Candidato divisivo (clivagem editorial da semana)

    Added

    • Bloco "Candidato divisivo" na coluna direita do bloco 2.3 (que estava vazia desde a remoção de "Evolução do sentimento" na v3.9.1). Aponta o pré-candidato com maior dispersão de sentimento entre veículos na semana corrente — sinal de polarização editorial. Métrica: desvio-padrão de sentiment_score por candidato, threshold mínimo de 10 artigos classificados.
    • Citação de matérias extremas: o card mostra qual veículo + qual matéria ancoraram o lado mais crítico e o mais elogioso da cobertura, com link clicável (target=_blank, rel=noopener) e título truncado em 90 caracteres. Concretiza pra o leitor a clivagem editorial.

    Changed

    • Label "amplitude" → "dispersão": o número exibido (ex.: 0.55) é desvio-padrão, não range max-min. Termo anterior induzia a leitura errada — quem visse "amplitude 0.55" e o range "-1.00 ↔ +1.00" estranhava a aritmética.
    • Range concreto adicionado logo abaixo do label (range -1.00 ↔ +1.00 em monospace) — leitor casual aproveita a leitura intuitiva; leitor técnico aproveita o std.

    Notes

    • Critério estatístico (std) é mais robusto a outliers que range simples. Um único artigo extremo de cada lado já fixa range = 2.00, mesmo com 99% da cobertura neutra; std reflete a distribuição real.
    • Card complementa o "Candidato destaque" da coluna esquerda: destaque captura movimento de volume; divisivo captura clivagem editorial. Duas leituras independentes da semana.

  2. v3.9.1 2026-04-29 Refinamento da Cenário Semanal

    Added

    • Dumbbell de volume por candidato (seção 2.4): visualização semana corrente × semana anterior. Bolinha cinza no valor da semana passada, bolinha colorida (cor do candidato) na semana atual; linha verde aponta crescimento, vermelha aponta queda. Resolve a comparação cruzada entre candidatos sem o ruído de uma timeline (descartada por excesso de séries).

    Changed

    • Reordenação de blocos da Cenário Semanal: Sentimento (destaque + por candidato) agora vem antes de Tópicos emergentes — leitura imediata do clima da semana, com aprofundamento em pauta logo depois.
    • Critério do Candidato destaque migrado para compósito growth × log1p(volume) (mesma fórmula dos tópicos emergentes). Antes era |Δ| absoluto — capturava também colapsos. Novo critério filtra score > 0: destaque é sempre editorial positivo. Quando ninguém está em alta (caso comum nas primeiras horas de uma semana), o bloco mostra mensagem honesta.
    • KPI "Sentimento médio" ganhou detail com delta vs semana passada (↑/→/↓ vs +X.XX). Card "Evolução do sentimento" do bloco 2.3 removido — era informação duplicada.

    Fixed

    • app.py registrava paths antigos após a renumeração pages/N_*.py da v3.9.0. st.navigation quebrava ao tentar montar páginas — HTTP 200 do Streamlit não detectava (a app sobe; o erro só dispara ao trocar de página). Mapa _REDIR e lista de st.Page(...) atualizados.
    • KPI "Candidatos cobertos" (Cenário Semanal) contava nunique() em article_candidates da semana sem filtrar dropped. Resultado: 14 vs 12 mostrados no grid (4 dropped tinham vínculos históricos contando dobrado). Agora segue o mesmo critério do grid (pre-candidate + candidate por padrão; só candidate quando only_confirmed=True).

    Notes

    • Janela do Cenário Semanal continua segunda-domingo. No meio da semana, o dumbbell e o destaque mostram comparação parcial (3 dias da semana corrente × 7 da anterior) — esperado.
    • Removido um falso positivo manualmente do banco em 29/04: artigo "Datafolha divulga 1ª pesquisa de opinião após registro de candidaturas" (Agência Brasil), vinculado erroneamente a Cabo Daciolo. Conteúdo era de eleição passada com published_at falsamente atualizado pela republicação. Verificador critério 6 não pegou — vale revisar regras de período eleitoral consumado se virar recorrente.

  3. v3.9.0 2026-04-29 Cenário Geral × Cenário Semanal: split editorial

    Added

    • Nova página: Cenário Semanal. Janela fixa segunda-domingo da semana corrente, sem filtro de período. Conteúdo: KPIs da semana (volume + Δ vs anterior, candidatos cobertos, fontes únicas, sentimento médio), grid de pré-candidatos com volume e sentimento da semana + delta, tópicos emergentes, candidato destaque, evolução do sentimento, sentimento por candidato (grid horizontal), lista de artigos publicados na semana.

    Changed

    • Cenário Geral refocada para visão histórica: removidas seções de "Esta Semana", "Tópicos emergentes desta semana", "Candidato destaque", "Sentimento da semana" e "Sentimento por candidato" (semanais) — todas migradas para Cenário Semanal.
    • Pills de período saíram da sidebar. Agora vivem inline no body de Cenário Geral (única página com janela ajustável). Default: Tudo (toda a série desde 25/03/2026). Outras opções: 90 dias, 30 dias, 7 dias, Personalizado. Cenário Semanal e demais páginas usam janela fixa por desenho.
    • Ordem do menu: Início → Cenário Geral → Cenário Semanal → Pré-candidatos → Comparativo → Radar → Espectro Editorial → Zeitgeist → Análises → Metodologia → Changelog. Arquivos pages/N_*.py renumerados em cascata.
    • Grid de pré-candidatos imediatamente após os KPIs em ambas as páginas (geral com volume total no período; semanal com volume da semana + delta vs anterior).

    Notes

    • Janela do Cenário Semanal é segunda-domingo (semana civil corrente). Não confundir com a janela do resumo semanal editorial (sábado-sexta, publicado no sábado seguinte) — janelas diferentes para usos diferentes.
    • boot() ganhou parâmetros days_back e date_range para que cada página controle sua própria janela; sidebar ficou só com brand + toggle "apenas confirmados" + tema.

  4. v3.8.2 2026-04-29 Recorte do dashboard agora é editorial, não de coleta

    Fixed

    • Timeline de cobertura escondia silenciosamente artigos válidos do início da série. load_data() filtrava por fetched_at >= now() - 30d. Como o coletor entrou em produção em 25/03 capturando publicações retroativas, 871 artigos publicados entre 25-30/03 ficavam fora do dashboard — e o problema piorava 1 dia por dia (cada amanhã, mais 1 dia da janela editorial sumia do gráfico).
    • Filtro passa a ser por published_at com cutoff sempre limitado por MIN_PUBLISHED_DATE = 2026-03-25 (recorte oficial). Janela "30 dias" agora significa "publicado nos últimos 30 dias", não "coletado nos últimos 30 dias".
    • Período "Personalizado" migrado de fetched_at para published_at (com parse_published_dates para lidar com formato misto com/sem timezone — pd.to_datetime direto gera NaT silenciosamente, conforme gotcha já documentado).

    Notes

    • Mudança afeta arquivos: src/core/data.py (queries SQL) e src/core/bootstrap.py (recorte personalizado).
    • Cache @st.cache_data(ttl=300) é invalidado no restart do eleicoes-dashboard.service.

  5. v3.8.1 2026-04-28 Leonardo Péricles dropped

    Changed

    • Leonardo Péricles (UP) marcado como status='dropped' no banco — substituído por Samara Martins como pré-candidato da Unidade Popular em 08/04/2026. A descoberta veio da análise do resumo mensal de abril (apenas 24 artigos sobre Péricles vs 108 sobre Samara). Status alterado retroativamente em 28/04/2026 para refletir a transição partidária.
    • Coletores Brave/Google News/Tavily passam a ignorar Péricles automaticamente (registros históricos preservados no banco).
    • README atualizado: Péricles movido para "Descontinuados".

  6. v3.8.0 2026-04-28 Resumo Mensal eleitoral: novo produto editorial

    Added

    • Resumo Mensal de Eleições 2026 — espelha a arquitetura do resumo semanal (Opus 4.7 + extended thinking + ordem das seções por volume), mas com fôlego de balanço — 1500–2000 palavras, identificando tendências consolidadas ao longo do mês, viradas de narrativa e comparações com o mês anterior quando os dados sustentam.
    • Janela editorial: dia 26 do mês anterior ao dia 25 do mês alvo. O ciclo fecha no dia 25; draft sai na manhã do dia 26.
    • Cron: monthly-summary.timer na LXC-121 dispara dia 26 de cada mês às 08h00 (BRT). Próximo disparo automático: 26/05/2026.
    • Tag dedicada: resumo-mensal (separada de resumo-semanal).
    • Suporte a catch-up retroativo via flag --month YYYY-MM. "Resumo de abril de 2026" (cobertura completa do primeiro mês desde 25/03/2026) gerado manualmente em 28/04/2026.
    • Página Metodologia do dashboard: seção "Resumos editoriais — produtos associados" reescrita pra cobrir as duas séries (semanal + mensal).

    Changed

    • Streaming obrigatório no SDK Anthropic — chamadas com extended thinking (12K) + max_tokens 28K + prompt grande passam de 10min e exigem client.messages.stream(). Aplicado em ambos weekly_summary.py e monthly_summary.py (preventivo no semanal antes de 02/05).

    Notes

    • O resumo mensal vive no projeto blog-automation (/opt/blog-automation/produtores/monthly_summary.py na LXC-121), não no eleicoes2026. Esta entrada documenta a mudança aqui porque o produto editorial é parte do ecossistema visível e consome dados deste banco.

  7. v3.7.3 2026-04-28 Resumo Semanal eleitoral: Opus 4.7 + ordem dinâmica por volume

    Changed

    • Modelo editorial do resumo semanal: Claude Opus 4.7 (primário) com extended thinking (budget_tokens=12000). Cadeia de fallback: Opus 4.7 → Opus 4.6 → Sonnet 4.6 → Haiku 4.5 — todos com thinking habilitado. Antes: Opus 4.6 sem thinking, com fallbacks Sonnet 4.6 → Haiku 4.5.
    • Ordem das seções do post: agora dinâmica, baseada no volume de menções da semana (decrescente). O pré-candidato com mais artigos publicados abre a análise; os demais aparecem em sequência. Antes: hierarquia fixa Lula → Flávio → Tarcísio → demais.
    • max_tokens: 8000 → 28000 (16K saída visível + 12K thinking).
    • Página Metodologia do dashboard: nova seção "Resumo semanal — produto editorial associado" descrevendo cron, modelo, ordem, continuidade narrativa e revisão humana.

    Fixed

    • Bug latente em generate_image_prompt — função lia data[c]['total_articles'] mas o campo nunca era preenchido em fetch_articles_data. Resultado: o prompt de imagem sempre caía no fallback genérico ("Two or three bold geometric shapes"), independentemente do número de candidatos ativos na semana. Agora total_articles é gravado por candidato (soma das contagens de sentimento) e a paleta/composição da imagem reflete o volume real.

    Notes

    • O resumo semanal vive no projeto blog-automation (/opt/blog-automation/produtores/weekly_summary.py na LXC-121), não no eleicoes2026. Esta entrada documenta a mudança aqui porque o produto editorial é parte do ecossistema visível e consome dados deste banco.
    • Próximo resumo com a nova configuração: sábado 02/05/2026.

  8. v3.7.2 2026-04-27 Upgrade de modelo e verificador anti-FP mais rigoroso

    Changed

    • Modelo de IA: todos os produtores (sentimento, tópicos, verificador, gênero, Zeitgeist) migram de gemini-2.5-flash-lite para gemini-3.1-flash-lite-preview via GEMINI_MODEL em src/gemini_client.py.
    • Verificador anti-FP: novo critério 6 — artigos sobre ciclos eleitorais anteriores (2014, 2018, 2022) sem gancho em 2026 são removidos. Corrige falsos positivos históricos indexados pelos buscadores.

  9. v3.7.0 2026-04-21 Zeitgeist: 6ª dimensão analítica

    Added

    • Nova página Zeitgeist — entre "Espectro Editorial" e "Análises" no menu. Mede a aderência do debate eleitoral a seis agendas globais estruturais: clima, transição energética, inteligência artificial, geopolítica, biodiversidade e crise da democracia.
    • Produtor src/produtores/zeitgeist.py — classificador multi-rótulo por artigo via Gemini 2.5 Flash Lite com JSON Schema enforced. Threshold de aderência confidence ≥ 0.5; evidência é trecho literal do texto para auditoria.
    • Schema:
      • Tabela article_zeitgeist(article_id, cluster, confidence, evidence, created_at) — N:M, com CHECK constraint nos 6 clusters canônicos.
      • Tabela article_zeitgeist_processed(article_id, processed_at) — distingue "ainda não classificado" de "classificado sem aderência" (a maioria dos artigos).
    • Pipeline incrementalrun_coleta.sh agora roda produtores/zeitgeist.py depois do verificador. Só processa artigos ainda não classificados.
    • Visualizações na página:
      • KPIs globais (artigos classificados, com aderência, cluster dominante, total de vínculos).
      • Bar chart horizontal de volume por cluster.
      • Ranking de aderência global por pré-candidato (% dos artigos que tocam agenda global).
      • Heatmap Candidato × Cluster (composição temática individual).
      • Linha temporal semanal por cluster.
      • Heatmap Cluster × Espectro Editorial.
      • Expander com amostras aleatórias de evidências por cluster.
    • Classificação retroativa de todo o corpus (~10 mil artigos) feita em 21/04/2026.

    Rationale

    Material central dos capítulos 4 ("A corrida pelo enquadramento") e 9 ("O que a máquina viu") do livro A Lente e o Espelho. A implementação com volume atual (baixo) evita reprocessamento caro em setembro/2026 quando o corpus estará várias vezes maior.

    Notes

    • "Democracia" tem escopo estrito: só erosão institucional, desinformação sistêmica, regulação de plataformas e ataques ao STF/TSE — não cobre rejeição/aprovação presidencial ou disputas comuns entre candidatos.
    • "IA" exclui menções a ferramentas editoriais da redação ("LE.IA do Estadão", resumos gerados por IA) — só conta IA como agenda política/social.
    • "Geopolítica" não é ativada automaticamente por declaração política em solo estrangeiro; o conteúdo precisa desenvolver relações internacionais substantivamente.
    • A maioria dos artigos retorna lista vazia de clusters — é o comportamento desenhado.

  10. v3.6.0 2026-04-20 Gênero jornalístico no dashboard + reordenação do Cenário Geral

    Added

    • Seção "Gênero jornalístico" na página Espectro Editorial — combina três blocos:
      • Filtro por gênero (multiselect) que afeta todos os gráficos de espectro abaixo. Permite perguntas como "de que espectro vêm as opiniões sobre X?" ou "como análises se distribuem entre veículos?".
      • Distribuição global de gêneros — bar chart horizontal com o volume de artigos por categoria (Notícia, Análise, Opinião, Entrevista).
      • Cruzamento Gênero × Espectro editorial — heatmap com contagem absoluta de artigos em cada combinação (genre × editorial_lean).
    • Os dados de articles.genre já vinham sendo coletados pelo produtor produtores/genero.py (Gemini 2.5 Flash Lite), mas não tinham UI dedicada.

    Changed

    • Cenário Geral — reordenamento de seções:
      • "Pré-candidatos monitorados" (grid de cards) agora aparece logo depois dos KPIs globais, antes da Timeline de cobertura. Dá contexto quantitativo por candidato antes do gráfico temporal.
      • "Exportar artigos (CSV)" movido para depois da Timeline de cobertura. O botão sai do alto da página e fica próximo aos dados que o leitor acabou de visualizar.

    Reason

    • articles.genre (4 classes) era o único sinal de classificação estruturada sem representação no dashboard. O filtro em Espectro Editorial é a integração mais útil: cruza gênero com viés editorial e permite recortes analíticos novos.
    • O grid de pré-candidatos funcionava como um "sumário visual" escondido abaixo da Timeline. Subindo-o, a página abre com os números por candidato em primeiro plano.

    Fixed

    • Margens dos gráficos de gênero (patch pós-deploy) — bar chart de distribuição e heatmap Gênero × Espectro estavam cortando os rótulos dos eixos ("Notícia/Análise/Opinião/Entrevista" e "Esquerda/Centro/Direita"). Margem esquerda aumentada para 90px e títulos redundantes dos eixos removidos.

  11. v3.5.3 2026-04-20 Limpeza de UI: Sobre vira seção de Metodologia, Análises vira página própria

    Changed

    • Página "Sobre" mesclada no topo de "Metodologia" — descrição do painel, disclaimer de imparcialidade e guia de navegação agora abrem a página Metodologia. Remove duplicação e encurta o menu.
    • Análises vira página independente — o feed de matérias SapiensLabs saiu de Metodologia e virou entrada própria no menu, entre Espectro Editorial e Metodologia.
    • Exportar CSV reposicionado — botão de download agora aparece logo após os KPIs globais (antes ficava depois dos tópicos emergentes).
    • Mapa de tópicos (treemap) limitado a top 25 — mantido o mínimo de 5 menções. Reduz ruído visual da cauda longa.
    • Dropdown de Pré-candidatos ordenado por menções (desc) — antes alfabético; agora os candidatos mais discutidos aparecem no topo.
    • Agenda de coleta corrigida na UI — KPI "Última coleta" e Metodologia passam a exibir 07h, 14h e 21h (BRT), refletindo o timer configurado na v3.4.2.

    Removed

    • Banner de disclaimer no topo do Cenário Geral ("Monitoramento automatizado — não é pesquisa eleitoral"). O mesmo texto permanece na Metodologia, agora a primeira coisa que o leitor encontra ao abrir a página.
    • Link "Ver mapa completo de tópicos →" após os tópicos emergentes. Âncora desnecessária — o treemap está a uma rolagem de distância.
    • Função page_sobre() removida do código; rota ?page=Sobre redireciona para Metodologia.

    Reason

    • Encurtar o menu lateral e reduzir duplicação entre "Sobre" e "Metodologia" — o leitor que buscava transparência metodológica já caía em Metodologia, e o disclaimer editorial aparece agora no topo dessa mesma página.
    • Separar Análises em página própria dá destaque ao feed e evita enterrá-lo dentro da metodologia.
    • Treemap cheio de 100+ tópicos fragmentava a leitura. 25 já cobre >80% do volume.

  12. v3.5.2 2026-04-20 Cenário Geral: tópicos emergentes e treemap

    Added

    • Destaque da semana — o tópico emergente com maior score agora aparece visualmente destacado (card com borda âmbar e fundo tintado) antes dos demais na lista.
    • Grid de tópicos emergentes — ao invés de lista vertical, os 7 tópicos da semana aparecem em grid de 4 colunas horizontais, logo após a Timeline de cobertura.
    • Mapa de tópicos (treemap) — nova seção no Cenário Geral com treemap de todos os tópicos com 5+ menções desde o início da coleta. Área proporcional ao volume; coloração por densidade.

    Changed

    • Posição dos tópicos emergentes — movidos para imediatamente após a Timeline de cobertura (antes ficavam abaixo do heatmap candidato × semana).
    • Evolução de tópicos — volta a ser full-width, sem competir com os emergentes em layout de colunas.

    Reason

    • Tópicos emergentes são o sinal editorial mais imediato — faz sentido aparecer logo depois do contexto temporal que a timeline oferece.
    • O treemap resolve a pergunta "quais são os tópicos?" de forma visualmente direta, mostrando de uma vez a concentração nos 4 dominantes e a cauda longa.