Commit graph

2327 commits

Author SHA1 Message Date
Francisco Solla
fe81358fe3 B170 — spec do contrato do colapso de chips + shift único do load SSR deferido documentado
F1: RelationChipCell ganha spec unitário (relationChipCellCollapse) que pina o
colapso medido pelo layout real (16 chips → slice de 3 linhas = 12), expande
pelo 'Ver mais…' e recolhe pelo 'Ver menos', com getBoundingClientRect stubado
por índice — a lacuna que o B169 deixou (specs com measureOverflow:false ou
1 chip) não tinha regressão do comportamento de colapso após a mudança de timing.

F2: medição PerformanceObserver no worktree confirma o resíduo pré-hidratação
do B169 sem regressão material: load SSR→hidratação com shifts únicos
[0.139, 0.043, 0.257] (fontes do shell, nenhuma célula de chips) e ordenação
client-side com zero shifts novos; eliminá-lo exigiria estimativa de largura
(rejeitada) ou mudança de layout/regra (anti-goal) → defer documentado.

Sem migration, dados, access ou mudança visual.
2026-08-09 01:36:59 -03:00
Francisco Solla
fd1f6b267b docs(plans): C96 — registra triage de débitos no impl plan (defer S1/S2 + descartes) 2026-08-09 01:26:45 -03:00
Francisco Solla
c9f42bfc70
Merge pull request #465 from fsolla/B174-sollinha-no-deep-infra-llm-mesma-api-e-chave-dos-agente
B174 — Sollinha no Deep Infra (LLM) — mesma API e chave dos agentes
2026-08-09 01:20:34 -03:00
Francisco Solla
01ffb86c8d
Merge pull request #466 from fsolla/plans/plan-issue-8
docs(plans): OPS20 — isola porta do e2e por worktree
2026-08-09 01:06:47 -03:00
Francisco Solla
313e0ed0c8 refactor(C96): flatten advisor scope intersection in buildFeedWhere
Simplify reviewer: the duplicated scope fragment push after the filter
branch is flattened into a single standalone guard, preserving exact
semantics across all four corners (filter set/unset × scope null/non-null).
2026-08-09 01:05:25 -03:00
Francisco Solla
47f30d1bb1 docs(plans): OPS20 — isola porta do e2e por worktree (PLAYWRIGHT_BASE_URL no .env.test.local) 2026-08-09 01:03:18 -03:00
Francisco Solla
8a8d6631aa docs(plans): remover placeholder literal de classe Tailwind do impl plan B175 2026-08-09 00:56:01 -03:00
Francisco Solla
071a2eb32f
Merge pull request #463 from fsolla/plans/plan-issue-7
docs(plans): B177–B179 — planos de intenção da família Sollinha
2026-08-09 00:55:34 -03:00
Francisco Solla
5b342146d5 fix(C96): intersect creator scope in calendar feed read
buildFeedWhere trusted filterMunicipality without intersecting the
creator's current municipality scope when accessibleMunicipalityIds is
non-null (advisor). An advisor removed from a municipality after creating
a pinned feed kept serving its activities. Now the read re-derives the
creator's scope on every request (fail-closed, aligned with C16) and
intersects it into the where clause via the canonical
advisorMunicipalityScopeWhere fragment.

Int tests cover: advisor in-scope lists, advisor removed stops serving,
coordinator (unrestricted) unchanged. No migration (config/consulta only).
2026-08-09 00:55:11 -03:00
Francisco Solla
74fb12723b docs(plans): B177–B179 — planos de intenção da família Sollinha (cidades mais votadas · Salvador cidade · gênero masculino) 2026-08-09 00:52:42 -03:00
Francisco Solla
0c7adad44b
Merge pull request #459 from fsolla/plans/plan-issue-5
docs(plans): B176 — filtrar municípios por Dobradinha/Liderança/Partido + coluna Dobradinhas ao Assessor
2026-08-09 00:43:12 -03:00
Francisco Solla
175483e7b0 docs(plans): B176 — filtrar municípios por Dobradinha/Liderança/Partido na omnibox + coluna Dobradinhas ao Assessor 2026-08-09 00:38:58 -03:00
Francisco Solla
e65534ca9b test(e2e): atualizar marcador do território no picker de colunas (coluna Municípios saiu na B175) 2026-08-09 00:38:27 -03:00
Francisco Solla
9d827fbd0d style(docs): formato prettier no impl plan B174 2026-08-09 00:06:12 -03:00
Francisco Solla
3a8506ad06 chore(ai-chat): Sollinha via Deep Infra — mesma API e chave dos agentes
Troca o provider da Sollinha de @ai-sdk/deepseek (api.deepseek.com) para
@ai-sdk/deepinfra (API OpenAI-compatível da Deep Infra), mantendo o mesmo
modelo deepseek-ai/DeepSeek-V4-Flash e as mesmas tools. Uma chave só
(DEEPINFRA_API_KEY), a mesma dos agentes; rollback = git revert.

Closes #449
2026-08-09 00:06:12 -03:00
Francisco Solla
e3f6d3f5eb
Merge pull request #457 from fsolla/C89-pagina-atualizacoes-feed-de-cards-filtro-criar-modal-bot
C89 — Página Atualizações: feed de cards + filtro + criar (modal / bottom sheet)
2026-08-09 00:05:05 -03:00
Francisco Solla
e75bb1c2f3 feat(campaignTerritories): repintar a lista de Territórios no padrão da lista de Municípios (B175)
- Colunas responsivas ao painel via @container/territory-list (P0→P3), sem scroll horizontal
- Contagem de municípios no nome ("Irecê (20)"); % e votos absorvidos na célula 2022 (hover = válidos)
- Célula 2026 no detalhe de Municípios (valor central + %, faixa de cenários no hover, leitura)
- Colunas de rede só leitura: Assessor, Liderança, Dobradinha (para todo o staff)
- Cobertura oculta por padrão no seletor; labels curtos (2022/2026/Captura/Cobertura)
- loadTerritoryOverview devolve { rows, references }; rollup puro com soma por cenário, hasEstimate e uniões de rede
2026-08-08 23:58:54 -03:00
Francisco Solla
c9134becd1
Merge pull request #456 from fsolla/C92-link-de-import-corrigir-criacao-do-feed
fix(C92): corrige criação do link de import da agenda (feed)
2026-08-08 23:39:43 -03:00
Francisco Solla
29ed733190 fix(C92): calendar feed creation stripped by admin-only system fields
createCalendarFeedLinkRecord failed with `overrideAccess:false` +
`user: campaignUser` because Payload stripped the required
`secretSlug`/`createdBy` fields (create access was admin-only) -> 400
behind the generic message; revokeCalendarFeedRecord silently no-opped
(revokedAt update access also admin-only).

- canCreateCalendarFeed now enforces advisor filterMunicipality scope
  on data (canCreateSupporter precedent) + canSetCalendarFeedSecret /
  canSetCalendarFeedRevocation permit staff to mint the secret on create
  and mark a feed revoked; secret read stays `() => false` and update
  admin-only.
- CalendarFeed stamps createdBy via stampCampaignCreatedBy; secret
  create + revokedAt update use the new staff field accesses.
- Action refactored to `*Record` (payload, actor) cores + thin wrappers;
  assertFilterMunicipalityInScope (tour precedent); console.error keeps
  the real error on the server while the friendly message stays.
- 10 int tests for create/scope/revoke/leader/secret; fixture tracks
  calendarFeed cleanup.

Closes #436
2026-08-08 23:13:30 -03:00
Francisco Solla
5a51d60c9e style(C89): formata (prettier) 2026-08-08 23:11:05 -03:00
Francisco Solla
8d96263554 docs(plans): C89 — registra triage de débitos no impl plan (defer S1 + descartes) 2026-08-08 23:07:23 -03:00
Francisco Solla
7343f15053 feat(C89): página Atualizações — feed de cards + filtro omnibox + criar (modal/bottom sheet)
Substitui o placeholder B164 por um feed operacional da carteira (staff):
- Cards com avatar do autor, polaridade/urgente/adversário, município e data
- Filtro omnibox (município via dotted-path, polaridade, urgente, autor, busca)
  no padrão das listas (URL canônica + adapter puro)
- Criação in-place: modal desktop / bottom sheet mobile, reusando o registro
  unificado (C87) com prefill do município do filtro ativo
- Leader lockdown intacto (gate staff + canReadMunicipalityUpdate fail-closed)
- parseMunicipalityUpdateFormData único para os 3 forms de atualização
- Loader cruzando a carteira sem cláusula de município (access por ator)
- Int/unit specs (19 unit + 5 int) + convenções

Fix real: o modal de criação não pode ser filho React do <form> de filtros —
React 19 não liga progressive enhancement em action-form aninhado.
2026-08-08 23:07:23 -03:00
Francisco Solla
0a073c8e61
Merge pull request #454 from fsolla/B171-barra-inferior-mobile-folga-no-topo-rotulos-sem-sobrepo
fix(campaign): barra inferior mobile — folga no topo e rótulos sem sobreposição
2026-08-08 19:15:59 -03:00
Francisco Solla
5a3ff06b9f docs(plans): B171 — gatilho deferido do /simplify no impl plan 2026-08-08 18:46:10 -03:00
Francisco Solla
f3d2f46a58 test(campaign): reforça e2e da barra inferior mobile após /simplify
- pina paddingTop >= 10px (pt-2.5) e cobre viewport 320px — o aceite da
  intenção promete rótulos legíveis em qualquer largura mobile.
2026-08-08 18:45:42 -03:00
Francisco Solla
2ba0cebf6f
Merge pull request #452 from fsolla/C91-criar-evento-inline-no-calendario-da-agenda-estilo-googl
C91: criar evento inline no calendário da agenda (estilo Google Calendar)
2026-08-08 18:45:27 -03:00
Francisco Solla
ecb1af695a
Merge pull request #453 from fsolla/plans/plan-issue-3
docs(plans): B175 — repintar lista de Territórios (padrão Municípios)
2026-08-08 18:40:27 -03:00
Francisco Solla
330aa2aa62 docs(plans): B175 — repintar a lista de Territórios no padrão da lista de Municípios 2026-08-08 18:38:47 -03:00
Francisco Solla
a1a0e3701d
Merge pull request #434 from fsolla/B167-migrar-o-chat-sollinha-entre-painel-e-drawer-ao-redimen
B167 — Migrar o chat Sollinha entre painel e drawer ao redimensionar
2026-08-08 18:38:24 -03:00
Francisco Solla
eb94a81ebc fix(campaign): barra inferior mobile — folga no topo e rótulos sem sobreposição
B171 #443
- CampaignBottomNav: pt-2.5 no nav (respiro da borda superior) e rótulos
  text-[10px] nowrap com gap-1 — sem encolher a área de toque.
- e2e: assert paddingTop >= 8px, rótulos < 12px e sem sobreposição horizontal.
2026-08-08 18:37:12 -03:00
Francisco Solla
c1bedcf838 test(campaignMunicipalities): torna o assert Otimista: 5.000 determinístico
O getByText sem índice também casa com o span sr-only do hover-preview quando
uma linha está hovered — strict-mode violation flaky no CI. .nth(0) fixa no
resumo da célula.
2026-08-08 18:29:42 -03:00
Francisco Solla
77673147ca feat(C91): cria evento inline no calendário da agenda (popover/drawer no slot clicado) 2026-08-08 18:27:25 -03:00
Francisco Solla
5b59e07143
Merge pull request #450 from fsolla/plans/plan-issue-1
docs(plans): B173-B174 — Sollinha: consulta por voz + LLM movido para a Deep Infra
2026-08-08 18:22:55 -03:00
Francisco Solla
343f9f0fae docs(plans): B173-B174 — Sollinha: consulta por voz no chat + LLM movido para a Deep Infra 2026-08-08 18:20:51 -03:00
Francisco Solla
77498c83c1
Merge pull request #447 from fsolla/plans/plan-issue-2
docs(plans): B172 — tendência colapsa para a coluna Ações na lista de municípios
2026-08-08 18:12:13 -03:00
Francisco Solla
cfb27296f6 test(campaignActivity): fecha o chat antes do passo mobile da agenda (B167)
B167 migra um chat aberto no painel desktop para o drawer full-screen ao
encolher a viewport — o drawer cobriria o calendário no passo mobile deste
spec. Fecha o chat antes do resize para garantir a superfície de teste.
2026-08-08 18:11:09 -03:00
Francisco Solla
89445d17fb docs(plans): B172 — tendência colapsa para a coluna Ações na lista de municípios
Sucessor/refino do B158: onde a coluna Tendência colapsaria para ícone no
próprio lugar, esconder a coluna inteira e mostrar o editor como ícone em
Ações, ao lado do ícone de atualização. Uma instância por linha (invariante
B158). Related #446.
2026-08-08 18:09:33 -03:00
Francisco Solla
9b6fa2763c
Merge pull request #445 from fsolla/plans/plan-issue
docs(plans): mark B171 plan ready
2026-08-08 18:06:53 -03:00
Francisco Solla
a097252af7 docs(plans): B171 status ready após promote 2026-08-08 18:05:30 -03:00
Francisco Solla
031521b4f5
Merge pull request #442 from fsolla/B169-estabilizar-a-lista-de-dobradinhas-parar-o-flicker-de-l
B169 — Estabilizar a lista de Dobradinhas (parar o flicker de linhas/colunas)
2026-08-08 18:04:19 -03:00
Francisco Solla
63e5ea1c51
Merge pull request #444 from fsolla/plans/plan-issue
docs(plans): B171 barra inferior mobile + C89 página Atualizações
2026-08-08 18:04:17 -03:00
Francisco Solla
bef68678ff docs(plans): B171 barra inferior mobile (folga + rótulos) e C89 página Atualizações (feed + filtro + criar) 2026-08-08 18:01:29 -03:00
Francisco Solla
3d55d5760f B169 — estabilizar a lista de Dobradinhas: medir overflow de chips antes da paint (useLayoutEffect)
O ciclo medir→recolher de RelationChipCell rodava em useEffect (pós-pintura),
fazendo cada remount (navegação RSC, paginação, ordenação, filtro) pintar o
clamp max-h-18 e só então colapsar para o slice de 3 linhas — uma onda de
LayoutShift por célula (tabela 1122→682px). Mudar os 3 effects de
medição/invalidação para useLayoutEffect faz a primeira pintura já chegar na
altura final (medido: tabela estável, zero LayoutShift nas navegações).

Documenta o resíduo do load SSR (paint pré-hidratação) e registra follow-up
B170 (#441) para o spec do contrato de colapso + avaliação do shift único.
2026-08-08 17:53:20 -03:00
Francisco Solla
0e38d19d42 feat(B167): migra o chat Sollinha entre painel e drawer ao redimensionar
- Converse (useChat) lifts to the provider: survives desktop panel <-> mobile
  drawer swaps, internal /campanha navigation and resize (new tab still resets).
- Chat Panel/Separator always mounted (RRP panel-count change forces a full
  navigation); footprint hidden via elementRef + .b167-ai-chat-hidden
  (display:none !important), avoiding RRP's imperative collapse/expand races.
- Single 'open' flag drives both surfaces (open && viewport); reconciled with
  the panel at desktop settle and on user drag-collapse (gated by isUserInteraction).
- Mobile Drawer extracted to CampaignAIDrawer; FAB/setOpen unified; focus moves
  into the chat on the mobile->desktop swap.
- e2e campaignAiChatResize: desktop->mobile, mobile->desktop, closed stays
  closed, fresh mobile visit closed, navigation survival, new tab resets.
- Impl plan: docs/plans/migrar-chat-painel-drawer-resize-impl.md

Closes #416
2026-08-08 17:52:02 -03:00
Francisco Solla
09d44c1b9d
Merge pull request #435 from fsolla/C90-remodelar-responsaveis-da-atividade-campo-unico-polimorf
C90 — remodela responsáveis da Atividade (campo único polimórfico)
2026-08-08 17:25:02 -03:00
Francisco Solla
d48cb9ed91
Merge pull request #440 from fsolla/plans/c92-c95-agenda-header-feed
docs(plans): C92–C95 — agenda: feed link, sem-filtros, combobox e header do app
2026-08-08 17:23:19 -03:00
Francisco Solla
0d5bf274ff docs(plans): C92-C95 — agenda: corrigir feed link, sem-filtros, combobox e header do app 2026-08-08 17:20:48 -03:00
Francisco Solla
63642483a4 feat(C90): remodela responsáveis da Atividade em campo único polimórfico
Um campo responsible (staff campaignUser · leadership · stateDeputy) multi-valor
substitui responsible/Contact + advisors + leadership; assessor mantém acesso via
notação-objeto equals no access; nova migração esquema+dados (advisors/leadership
→ responsible); busca q da lista título-only; notificação notifica staff do campo.
Closes #426
2026-08-08 17:10:48 -03:00
Francisco Solla
8b2bc51aa5
Merge pull request #433 from fsolla/plans/plan-issue
worktree: plan cria um worktree diferente por invocação (paralelismo /plan-issue)
2026-08-08 16:52:26 -03:00
Francisco Solla
6c8c466b40 fix(worktree): plan cria um worktree diferente por invocação (paralelismo /plan-issue)
Cada 'pnpm worktree plan' agora deriva um branch próprio: plans/plan-issue-<bag>
quando um bag é passado (sufixo -2/-3 em colisão) ou o próximo sequencial
plans/plan-issue-<n> quando não. O prefixo minúsculo plans/… nunca colide com o
branch <Code>-<slug> de 'next'. planBranchName (scripts/lib/worktree.mjs)
unit-testado; docs e shell/command atualizados.
2026-08-08 16:40:05 -03:00