- layout=grid no botão com w-full/min-w-0 sem box-content no mobile
- li min-w-0, gap-2, data-layout=grid-3 no strip
- e2e com geometria (boundingBox) em viewport 390
- impl plan docs/plans/inicio-acoes-grade-3cols-2rows-impl.md
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Allow empty motivo on sinal through collection beforeValidate; distinguish
warm-typeless vs cold in the v2 signal select; reuse list signal form action.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Rota paralela /campanha/municipio/<slug>/v2 com selects de nível, tendência e
sinal (modal de motivo opcional), classe territorial e agregado. Soft-dep B134:
motivo opcional no movimento de nível e remoção do campo “voltar atrás” do
write path/lista.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Insert Organizações after Lideranças in staffNav so staff can discover
the existing /campanha/organizacoes list from the structural nav.
Leaders remain on leaderNav; isCampaignNavActive already covers list,
detail, and /nova paths.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Adiciona dimensão municipality na URL e omnibox da lista de assessores,
espelhando o precedente de lideranças: chips removíveis, busca tipada no
catálogo e filtro server OR via municipality.advisors.
Closes#310
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- URL state: organization / stateDeputy (OR inclusivo por dimensão)
- Facets cross-filtered em leadershipData
- Adapter omnibox + wiring na página
- Testes unit/int e plano de implementação
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- wizardPreviousHref em wizardActionChain para todos os elos B98
- Avanço encadeado com router.push; Voltar no chrome com replace
- Testes unitários para href anterior e navegação pending
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- Add q param to demand list URL contract and buildDemandListWhere
- Extend demandOmnibox with kind + search chips/suggestions/actions
- Search title and leadership contact name (visible list columns)
- clearDemandOmnibox drops bar filters but keeps activity deep-link
- Unit + int tests; impl plan docs/plans/demandas-omnibox-tipo-busca-impl.md
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Adiciona dimensão Fonte ao estado de lista, where-builder, aggregate SQL
e adapter omnibox (B128), com guard isSupporterSource e testes.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- Block Dialog onOpenAutoFocus and Drawer initialFocus so search does not
steal focus on open (actions stay visible per B132 idle state).
- Reserve md:pr-10 on search chrome so desktop close button does not overlap.
- Enable showSwipeHandle on mobile drawer (no X button).
- Unit tests for idle state, swipe handle, and close spacing.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- Make engagement level note optional in schema and UI
- Remove reversalSignals field from popover, action snapshot and DB
- Add data migration to strip reversalSignals from movimento snapshots
- Wizard trend note step no longer requires text; labels show (opcional)
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Registra a intenção de produto (#288): soltar Motivo no wizard de tendência e no nível de envolvimento, e apagar do modelo/DB o campo de sinais de reversão.
- CampaignHomeActionStrip: grid-cols-3 no mobile; variante grid para overlay
- CampaignQuickActionsOverlay: grade no lugar da strip; altura por conteúdo;
pt-4 na busca focada; limpa query ao fechar
- CampaignQuickActionsHost: clear() em fechamento e mudança de rota
- Testes unit atualizados; impl plan em docs/plans/
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Use hook.navigate so draft search cannot clobber chips; replace cmdk with
ARIA combobox keyboard contract; memoize suggestion seeds per facet snapshot.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Replace the stacked município filter controls with a shared omnibox
(chips + suggestions) backed by the frozen list URL contract; scenario
and non-default sort appear as presentation chips.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Remove MunicipalityListOverview from /campanha/municipios and drop the
overview field/computation from loadMunicipalityListPageBundle. Filters,
scenario selector, and per-row goal coverage for sorting remain unchanged.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Remove o bottom drawer não-modal (snap/peek/scroll-coupling) e introduz
um FAB em todas as larguras fora do Início e wizards. Abrir o FAB mostra
overlay modal: Dialog no desktop (busca em cima) e Drawer no mobile
(ações em cima), reutilizando strip e busca globais do Início.
Closes#260
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Change DEPLOY_COOLDOWN_MS constant, update ci.yml deferral log, and
adjust unit test pins. Closes#259.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Replace the W4d filename-based convention spec with a sweep of every
src/app/(campaign) file that calls mapCampaignFormActionError without
runCampaignFormAction/Redirect. Migrate profile, leaderSupporter, and
convite-login to the shared wrappers; allowlist auth/password and the
existing bespoke formActions exceptions with documented reasons.
Closes#241
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Revert handle to the top of the sheet; recalibrate collapsed/dock snaps
for handle+search and 2-line action labels; scroll ↓ collapses and ↑
re-docks; collapsed keeps a placeholder-less search peek that expands
on focus.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Lift TooltipProvider in the campaign app layout so it wraps
CampaignAppScrollChrome (scroll + quick-actions drawer). Focus→suggest
with priority-alta hits mounted CampaignHoverTooltip outside the old
provider and crashed the page. Unit pins cover focus→suggest and type→search.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Promote alone left the staged deployment on *.vercel.app only. Assign the
custom hostname via POST /v2/deployments/{id}/aliases after verifying it is
attached to the project domains list.
Disabling Git auto-deploy is correct for Actions-gated production. The
separate project toggle "Auto-assign Custom Production Domains" must stay
ON — when OFF, `vercel deploy --prod` only aliases *.vercel.app and leaves
the custom domain on an older Current (exactly what we saw after #122).
After each deploy, ensure-production-alias re-enables auto-assign if needed,
promotes the deployment, and verifies pt.jorgesolla.com.br is attached.
Also adds workflow_dispatch "Vercel promote production" for promote-without-rebuild.
Após salvar (ou Pular) votos/tendência/sinal/liderança, navega ao
próximo elo da matriz v1 no mesmo município via entryAction, em vez
de voltar ao Início. Helper puro wizardActionChain + skips alinhados.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Plano pós-gate: corrige geometria do snap (conteúdo fora da banda
visível) e define load em dock (ações+busca), collapse no scroll down
e reopen só por tap/pull.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Cursor's Create-Agent API defaults omitted `fast` to true, so pool
workers requesting composer-2.5 were billed as composer-2.5-fast.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Quebra o empty state do passo 1 dos wizards (/campanha/acoes) em três
entregáveis: chassis+esquecidos (B92), continuity visitados/última ação (B93),
geo mais próximo (B94). Aguarda gate de confirmação antes do agent:register.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
checkout/setup-node/pnpm já estavam em v5/v6 (Node 24); o aviso restante
vinha de styfle/cancel-workflow-action@0.12.1 (node20) usado no fail-fast.
Documenta runtimes nativos em AGENT-OPS.md.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Freshness audit confirmou que perf de import/lista de apoiadores já
estava entregue em main desde 2026-07-19; atualiza status do plano
e CHANGELOG-AGENTS.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Add composite action wrapping styfle/cancel-workflow-action@0.12.1 and
invoke it with if: failure() on every parallel job in ci-pr.yml and ci.yml.
Workflow-level actions: write permission enables cancellation. Document
fail-fast behavior in docs/AGENT-OPS.md CI table.
Closes#52
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Registra catálogo contextual no drawer B79 para /campanha/liderancas:
lista com update-leadership; detalhe com cinco wizards e prefill de
município quando N=1. Adiciona query leadershipId no wizard A4 e
CampaignQuickActionContextSync na ficha.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
agent-pr-workflow was correct but not alwaysApply, so Cloud agents
followed ManagePullRequest's draft default. Make the rule always-on,
document the ManagePullRequest path, and narrow the engineering-audit
"no auto-merge" exception to the audit sign-off PR only.
Match the Vercel Actions KB (job-level org/project env, global CLI),
validate team_/prj_ secret shapes, and document the misleading
Project Settings 403. Org/project secrets were resynced from local link.
Remove stage/promote/Neon smoke. PR CI targets main; ci.yml full-suite
verifier deploys via vercel CLI and requeues when HEAD moves. Pool uses
POOL_GITHUB_TOKEN and POOL_BASE_REF=main. Docs/skills/rules retargeted.
Warm Cloud snapshots often have PostgreSQL online without the teqo
role/DBs. start_postgres previously gated on teqo_ready, exited before
bootstrap_databases, and marked the environment INSTALL_FAILED even
though agents still ran. Also pin DATABASE_URL and assert migrations
in cloud-setup so a silent no-op migrate cannot slip through.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
The SavedFilters incident shape — a page.goto fired while the previous
heavy RSC navigation was still in flight (net::ERR_ABORTED) — gets a
build-level guard: two gotos with no settle between them (await expect /
waitForURL / click / reload / login / catch) fail the suite. Measured
baseline on the current tree: 58 gotos across 17 specs, 0 unsettled
pairs — the six SOFT pairs from the miss audit all settle on awaited
assertions, so the guard starts clean without churning them.
TESTING.md records the convention the miss asked for: goto for cold
loads and URL contracts; in-shell navigation for continuity scenarios;
interactive-state waits before dynamic clicks; a dev-mode caveat for the
campaignLeaderships chip spec (deterministic dev failure at the
suggestion/commit step, prod green — ledgered).
Remove interview audio/transcripts/sheets from the tree, add LICENSE
(UNLICENSED), /private/ convention for local-only sensitive docs, and
public-clean CUSTOMER + session summaries for cloud agents.
* docs(A6): freshness audit da #27 no plano de dobradinhas 2026
electionInsights.ts foi deletado no Pass 2 W4a (modulo puro novo),
electionAlliances.ts nao nasce (campoParties + electionPartySpectrum ja
carregam a taxonomia), questoes em aberto resolvidas (tiers, score,
proporcionais, lockdown de lideranca), card na aba Eleicoes, overview da
lista fora de escopo, cache election-tse com bust na conciliacao Fase 5.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* feat(A6): insight de dobradinhas 2026 na aba Eleicoes do municipio
Lista ranqueada de candidatos proporcionais que concorrem de novo em 2026
(runningAgain2026=sim) por geografia do municipio: score 0,6 alinhamento
(campo 2026 + espectro Bolognesi) + 0,4 forca local normalizada pelo maximo
do conjunto. Estado pendente ate a conciliacao pos-15/08; Solla excluido
(referencia, nao parceiro); leitura derivada sem escrita; loader cacheado
sob a tag election-tse como os irmaos; link para /campanha/dobradinhas
como caminho de registro operacional.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* test(A6): cobertura unit/int do insight + lease das colecoes eleitorais
Unit: tiers (campo/espectro/falha-para-o-meio), score, ordenacao, empates,
limite, zero votos. Int: pending2026 sem conciliacao (mesmo com votos
locais), so adversarios, misto com exclusao de Solla/nao e geografia
alheia. Lease advisory election-collections serializa os dois specs que
tratam as colecoes eleitorais como test-owned (o import wipe-all apagaria
as fixtures do novo spec no meio do assert, 48-way paralelo).
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* refactor(A6): fixes do /simplify (3 reviewers paralelos)
P1: campo coalition morto removido do input/select/mapping (sem consumidor).
P1: hooks do lease com timeout explicito de 120s nos dois specs eleitorais
(o wait advisory passa dos 10s default do Vitest sob contencao — flake em
ambas as direcoes). P2: sonda de conciliacao via payload.count (idioma da
casa), desempate final por candidateNumber (ordem deterministica), geography
como prop na secao (sem lookup duplicado), casing Dep. Federal/Estadual
alinhado, marcador 1313 via BASELINE_TICKET_2022, entrada no CHANGELOG.
Declinados com justificativa: zones como tupla nao-vazia (churn em tipo
compartilhado por assert provada no catalogo) e early-start da promise
antes do Promise.all (loader-dentro-do-Suspense e o idioma da casa; ganho
so em cache frio).
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Os scripts do pool NAO sao dependency-free: agent-pool.mjs -> agent-github.mjs
-> scripts/lib/cli.mjs -> dotenv. O workflow agora instala deps como os irmaos
(pnpm/action-setup + cache + pnpm install --frozen-lockfile). Guard adicional:
pull_request closed sem merge nao dispara o tick (ruido em todo PR de stage).
Verificado localmente: o script carrega e para na leitura estrita de variables
(fail-closed desenhado; em GHA o GITHUB_TOKEN tem actions:write).
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Monta CampaignQuickActionsDrawer não-modal no layout (app) para staff fora
do Início e de /acoes, com snap collapsed/expanded, padding de peek no scroll,
registry vazio para catálogos B80+, e busca global reutilizada via
CampaignStaffGlobalSearch.
Closes#15
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Merge escala-dry B68+ into O0+ (same kimi-k3-low model). Split B79
chassis from drawer search (B91) so B80–B90 unblock without the search half.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
- Collections Notification e PushSubscription com migration
- Sino no header (mobile + desktop) com drawer de avisos lidos/não lidos
- Hooks em municipalityUpdate, supporter, activity e convite aceito
- Push Web via web-push + handlers no service worker /campanha/sw.js
- Opt-in LGPD em /campanha/perfil (chave campanha-notificacoes-push)
- Testes unit/int de contrato e access
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
agent:promote passa a escolher o SHA mais novo à frente de main com
ci-stage success e usa promote/last-green quando o head de stage está
vermelho, destravando o bootstrap manual para main.
Document native Postgres on Cloud (no db:start) and that gate:fast/push need no DB. Print rename_chat title in agent:claim brief; reinforce rename_chat + pnpm push (not raw --no-verify) in work-issue skill.
Reduz o espaçamento horizontal entre botões de ação rápida na home
do /campanha, conforme feedback pós-B72. Mantém círculo 48px, largura
w-[4.75rem], pan B67 e snap inalterados.
Closes#13
* feat(ops): auto-promote stage→main e merge em stage sem exigir head
Substitui o promote manual por workflow disparado no ci-stage green,
relaxa strict na proteção de stage (script configure:branch-protection)
e documenta o novo paradigma em AGENT-OPS e work-issue.
* style: format AGENT-OPS and configure-branch-protection for ci-pr
* feat(ops): pnpm push com ensure-repo-deps determinístico
Bootstrap install + Husky antes de todo push (pnpm push e pre-push).
Documenta fluxo canônico em work-issue, agent-pr-workflow e AGENT-OPS.
* fix(ops): pnpm push roda gate no script, sem depender do Husky
Cloud environment.json chama prepare explicitamente após install.
* test(int): isolate advisor portfolio search from shared cairu slug
Parallel int specs were stomping municipality.advisors on the fixed
cairu row; allocate per-test municipalities instead.
* feat(agent-pool): fundacao read-only do orquestrador (fase A)
- docs/plans/agent-pool-orchestrator.md: plano completo (14 secoes)
- buildClaimQueue extraido de agent-claim para agent-github (comportamento identico, pinado)
- agent-pool-eligibility: isAutonomousClaimable puro e fail-closed + buildPoolQueue
- agent-pool-state: parsePoolConfig, marcadores pool-worker, classifyPoolClaim, spawn plan, auto-stop
- agent-pool-github: leitura de repo variables (degrada nao-estrito), claims/PRs/migration-lock
- pnpm agent:pool -- status|tick --dry-run (inspecao local; live chega na fase B)
- 34 specs unit novos (992/992 verde); lint/tsc/knip/cycles/format verdes
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* feat(agent-pool): spawn remoto de workers via Cursor API (fase B)
- agent-pool-cursor: client fino da Cloud Agents API v1 (fetch injetavel; CursorApiError com status/body)
- agent-pool-models: resolvePoolModel contra /v1/models (id/alias, sufixo -fast -> param, fallback composer-2.5 com warn)
- agent-pool-prompt: contrato do worker (claim pre-feito, pula passo 1; PR base stage + Closes #N; promote proibido)
- claim coordenado no tick: lock otimista + flip + marcador; agentId idempotente bc-<uuid>; 409 recupera; rollback em falha de spawn
- agent:pool workflow --action start|stop|pause|resume|tick|status (variables POOL_*); doctor; wrappers gh workflow run
- .github/workflows/agent-pool.yml (dispatch-only; schedule/triggers na fase C)
- 19 specs novos (1011/1011); lint/tsc/knip/cycles/format verdes
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* feat(agent-pool): ciclo de vida do supervisor (fase C)
- derivePoolClaims com status real dos runs (getCursorRun), heal de spawn via agentId deterministico, cancel de duplicatas
- reconcilePoolClaims: falha terminal -> comentario + blocked + archive; merge concluido -> slot livre + archive
- auto-stop real: fila drenada + zero ativos -> POOL_ENABLED=false (exclusoes migration-busy nao desligam)
- job summary markdown (GITHUB_STEP_SUMMARY) — superficie remota de status
- workflow: schedule */10min + pull_request closed em stage (ativam na default branch apos promote)
- 2 specs novos (1013/1013); lint/tsc/knip/cycles/format verdes
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* docs(agent-pool): runbook operacional e adendo do spike (fase D)
- skill agent-pool: runbook humano (pre-requisitos, start/stop/pause remoto, ciclo de vida, triage, smoke de aceite)
- AGENT-OPS: linha na tabela de comandos + secao Agent pool (canal, secrets, ativacao pos-promote)
- CHANGELOG-AGENTS: entrada curta da entrega
- engineering-audit: pause/resume do pool no protocolo do modo solitario
- plano secao 14.1: evidencias do spike 2026-07-30 (environment repo-file confirmado, id bc-<uuid>, degradacao 403, pendencias do primeiro run com CURSOR_API_KEY)
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
* fix(test): teardown flake no homeSearchUi.unit.spec (dono do CI)
O scheduler do react (prefetch do next/link) podia disparar apos o teardown
do jsdom e derrubar o job unit com 'window is not defined' (run 30587862940).
afterEach(cleanup) — padrao dos 14 specs irmaos.
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
---------
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
Adiciona trailing actions nas linhas de resultado da busca global:
- WhatsApp em lideranças e assessores (reusa whatsAppHrefForPhone)
- Compartilhar em demandas e atividades (Web Share nativo com fallback wa.me)
- trailingAction fora do Link da linha para não roubar navegação
Closes#9