Commit graph

637 commits

Author SHA1 Message Date
Francisco Ignácio Fontoura Solla
2abcaeaaa5 docs: record cutover checklist progress 2026-07-31 20:57:50 -03: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
5237fa9d79 docs(skills): model-selection Composer / Grok / Kimi K3 only
Collapse the canonical table; bipartition for complex issues; drop
K2.7/Haiku/GLM/Gemini from the happy path.
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
503a775b9f fix(cloud): ensure-postgres bootstrap before teqo readiness check
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>
2026-07-31 20:57:18 -03:00
Cursor Agent
7a876ec334 refactor(notifications): bell loaders read through owner access, no bypass
countUnreadNotifications/loadNotificationList took a caller-supplied
recipientID with module-level admin bypass — one misuse away from reading
someone else's inbox. They now take the actor (CampaignUser) and read
with overrideAccess: false under canReadOwnNotifications, keeping the
explicit recipient filter as a second fence. Pin: owner isolation at the
loader level in campaignNotifications.int.spec.ts.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 20:57:18 -03:00
Cursor Agent
6705db80eb security: lock public globals update to payloadAdminOnly (Pass 4 P0)
The four public globals (site-settings, home, metadata, privacy-policy)
spelled update access as "any authenticated user" — and campaign JWTs
authenticate against /api/*, so any campaign session (leader included)
could PATCH the public site. payloadAdminOnly matches the collection
lockdown precedent; editors lose config-global writes deliberately
(content editing stays on canManagePublishedContent collections).

Pins: identity + deny (coordinator/editor) + allow (admin fn) + anonymous
read in collectionAccessLockdown.int.spec.ts. Recurrence guard:
globalAccessConventions.unit.spec.ts bans the Boolean(user) shape in
src/globals.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-31 20:57:18 -03:00
Cursor Agent
84fed02ee5 test(miss-54): deterministic guard for unsettled goto→goto + nav convention
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).
2026-07-31 20:57:18 -03:00
Cursor Agent
5c59793e4c test(miss-53): gate WebAuthn ceremonies on authenticator readiness
The app's biometrics probe is one-shot per island mount: when
isUserVerifyingPlatformAuthenticatorAvailable() resolves before the CDP
virtual authenticator answers, the enrollment form / biometric button
never mount and no wait flips them (prod-build CI flake). New
expectCampaignBiometricsReady(page) polls the platform answer BEFORE the
surface whose island probes it; adopted at both ceremony entries in
campaignWebAuthn (verified green locally). Conventions pin:
e2eNavigationConventions fails the build when a virtual-authenticator
spec skips the readiness gate.
2026-07-31 20:57:18 -03:00
Francisco Ignácio Fontoura Solla
d28ecb831a style: prettier A6-pre dobradinha baseline plan 2026-07-31 20:57:18 -03:00
Francisco Ignácio Fontoura Solla
b1a34a8c3a fix(tests): allocate homeSearch municipalities; scope B42 trend drawer 2026-07-31 20:57:17 -03:00
Cursor Agent
e51a1dc9b2 style: prettier campaignHomeActions after URL anchor edits 2026-07-31 20:57:17 -03:00
Cursor Agent
03314e620a test(miss-73): deterministic allocator guardrails in conventions spec
Recurrence prevention for the deadlock class, three rules:
1. a spec file calling getMunicipality(<arg>) while mutating
   municipalities (assign/touch/create*/payload.update municipality)
   fails the build — the class miss #73 named;
2. hardcoded municipio=<slug> deep links banned in tests/e2e —
   claimMunicipality().slug is the only source;
3. e2e name: /.../ regex literals containing a catalog municipality name
   must be ^-anchored — the literal-regex dodge of the P3-C template
   guard, keyed on the catalog so copy regexes stay untouched.
2026-07-31 20:57:17 -03:00
Cursor Agent
6b894a04c5 test(miss-73): allocate municipalities, never pin seeded slugs (deadlock class)
Int specs pinning seeded rows (cairu/feira-de-santana/catalog[0..2] or
class-derived fixed slugs) and mutating them deadlocked municipality_rels
under the parallel suite (40P01); e2e specs deep-linking ?municipio=cairu
raced the same row from two workers.

- homeSearchStateDeputies: 2 fixed slugs -> 2 allocations.
- municipalityPageData classe test: rewritten class-AGNOSTIC — allocates
  rows until two distinct territorial classes (same pinned behavior:
  filter narrows, totals honest, classe sort = descending weight), no
  fixed reduto/marginal slugs. nivel test + facet test: plain allocations.
- campaignHomeActions/campaignWizardChrome: 11 hardcoded cairu deep links
  -> claimMunicipality(); hit clicks disambiguate by href (catalog names
  are not prefix-unique); caption/URL assertions use ^-anchored full-URL
  regexes (P3-C template guard). /Cairu/i literals gone.

Verified: int 17/17, e2e 18/18 (dev mode), unit 1106/1106.
2026-07-31 20:57:17 -03:00
Francisco Ignácio Fontoura Solla
f27e801e25 docs: restore A6-pre dobradinha baseline plan
Needed by open issue A6-pre; file lived only on a filtered agent branch tip.
2026-07-31 13:49:53 -03:00
Francisco Solla
9e6dd4c061
Merge pull request #9 from fsolla/stage
Promote stage → main (auto)
2026-07-31 13:43:05 -03:00
Francisco Solla
7a66fe4f25
Merge pull request #5 from fsolla/cursor/p4-shared-sheet-host-78a7
Miss #52 guardrail: shared sheet host on the chip-relation lists + fail-loud guard
2026-07-31 13:21:48 -03:00
Francisco Solla
dcaeb4a22a
Merge pull request #3 from fsolla/cursor/p4-script-guard-hardening-78a7
Pass 4 P1: seed-posts missing dieWithLabel import + script/lib guard hardening
2026-07-31 13:21:35 -03:00
Francisco Solla
77fb5384d4
Merge pull request #7 from fsolla/cursor/p4-audit-artifacts-78a7
Pass 4 audit artifacts: plan, ledger reconcile, delivery plan, GUARDRAILS.md
2026-07-31 13:20:40 -03:00
Cursor Agent
836a819074 docs(testing): suite counts truth-up (117 unit / 71 int / 17 e2e, 48 cases) + allocator contract 2026-07-31 13:17:28 -03:00
Cursor Agent
d2791050da docs(pass-4): audit artifacts — plan section, ledger reconcile, delivery plan, GUARDRAILS.md
Autonomous engineering-audit 2026-07-31 (precheck: gh-doctor OK, pool
desligado). Delta anchor Pass 3 (880 files in 3 days). Baseline green
(tsc/lint/knip/cycles; 774 files madge).

- IMPROVE-CODE-QUALITY-PLAN: Pass 4 section — 1 P0 (globals Boolean(user)
  -> PR #91), 1 P1 (seed-posts dieWithLabel -> PR #92), 5 misses -> 5
  guardrails (PRs #93-#95, #83 verified+closed), decisions D1-D6.
- TECH-DEBT: rows 33/34 verified fixed and closed (P3-A/P3-B); 17/19/23/
  35/40/45 updated with measured counts and trigger status; 15 new rows
  with evidence (homeSearch twins, notification write path, wizard
  drawers, B14-class labels import, bypass-header dodge, dev-mode chip
  failure with instrumentation, god modules, fixture honesty...).
- docs/plans/entrega-engenharia-p4.md: waves P4-A..P4-L, guard map
  (9 new guards, 2 hardened, judgment-only residue declared), 12
  defer+trigger, 6 rejected look-alikes, execution rules.
- docs/GUARDRAILS.md (new, OPS2 scope): one row per guardrail — origin,
  determinism class 1-6, mechanism, status; active, precedents, queue.
- CHANGELOG-AGENTS: one delivery entry per convention.

Aikido not run (MCP unavailable in this Cloud env — ledger row noted).
Closes #43
2026-07-31 13:17:27 -03:00
Cursor Agent
c83cf28497 test(miss-52): sheet cells without the shared host fail loud
- CampaignCellEditOverlay: dev-mode console.error when a variant=sheet
  cell mounts without CampaignListSheetProvider (prod keeps the
  lazy-mount fallback for resilience; unit tests exercise it, so the
  invariant is development-only).
- sharedSheetHostConventions.unit.spec.ts: any tsx rendering
  <MunicipalityPortfolioCell / <LeadershipStateDeputyRelationCell must
  reference CampaignListSheetProvider — the next chip table cannot
  reintroduce per-cell Drawers by omission.
2026-07-31 13:17:19 -03:00
Cursor Agent
6f42bc3bf3 fix(miss-52): one shared Drawer for the chip-relation lists too
The B42 fix reached the municípios mobile cards, but the three
chip-relation surfaces still mounted a Drawer root per OPENED cell on
coarse pointers (lideranças 50 cells, dobradinhas 50, assessores 25):
the exact hundreds-of-hidden-instances class that tripped React #130 in
prod. Each now wraps its table in CampaignListSheetProvider — cell
bodies portal into the single host Drawer, fine-pointer popover path
untouched (behavior delta: after opening N cells sequentially on touch,
N drawer roots -> 1).
2026-07-31 13:17:19 -03:00
Cursor Agent
9ae062c77c refactor(lib): close the lib→utilities type-import hole + Local API omission guard
- suggestionCatalog type-imports MunicipalityTerritorialClass from
  lib/territorialClassAnchors (the single source) instead of the
  utilities re-export — direction inversion introduced in Pass 3.
- ESLint src/lib zone: @/utilities|components|app restriction now rejects
  type imports too (allowTypeImports: false); shared types live in lib
  contract modules by policy.
- engagementLevel imports DAY_MS from lib/text (fold missed in P3-K).
- searchHomeAdvisors: delete stale 'Intentional admin bypass' comment —
  the call is overrideAccess: false under the staff gate.
- New guard localApiOverrideAccessConventions.unit.spec.ts: payload calls
  with user must declare overrideAccess (baseline measured: 59 calls, 0
  missing), and runtime dynamic import/require of payload/next server
  modules is banned in utilities (dodges the server-only sweep).
2026-07-31 13:17:10 -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
bfbb0ec713 style: prettier-format public-release docs
Fixes format job failure on stage/main after the public-tip sanitize commit.
2026-07-31 13:16:22 -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 Solla
8dd60cf962 A6 — Dobradinha 2026 automática quando o TSE publicar candidaturas (pós-15/08) (#82)
* 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>
2026-07-31 00:14:27 -03:00
Francisco Solla
15c6a96e1c Merge pull request #77 from fsolla/cursor/b79-quick-actions-drawer-54a3
B79 — Chassis do bottom drawer de ações rápidas + busca global (mobile, não-modal)
2026-07-30 23:45:02 -03:00
Francisco Solla
f357fcd780 fix(agent-pool): tick falhava em ERR_MODULE_NOT_FOUND (dotenv) (#72)
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>
2026-07-30 23:41:59 -03:00
Cursor Agent
118544cbaa fix: remove leftover merge conflict markers in app layout 2026-07-31 02:37:17 +00:00
Cursor Agent
f1759c57a9 fix: remove unused HomeSearchProvider import (CI lint/typecheck) 2026-07-31 02:34:15 +00:00
Cursor Agent
2f1e2b7958 style: prettier after B91 scope trim 2026-07-31 02:34:15 +00:00
Cursor Agent
83f0b1cf48 fix: remove leftover merge conflict markers in int test 2026-07-31 02:34:15 +00:00
Cursor Agent
c7aac4da1b test: pin home search municipality scope fixtures to distinct slugs 2026-07-31 02:34:15 +00:00
Cursor Agent
5d45909780 fix: drop unused quick-action setter hook until B80 2026-07-31 02:34:14 +00:00
Cursor Agent
224cbf84f5 test: cover quick action context setter hook for knip 2026-07-31 02:34:14 +00:00
Cursor Agent
b756f5cdf4 style: prettier 2026-07-31 02:34:14 +00:00
Cursor Agent
a2eabaccba B79 — chassis do bottom drawer de ações rápidas + busca global (mobile)
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>
2026-07-31 02:34:08 +00:00
Francisco Solla
b2b11c3dfe Merge pull request #81 from fsolla/cursor/d2-push-sino-in-app-af30
D2 — Push + sino in-app
2026-07-30 23:25:11 -03:00
Francisco Solla
5a6591e9b1 chore(ops): engineering-audit pronta para rodada autônoma no Cursor Cloud (#79)
- Precheck solitário fail-closed (pnpm agent:pool -- status; gh read-only no Cloud não pausa o pool)
- Sign-off em modo autônomo = PR dos artefatos (Ready, base stage); P0/P1 e guardrails de misses executam na sessão
- Harvest kind:agent-miss: investigação via gh issue view; fechamento via Closes #N + flip determinístico do issue-done-on-stage-merge.yml
- Âncora de delta: foco no churn desde a data do último Pass em vez de --since=3months

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
2026-07-30 23:13:34 -03:00
Cursor Agent
b9a81f7ad0 D2 — skip notification hooks in Vitest; fixture cleanup for push rows 2026-07-31 02:09:52 +00:00
Francisco Solla
7448d4c805 Merge pull request #78 from fsolla/cursor/consolidate-dry-fatia-b79-1e6b
ops — consolidar O0+/B68+ e fatiar B79→B91
2026-07-30 23:08:30 -03:00
Cursor Agent
5700817563 docs: consolidate O0+/B68+ and fatia B79→B91
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>
2026-07-31 01:57:16 +00:00
Francisco Solla
99330f845d Merge pull request #75 from fsolla/cursor/b5-geometry-factory-ac3f
B5 — Cache CLI compartilhado + factory mun/TI (F2–F3)
2026-07-30 22:53:55 -03:00
Cursor Agent
de67acf41b D2 — Push + sino in-app para /campanha
- 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>
2026-07-31 01:51:41 +00:00
Francisco Solla
211f53b137 Merge pull request #74 from fsolla/agent/promote-last-green
feat(ops): promote último ci-stage green + fix deadlock homeSearch specs
2026-07-30 22:42:18 -03:00
Cursor Agent
479af4f2ef style: prettier bahiaGeometryModuleFactory 2026-07-31 01:42:01 +00:00
Cursor Agent
8188c9a386 refactor(B5): reuse BahiaFeature type and drop wrapper casts 2026-07-31 01:41:00 +00:00