Commit graph

155 commits

Author SHA1 Message Date
Francisco Solla
55178247c8
Merge pull request #409 from fsolla/C15-fullcalendar-em-campanha-agenda
feat(campanha): C15 — FullCalendar em /campanha/agenda
2026-08-07 04:56:52 -03:00
Francisco Solla
59983b33f7 feat(campanha): C15 — FullCalendar em /campanha/agenda
Issue #390 — entrada operacional staff com FullCalendar v7 route-local
(semana/mês/lista), filtros compartilháveis por município/deputado/tag,
criação pelo slot, detalhe por URL e remarcação drag/resize sob RBAC,
transação e lock por atividade.

- /campanha/atividades e giros permanecem como lista/fluxos legados
- Sem migration/collection nova; reutiliza activity de C14
- Fuso Bahia, range exclusivo, erro/revert, loading/empty testados
- Leader negado, advisor limitado pelo access atual
- E2E cobre filtros, drag, mobile 390x844 e slot prefill
- Int specs cobrem RBAC, concorrência e defense-in-depth

Impl: docs/plans/fullcalendar-agenda-campanha-impl.md
2026-08-07 04:37:36 -03:00
Francisco Solla
af6ae72034 feat(scripts): worktree() shell function applies the --go cd 2026-08-07 01:37:02 -03:00
Francisco Solla
1c0648d59a feat(scripts): deterministic worktree + issue CLI (next --go, kill, all) 2026-08-07 01:27:22 -03:00
Francisco Ignácio Fontoura Solla
48623b0d06 fix(campanha): preserve StateDeputy migration identity 2026-08-06 18:38:47 -03:00
Francisco Ignácio Fontoura Solla
033c270a89 feat(campanha): B163 — editar contatos das dobradinhas 2026-08-06 16:52:55 -03:00
Francisco Solla
7700bff39d chore: update references to .cursor bootstrap paths
Point environment.json, hooks, skills, and docs at the relocated .cursor/ files.
2026-08-05 01:39:42 -03:00
Francisco Ignácio Fontoura Solla
896d957497 chore: migrate .cursor/ references to .agents/ folder
Replace all project-local .cursor/ path references with .agents/ across
rules, skills, environment config, hooks, and ignore files. Keep Cursor
editor paths (~/.cursor/, window.cursor, CURSOR_API_KEY) and vendored
Impeccable editor-hook paths unchanged.
2026-08-05 00:09:09 -03:00
Cursor Agent
30a5a8a5e3
B151 — FAB secundário no detalhe município v2 (#334)
- Catálogo v2 de ações rápidas: dossiê, eleições, nova liderança, giro
- Integra no chassis B126 via registry + context sync na rota v2
- Omitido registrar sinal (já na faixa de status B147)

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 01:03:10 +00:00
Cursor Agent
07c884ee2e
style: prettier AGENT-OPS and promote-related script 2026-08-03 00:23:26 +00:00
Cursor Agent
7665b1062c
fix(ops): OPS18 simplify — Related regex, already-ready, job gate
Aperta parseRelatedIssueNumbers (anti hyphen), canPromotePlanIssue
already-ready, workflow só com Related # no body + PR_BODY, soft-fail
por Issue no Action script.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:22:55 +00:00
Cursor Agent
b7f4e16c0f
feat(ops): OPS18 — Action promote Related #N no merge
Safety net dual com agent:ready: no merge em main, workflow lê Related #N
e promove Issues ainda aguardando plano (canPromotePlanIssue), soft-skip
idempotente. Helper parseRelatedIssueNumbers + pins unitários.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:20:48 +00:00
Cursor Agent
6773bbb526
docs(ops): alinhar contrato agent:ready ao canPromotePlanIssue 2026-08-03 00:06:14 +00:00
Cursor Agent
9d6f80b464
style: format agent-plan-lifecycle with Prettier 2026-08-03 00:06:14 +00:00
Cursor Agent
d2cc1d2693
feat(ops): OPS17 — plan-issue blocked até plano em main
Register com --plan nasce blocked (não claimável); pnpm agent:ready
promove após o plano em main. Gate da skill plan-issue endurecido.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-03 00:06:14 +00:00
Cursor Agent
6b8aa8b6cf
fix(campanha): B147 simplify — sinal empty body + cold select
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>
2026-08-02 23:33:46 +00:00
Cursor Agent
c66ffd598c
fix(campanha): map municipio v2 route in e2e affected manifest
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 23:30:51 +00:00
Francisco Solla
1771c5c2c4
Merge pull request #282 from fsolla/cursor/pool-i265-cbfa8dec-92a1
B128 — Adotar barra omnibox nas demais listas /campanha
2026-08-02 18:12:49 -03:00
Cursor Agent
f59d4a6736
chore: format + e2e manifest mappings for B128 omnibox modules 2026-08-02 20:56:12 +00:00
Francisco Ignácio Fontoura Solla
0baeda22a0 Fix e2e failures from FAB chrome waits and B27 advisor strict-mode.
B126 mobile specs looked for a page heading that shell chrome replaced;
wait on campaignPageChrome with exact title text, and wrap the desktop
title so subtitle no longer collides. Pin B27 to the município-specific
assessores trigger and map home-search libs to campaignMunicipalities.
2026-08-02 17:49:08 -03:00
Cursor Agent
076c047c02
chore: map B127 omnibox paths in e2e affected manifest 2026-08-02 20:30:55 +00:00
Francisco Solla
7839a88a5a
Merge pull request #270 from fsolla/cursor/pool-i250-d89b6314-599f
B123 — Campanha — orientação na shell + aba (sem títulos grandes de seção)
2026-08-02 16:16:58 -03:00
Cursor Agent
b6e1f4b5ce
ci: invoke knip via pnpm script (fixes spawnSync exit 13 flake) 2026-08-02 19:01:57 +00:00
Francisco Solla
62fb4c66e8
Merge pull request #263 from fsolla/cursor/pool-i259-b024c8a7-cbc1
OPS16 — CI: cooldown de deploy de produção 30 → 15 min
2026-08-02 15:46:51 -03:00
Cursor Agent
cad3556bce
OPS16: reduce production deploy cooldown from 30 to 15 minutes
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>
2026-08-02 18:38:36 +00:00
Cursor Agent
7e6bc9d984
B125 — nearest município first in search suggest + wizard
- Restore B117 home search: scopeMunicipalities, merge prefix, session prompt
- Shared useNearestMunicipalitySlug (B14 key) for busca geral + wizard
- Wizard merge uses geoSlug only — no Perto de você / km copy on rows
- Impl plan: docs/plans/municipio-geo-topo-sugestoes-busca-impl.md

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-02 18:21:52 +00:00
Francisco Ignácio Fontoura Solla
8bca9d8e82 Separate intention plans from engineering execution in agent skills.
plan-issue now shapes product intent only; agent-work-issue (pool) and
work-issue (human gate) deliberate the implementation plan before coding.
2026-08-02 14:02:18 -03:00
Francisco Ignácio Fontoura Solla
186950168b Raise agent pool hard max slots from 8 to 12.
Default remains 5; parsePoolConfig now clamps POOL_MAX_SLOTS up to 12.
2026-08-02 13:30:36 -03:00
Cursor Agent
fded303fe6
fix(ci): stop trusting GET /v13 alias for production domain ownership
CI short-circuited "already aliased" when v13 listed pt.jorgesolla.com.br
on a fresh --prod deploy while the domain still pointed at an older
Current. Verify only via GET /v2/.../aliases and /v4/aliases?domain=.
Also drop invalid --yes on vercel alias set (CLI 55).
2026-08-01 16:12:30 +00:00
Cursor Agent
fdd318692c
fix(ci): clear domain gitBranch so CLI prod deploys can alias
Git-branch-bound domains only move via Git Integration. With Git
auto-deploy OFF, clear the binding, then promote + alias + verify.
2026-08-01 15:59:41 +00:00
Cursor Agent
bcca5da92c
fix(ci): verify domain alias via aliases API + vercel alias set
Promote + POST aliases still left pt.jorgesolla.com.br off the staged
deployment's GET /v13 alias list. Verify with GET /v2/.../aliases and
GET /v4/aliases?domain=, log steps live, and also run `vercel alias set`
(recommended when Git Integration is off).
2026-08-01 15:48:59 +00:00
Cursor Agent
c59b3fe31d
fix(ci): explicitly alias pt.jorgesolla.com.br after Vercel promote
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.
2026-08-01 15:37:16 +00:00
Cursor Agent
baa8f14f82
fix(ci): promote Vercel deploy to pt.jorgesolla.com.br
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.
2026-08-01 15:26:31 +00:00
Cursor Agent
dcce160a4d
fix(ci): lazy-load dotenv in cli.mjs for deploy cooldown
vercel-deploy-cooldown.mjs only needs dieWithLabel from cli.mjs, but the
module eagerly imported dotenv. The deploy job runs the cooldown check
before pnpm install, so Node failed with ERR_MODULE_NOT_FOUND.

Require dotenv inside loadCliEnv() so lightweight CI steps can import
dieWithLabel without node_modules.
2026-08-01 14:13:10 +00:00
Francisco Solla
a7394d3b9e
Merge pull request #119 from fsolla/cursor/pool-i114-36b6c1a5-2d0b
B100 — Bottom drawer mobile — dock visível + recolhe no scroll
2026-08-01 08:49:14 -03:00
Cursor Agent
1ad8863994
OPS12 — CI bloqueia Closes/Fixes em PR só docs/plans
- Lógica pura em plansOnlyClosesGuard.mjs + CLI check-plans-only-pr-closes
- Job plans-only-closes em ci-pr.yml (rollup checks)
- Unit tests com fixture do incidente #115
- plan-issue, agent-pr-workflow, PR template e GUARDRAILS atualizados

Closes #116

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 11:26:19 +00:00
Cursor Agent
0e510e2658
Map Drawer.tsx to campaignMunicipalities e2e in affected manifest 2026-08-01 11:20:14 +00:00
Cursor Agent
f7d6a6d77d
style: format vercel-deploy-cooldown.mjs 2026-08-01 10:55:36 +00:00
Cursor Agent
cbddd8c796
OPS11 — cooldown de 30 min entre deploys de produção (Vercel)
- Script vercel-deploy-cooldown consulta último deploy READY via API Vercel
- Job deploy em ci.yml adia upload quando idade < 30 min (sucesso, não falha)
- Job requeue espera o residual e re-dispara ci.yml
- vercel deploy passa --archive=tgz para reduzir pressão de upload
- Testes unitários para computeCooldownWait e fetch da API

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 10:54:55 +00:00
Cursor Agent
8f52e17396
chore: map B94 paths in e2e affected manifest 2026-08-01 07:44:00 +00:00
Cursor Agent
feb44cd3db
fix(agent-pool): stop exporting unused POOL_DEFAULT_MODEL_SLUG
Knip treats unused exports as errors; the slug stays a module-local const.
2026-08-01 06:58:33 +00:00
Cursor Agent
196e15b827
fix(agent-pool): pin fast=false on Cloud Agent spawns
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>
2026-08-01 06:56:57 +00:00
Cursor Agent
41a9544e0a
chore: map B90 quick-action paths in e2e manifest 2026-08-01 06:28:15 +00:00
Cursor Agent
73159f0cb4
chore: map B84 quick-action lib paths in e2e affected manifest 2026-08-01 04:35:38 +00:00
Francisco Ignácio Fontoura Solla
a7a3883bc2 chore: remove cutover residue (stage scripts, checklist, PR template)
Delete dead db:refresh:stage / agent:promote; mark CUTOVER done; drop
STAGE_DATABASE_URL checklist item that no longer applies.
2026-08-01 01:00:39 -03:00
Cursor Agent
18fe4f8e9b
fix(agent-pool): ban -fast model slugs
Never map or request fast=true. Slugs ending in -fast are stripped to
the base (with a warn); model-selection and the pool plan document the ban.
2026-08-01 03:34:35 +00:00
Cursor Agent
629364f3e4
fix(agent-pool): map Grok effort + Kimi reasoning slugs to Cloud API
cursor-grok-4.5-{low,medium,high}[-fast] and kimi-k3-low were falling
back to composer-2.5 against live /v1/models (grok-4.5 + effort,
kimi-k3 + reasoning). Teach resolvePoolModel the mapping, document
when to pick each Grok effort in model-selection, and align plan/work
skills.
2026-08-01 03:32:41 +00:00
Cursor Agent
d93a0c361f
fix(agent-pool): include issue state in claim queue JSON
isAutonomousClaimable requires state === OPEN; omitting it from gh
--json made every ready issue look not-open and zeroed the pool queue.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-08-01 03:20:27 +00:00
Francisco Ignácio Fontoura Solla
f021992de0 ci: main-only cutover with gated Vercel deploy
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.
2026-07-31 20:57:18 -03:00
Francisco Ignácio Fontoura Solla
42d1a7be93 ci(pr): prettier + ignore local tool artifacts in format check 2026-07-31 20:57:18 -03:00
Francisco Ignácio Fontoura Solla
9d810d1564 ci(pr): cascade phase1→phase2 with blast-radius skips
Add scope classifiers for code/build jobs, always-on test-location
guardrails, and gate:ci parity. Default affected base is origin/main.
2026-07-31 20:57:18 -03:00
Cursor Agent
0991c04cd7 fix(seed-posts): import dieWithLabel before calling it (Pass 4 P1)
The P3-H CLI consolidation left seed-posts calling dieWithLabel with no
import — a ReferenceError on the empty-fetch abort path, invisible to
lint/typecheck/knip. Recurrence guard in the same delivery:
scriptCliConventions.unit.spec.ts fails the build when a script calls
dieWithLabel/dieAgent without importing (or defining) it, and bans
re-spelled 'const DAY_MS =' outside src/lib/text.ts (P3-K's fold leaked
one private copy in engagementLevel.ts).
2026-07-31 13:17:10 -03:00
Francisco Ignácio Fontoura Solla
0b69d2b91d chore: public release tip — All Rights Reserved, sanitize field material
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.
2026-07-31 12:53:12 -03:00
Francisco Ignácio Fontoura Solla
b533139eb2 feat(ops): promote último commit ci-stage green sem exigir head verde
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.
2026-07-30 21:56:50 -03:00
Francisco Ignácio Fontoura Solla
5987aedeaf chore(ops): Cloud Agents rename session and use pnpm push without Docker
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.
2026-07-30 21:40:46 -03:00
Francisco Solla
e04db48742 feat(ops): auto-promote stage→main e merge em stage sem exigir head (#68)
* 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.
2026-07-30 21:12:52 -03:00
Francisco Solla
680ff56754 feat(agent-pool): orquestrador de pool de workers Cursor Cloud (fases A–D) (#65)
* 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>
2026-07-30 20:08:34 -03:00
Cursor Agent
8ff9e20a88 fix(B55): defer share strategy to click + stabilize unit tests 2026-07-30 22:47:03 +00:00
Francisco Ignácio Fontoura Solla
f4a41ccc11 style: format gate-ci; preflight só teqo_test no gate:ci
Prettier em gate-ci.mjs e gate-push-local.md. db:doctor exigia DATABASE_URL
de dev — worktrees sem .env bloqueavam o push antes de chegar no format:check.
2026-07-30 18:53:17 -03:00
Francisco Ignácio Fontoura Solla
644047d92d chore(ops): gate:ci no pre-push espelha ci-pr com blast radius
Agentes rodam o mesmo escopo affected que o CI de feature antes do push;
documenta PR Ready/auto-merge e pula build Vercel em branches agent/*.
2026-07-30 18:48:10 -03:00
Francisco Ignácio Fontoura Solla
8e93f02556 Revert "chore(ops): gate:ci no pre-push espelha ci-pr com blast radius"
This reverts commit 784d4cd2e3.
2026-07-30 18:47:45 -03:00
Francisco Ignácio Fontoura Solla
784d4cd2e3 chore(ops): gate:ci no pre-push espelha ci-pr com blast radius
Agentes rodam o mesmo escopo affected que o CI de feature antes do push;
documenta PR Ready/auto-merge e pula build Vercel em branches agent/*.
2026-07-30 18:45:24 -03:00
Francisco Ignácio Fontoura Solla
6a20e98047 fix(campanha): share one Drawer across municipalities mobile cards
Root cause of the prod-build React #130 on /campanha/municipios: the
md:hidden mobile-cards tree still hydrated ~25 rows x ~5 sheet controls
(~125 eager Drawer/DrawerCloseButton instances) even on wide viewports.
Filtered ?q=... routes failed more often only because they exercise the
list with filters active — the search param itself was not the bug.

CampaignListSheetProvider hosts a single bottom Drawer for the whole
mobile section; CampaignCellEditOverlay sheet cells portal their
body/footer into it while keeping per-cell open state and autosave
scaffolds. Footers with DrawerCloseButton are only created once a sheet
actually opens. Desktop popover path is unchanged; per-cell Drawer
remains the fallback for surfaces without the provider.

Also: DrawerCloseButton (function render prop, avoids base-ui element
render in prod bundles) replaces the DrawerClose render={<Button/>}
pattern across call sites; stale e2e selectors refreshed; e2e affected
script + playwright github/list reporters for CI; use-mobile reverted
(no consumers of the gate remain).

Guardrail filed as issue #52.
2026-07-30 17:37:20 -03:00
Francisco Ignácio Fontoura Solla
2e0cc2c03e chore(ci): parallel PR jobs, affected tests, push gate, owner-of-red-CI policy
- ci-pr.yml: split the serial checks job into parallel lint/format/
  typecheck/knip/cycles + unit/int (vitest --changed vs PR base via
  scripts/test-affected.mjs, full fallback on high-risk paths) + e2e
  (manifest path->spec via scripts/e2e-affected.mjs, blocking) + build;
  migration-lock gains checkout + pull-requests:read (fixes the failures
  that blocked PR #50)
- ci.yml (main): full safety net — seed:minimal + int full + build + e2e
- package.json: gate:fast / gate:push; .husky/pre-push runs gate:push
- docs: "Dono do PR, dono do CI" policy in AGENT-OPS + work-issue +
  engineering-standards; changelog entry; plans for OPS3-OPS7
2026-07-30 17:37:20 -03:00
Francisco Ignácio Fontoura Solla
0ac6863ed8 feat: project-status + agent:status 2026-07-30 12:22:05 -03:00
Francisco Ignácio Fontoura Solla
111308f00e feat: work-issue skill 2026-07-30 12:22:05 -03:00
Francisco Ignácio Fontoura Solla
1c1a379897 feat: plan-issue skill 2026-07-30 12:22:05 -03:00
Francisco Ignácio Fontoura Solla
f7e7f98d46 fix: stage DB uses unpooled Neon endpoint (pooler hangs the int suite — session state/advisory locks) 2026-07-30 06:40:20 -03:00
Francisco Ignácio Fontoura Solla
f5cc98463d chore: drop unused exports flagged by knip 2026-07-30 05:24:52 -03:00
Francisco Ignácio Fontoura Solla
5b857814c3 chore: format agent scripts 2026-07-30 05:16:00 -03:00
Francisco Ignácio Fontoura Solla
c362b63adb feat: agent ops scripts (claim/register/prioritize/file-miss/promote) + roadmap issues seeded 2026-07-30 05:15:04 -03:00
Francisco Ignácio Fontoura Solla
3120d0b8fa feat: db:refresh:stage — weekly Neon branch refresh + secret swap (human only) 2026-07-30 05:04:14 -03:00
Francisco Ignácio Fontoura Solla
cc8492d831 chore: format seed and workflow files 2026-07-30 04:45:44 -03:00
Francisco Ignácio Fontoura Solla
6ac26404d2 feat: db:seed:minimal — minimal synthetic campaign DB for agents/CI 2026-07-30 04:43:01 -03:00
Francisco Ignácio Fontoura Solla
e462d39fda B13+: concordância LQ, readout de escopo no mapa e DRY do build de agregados.
Rede de segurança para E15, copy honesta no Quadro para assessores, uma varredura federal por ano no artefato e tupla de rank no bundle RSC.
2026-07-29 16:26:43 -03:00
Francisco Ignácio Fontoura Solla
4806c417c8 Engineering Pass 3: consolidate patterns and lock them with guards.
Fold duplicated campanha access, loaders, list/filter/form shells, and scripts into shared modules; reorganize utilities by domain; stabilize e2e; and document prevention-first audit workflow so the same smells cannot creep back in.
2026-07-29 06:11:29 -03:00
Francisco Ignácio Fontoura Solla
2c30944593 B8+: escala das malhas em unidades reais, contrato do map key e degradacao
F1 — a tolerancia de simplificacao e os digitos de quantizacao viraram
politica em unidades de solo em scripts/lib/topology.mjs, consumida pelos
dois scripts de geometria. Os quantis 0.35 copiados cortavam as 19 ZE de
Salvador a ~0.6 m2 e os 417 municipios a ~1.78 km2; com tolerancia
absoluta e a grade de ~103 m do estado, a malha das zonas caiu de 480 para
30.2 pontos/feature. bahia-municipalities segue byte-identico e o tripwire
de bytes deu lugar a pontos/feature.

F2 — featureMapKey passou a ser asserido sobre features reais das tres
malhas comprometidas (417 codarea, 27 code, 19 slug), e o comentario de
MAP_KEY_PROPERTIES agora diz o que o codigo faz: as propriedades sao
mutuamente exclusivas, nao ordenadas por especificidade.

F3 — a malha das zonas e um detalhe sobre o mapa, nao o mapa: se o chunk
falha, Salvador cai no poligono municipal que ja esta desenhado embaixo e
o resto da Bahia continua funcionando, com o motivo logado. A ressalva de
aproximacao saiu do gate de comparacao e passou a depender de
bundle.hasZoneMunicipalities, derivado no servidor de municipality.kind.

F4 — orfaos deletados: os dois acessores sem chamador, isZoneMapKey (o
servidor ja sabe a regra), o wrapper simplifyTopology e o helper
polygonCount com um branch inalcancavel. MunicipalityMapNavigation
colapsou em string | undefined e MunicipalitiesByMapKey em
Record<string, string>.
2026-07-27 01:59:36 -03:00
Francisco Ignácio Fontoura Solla
bb5ac362ed Add users.roles so Payload /admin can separate editors from admins.
Editors publish post/tag/media without PII or campaign access; existing users backfill as admin.
2026-07-27 01:54:29 -03:00
Francisco Ignácio Fontoura Solla
7b70322118 Document B8 F2 and apply the simplify pass findings.
Records the Salvador zone delivery where the next agent will look for it —
roadmap, plan as-built, notebook and the geometry/map sections of AGENTS.md —
including the two measurements that are easy to re-derive wrongly (the bay
water in Salvador's municipal polygon, and ZE 16 wrapping ZE 14, which is why
neither an area ratio nor a centroid check is a valid overlap test).

Simplify fixes: the build script re-indexes simplified geometries by a unique
id instead of neighbourhood name, so a repeated name in a future mesh cannot
silently collapse two polygons inside a committed artifact; a stale comment
claiming zone polygons do not exist; and two int assertions that the Fase 0
catalog hydration turned tautological.

Ledgers the Aikido outage: the scanner returns Opengrep exit 2 for any input,
so the mandatory per-change scan was skipped, not passed.
2026-07-26 23:25:42 -03:00
Francisco Ignácio Fontoura Solla
84e796ab49 B8 F2: polígonos das ZE de Salvador e re-keying do coroplético por map key
Salvador era um polígono só carregando os votos da cidade inteira, então o
coroplético não conseguia responder "qual pedaço de Salvador está fraco / é
meu". As 19 ZE ganham polígono próprio, dissolvido da malha de bairros do IBGE
(Censo 2022) pela lista de circunscrição da RA 02/2017 do TRE-BA, e o mapa passa
a pintar por map key (slug para as zonas, ibgeCode para o resto) em vez de
codarea. O polígono municipal de Salvador continua desenhado por baixo, sem dado
e sem interação, para não abrir buraco no contorno do estado.

Aproximação declarada na copy e no cabeçalho do script: o TRE publica a
circunscrição como lista de bairros, então o bairro é o átomo geométrico —
Periperi, que a resolução corta na Rua das Pedrinhas, vai inteiro para a ZE 17.
competitiveRank segue por cidade (o artefato TSE só tem federalRankByIbgeCode).

Sem migration, sem collection, sem action, sem Consent.
2026-07-26 23:08:09 -03:00
Francisco Ignácio Fontoura Solla
29f45e093a B13: escala relativa no mapa dos Municipios (quantis/LQ/posicao) + artefato TSE v3
O coropleto do Inicio era quase monocromatico porque 0-100% dos validos comprime
uma disputa cujo topo estadual e 4,71%. Tres escalas relativas ao proprio
candidato, todas em classes discretas: quantis (novo default), padrao proprio
(LQ) e posicao no municipio, ao lado de "% dos validos" (B11) e "Total (votos)".

Artefato v3: federalRankByIbgeCode com a colocacao entre todos os candidatos com
votos > 0 na geografia (2014/2018/2022), chaveado por ibgeCode porque e o que o
mapa desenha. Fica no artefato commitado, nao em query de request, que varreria
~100 mil linhas por ano para um dado imutavel. 534 -> 623 KB (orcamento 700 KB).

LQ virou 5 classes nas ancoras do E10, nao diverging: o plano pedia as duas
coisas e se contradizia. Vermelho x azul continua significando "Solla x
adversario" e segue exclusivo do compare.

computeAggregateTerritorialClass classifica um grupo de slugs como um territorio
so, somando insumos e rodando o mesmo classificador (LQ e razao; a media de
razoes nao e a razao das somas) - o E12 herda o helper. TERRITORIAL_CLASS_ANCHORS
mudou para src/lib/territorialClassAnchors.ts para nao arrastar o artefato TSE
ao bundle do cliente.

Quantis sobre o escopo de acesso do usuario, degradando para 3 classes abaixo de
10 municipios com a legenda declarando a contagem efetiva. Rank indisponivel em
2026 (dado TSE); LQ em 2026 reusa o padrao estadual de 2022.

Bolhas opcionais por validos projetados (area proporcional ao valor, cor da
classe E10, interactive: false). 417 marcadores medidos antes de otimizar - nao
derrubaram o frame, entao o corte para top-K nao foi feito.

Sem migration, sem collection, sem server action; bundle client de /campanha
byte a byte igual.
2026-07-26 04:22:56 -03:00
Francisco Ignácio Fontoura Solla
c00f83d870 Tooling: pnpm db:doctor + preflight no guard-dev-db (remedios nomeados, deteccao de volume compartilhado pos-corrupcao WAL), madge check:cycles e prettier no CI/pre-push, guard rails de data migration no skill, notas de processo (knip --fix, pipes) e gate atualizado nos docs/rules 2026-07-25 18:02:02 -03:00
Francisco Ignácio Fontoura Solla
e6f7c2e70f Tooling: prettier como autoridade de formatacao (organize-imports deterministico, scripts format/format:check, normalizacao mecanica de 312 arquivos; artefatos gerados e migrations excluidos via .prettierignore) 2026-07-25 17:22:20 -03:00
Francisco Ignácio Fontoura Solla
0c1127b35a Pass 2 W4a: electionInsights.ts deletado (941 linhas, 71 exports, 2 vivos)
- formatElectionNumber -> src/lib/electionFormat.ts (13 importers); computeVoteTrend + tipos -> src/lib/voteTrend.ts
- ~52 exports sem consumidor deletados (limiares 35/20/10 da era nucleos, gap vs 2022, conversao, mobilizacao, ticket flip/leverage) - decisao D2; formulas no git history; E10 nasce em modulo novo (nota no plano classificacao-territorial-relativa.md)
- specs: voteTrend.unit.spec.ts (pins vivos + pin do defeito E18 de fracao), electionPartySpectrum.unit.spec.ts sem os blocos de ticket; electionInsights.unit.spec.ts deletado
- fix de regressao W2 pega pelo knip: scripts/import-projecao.mjs importava voteEstimate/slug nos paths antigos (knip agora roda sem pipe mascarando exit code)
- knip unused exports: 157 -> 140
2026-07-25 14:57:49 -03:00
Francisco Ignácio Fontoura Solla
717d584f6d E8 follow-up: touch-friendly metric tooltips, 2014/2018 majoritarian seed, E18 docs plan
- MunicipalityHoverTooltip/MunicipalityGoalAccountCard: hover/focus tooltips on
  the 4 "Conta da cadeira" diagnostic numbers, hardened per /impeccable
  critique (touch dead-end fix via controlled open + pointerup toggle +
  outside-tap dismiss, tooltip no longer covers "Cobertura da meta", clearer
  two-tier copy, distinguishable button trigger, thicker 0% progress bar).
- seed-tse-results.mjs/electionResultsBuild/electionResultsParse: seed also
  imports presidente/governador for 2014/2018 (previously deputado federal
  only), with vote-em-transito duplicate merging so the unique constraints
  hold; artifact/formulas stay 2022-only by design.
- Registered E18 (documentacao-conceitos-campanha) roadmap item/plan for a
  future /campanha/conceitos glossary page.
2026-07-24 22:55:51 -03:00
Francisco Ignácio Fontoura Solla
5a4a9033ed E8: Conta da cadeira (metas derivadas, potencial por município, cobertura)
- campoParties.ts + committed election-aggregates artifact v2 (campo federal
  votes, federal tally, 2022 majoritarian presidente/governador)
- global campaignGoals (state goal + margin) with staff-only read /
  unrestricted-write access
- municipalityPotential.ts (teto do campo, captura, share intracampo,
  roll-off, proportional state-goal decomposition) and goalCoverage.ts
  (meta vs comprometido semantics locked this session)
- UI: dashboard + list overview 'Cobertura da meta' metric, new list column,
  detail page 'Conta da cadeira' card
- /simplify pass: dropped dead per-request TI-warning computation, O(1)
  potential lookup, deduped near-identical election loaders/tally types/
  percent formatters
2026-07-24 22:54:27 -03:00
Francisco Ignácio Fontoura Solla
0407f02ce2 Import projection-sheet strategy columns into municipalities (E4R fase 2)
- pnpm db:seed:projecao now also imports SITUAÇÃO -> politicalTrend,
  DOBRADINHAS -> stateDeputy + stateDeputies + dobradinhaNotes,
  LIDERANÇAS -> name-only contact + leadership (statewide slug dedupe),
  ASSESSOR RESPONSÁVEL -> campaignUser + advisors (Edizio=coordinator,
  Solla=candidate, placeholder @planilha.invalid emails),
  ENCAMINHAMENTOS -> nextSteps, OBSERVAÇÃO -> strengths/risks (curated).
  PRIORITÁRIAS overrides MAPA GERAL when non-empty; Salvador stays skipped;
  relationships are unions; re-run is idempotent.
- parseSituationCell + splitNameCell (noise/collective/action filters,
  honorific protection, parenthetical extraction) with unit tests.
- Contact.phone optional (migration 20260724_175500_contact_phone_optional);
  phone invariant hooks skip phone-less contacts; invite flows guard.
- candidate role now eligible for municipality/action-plan advisors
  (eligibleCampaignStaffWhere) per product decision.
2026-07-24 15:58:06 -03:00
Francisco Ignácio Fontoura Solla
c07969f4a7 Remove duplicated voteGoals; seed projection sheet into expectedVotes.
Meta Bom/Regular/Mínimo duplicated the estimate scenarios — keep a single municipality series (pessimista/média/otimista), backfill then drop the old columns, and map the spreadsheet onto expectedVotes.
2026-07-24 14:04:44 -03:00
Francisco Ignácio Fontoura Solla
d14ed67801 Ship E4R: always-overwrite seed of projection spreadsheet into voteGoals and priority.
One-shot CLI (`pnpm db:seed:projecao`) matches MAPA GERAL to municipalities, skips Salvador, and re-seeds when a newer sheet arrives; dry-run + docs/roadmap updated.
2026-07-24 13:13:46 -03:00
Francisco Ignácio Fontoura Solla
a32ba3b4f0 Cache the campaign hot path: committed TSE artifact + request-scoped dedup
- committed artifact src/lib/electionAggregates/bahia-federal-baseline.json
  (Solla nominal + federal T1 valid votes per catalog municipality × TSE year,
  Salvador split by zone) generated by pnpm build:election-aggregates from the
  locally seeded TSE data; typed loader src/lib/bahiaElectionAggregates.ts;
  snapshot spec pins artifact ↔ catalog ↔ baseline ticket
- map bundle: historical years now read the artifact (was 6 statewide
  city×zone scans per dashboard visit); compare mode keeps only the OTHER
  candidate on the DB path (Solla side from the artifact)
- loadMunicipalityScope (React cache()): one municipality find + pledge
  aggregate per request shared by dashboard KPIs, map bundle, and the
  municípios list overview (was 2-3 duplicate loads)
- unstable_cache + election-tse tag on the immutable elections-tab loaders
  (baseline, candidate comparison, candidate options); tag added to the
  /api/revalidate allowlist — runbook: re-seed then bust the tag
- municipalityMapContract.ts: client-safe map vocabulary/bundle types so the
  client panel no longer imports the server data module (build had pulled
  @payload-config into the client graph); municipalityMapData is server-only
  and re-exports the contract; PLAZA_MAP_* renamed to MUNICIPALITY_MAP_*
- petition generateStaticParams enumerates bare ids (getPetitionIds)
2026-07-23 23:06:28 -03:00
Francisco Ignácio Fontoura Solla
0e4e6855dc Add the tooling gate: knip, CI, zero-warning lint, as-never ban
- knip (files/deps at error level; unused exports ledgered as warn) with
  config for Payload/Next entries; deleted the dead modules it confirmed:
  RecentlyVisited + UpcomingActionPlansCard + actionPlanUpcomingPreview,
  lazy-dialog helpers, tseZone, federalCandidateTotalsAggregate (test-only),
  unused ui kit files, one-shot rename script; pruned unused radix deps and
  typescript-eslint; added pg/@types/pg (pinned to drizzle's 8.10.2)
- GitHub Actions CI on the mirror: lint, typecheck, knip, unit, migrate, int
  against a Postgres 17 service
- eslint: unused-vars with ^_ ignore patterns (migrations args exempt),
  repo-wide ban on `as never` (no-restricted-syntax), lint gate at
  --max-warnings=0; fixed all 54 pre-existing warnings (dead imports,
  hooks deps, tracking-pixel img disable with impeccable config exception)
- tsconfig: include consolidated from 219 lines to 5 (wildcard covers all
  .next dist variants), noUnusedLocals on
- typed replacements for every as-never: hookFilledCreateData (actions
  create data completed by collection hooks), drizzle scopeColumn narrowing,
  tests' stub<T> helper (property-level checking kept, completeness waived)
- test infra: leased-consent generalization used by onda0 spec (shared
  leases over the stable consent keys; window race ledgered), purge fix
- docs: IMPROVE-CODE-QUALITY-PLAN.md tracker, TECH-DEBT.md ledger,
  TESTING.md safety-net map (package.json also gains the Phase 2
  build:election-aggregates script entry; the script lands next commit)
2026-07-23 23:06:12 -03:00
Francisco Ignácio Fontoura Solla
e2724c10da Remodel the campaign vertical from Praça to Município
Rename the operational unit "Praça"/"Núcleo" to "Município" (code identifier
`municipality`) and land the 2026-07-23 course changes:

- New `candidate` role with unrestricted visibility (`isCampaignStaff` now
  includes it) alongside coordinator/advisor; leader is locked down to the
  supporter contact tool only.
- Demandas become staff-only; dobradinhas modeled via a `stateDeputy` entity.
- Camaçari consolidated to a single município (ZE 170/171 aggregated);
  Salvador keeps its 19 zone municípios.
- Map moves to the staff dashboard; `/campanha/municipios` is list/overview.
- Vote pledges keep the declared vs estimated (scenario) asymmetry; leaders
  never see estimates.

Destructive migration for the campaign vertical (drops nucleus/plaza-era
tables, wipes campaign rows, seeds 435 municípios). Public-site data untouched.

Includes the post-delivery /simplify cleanups: shared reloadStaffActor /
reloadCoordinatorActor helpers, req.context cache for getFreshCampaignUser,
parallelized dashboard loads, candidate dashboard-copy fix, and dead
leader-dashboard / roleKind code removal.
2026-07-23 21:36:20 -03:00
Francisco Ignácio Fontoura Solla
87c36e4856 Deliver A8 IBGE voter profile on Eleitorado tab with post-simplify scale plan.
Adds static SIDRA demographics, territory-weighted derivation, electorate UI with opt-in copy to manual profiles, shared territory-city resolution, and registers A8+ fill-in debt from capture-review-debts.
2026-07-19 23:05:27 -03:00
Francisco Ignácio Fontoura Solla
c2381cecde Deliver A7 Fase 2 cityCode TSE geography filters and absorb simplify debts.
Switch election geography queries from cityName to TSE cityCode via a static Bahia map and nucleusElectionGeography module, with simplify cleanup and plan updates for F3–F5 follow-ups.
2026-07-19 22:48:08 -03:00
Francisco Ignácio Fontoura Solla
0460b08429 Add allowlisted global cache revalidation for Onda 0 F1.
Extend POST /api/revalidate with posts and global_privacy-policy tags so
direct-DB Onda 0 writes can bust /privacidade without an admin edit.
2026-07-19 22:21:16 -03:00
Francisco Ignácio Fontoura Solla
96329bd46e Deliver E7 Fase 2 int tests for nucleus list election overview.
Add integration coverage for loadNucleusListElectionOverview (gap, trend,
conversion), extend TSE fixtures for multi-year seeding, register E7 Fase 4
test-helper debts on the roadmap, and simplify seed-consent exit handling.
2026-07-19 16:45:36 -03:00
Francisco Ignácio Fontoura Solla
14cfcdb3f6 Restore full roadmap detail and align project documentation.
Expand the compiled next-steps doc back into the full delivery history, cross-reference plan statuses, and sync AGENTS.md, PRODUCT.md, and the Núcleos project notebook.
2026-07-19 16:19:36 -03:00
Francisco Ignácio Fontoura Solla
71421c725c Compile the roadmap into next-steps docs and align project references.
Replace the delivery diary with open items and windows, and sync AGENTS, notebook, README, and plan pointers with provisional Onda 0 Consent hold.
2026-07-19 16:13:47 -03:00
Francisco Ignácio Fontoura Solla
b0f4ebc1ed Add E2 TSE 2014/2018 vote series and historical trend insights.
Extends the electoral baseline with multi-year seeding, computeVoteTrend, list/detail UI, and registers post-simplify follow-ups as E7.
2026-07-19 05:09:43 -03:00
Francisco Ignácio Fontoura Solla
cc66ec3c31 Deliver Onda 0 MVP: provisional Consent, privacy policy, and /privacidade.
Auto-provision legal texts via migrations and db:seed:consent so local and
production deploy stay fail-closed-ready; register O0+ simplify follow-ups.
2026-07-19 03:38:21 -03:00