From 31f78f07ad0da66be8e0fa53c47f030a17198bec Mon Sep 17 00:00:00 2001 From: Francisco Solla Date: Fri, 9 Oct 2026 03:34:05 -0300 Subject: [PATCH] =?UTF-8?q?feat(briefing):=20pedido=20dual=201313=20+=20Lu?= =?UTF-8?q?la=2013=20e=20miss=C3=A3o=20do=202=C2=BA=20turno?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit O briefing de capacitação passa a renderizar o pedido dual (deputado federal 1313 e, no 2º turno, Lula 13) e a exigir ao menos uma pergunta de 2º turno no Q&A; dossiê e boletim seguem sem CTA (prova material do argumento, não peça de rua). Registra o changelog da entrega. --- .../briefing-capacitacao-solla/SKILL.md | 27 +++++++++++++++---- .agents/skills/dossie-solla-cidade/SKILL.md | 12 +++++++++ .opencode/agent/briefing-capacitacao-solla.md | 9 ++++--- .../2026-10-09-relatorio-cidade-2turno.md | 1 + scripts/lib/briefingRender.mjs | 4 +-- tests/unit/briefingRender.unit.spec.ts | 2 ++ tests/unit/briefingSkill.unit.spec.ts | 2 ++ 7 files changed, 47 insertions(+), 10 deletions(-) create mode 100644 docs/changelog/2026-10-09-relatorio-cidade-2turno.md diff --git a/.agents/skills/briefing-capacitacao-solla/SKILL.md b/.agents/skills/briefing-capacitacao-solla/SKILL.md index 33eae059..317fbfd7 100644 --- a/.agents/skills/briefing-capacitacao-solla/SKILL.md +++ b/.agents/skills/briefing-capacitacao-solla/SKILL.md @@ -1,6 +1,6 @@ --- name: briefing-capacitacao-solla -description: 'Gera o Briefing de capacitação Solla 1313 por recorte (cidade · instituição · tema): PDF A4 de até 4 páginas + companion .md, derivado do dossiê já pesquisado (sem segunda pesquisa factual), todo de recorte — princípios/crenças e defesas de Solla com fonte, fatos-âncora e o pedido literal do voto 1313, e perguntas prováveis × melhores respostas dos dois lados; aceita um recorte ou um lote separado por vírgula.' +description: 'Gera o Briefing de capacitação Solla 1313 por recorte (cidade · instituição · tema): PDF A4 de até 4 páginas + companion .md, derivado do dossiê já pesquisado (sem segunda pesquisa factual), todo de recorte — princípios/crenças e defesas de Solla com fonte, fatos-âncora e o pedido literal do voto (1313 e, no 2º turno, Lula 13), e perguntas prováveis × melhores respostas dos dois lados; aceita um recorte ou um lote separado por vírgula.' --- # Briefing de capacitação Solla 1313 (C210) @@ -13,7 +13,8 @@ capa, manual genérico, roteiro de passos, anti-padrões nem limites: 1. **O que Solla defende** — princípios/crenças do recorte (abertura) + posições com lastro (fonte e data); 2. **O essencial do recorte** — fatos-âncora com **fase junto ao valor** e o - **pedido literal** do voto + **uma linha** de plano; + **pedido literal** do voto (1313 e, no 2º turno, Lula 13) + **uma linha** de + plano; 3. **Perguntas prováveis × melhores respostas (1/2 e 2/2)** — as perguntas reais do recorte, metade do documento, com os dois lados. @@ -29,6 +30,16 @@ invocação) e também roda sozinho. O layout vem do design hi-fi aprovado `docs/plans/briefing-capacitacao-solla-ui-design.html` — o port é classe-a-classe, sem improviso visual. +## Missão do 2º turno (Lula × Flávio — 25/10/2026) + +O briefing é o insumo de quem pede voto na rua: desde 08/10/2026 o pedido é +**dual** — o voto 1313 (Solla) e, no 2º turno, o voto 13 (Lula). O pedido é +**literal do renderer** (não se reescreve no JSON); o `plan` é a única linha em +que o autor diz como combinar os dois. Os números do 2º turno (Lula × Flávio, +X₁/X₂) **não entram** neste contrato: vivem no relatório de cidade +(`relatorio-cidade`, seção "2º turno no município"), e cenário/estimativa seguem +proibidos aqui. + ## Quando usar - A coordenação pede "o briefing de " para quem vai panfletar/pedir @@ -131,7 +142,7 @@ Escrito pelo autor, validado pelo build (`scripts/lib/briefingContent.mjs`): { "factId": "era_b_equipamentos", "sourceUrl": "https://…", "title": "≤120", "note": "≤200" }, { "gapReason": "sem fala própria localizada", "title": "…", "note": "…" } ], - "plan": "≤220 chars — uma linha de plano de voto/compromisso nomeado", // obrigatório + "plan": "≤220 chars — uma linha de plano de voto/compromisso nomeado (pode dizer como combinar o 1313 com o voto 13 no 2º turno)", // obrigatório "qa": [ // ≥4, com ≥1 "direita" e ≥1 "esquerda" { "side": "direita|esquerda|entrega", "question": "≤180", "acknowledge": "≤200", "answer": "≤520", "close": "≤200", @@ -151,6 +162,9 @@ Regras duras: autor copia o `sourceUrl` do item do research no campo `sourceUrl` do âncora (o par `factId` + `sourceUrl` precisa bater — par errado falha fechado); - `qa` cobre os dois lados (≥1 `direita` e ≥1 `esquerda`); `entrega` é opcional; + desde 08/10/2026, inclua **ao menos uma pergunta de 2º turno** (por que votar + em Lula; o que está em jogo para a cidade) — ancorada no mesmo ledger, sem + cenário nem número de pesquisa; - **proibido** qualquer chave de cenário/estimativa/staff-only (`estimatedVotes`, `scenario`, `projection`, `polls`, …) — o briefing não tem campo numérico; valor/fase vêm do fato-âncora no render; @@ -161,8 +175,8 @@ Regras duras: perguntas** (o build divide a lista ao meio). O pedido é **literal do renderer** (não reescreva no JSON): "Posso contar com -você? Para deputado federal, **vote 1313, Jorge Solla**." — o `plan` é a única -linha de orientação que o autor escreve. +você? Para deputado federal, **vote 1313, Jorge Solla.** E no 2º turno, **vote 13, Lula.**" — o `plan` é a única linha de orientação que o autor escreve +(ex.: onde/como combinar o pedido municipal com o voto em Lula). ## Recibo do autor @@ -221,6 +235,9 @@ já carrega o aviso de insumo. fonte; lacuna explícita em vez de inferência. - **Sem cenário eleitoral/estimativa/staff-only** (nada de `estimatedVotes`, projeção, pesquisa); o briefing não promete efeito. +- **Pedido dual literal**: a folha "O pedido" renderiza 1313 + Lula 13 (2º + turno) — não é campo do JSON; números de 2º turno continuam fora do briefing + (vivem no relatório de cidade). - **Empenho ≠ pagamento**; esfera explícita nunca somada; leitura relativa (nunca % estadual absoluto); PII mínima (telefone/e-mail nunca entram). - **Voz com dono único**: reusa `.opencode/skills/solla-comunicacao/SKILL.md` + diff --git a/.agents/skills/dossie-solla-cidade/SKILL.md b/.agents/skills/dossie-solla-cidade/SKILL.md index 527666f6..5c5f2acd 100644 --- a/.agents/skills/dossie-solla-cidade/SKILL.md +++ b/.agents/skills/dossie-solla-cidade/SKILL.md @@ -15,6 +15,18 @@ eleitor, sem declaração de fontes) **e** o **Briefing de capacitação** (3º entregável: até 4 páginas para quem vai pedir o voto 1313, insumo interno). Os layouts vêm dos artefatos hi-fi aprovados pelo `designer`. +## Missão do 2º turno (Lula × Flávio — 25/10/2026) + +O dossiê é a **prova material** do 2º turno: o que Solla e o campo PT/federal +entregaram à cidade sustenta o pedido de voto para Lula em 25/10. O **boletim +modelo** continua sem CTA (insumo de comunicação, não peça de rua); o **briefing +de capacitação** (3º entregável) leva o pedido **dual** — 1313 e, no 2º turno, +Lula 13 (ver `briefing-capacitacao-solla`). Nada muda no escopo da pesquisa por +era (o dossiê é histórico e com fonte; ruído eleitoral de 2026 segue excluído das +buscas). O recorte numérico do 2º turno por município/ZE **não vive aqui**: vive +no relatório de cidade (`relatorio-cidade`, seção "2º turno no município", +artefato de `pnpm build:second-round`) e não deve ser inventado no dossiê. + ## Quando usar - A comunicação pede "o dossiê de ", o "boletim modelo de " diff --git a/.opencode/agent/briefing-capacitacao-solla.md b/.opencode/agent/briefing-capacitacao-solla.md index b657e7f7..9aeb5ba8 100644 --- a/.opencode/agent/briefing-capacitacao-solla.md +++ b/.opencode/agent/briefing-capacitacao-solla.md @@ -27,11 +27,13 @@ dossiê daquele recorte estar pesquisado. - `essential` (≥3) — fatos-âncora que sustentam a conversa (sem trajetória de formação), com a fase junto ao valor; - `plan` — **uma linha** (≤220 chars) de plano de voto/compromisso nomeado - (o pedido literal é do renderer, não o reescreva); + (o pedido literal — 1313 e Lula 13 no 2º turno — é do renderer, não o + reescreva; você pode usar o `plan` para dizer como combinar os dois); - `qa` (≥4; mire **8–10**) — perguntas prováveis com `side` (`direita|esquerda|entrega`), `question`, `acknowledge`, `answer` (ancorada em `factId` real ou declarada como lacuna) e `close`, cobrindo os dois - lados. + lados; inclua **ao menos uma pergunta de 2º turno** (por que votar em Lula; + o que está em jogo para a cidade), sem cenário nem número de pesquisa. 3. Devolver **apenas o recibo curto** (seção "Recibo do autor" da skill). ## Limites @@ -51,7 +53,8 @@ dossiê daquele recorte estar pesquisado. (`estimatedVotes`, `scenario`, `projection`, `polls`, …): o briefing é capacitação, não leitura eleitoral. - Copy pt-BR, sem PII (telefone/e-mail nunca), sem CTA público, sem promessa de - entrega; o pedido literal do voto 1313 é do renderer. + entrega; o pedido literal do voto (1313 e, no 2º turno, Lula 13) é do + renderer. - Reuse a voz do `solla-comunicacao` (rebates e fórmula de resposta a crítica), sem inventar tom novo. - **Não** faça pesquisa web nova, **não** edite os `research.json`, **não** rode diff --git a/docs/changelog/2026-10-09-relatorio-cidade-2turno.md b/docs/changelog/2026-10-09-relatorio-cidade-2turno.md new file mode 100644 index 00000000..f463c192 --- /dev/null +++ b/docs/changelog/2026-10-09-relatorio-cidade-2turno.md @@ -0,0 +1 @@ +**Relatório de cidade no 2º turno (Lula × Flávio, 25/10/2026) — artefato TSE 2026, seção própria no PDF e pedido dual no briefing (2026-10-09):** a família de documentos de cidade passou a servir explicitamente à eleição de Lula no 2º turno. Novo artefato commitado `src/lib/electionAggregates/bahia-second-round-2026.json` (loader `src/lib/bahiaSecondRound.ts`, regra compartilhada `src/lib/secondRoundRole.ts`, builder `pnpm build:second-round` / `scripts/build-second-round-ba.mjs`): cruza o TSE 2026 presidente 1º turno por seção (o mesmo shard oficial do `/potencial`, agregado à geografia do catálogo — Salvador por ZE) com a fatia presidencial de 2022 e o resultado federal de Solla 2026 da análise interna (`analise-eleicoes-2026/nota-solla-2turno`), valida cada número contra `bahia-federal-baseline.json` e contra a análise, e pina os totais da BA (Lula 5.664.771 × Flávio 2.442.585; Solla 152.049). O relatório de cidade ganha a seção **"2º turno no município (Lula × Flávio)"** (nº 2, logo após a conta eleitoral): números oficiais 2022→2026 (Lula, adversário Bolsonaro→Flávio, Solla, comparecimento, abstenção, brancos+nulos), X₁/X₂ pela MESMA fórmula da página pública, papel determinístico da cidade — `prioridade`/`mobilizacao` (Lula caiu e Solla cresceu), `defesa` (os dois caíram) e `expansao` — e o movimento local pesquisado no novo item de checklist `segundo_turno` (atos, palanques, posições, com URL+data; sem fonte vira lacuna). A seção é **cenário, não promessa** (X₁/X₂ são votos em jogo; persuasão em eleição geral tem efeito médio ~0) e fica **fora da página 1** de propósito: a página 1 é medida e falha fechada, e conteúdo determinístico não encolhe no fallback de texto. Na família do dossiê, o **briefing de capacitação** passa a renderizar o **pedido dual** ("vote 1313, Jorge Solla. E no 2º turno, vote 13, Lula.") com ao menos uma pergunta de 2º turno no Q&A, sem cenário/estimativa no contrato; dossiê e boletim seguem sem CTA (prova material do argumento, não peça de rua). Testes: 8 unit novos/atualizados no artefato e na seção (cobertura do catálogo 435, pins de totais, reclassificação dos papéis, ZE 19/15/9/12 × 16/4, X₁/X₂ da ZE 1 do Salvador), pins da missão nas skills `relatorio-cidade` e `briefing-capacitacao-solla`, e o literal do pedido dual no renderer; o build real (Chromium + snapshot de Amargosa) foi rodado com a seção nova e a página 1 segue fechando no orçamento. diff --git a/scripts/lib/briefingRender.mjs b/scripts/lib/briefingRender.mjs index 6fd60a80..c3f95587 100644 --- a/scripts/lib/briefingRender.mjs +++ b/scripts/lib/briefingRender.mjs @@ -16,7 +16,7 @@ import { resolveDossierUnit } from './dossieUnit.mjs' import { htmlEscape, moreItemsLabel } from './reportText.mjs' const BRIEFING_REQUEST_LINE = - 'Posso contar com você? Para deputado federal, vote 1313, Jorge Solla.' + 'Posso contar com você? Para deputado federal, vote 1313, Jorge Solla. E no 2º turno, vote 13, Lula.' const BRIEFING_PRINT_CSS = ` :root { @@ -263,7 +263,7 @@ export const renderBriefingMd = (content, { unit, report }) => { '', '## O pedido', '', - '> “Posso contar com você? Para deputado federal, vote 1313, Jorge Solla.”', + '> “Posso contar com você? Para deputado federal, vote 1313, Jorge Solla. E no 2º turno, vote 13, Lula.”', '', `**Plano:** ${content.plan}`, '', diff --git a/tests/unit/briefingRender.unit.spec.ts b/tests/unit/briefingRender.unit.spec.ts index 12202aa7..e24975b1 100644 --- a/tests/unit/briefingRender.unit.spec.ts +++ b/tests/unit/briefingRender.unit.spec.ts @@ -111,6 +111,7 @@ describe('renderBriefingHtml', () => { it('renders the literal request with the vote number and the one-line plan', () => { expect(html).toContain('vote 1313, Jorge Solla') + expect(html).toContain('vote 13, Lula') expect(html).toContain('request-line') expect(html).toContain('request-block') expect(html).toContain('compromisso nomeado') @@ -178,6 +179,7 @@ describe('renderBriefingMd (companion superset)', () => { expect(md).toContain(droppedQuestion.question) expect(md).toContain('Insumo interno de capacitação — não publicar') expect(md).toContain('vote 1313, Jorge Solla') + expect(md).toContain('vote 13, Lula') expect(md).toContain('**Plano:** Combine onde, quando e como votar') expect(md).toContain('[fonte](https://saude.test/ambulancia)') expect(md).toContain('## O que Solla defende') diff --git a/tests/unit/briefingSkill.unit.spec.ts b/tests/unit/briefingSkill.unit.spec.ts index 56f3dcbb..7ff62164 100644 --- a/tests/unit/briefingSkill.unit.spec.ts +++ b/tests/unit/briefingSkill.unit.spec.ts @@ -37,6 +37,8 @@ describe('skill /briefing-capacitacao-solla documents the flow', () => { it('pins the hard product literals', () => { expect(skill).toContain('Insumo interno de capacitação — não publicar') expect(skill).toContain('vote 1313') + expect(skill, 'the 2º-turno mission is part of the ask').toContain('Missão do 2º turno') + expect(skill, 'the pedido is dual since 08/10/2026').toContain('vote 13, Lula') expect(skill).toMatch(/4 páginas/) expect(skill).toContain('insumo interno') expect(skill).toMatch(/sem CTA público/i)