Commit graph

1138 commits

Author SHA1 Message Date
Francisco Solla
33573dd0c0 fix(C224): saneia o env do spawn do yt-dlp (Closes #1338) 2026-09-25 10:14:39 -03:00
Francisco Solla
0b05dfe9a0 fix(C223): aceita falas longas no acervo
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-25 02:11:56 -03:00
Francisco Solla
57d24687eb chore(OPS129): atualiza modelos das flags do worktree
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-25 01:48:20 -03:00
Francisco Solla
01831446df feat(S41): assina e ancora eventos de agenda do link (Closes #1335) 2026-09-25 01:47:18 -03:00
Francisco Solla
0fa618d0af fix(ia-egress): estabiliza a rota ate o deepseek com proxy na tailnet + probe no deploy 2026-09-25 01:43:37 -03:00
Francisco Solla
c013de13d6 fix(S36-FOLLOWUP): logo do header da Central sem corte — janela na razão da tinta 2026-09-25 00:44:57 -03:00
Francisco Solla
63bd370b6c feat(C222): apagar uma peça na Central de Conteúdos (Closes #1330)
Hard delete por peça (sem lixeira/lote/telemetria) em qualquer estado, com confirmação que nomeia o link público só quando publicado; access próprio da vertical + admin (advisor/leader fail-closed), cascata da mídia pós-commit e bust da tag contentPieces no afterDelete; máquina do diálogo extraída no 3º call site (C183/C199/C222).
2026-09-24 23:49:28 -03:00
Francisco Solla
4e7b844419 fix(C192/S28/C219): busca por tema indisponivel — thinking do deepseek-flash truncava o JSON 2026-09-24 23:09:49 -03:00
Francisco Solla
b5c4e274a2 fix(C220-FOLLOWUP): early-stop da janela de link do Instagram na Central
O resolver pedia a janela de 500 (ate 10 paginas de cursor) antes de casar o
shortcode; erro em pagina >=2 virava 'indisponivel' mesmo com o post na pagina 1.
O dono da paginacao ganha shouldStopAt (board/sync intocados) e o resolver para
na pagina que contem o post — a colagem tipica volta a custar uma chamada.
2026-09-24 22:59:40 -03:00
Francisco Solla
c9ab467f23 feat(C217): cortes e links compartilhaveis na fonte "Falas na internet" (Closes #1293) 2026-09-24 20:17:54 -03:00
Francisco Solla
92d975b8bf refactor(C216-FOLLOWUP-DRY): aplica achados do simplify (Related #1325) 2026-09-24 19:29:27 -03:00
Francisco Solla
72a692f586 refactor(C216-FOLLOWUP-DRY): excerpt e chips compartilhados nos cards de fala (F3) (Related #1325) 2026-09-24 19:29:27 -03:00
Francisco Solla
b119d203aa feat(S37): liderancas que aparecem nas pecas na Central de Conteudos (Closes #1303)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-24 17:40:57 -03:00
Francisco Solla
d0063d39f3 refactor(C216): aplica achados do simplify (Related #1292) 2026-09-24 17:01:42 -03:00
Francisco Solla
425361d278 feat(C216): terceira fonte do acervo — falas na internet (Closes #1292) 2026-09-24 17:01:42 -03:00
Francisco Solla
13b5a3c1d1 feat(S38): alterna peças e cards no board e certifica o design (Closes #1304) 2026-09-24 16:57:03 -03:00
Francisco Solla
e7055ae33d refactor(S38): reusa o label do dono, fidelidade ao artefato e simplifica o filtro (Related #1304) 2026-09-24 16:57:03 -03:00
Francisco Solla
e8d88803fe test(S38): ajusta o board misto e a navegação do e2e do catálogo (Related #1304) 2026-09-24 16:57:03 -03:00
Francisco Solla
bf2c7a25c4 feat(S38): cards personalizáveis como itens do catálogo (Closes #1304) 2026-09-24 16:57:03 -03:00
Francisco Solla
f750084c41 fix(cards): tiles da home usam espaçador de proporção (WebKit #265243)
No Orion/Safari os seis tiles de modelos colapsavam (só os rótulos
ficavam): a caixa do CardModelTile tirava a altura de um `aspect-ratio`
inline sendo filha de um flex com `overflow: hidden` — o construto do
bug WebKit #265243 (fix só no WebKit main 2026-05), invisível para o CI
Chromium-only.

O tile passa a tirar a altura de um espaçador em fluxo com
padding-bottom percentual (data-card-tile-ratio). Guardas: unit por
modelo (RED sem o fix), sweep de convenção nos cards e e2e de geometria
após relayout forçado. Post-mortem + changelog na mesma entrega.
2026-09-24 16:41:18 -03:00
Francisco Solla
59f70dccf3 fix(C221): "Limpar" do omnibox não quebra linha no mobile (Closes #1313) 2026-09-24 16:35:13 -03:00
Francisco Solla
02ca466469 feat(S40): arte genérica do Time do estadual e janela vazia sem silhueta (Closes #1316) 2026-09-24 16:23:44 -03:00
Francisco Solla
cdd188755c style(C218): plano de implementação e spec no formato do prettier 2026-09-24 15:51:37 -03:00
Francisco Solla
9c0b44a2c0 feat(C218): skill catalogo-falas-web — atualização incremental do catálogo (Closes #1294) 2026-09-24 15:51:37 -03:00
Francisco Solla
11de48f726 feat(S39): seção da Central de Conteúdos na home (Closes #1305) 2026-09-24 14:53:36 -03:00
Francisco Solla
38e6742673 feat(C219): paridade de busca e filtros nas gravações do acervo (Closes #1295)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
Classificação automática com proveniência (job + CLI recordings:classify), facetas ano/tema/alcance/município/duração na URL canônica, busca por tema no corpus próprio, ordenação e a barra de filtros portada do design aprovado sobre os shells compartilhados. Deep-links existentes byte-idênticos; Câmara intocada.
2026-09-24 04:00:06 -03:00
Francisco Solla
8f3118312a fix(C220): link do proprio Instagram baixa e cataloga a peca (Closes #1302) 2026-09-24 03:51:17 -03:00
Francisco Solla
8318fb5fce feat(C215): ingestão de falas da internet no acervo — origem web, espelho privado e catálogo (Closes #1291) 2026-09-24 03:26:10 -03:00
Francisco Solla
2c8b38f2be feat(S34): colinha usa a arte exata com a linha do estadual preenchida (Closes #1298) 2026-09-24 02:20:44 -03:00
Francisco Solla
9069d23d88 feat(S33): ajuste da foto do card do time sem limite (Closes #1297) 2026-09-24 01:38:06 -03:00
Francisco Solla
3864a823ff fix(S32): e2e do C213 acompanha a coluna variant do evento 2026-09-23 18:12:42 -03:00
Francisco Solla
e8a190005a feat(S32): contadores anônimos de download dos cards na home staff (Closes #1273) 2026-09-23 18:12:42 -03:00
Francisco Solla
68065032f5 fix(S28): lê os headers só no caminho de tema e estabiliza o e2e do streaming
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-23 15:35:21 -03:00
Francisco Solla
8d81883509 feat(S28): busca por tema na Central de Conteúdos pública 2026-09-23 15:35:21 -03:00
Francisco Solla
f47c2645ac feat(C213): contadores anônimos de circulação por peça na Central de Conteúdos (Closes #1258)
Collection contentEvent (hidden, sem hooks, sem PII) + beacon público
POST /api/content-events fail-soft, download contado no servidor na rota
de mídia, agregação em uma query group-by e a coluna "Circulação" na lista
interna + painel na ficha (port classe-a-classe do artefato estendido,
crítica final do designer certificada).
2026-09-23 15:29:43 -03:00
Francisco Solla
75e5825b05 refactor(S27-FOLLOWUP-DRY): dono único do OG image de fallback do frontend público (Closes #1276)
O fallback de imagem OG (própria → global `metadata` → null, sempre absoluto
no deployment origin) deixa de estar copiado em 6–7 páginas públicas e ganha
o dono server-only `src/utilities/ogImageReads.ts` (`resolveOgImage(configured)
→ { url, media }`), com `resolveShareLinkOgImageUrl` delegando (sem twin) e os
8 consumidores migrados — 2 do S27, jingles, corte, abaixo-assinado ×2, artigo
e layout. `seo.ts` segue puro; sem migration, sem Consent/access, Impeccable A.

- unit novo do resolver (8 casos) + pin do módulo em codebaseConventions; int
  do shareLink verde sem tocar asserção; e2e frontendConteudos/frontendJingles/
  campaignSpeechCut/frontendShareLink/frontend verdes, com asserts novos de
  og:image (helper `metaContent` extraído do spec do share-link)
- dono novo entra no E2E_AFFECTED_MANIFEST nas 4 entradas de OG públicas
- deltas intencionais registrados: deployment origin no lugar do canônico em
  corte/abaixo-assinado/artigo e OG absoluto no layout
2026-09-23 14:30:40 -03:00
Francisco Solla
48a01de58b fix(S29-FOLLOWUP): .ics do link de anúncio e feed — folding RFC 5545 (75 octets) no owner ical.ts (Closes #1281) 2026-09-23 14:16:25 -03:00
Francisco Solla
c6620c2511 feat(C214): briefing 100% recorte — 4 folhas do recorte + âncora item-level (Closes #1284)
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).
2026-09-23 13:17:37 -03:00
Francisco Solla
2a0dca6243 fix(S29): achados da review — snapshot pós-rebase, manifest e2e e a11y do anúncio
- snapshot drizzle da migration regenerado pós-rebase (inclui as tabelas do
  S27; sem ele o próximo migrate:create recriaria content_piece)
- manifest e2e: CampaignFooter/jingleReads/campaignTime acordam o
  frontendShareLink; dynamicParams inerte removido da rota .ics
- anúncio: dl válido (Local sem dd), aria-live só no status/chip, sem
  hasImage/cast; hook direct deixa o erro de URL falar antes (+ teste int)
- débitos triados no impl plan (folding .ics -> #1281; deferidos com gatilho)

Related #1268
2026-09-23 12:37:00 -03:00
Francisco Solla
b0bac78090 feat(S31): colinha de voto — 6º modelo com o estadual escolhido (Closes #1272) 2026-09-23 12:33:04 -03:00
Francisco Solla
b8051bb7e0 feat(S29): link com destino trocável e página de anúncio da atividade
- shareLink ganha modo (direct|announcement), pool de destinos com "Destino no
  ar" por linha e dados do evento; destination escalar sai via migration com
  backfill lossless (legado vira direct com destino no ar)
- página de anúncio pública portada classe-a-classe, header campaign-site
  extraído (CampaignPageHeader) e ativação/troca sem reload por poll da rota
  /api/share-link/<slug>/live (fail-closed, no-store)
- agenda Google (action=TEMPLATE) + .ics por rota sob o slug; compartilhar o
  link curto (kind event); S19 intacto e 404 uniforme preservado

Related #1268
2026-09-23 11:48:12 -03:00
Francisco Solla
dda55adc27 feat(S27): Central de Conteúdos pública — Peça voto pra Solla 1313
/conteudos + /conteudos/<slug>: catálogo filtrável (Tipo · Cidade · Região ·
Tema · Instituição + termo na URL canônica), play sob demanda (Vídeo/Áudio só
carregam no toque; Foto com preview leve), Baixar e Compartilhar do próprio
card com a mensagem de voto por tipo (wa.me sem destinatário, editável; "A
mídia" usa a folha nativa e cai em download onde o aparelho não suportar) e o
card personalizado como peça sintética do catálogo → /cards.

- leitura pública nova (contentPieceReads) cacheada na tag contentPieces com o
  gate where status=publicado + contentPieceIsPublic; a rota GET
  /conteudos/<slug>/midia reusa buildPrivateMediaResponse (range, disposition,
  private no-store, 404 uniforme) com download jorge-solla-1313-<slug>.<ext> e
  a allowlist inline do dono estendida (webp/gif/avif + áudios das peças)
- contrato público puro do catálogo (filtros/VM/download) + mensagens de voto
  (contentPieceShare); OG com fallback do global; conteudos entra nos slugs
  reservados; kill switch por peça vale na hora (lista, página, rodapé/selo);
  descoberta condicional no CampaignFooter e no header local
- UI portada classe-a-classe do design aprovado (cenas 01–08, com as cenas
  06–08 estendidas no trigger a); sem migration, sem Consent e sem access novo;
  contentMedia segue privada (sem segunda cópia de mídia)
- testes: 2 unit specs novos, 18 casos int (leitura pública + rota de mídia) e
  e2e frontendConteudos (5 casos); manifest e curado atualizados
- follow-up de engenharia: #1276 (docs/plans/escala-dry-pos-s27.md)

Closes #1255
2026-09-23 11:13:57 -03:00
Francisco Solla
6480768926 feat(S30): card Time do estadual — 5º modelo com as 53 dobradinhas (Closes #1271) 2026-09-23 10:06:17 -03:00
Francisco Solla
cb61cf1152 feat(C211): Central de Conteúdos interna — envio em lote, link, catalogação e publicação
Envio em lote (1 request raw-body por arquivo, fan-out ≤2, até 50 arquivos) e
adicionar por link (Instagram/YouTube; extração só pela Graph API da conta
própria, senão peça-link) em /campanha/comunicacao/conteudos. Cada peça tem
estado próprio (Processando/Pronto/Falhou + Reprocessar), transcrição/texto e
catalogação automática revisável; publicar/despublicar preserva arquivo, slug
e publishedAt.

- collections contentPiece + contentMedia (upload privado no S3) e migration
  20260923_032714_add_content_piece (slug único gerado no 1º publish,
  sourceUrl única, searchText com índice trigram)
- pipeline reusa C199 (job after() + reaper + retry condicional, transcrição
  DeepInfra, ffmpeg/chunk), o classificador de facetas do acervo e o
  institutionCatalog; curatedFields impede o job de sobrescrever curadoria
- gate único canReadCommunicationCatalog (advisor/leader negados); delete
  só pelo admin; sem Consent novo
- UI portada do design aprovado (lista desktop + cards mobile, diálogo de
  lote com progresso por arquivo, diálogo de link, ficha editável, kill
  switch); nav/chrome/column-picker/manifest atualizados
- instagramFeed expõe mediaUrl; revalidateTag ganha wrapper seguro fora de
  request (fixtures/scripts)
- testes: 2 unit specs, 1 int spec (16 casos) e 7 e2e na vertical
- follow-up de engenharia: #1267 (docs/plans/escala-dry-pos-c211.md)

Closes #1254
2026-09-23 02:25:15 -03:00
Francisco Solla
3a1878691b feat(C209): dossiês e boletins Solla sóbrios e analíticos — O essencial, defesa e consulta rápida (Closes #1251) 2026-09-22 22:17:27 -03:00
Francisco Solla
f63e5cb9b4 feat(C210): briefing de capacitação — até 4 páginas por recorte (3º entregável dos dossiês) (Closes #1252) 2026-09-22 21:30:50 -03:00
Francisco Solla
bb550cebff feat(S25): player próprio da Rádio 1313 na home — exclusividade, share e fail-soft (Closes #1239) 2026-09-21 13:39:42 -03:00
Francisco Solla
3e632df4d0 fix(worktree): espelha PORTAL_TRANSPARENCIA_API_KEY no env provisionado
A lista de envs espelhadas sai do inline do worktree.mjs para o helper puro
MIRRORED_WORKTREE_ENV_KEYS/mirroredEnvCopiedLines (worktree-env.mjs, unit-testado)
e passa a incluir a chave do Portal da Transparência: sem ela, build-city-report
num worktree degradava as emendas oficiais para lacuna mesmo com a chave no
checkout principal. .env.example documenta a chave e o espelhamento.
2026-09-21 13:20:35 -03:00
Francisco Solla
8a5e271f6d feat(S26): título completo e crédito do artista no card do jingle (Closes #1240) 2026-09-21 12:50:17 -03:00
Francisco Solla
5aefb2f3ba feat(S24): rádio na home — embed direto do zeno.fm, sem facade (Closes #1235)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-20 22:36:25 -03:00
Francisco Solla
908a31eea4 feat(S23): card Time de você no celular — drawer até o topo e nada sobre a imagem (Closes #1234) 2026-09-20 21:54:41 -03:00
Francisco Solla
d86b3aa0a1 feat(S22): jingles e rádio na home — a seção de som (Closes #1228)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-20 18:29:47 -03:00
Francisco Solla
33a8f53e20 OPS71: tornar worktree fix (sem argumento) driverless 2026-09-20 17:35:51 -03:00
Francisco Solla
48e08bf7f5 fix(cards): recorte no celular (WASM/WebGL) e volta do enquadramento S15
O recorte do card 'Time de você' falhava em navegadores endurecidos (IronFox/Tor
desligam WebAssembly e WebGL por padrão) com a copy errada de 'tente outra foto';
o motor MediaPipe exige ambos (o grafo pede kGpuService mesmo com delegate CPU).
Agora o adapter sonda WASM/WebGL antes do download e devolve 'unsupported' com
mensagem acionável; a entrada de inferência é capada em 1600 e a foto passa pelo
loadCardPhoto (foto de 61MP que falhava agora conclui).

O enquadramento automático volta ao S15 (bbox cobre a janela): o S18 mirava a
caixa do rosto em 103px e deixava o busto inteiro pequeno na janela. Saem o
detector de rosto (asset removido), frameCardPhotoOnFace, a referência 103px, o
piso 0.2 e a âncora S20 (inerte sob o cover). S16/S17 intactos.
2026-09-20 17:33:29 -03:00
Francisco Solla
c7eeb5dbd8 feat(S21): jingles de Jorge Solla no site público — ouvir e baixar (Closes #1222)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
2026-09-20 01:48:20 -03:00
Francisco Solla
8e431bd876 feat(reels): navegação visível, trilho de comando e cena profile na skill de reels
- 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
2026-09-20 00:11:27 -03:00
Francisco Solla
e652f0ae45 feat(S20): ajuste lateral da foto do card time sem limite artificial (Closes #1216) 2026-09-19 16:32:33 -03:00
Francisco Solla
8b74aa705a fix(S19): imagem do cartão no origem do deploy, não no domínio canônico
O resolveShareLinkOgImageUrl absolutizava /api/media/file/… contra o siteUrl do global metadata (hoje https://jorgesolla.com.br, servido pelo WordPress antigo), que responde 404 no proxy de mídia — o WhatsApp lia título/descrição mas derrubava a miniatura (caso real do cartão plenaria-cultura, da plenária de 19/09).

- resolveDeploymentOrigin (novo em seo.ts): NEXT_PUBLIC_SITE_URL primeiro (inlinado no build de produção, mesmo carrier do isStagingSite), fallback no URL do global; canonical/og:url seguem a cadeia global-first documentada — só a URL do asset muda.
- Unit do resolver (env vence/fallback/vazio); int pina o env sobre um URL de global estrangeiro.
2026-09-19 16:28:32 -03:00
Francisco Solla
ca59523759 feat(C207): projeção no último período do trio do gerador de gráficos (gate 2026-09-19) 2026-09-19 16:00:59 -03:00
Francisco Solla
468f33e5b2 feat(S19): links de compartilhamento com miniatura OG (Closes #1207) 2026-09-19 14:02:17 -03:00
Francisco Solla
cde96b26d0 feat(S18): cabeça do visitante proporcional à dos candidatos no card Time de você
- FaceDetector (blaze_face_full_range, Apache-2.0, lazy/on-device) mede o maior rosto no canvas do recorte; math pura frameCardPhotoOnFace escala a face à referência TEAM_CARD_FACE_REFERENCE_SIZE=103 (mediana das 5 caixas da arte-mestre).
- Piso do time CARD_TEAM_PHOTO_MIN_ZOOM=0.2 com clamp contain/cover por eixo (minZoom opcional preserva os 3 modelos S13/S14); fallback silencioso ao enquadramento S15 sem rosto/falha.
- Stub e2e estendido ('noface'); unit novo da math e da seleção do rosto; craft com retrato real 86-98px vs 103 (±20%); crítica Tier 1 certificada.

Closes #1197
2026-09-19 13:42:22 -03:00
Francisco Solla
ca19b2c86f feat(C205): linha de três séries e marca maior no rodapé do gerador de gráficos (Closes #1212) 2026-09-19 13:35:01 -03:00
Francisco Solla
dbd9ecdfd4 feat(S16): banner azul dinâmico no card "Time de você" — nomes longos cabendo (Closes #1195) 2026-09-19 13:05:52 -03:00
Francisco Solla
384cfe98e8 feat(C191): coluna de comparação entre categorias e variante duas colunas positivas — unidade %, kicker pela relaçã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).
2026-09-19 12:57:40 -03:00
Francisco Solla
0d6518c3d1 feat(C200): separar falas por pessoa nas gravações enviadas (Closes #1167) 2026-09-19 12:32:46 -03:00
Francisco Solla
0dae7d4ac1 refactor(C203): seletor de chave no dono do kit, guard estrito e nomes (simplify)
- readKitAssets({ keys }) lê só o ativo pedido; o entry pede namePositive (não falha por ativo alheio)
- guard do brandLogo com regex estrita de data URI PNG/base64 (vazio/aspas fora)
- helper brandMark (sem colisão com a opção brandLogo); JSDoc @param/@returns no dono
- entry-spec: teste dedicado do ativo com repoRoot tmp; stub base64 válido; helper tipado
- triage pós-simplify no impl plan (S9 defer com gatilho; S10 explicitamente fora)
2026-09-19 11:24:06 -03:00
Francisco Solla
258fd22379 feat(C203): gráficos do Instagram na marca e paleta oficiais do kit 1313
- 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
2026-09-19 11:24:06 -03:00
Francisco Solla
8a73eb2154 fix(flip): removeLabels idempotente — restaura o ignoreNotFound revertido pelo C140 (descoberto no PR #1202) 2026-09-19 11:15:34 -03:00
Francisco Solla
d7d4258cd7 feat(S17): controle "Harmonizar cores" no ready do card Time de você
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).
2026-09-19 10:55:18 -03:00
Francisco Solla
cd4f711f29 fix(ci): escaneia git ls-files -z no guard de conflitos — path não-ASCII derrubava o verify da main
O path public/campaign-kit/coração.png (C204) vinha citado pelo git ls-files padrão e o readFileSync estourava ENOENT no job verify do deploy (main vermelha desde o merge do C204).
2026-09-19 10:55:18 -03:00
Francisco Solla
4ac68de29c feat(C191): barra de variação (delta) no gráfico de Instagram — base e extensão por categoria, sem valência
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).
2026-09-19 01:23:23 -03:00
Francisco Solla
31ebb932af feat(C197): narração rascunho (TTS pt-BR) + transcrição sempre no pacote do reel (Closes #1156) 2026-09-19 00:33:37 -03:00
Francisco Solla
c0760f4234 docs(OPS128): remove verificação pós-deploy em staging do fechamento do work-issue (Closes #1188) 2026-09-19 00:29:23 -03:00
Francisco Solla
d0f606a55d feat(C199): gravações enviadas no acervo de comunicação (Closes #1166) 2026-09-18 23:42:30 -03:00
Francisco Solla
fdbab4b91c
Merge pull request #1175 from fsolla/fix/token-401
fix: 401 do GITHUB_TOKEN local (PAT expirado) — dica acionável, testes e docs
2026-09-18 23:40:26 -03:00
Francisco Solla
5b27bfa0c2
Merge pull request #1183 from fsolla/C196-skill-de-geracao-de-reels-captura-composicao-do-video
C196 — skill /reels-tutoriais: captura + composição do vídeo (kit oficial 1313)
2026-09-18 23:40:06 -03:00
Francisco Solla
8bf79ff4cc feat(C191): linha de duas séries no gráfico de Instagram — valência bom/ruim, projeção e cruzamento
Skill, núcleo (chartData), desenho (dualLineChart/renderer), design CENA 02B certificado e testes.
2026-09-18 23:12:05 -03:00
Francisco Solla
83092adabf chore(C196): merge origin/main (resolve SCRIPTS_SPEC_PINNED com reel-ingest do C195) 2026-09-18 22:55:52 -03:00
Francisco Solla
a8a5ed324f
C195 — Ingestão do pacote do reel na biblioteca privada (#1182)
C195 — Ingestão do pacote do reel na biblioteca privada
2026-09-18 22:30:57 -03:00
Francisco Solla
8041f64b0b chore(C196): merge origin/main (resolve lista de commands) 2026-09-18 22:24:21 -03:00
Francisco Solla
560f2e494a feat(S15): card "Time de você" — quarto modelo auto-serviço no funil público (Closes #1161) 2026-09-18 22:17:52 -03:00
Francisco Solla
7079c63949 Merge remote-tracking branch 'origin/main' into C195-ingestao-do-pacote-do-reel-na-biblioteca-privada
# Conflicts:
#	src/lib/reel.ts
2026-09-18 22:01:32 -03:00
Francisco Solla
7e164b637d fix(C194): port fiel ao artefato após crítica do designer (#1153)
- player mobile 226px (CTA do detalhe acima da dobra), 330px a partir de lg
- painel de downloads no mobile: CTA primário primeiro, 'Outros arquivos' depois
- cards mobile só com título/funcionalidade; data e 'Abrir reel' a partir de lg
- despublicado: aviso + publicação antes da mídia bloqueada; 'Sobre o reel' depois
- feature sem '(#cards)' na UI e data de publicação só com o dia
- 'Abrir reel' aria-hidden (o card inteiro é o link)

Design tier: openai/gpt-5.6-sol — crítica final certificada (v3, 10 capturas).
2026-09-18 21:54:37 -03:00
Francisco Solla
448f3845a2 feat(C194): biblioteca de reels na vertical Comunicação (#1153)
Lista publicados-only com capas 9:16, detalhe com player 9:16 e painel de
downloads (vídeo sem áudio primário; com áudio, mp3 e .srt quando existem;
transcrição em texto) e kill switch reversível: despublicar tira da lista e
bloqueia a mídia (C193 decision B), republicar reativa e re-carimba publishedAt.

Fiação: gate communicationCatalog (rename do speechCatalog), 3º sub-item da
vertical no nav, rule da lista no chrome, paths e loader próprios; sem
migration, sem Consent, sem tocar Media.read ou a rota de mídia do C193.

Design tier: DEGRADED — crítica final do designer indisponível no tier
primário (limite de uso); requer sign-off humano antes de push/PR.
2026-09-18 21:54:37 -03:00
Francisco Solla
8504b3b13a feat(C196): skill /reels-tutoriais — captura mobile + composição de vídeo
- 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
2026-09-18 21:50:28 -03:00
Francisco Solla
5afa16c33b feat(C195): ingestão do pacote do reel na biblioteca privada (Closes #1154) 2026-09-18 21:47:48 -03:00
Francisco Solla
adf21ba5c7 fix(C190): boletim de uma página cabe por medição (painel de acervo + fit)
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
2026-09-18 19:08:45 -03:00
Francisco Solla
ddfd8b31f3 feat(C191-runtime): cobertura do entry/PNG real e parse pt-BR explícito (Closes #1151) 2026-09-18 19:08:22 -03:00
Francisco Solla
10bab7d988 fix: 401 do GITHUB_TOKEN local (PAT expirado) — dica acionável, testes e docs (Related #1169)
O GITHUB_TOKEN exportado no shell desde o OPS71 (PAT fine-grained) expirou e,
inválido, sombreava a credencial válida do gh (keyring) — quebrando
pnpm issue/agent:*/github-pr.mjs e o próprio gh (o bash dos agentes herda o env
do opencode serve, não do .bashrc). github-api.mjs passa a anexar dica acionável
a todo 401 (REST + GraphQL), com 2 testes de regressão; AGENT-OPS documenta a
expiração e a recuperação (derivar de gh auth token).

Mesmo lote do OPS71: o secret AUTOMERGE_PAT também expirou (safety net falha
fail-closed desde 21:39Z) — rotação é ação humana pendente.

C201/#1169: o typecheck da main (RED desde bdaf3c7c) foi corrigido pelo PR #1171;
este PR fecha o tracker item.

Post-mortem: docs/postmortems/2026-09-18-github-token-401.md
2026-09-18 19:00:11 -03:00
Francisco Solla
bdaf3c7cbb feat(C193): reel privado no CMS — modelo, upload privado e kill switch (Closes #1152) 2026-09-18 17:48:34 -03:00
Francisco Solla
45eef25b1a feat(C192): busca semântica no acervo de falas (Closes #1147)
Modo "Por tema" no acervo de falas: expansão determinística do tema via
DeepSeek (generateObject, timeout, fallback null) alimenta o motor lexical
existente (searchText/keywords OR), mantendo facetas AND, paginação por fala,
o OR de cortes do C174 e o access control intacto. Resultado de tema mostra
selo e "Por que apareceu" com trecho real (frase contínua), sem score;
degradação honesta para termo exato com aviso e vazio honesto com saídas.

- URL: mode=tema (default omitido; canonicaliza sem q), seletor otimista
- ai/expandSpeechSearchTheme + lib/speechThemeTerms (sanitiza saída do modelo)
- view model com themeMatchTerm + espelho speechMatchesSearchTerm
- UI do card de tema (selos, proveniência, ações) e aviso degradado
- sem migration/Consent/exposição pública; gate de leitura inalterado
- testes unit/int/e2e; design hi-fi estendido e certificado pelo designer
2026-09-18 17:48:28 -03:00
Francisco Solla
e91dea637f feat(C191): gráficos de dados para Instagram — skill + builder local (Closes #1145) 2026-09-18 17:32:48 -03:00
Francisco Solla
e5e1ae7ee8 feat(C190): dossiê Solla por tema/área + boletim modelo (skill + builder)
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
2026-09-18 17:02:56 -03:00
Francisco Solla
fd68014edc feat(OPS127): launch do worktree nasce na variante max (Closes #1149) 2026-09-18 16:55:08 -03:00
Francisco Solla
5644a9f947 feat(C186/C187): dossiê corrente sem caps + redação, síntese e gráficos (paridade cidade × instituição)
Some checks are pending
Deploy / preflight (push) Waiting to run
Deploy / verify (push) Blocked by required conditions
Deploy / deploy staging (teqo-staging) (push) Blocked by required conditions
Deploy / requeue when main advanced (push) Blocked by required conditions
Deploy / deploy production (teqo-1313) (push) Blocked by required conditions
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.
2026-09-17 23:00:08 -03:00
Francisco Solla
4b00a8778a feat(C188): relatórios e dossiês sem truncamento mecânico
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
2026-09-17 19:59:02 -03:00
Francisco Solla
cb5854d17e feat(C187): dossiê Solla por instituição + boletim modelo (skill + builder) (Closes #1135)
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.
2026-09-17 19:25:13 -03:00
Francisco Solla
f658d5eaaa fix(C186): dossiê/boletim sem cortes — copy reformulada (brief) + paginação (Related #1132)
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`.
2026-09-17 18:19:56 -03:00
Francisco Solla
23456bb81d refactor(C186): endurece o builder e enxuga o modelo do dossiê (review) (Related #1132) 2026-09-17 16:41:32 -03:00
Francisco Solla
264fbb8864 feat(C186): dossiê Solla por cidade + boletim modelo — skill + builder (Closes #1132) 2026-09-17 16:41:32 -03:00