Home abre no agradecimento pelos 152.049 votos com board 1+3, trajetória, bandeiras do mandato, galeria de fotos e rodapé institucional; chrome novo (header home/interno, lockup de nome, menu mobile acessível) e /artigos//fotos com título compacto.
As superfícies de campanha saem do ar (308 de /conteudos, /jingles e /cards), junto com newsletter, estúdio público de cards e UI da Central/jingles; download de foto e .ics perdem o 1313. Sem migration, sem Consent novo e sem apagar dados do CMS.
A federal foi decidida em 04/10; o documento de cidade passa a servir
inteiro à eleição de Lula. Saem conta eleitoral/cadeira de Solla,
concorrentes e pré-candidatos, emendas e entregas (sem fetch do Portal
da Transparência no builder), acervo de falas, panorama regional e
sinais/demandas; demografia, economia e transporte ficam como contexto
da visita.
A página 1 vira só mobilização: KPIs oficiais do artefato TSE 2026
(Lula/Δ, X₁/X₂, Solla), papel determinístico da cidade, quem mobiliza,
movimento local do 2º turno, riscos e o painel "O que pedir e falar"
(pedido Lula 13; guardrail de votos em jogo no lugar do defeso).
O checklist cai de 10 para 8 itens (emendas_web e quem_investe saem;
relacao_campo/disputa_local reancorados no 2º turno); listas
preCandidates/investments/emendasIndicators saem do contrato (arquivos
antigos seguem aceitos em replay). O snapshot enxuga para rede +
conjuntura + demografia (cityReportTerritory.mjs removido).
Prova: unit 5.232 verdes, int do snapshot sem PII e sem os grupos
aposentados, lint/format/typecheck/knip limpos e rebuild da fixture de
Cruz das Almas (9 seções, 16 páginas contra 21, página 1 fechando sem
fallback).
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.
Artefato oficial por unidade (município e ZE de Salvador): TSE 2026
presidente por seção + Solla 2026 e a fatia de 2022 da análise
2º turno; cada número validado contra o baseline TSE e os totais da BA
pinados (pnpm build:second-round).
O relatório ganha a seção "2º turno no município (Lula × Flávio)" com
X₁/X₂ pela mesma fórmula do /potencial, o papel determinístico da cidade
(prioridade/mobilizacao/defesa/expansao) e o novo item de pesquisa
segundo_turno (movimento local com fonte); a seção fica fora da página 1
porque é determinística e a página 1 falha fechada por medição.
- C237 (CENA 02F): --paired desenha duas colunas zero-based por categoria
(inicial cinza, recente vermelha, valência positiva compartilhada), com
legenda de períodos, valor sobre cada barra e rótulo sob o par; até 4
categorias; design DEGRADED com sign-off humano de 2026-09-29.
- C238/C239 (CENAS 02G/02H): --motion gera MP4 H.264 local (6s @ 30fps,
frames determinísticos por seek + ffmpeg do repo) para o par emparelhado,
a coluna de 2 períodos e o número-âncora; C238 com sign-off humano de
2026-09-30 e C239 aguardando gate.
- Superfície: CLI, SKILL.md, hi-fi e specs novos (chartMotion/
chartMotionRender; SCRIPTS_SPEC_PINNED sincronizado).
Design tier: DEGRADED (inline, tier 4 — frontier sem quota).
Skills vendoradas (UPSTREAM.md): suíte Taste (design-taste-frontend,
gpt-taste, redesign-existing-projects, briefs de estilo, stitch-design-taste,
full-output-enforcement), web-design-guidelines e awesome-design-md.
Playwright CLI global + skill. Guardrail de marca do kit 1313 retirado:
DESIGN.md §7 (Evolution) passa a ser o dono vivo das regras visuais.
Doutrina ui-design-html.md §Skills de design, designer/-degraded e
designer-campanha-solla alinhados; changelog DESIGN1.
Replaneja o Briefing de capacitação C210: saem capa/objetivo/trajetória e as
recomendações genéricas (roteiro de 5 passos, justificativa científica, evitar,
conferir, limites); as 4 folhas passam a ser todas do recorte — defesas
(princípios + posições com fonte), essencial (fatos-âncora com fase + pedido
literal e uma linha de plano), qa 1/2 e qa 2/2.
- briefingContent: contrato novo (plan no lugar de script.steps; avoid/checklist
removidos; shed qa → defesas) e âncora item-level por sourceUrl — o id de
checklist repete e o ledger resolvia pelo primeiro item; par errado falha
fechado (normalizeQa não repassava o sourceUrl, corrigido).
- briefingRender: 4 folhas novas (defesas/essencial/qa/qa-2) e companion .md;
CSS portado do design (principles-copy/request-block/request-plan).
- build-dossie-solla-briefing: âncoras e comentários do fluxo novo.
- Design hi-fi refeito (4 cenas do recorte), skill e agente autor atualizados.
- Specs briefingContent/briefingRender reescritos; gate:fast verde (lint,
typecheck, 389 arquivos / 4310 testes).
- captura: swipe de toque real, scrollIntoView suave visível, upload de foto
(fixture.photo) e cursor centralizado na origem
- shot list: bloco graphics (hook/cta/profile/cover) como fonte da mensagem,
badge de rótulo e distance do swipe validados
- superfície: port do design revisado (trilho de comando + cap, hook com
pattern/coração, CTA com punho, capa) e cena nova profile (avatar IG/WA)
- reel foto-de-perfil draft (8 cenas, 30,2s) + fixture sintética sem PII
- testes unit do schema e changelog da evolução
Skill, núcleo (chartData), renderer (columnBody/CSS), design CENA 02A com sign-off humano e testes.
Entrega: docs/research/graficos-instagram/a-maioria-dos-internados-nos-dois-hospitais-de-v-2026-09-19-feed.png (worktree work/21, sem claim).
- rodapé com jorge-solla-positivo.png (data URI, frame 286×90) no lugar do lockup tipográfico; renderer fail-closed sem a marca
- paleta oficial: destaque/valência boa #e4102f, sinal de marca #184e92; amarelo/verde só nos ativos
- dono único da leitura do kit (scripts/lib/campaignKitAssets.mjs; root por import.meta.url) reusado pelo reel
- lineChart default alinhado ao vermelho oficial; CHART_COLORS/dossiê intactos
- skill/command e pinos de prosa/teste atualizados; SCRIPTS_SPEC_PINNED + impl plan + changelog
Ajuste local de brilho/contraste/saturação (clamps fixos ≤12%, alpha byte-a-byte) para aproximar a selfie do tom da arte-mestre; variante gerada 1× no ready do useCardCutout e escolhida pelo toggle no mesmo canvas da prévia e do PNG. Sem migration/Consent/rede/persistência; os 3 modelos e o recorte intocados. Crítica do designer certificada no tier primário (artefato revalidado sem DEGRADED).
Skill, núcleo (chartData), renderer (deltaBody/CSS), design CENA 02C com sign-off humano e testes.
Entrega: docs/research/graficos-instagram/equipes-saude-vdc-2020-2026-feed.png (worktree work/20, sem claim).
- skill + command finos: shot list é a fonte única; ajuste regenera, nada publica
- scripts/build-reel.mjs + scripts/lib/reel*.mjs: captura CDP com timestamps de
parede (sem drift), cursor/halo DOM-injected, zoompan do log de cliques,
legendas queimadas, capa 1080x1350-safe, concat H.264 1080x1920/30fps
- ffmpeg: FFMPEG_PATH -> PATH -> @ffmpeg-installer (registry-only) com probe fail-closed
- kit oficial da campanha: public/campaign-kit (marcas positiva/negativa, numero,
estrela) + manual em docs/campaign-kit + README de regras; skill e agente de
design referenciam o material
- 26 testes unit novos + pin do command; changelog 2026-09-18-c196
Closes#1155
O run real (Educação) entregava o dossiê mas o boletim media 3502px vs 1133px úteis: os 15 fatos do acervo (sphere area) dominavam os destaques com o summary integral e não havia contador nem fit no one-pager.
- dossieBlocks marca as falas do acervo com sourcePanel: true; buildBulletin as mantém contadas no "e mais N" e fora das vagas impressas (destaques/E mais ficam com findings com fonte)
- buildBulletin ganha printLimit; emitHtmlPairPdf ganha onBulletinOverflow (espelho do onDossierOverflow do C188) e o builder do tema re-renderiza com 2 fatos a menos até caber, fail-closed
- boletim subject (tema/instituição) ganha o contador C188 que só o município tinha, com copy.remaining por descritor
- contrato do tema documenta brief/summary (C188) na skill e no subagente researcher
Terceira variante da família de dossiês: recorte pela área canônica do
acervo (SPEECH_TOPICS), com o pipeline C186/C187 generalizado para a forma
subject via THEME_UNIT (generalização aditiva; C186/C187 byte-idênticos).
- resolveSpeechTopic no dono speechFacets (fail-closed, sem slug inventado)
- themeSnapshot + extract-theme-snapshot (THEME_REPORT_CONFIRM=1, read-only)
- build-dossie-solla-tema (pack medido, PDF A4 + .md + boletim 1 página)
- skill/comando/2 subagentes (researcher por era + redator) + specs
- cenas theme-only no descritor (acervo universo/amostra, abrangência,
lacunas, hierarquia de fontes, pills do boletim) certificadas pelo designer
Closes#1143
Revisão de produto a partir do uso real (UFBA): as seções deixam de ser
capadas e fluem por quantas folhas precisarem, com packing medido
(probe → grow/shrink por folha, scripts/lib/dossiePack.mjs) e guarda de A4
no emit; o dossiê ganha redação de abertura (narrative.json escrito por
sub-agente e auditado pelo orquestrador), parágrafo de consolidação por
era, páginas de síntese e gráficos (recursos com fase, abrangência,
trajetória) e acervo como amostra declarada. O dono (dossieBlocks/
dossieRender/dossieUnit/buildPdf) foi generalizado e o ramo cidade adotou
as mesmas decisões; skills, comandos, agentes redatores, specs e designs
hi-fi re-sincronizados.
Dono único de orçamento de texto em reportText.mjs (capList,
excerptDeepDive, joinWithRemainder, summaryText/summarySurfaceText,
summaryListText), reusado por C163 e C186. Contrato summary por item nos
dois arquivos de pesquisa; superfície de resumo nunca corta com "…" e
aponta o aprofundamento; toda lista capada mostra contador; builders com
2 passadas guard-gated (integral → ponteiro → die fail-closed).
Closes#1136
Generaliza aditivamente o pipeline C186 (default município; specs verdes) via o
descritor scripts/lib/dossieUnit.mjs (municipality|institution), extrai o emit
A4/fit-guard para scripts/lib/buildPdf.mjs e a receita read-only para
scripts/lib/readOnlyExtract.mjs.
- Catálogo fail-closed src/lib/institutionCatalog.ts + institutionNameAliases.ts
(seed UFBA/Correios/Enfermagem; escape one-off --slug/--name; dedup).
- Skill/command/subagente /dossie-solla-instituicao; eras A/B/C reusadas.
- Abrangência instituição × setor × rede nunca somada; era sem fonte vira página
de lacuna explícita; lista capada declara "e mais N" (regra C188 no dono).
- Boletim modelo 1×A4 com fase junto ao valor, sem fontes, sem CTA; herda apenas
fatos com fonte do dossiê (incl. falas do acervo read-only).
- Sem schema/migration/DB write; artefatos gitignored.
O builder cortava o texto no meio com "…" quando não cabia no A4, perdendo
informação. Agora:
- contrato de pesquisa ganha `brief` (`title` ≤80 / `note` ≤120) reescrito pelo
researcher: o PDF imprime o brief reformulado e o registro/.md mantém
`answer`/`details` integrais (sem fonte nova, sem trocar a fase);
- sem `brief` o renderer cai no texto completo e a guarda de fit A4 falha
fechado — nunca mais corta em silêncio;
- tabelas longas (lacunas, notícias) e os cards de "Atuação registrada" das eras
são paginados em folhas de continuação: nada é truncado nem descartado;
- corrige honrarias da Era C vazando para a página da Era B;
- remove o `clipCopy`/`MAX_NEWS_ROWS`; SKILL.md e agent doc documentam o `brief`.
Contrato novo emendasIndicators[] (author+sphere obrigatórios, fonte obrigatória, fail-closed
para lacuna) alimenta um bloco indicatorList na página 1: uma linha por indício com
valor, finalidade, badge de esfera (município/região/polo) e link de fonte. O painel
fixo "O que NÃO anunciar" sai da página 1 e o par vira panel único de anúncio (3 bullets
invariantes viram 1), preservando a advertência de defeso. Atualiza a skill canônica e
os testes de validador/blocks/render.
O `pnpm knip` imprimia `ERROR: Error loading src/payload.config.ts
(...server-only...)` e saía 0 — gate verde com o ERROR silencioso, no CI
(`ci-pr.yml`/`deploy.yml`) e local. O plugin embutido do Payload carregava
`src/payload.config.ts` via jiti sob as condições Node padrão e o import
transitivo de `server-only` lançava (só o `react-server` traz o `empty.js`);
o `paths.server-only` do `knip.json` alimenta apenas o resolver estático, não
o carregamento jiti (e o `tsconfig` alias, que funcionaria no load, foi
rejeitado por re-apontar a guarda server/client — classe OPS69).
Fix: `"payload": false` e as contribuições do plugin explicitadas no
`knip.json` (`!src/payload-types.ts` load-bearing; `!src/migrations/**`
paridade), removendo o bloco `paths` inerte. Provado: `pnpm knip` sai 0 sem o
ERROR, um export morto plantado é detectado, e a corrida de controle com
`server-only` neutralizado dá findings idênticos.
Plano: docs/plans/ops-knip-importmap-artifact-impl.md
Nenhum modelo openai/* (luna/sol-fast/terra inclusive) fora dos agentes de design, por /models, --model, small_model ou config. Cobre o uso de gpt-5.6-luna em sessoes build. Regra always-on no AGENTS.md + doutrina/AGENT-OPS; guard estatico em tests/unit/openaiProviderScope.unit.spec.ts.
O frontier designer (openai/gpt-5.6-sol, OAuth ChatGPT Plus) só roda Criar/Criticar o artefato de item que muda UI. A regra vive na doutrina ui-design-html.md §Escopo de dispatch (gate de 3 perguntas + lista fechada); plan-issue e execution-pipeline apontam para o dono; o agente recusa fora do escopo e o smoke do guard vai para o designer-degraded.