diff --git a/.impeccable/config.json b/.impeccable/config.json
index ffa72c0d..e048c55c 100644
--- a/.impeccable/config.json
+++ b/.impeccable/config.json
@@ -6,27 +6,21 @@
{
"rule": "design-system-color",
"value": "#111827",
- "files": [
- "src/collections/CampaignUser.ts"
- ],
+ "files": ["src/collections/CampaignUser.ts"],
"createdAt": "2026-07-21T01:54:11.928Z",
"reason": "Pre-existing inline hex in the password-reset EMAIL HTML template; transactional email cannot use CSS tokens"
},
{
"rule": "broken-image",
"value": "*",
- "files": [
- "src/components/MetaPixel.tsx"
- ],
+ "files": ["src/components/MetaPixel.tsx"],
"createdAt": "2026-07-23T22:40:00.000Z",
"reason": "Meta's documented noscript tracking pixel: a hidden 1x1 whose src is a templated facebook.com/tr URL — not a rendered image"
},
{
"rule": "design-system-color",
"value": "#c86112",
- "files": [
- "src/app/(frontend)/styles.css"
- ],
+ "files": ["src/app/(frontend)/styles.css"],
"createdAt": "2026-07-25T02:48:38.641Z",
"reason": "Pre-existing public-site body brand gradient (live in production, predates the hook); flagged while an unrelated print block was added"
}
diff --git a/.impeccable/critique/2026-07-19T10-15-47Z__src-app-campaign-campanha.md b/.impeccable/critique/2026-07-19T10-15-47Z__src-app-campaign-campanha.md
index b1c3d937..ea6b97ca 100644
--- a/.impeccable/critique/2026-07-19T10-15-47Z__src-app-campaign-campanha.md
+++ b/.impeccable/critique/2026-07-19T10-15-47Z__src-app-campaign-campanha.md
@@ -8,25 +8,26 @@ p2_count: 2
timestamp: 2026-07-19T10-15-47Z
slug: src-app-campaign-campanha
---
+
Method: dual-agent (A: 89c6189f-1341-4e15-8d45-e1aa7c6f5167 · B: 3e87667e-e21e-4a29-85b4-db65afcc49c5)
# Critique: /campanha
## Design Health Score
-| # | Heuristic | Score | Key Issue |
-|---|-----------|-------|-----------|
-| 1 | Visibility of System Status | 3 | Pending/aria-live on filters; no freshness/"as of" on KPI aggregates |
-| 2 | Match System / Real World | 4 | Domain language precise (Núcleo vs Zona TSE disambiguated) |
-| 3 | User Control and Freedom | 3 | Clear filters/back; limited undo for irreversible paths |
-| 4 | Consistency and Standards | 3 | Strong component discipline; role dashboards diverge in max-width/chrome |
-| 5 | Error Prevention | 3 | Constrained selects + inline ZE validation |
-| 6 | Recognition Rather Than Recall | 4 | Filter state in URL; labels on actions |
-| 7 | Flexibility and Efficiency | 2 | No saved views; queues are one-by-one, no bulk |
-| 8 | Aesthetic and Minimalist Design | 2 | geral dashboard = even wall of same-weight Cards |
-| 9 | Error Recovery | 3 | Forgot-password names fallback; leadership empty does not |
-| 10 | Help and Documentation | 1 | Almost no glossary/tooltips for ZE / engajado / estimativa |
-| **Total** | | **28/40** | **Good** |
+| # | Heuristic | Score | Key Issue |
+| --------- | ------------------------------- | --------- | ------------------------------------------------------------------------ |
+| 1 | Visibility of System Status | 3 | Pending/aria-live on filters; no freshness/"as of" on KPI aggregates |
+| 2 | Match System / Real World | 4 | Domain language precise (Núcleo vs Zona TSE disambiguated) |
+| 3 | User Control and Freedom | 3 | Clear filters/back; limited undo for irreversible paths |
+| 4 | Consistency and Standards | 3 | Strong component discipline; role dashboards diverge in max-width/chrome |
+| 5 | Error Prevention | 3 | Constrained selects + inline ZE validation |
+| 6 | Recognition Rather Than Recall | 4 | Filter state in URL; labels on actions |
+| 7 | Flexibility and Efficiency | 2 | No saved views; queues are one-by-one, no bulk |
+| 8 | Aesthetic and Minimalist Design | 2 | geral dashboard = even wall of same-weight Cards |
+| 9 | Error Recovery | 3 | Forgot-password names fallback; leadership empty does not |
+| 10 | Help and Documentation | 1 | Almost no glossary/tooltips for ZE / engajado / estimativa |
+| **Total** | | **28/40** | **Good** |
## Anti-Patterns Verdict
@@ -49,36 +50,42 @@ A serious field desk with strong a11y/touch discipline and honest empty-state co
## Priority Issues
### [P1] Filter panel decision overload
+
**What:** `NucleusFilters` shows 6 fields at once on desktop (TI, município, ZE, cobertura, estimativa, prioridade) plus search.
**Why it matters:** Primary triage tool under time pressure; violates clarity-under-pressure and >4 options rule.
**Fix:** Keep territory + search primary; put coverage/estimate/priority behind "Mais filtros" at all breakpoints.
**Suggested command:** `/impeccable distill` / `/impeccable layout`
### [P1] Hero-metric Card grids contradict own anti-references
+
**What:** General dashboard, NucleusListOverview, SupporterListOverview all use Card → description → big number grids.
**Why it matters:** PRODUCT/DESIGN ban identical card grids / hero-metric templates; this is the strongest "template AI" tell.
**Fix:** Compact secondary metrics into a stat row; reserve Card + priority lift for 1–2 decisive numbers; rank action queues.
**Suggested command:** `/impeccable quieter` / `/impeccable layout`
### [P1] Side-tab accent on baseline row (detector)
+
**What:** `border-l-4 border-primary` on highlighted candidate in NucleusElectoralBaseline.
**Why it matters:** Absolute ban (side-stripe >1px); deterministic AI-tell.
**Fix:** Full border, background tint only, or leading mark — no thick left stripe.
**Suggested command:** `/impeccable quieter`
### [P2] Liderança empty state is a dead end
+
**What:** "Nenhum núcleo" / "vínculo engajado" + warning icon, no CTA.
**Why it matters:** Peer persona stranded; jargon without next step.
**Fix:** Mirror forgot-password — name who to contact (coordenador / WhatsApp).
**Suggested command:** `/impeccable clarify` / `/impeccable onboard`
### [P2] No freshness signal on aggregates
+
**What:** KPIs/overviews never show when data was computed.
**Why it matters:** Field decisions need trust in recency.
**Fix:** Relative "atualizado há…" near overview headers.
**Suggested command:** `/impeccable harden`
### [P3] Split brand chrome (mobile red bar vs desktop stone rail)
+
**What:** Mobile top bar is solid Mandate Red; desktop sidebar is quiet rail.
**Why it matters:** Breaks Signal Red Rule for Casey/Lia switching devices unless intentional "field mode."
**Fix:** Document as field-mode signal or quiet the mobile chrome.
diff --git a/.impeccable/critique/2026-07-19T11-03-23Z__src-app-campaign-campanha.md b/.impeccable/critique/2026-07-19T11-03-23Z__src-app-campaign-campanha.md
index 4aca3562..e2ae0c2f 100644
--- a/.impeccable/critique/2026-07-19T11-03-23Z__src-app-campaign-campanha.md
+++ b/.impeccable/critique/2026-07-19T11-03-23Z__src-app-campaign-campanha.md
@@ -8,25 +8,26 @@ p3_count: 2
timestamp: 2026-07-19T11-03-23Z
slug: src-app-campaign-campanha
---
+
Method: dual-agent (A: 43c7ddf0-03c4-40b6-86e4-167ed820fbc3 · B: c685e95f-8884-4bd6-9174-53d1a4613689)
# Critique: /campanha
## Design Health Score
-| # | Heuristic | Score | Key Issue |
-|---|-----------|-------|-----------|
-| 1 | Visibility of System Status | 4 | Freshness on KPI surfaces; filter aria-busy/live region |
-| 2 | Match System / Real World | 4 | Núcleo vs Zona TSE stated on list; domain language solid |
-| 3 | User Control and Freedom | 4 | Differentiated AlertDialogs; clear filter clear/back |
-| 4 | Consistency and Standards | 3 | List/dashboard on CampaignPageShell; detail/forms still ad-hoc max-w |
-| 5 | Error Prevention | 3 | Constrained selects + ZE validation; otherwise unchanged |
-| 6 | Recognition Rather Than Recall | 4 | URL filters; RecentlyVisited; freshness timestamps |
-| 7 | Flexibility and Efficiency | 2 | No saved views; triage queues still one-by-one (CSV bulk only) |
-| 8 | Aesthetic and Minimalist Design | 3 | Metric strips + one priority lift; MetricStrip still double-card surface |
-| 9 | Error Recovery | 3 | Leadership empty has CTA; coordenador empty still prose-only |
-| 10 | Help and Documentation | 2 | One Núcleo/ZE line; engajado / estimativa vocabulary still unexplained |
-| **Total** | | **32/40** | **Good** |
+| # | Heuristic | Score | Key Issue |
+| --------- | ------------------------------- | --------- | ------------------------------------------------------------------------ |
+| 1 | Visibility of System Status | 4 | Freshness on KPI surfaces; filter aria-busy/live region |
+| 2 | Match System / Real World | 4 | Núcleo vs Zona TSE stated on list; domain language solid |
+| 3 | User Control and Freedom | 4 | Differentiated AlertDialogs; clear filter clear/back |
+| 4 | Consistency and Standards | 3 | List/dashboard on CampaignPageShell; detail/forms still ad-hoc max-w |
+| 5 | Error Prevention | 3 | Constrained selects + ZE validation; otherwise unchanged |
+| 6 | Recognition Rather Than Recall | 4 | URL filters; RecentlyVisited; freshness timestamps |
+| 7 | Flexibility and Efficiency | 2 | No saved views; triage queues still one-by-one (CSV bulk only) |
+| 8 | Aesthetic and Minimalist Design | 3 | Metric strips + one priority lift; MetricStrip still double-card surface |
+| 9 | Error Recovery | 3 | Leadership empty has CTA; coordenador empty still prose-only |
+| 10 | Help and Documentation | 2 | One Núcleo/ZE line; engajado / estimativa vocabulary still unexplained |
+| **Total** | | **32/40** | **Good** |
## Anti-Patterns Verdict
@@ -49,30 +50,35 @@ Prior P1s (filter wall, hero-metric card grids, side-tab) are closed. The surfac
## Priority Issues
### [P2] Domain jargon still opaque beyond one sentence
+
**What:** engajado, estimativa confirmada vs proposta, support statuses lack tooltips/help.
**Why it matters:** Lia and first-timers translate under pressure; Help heuristic still weakest.
**Fix:** Inline ? / first-visit hint on SupportStatusBadge and estimate labels.
**Suggested command:** `/impeccable clarify`
### [P2] Dashboard queues cannot be triaged in bulk
+
**What:** Sem coordenador / stale updates / pending estimates are one-row links only.
**Why it matters:** Alex under time pressure on a growing queue; CSV bulk exists for import but not daily triage.
**Fix:** Multi-select + assign on the priority queue only.
**Suggested command:** `/impeccable layout`
### [P2] Dashboard heading outline skips h2
+
**What:** Detector + source: h1 "Visão geral" then QueueSection h3 before Indicadores h2.
**Why it matters:** Screen-reader document outline; Sam persona.
**Fix:** Promote Filas section title to h2, demote queue titles to h3; or insert sr-only/visible h2.
**Suggested command:** `/impeccable audit`
### [P3] Coordenador empty state has no CTA
+
**What:** Prose-only empty vs leadership empty with Ver meu perfil.
**Why it matters:** Last sibling of the old dead-end pattern.
**Fix:** Mirror EmptyContent CTA pattern.
**Suggested command:** `/impeccable onboard`
### [P3] MetricStrip double card surface + sidebar height transition
+
**What:** Overlay nested-cards on strip `bg-card` inside `bg-card`; Sidebar `transition-[width,height,padding]`.
**Why it matters:** Mild visual nesting / layout jank risk — not task-blocking.
**Fix:** Flatten inner metric cells to transparent; prefer transform/opacity on chrome.
diff --git a/.impeccable/critique/2026-07-19T15-10-58Z__src-app-campaign-campanha-login.md b/.impeccable/critique/2026-07-19T15-10-58Z__src-app-campaign-campanha-login.md
index 93022d5c..797ea4a7 100644
--- a/.impeccable/critique/2026-07-19T15-10-58Z__src-app-campaign-campanha-login.md
+++ b/.impeccable/critique/2026-07-19T15-10-58Z__src-app-campaign-campanha-login.md
@@ -6,25 +6,26 @@ p1_count: 2
timestamp: 2026-07-19T15-10-58Z
slug: src-app-campaign-campanha-login
---
+
Method: dual-agent (A: cd378fde-c091-463a-8e89-ca6cecac8904 · B: 44f7668c-1143-41ec-a147-a2dc2f4d7f9c)
# Critique: /campanha/login
## Design Health Score
-| # | Heuristic | Score | Key Issue |
-|---|-----------|-------|-----------|
-| 1 | Visibility of System Status | 3 | Pending state is clear (Spinner + “Entrando…”); auth failure is a single generic FieldError not tied to fields |
-| 2 | Match System / Real World | 3 | “E-mail ou celular” matches dual auth, but leadership phone path vs email-only reset is invisible on this screen |
-| 3 | User Control and Freedom | 3 | Forgot-password link exists; no show-password, no first-access/invite escape |
-| 4 | Consistency and Standards | 3 | Auth shell duplicated across login/esqueci/redefinir; Entrar lacks `w-full` unlike sibling forms |
-| 5 | Error Prevention | 2 | `inputMode="email"` on a dual identifier; validation authoritative only on server with generic messages |
-| 6 | Recognition Rather Than Recall | 4 | Standard login IA; placeholder shows both formats |
-| 7 | Flexibility and Efficiency | 2 | Single rigid credential path; no returning-user / PWA shortcut |
-| 8 | Aesthetic and Minimalist Design | 4 | Restrained Field Desk card on muted; Signal Red budget respected |
-| 9 | Error Recovery | 3 | Generic security error is correct but offers no next-step branch for phone-only / invite users |
-| 10 | Help and Documentation | 1 | Zero first-timer guidance on login; forgot-password already explains phone→coordenador invite |
-| **Total** | | **28/40** | **Good** |
+| # | Heuristic | Score | Key Issue |
+| --------- | ------------------------------- | --------- | ---------------------------------------------------------------------------------------------------------------- |
+| 1 | Visibility of System Status | 3 | Pending state is clear (Spinner + “Entrando…”); auth failure is a single generic FieldError not tied to fields |
+| 2 | Match System / Real World | 3 | “E-mail ou celular” matches dual auth, but leadership phone path vs email-only reset is invisible on this screen |
+| 3 | User Control and Freedom | 3 | Forgot-password link exists; no show-password, no first-access/invite escape |
+| 4 | Consistency and Standards | 3 | Auth shell duplicated across login/esqueci/redefinir; Entrar lacks `w-full` unlike sibling forms |
+| 5 | Error Prevention | 2 | `inputMode="email"` on a dual identifier; validation authoritative only on server with generic messages |
+| 6 | Recognition Rather Than Recall | 4 | Standard login IA; placeholder shows both formats |
+| 7 | Flexibility and Efficiency | 2 | Single rigid credential path; no returning-user / PWA shortcut |
+| 8 | Aesthetic and Minimalist Design | 4 | Restrained Field Desk card on muted; Signal Red budget respected |
+| 9 | Error Recovery | 3 | Generic security error is correct but offers no next-step branch for phone-only / invite users |
+| 10 | Help and Documentation | 1 | Zero first-timer guidance on login; forgot-password already explains phone→coordenador invite |
+| **Total** | | **28/40** | **Good** |
## Anti-Patterns Verdict
@@ -47,30 +48,35 @@ A clean, trustworthy ops gate that earns familiarity — then stalls for the peo
## Priority Issues
### [P1] Missing document heading landmark
+
- **What**: `CardTitle` is a `
` inherits base `leading-7` (28px) while CardDescription stays ~20px. Title glued to howto; second muted block breathes like article body. **Fix:** One muted block with explicit leading-snug; bump title→desc gap; never bare `
` under campaign theme without leading override. **Command:** `/impeccable layout` + `/impeccable typeset` ### P2 — Split-screen + public publications: recommend No + Login is ops gate (noindex); posts are public register. Phone users get scroll soup. Motivation ≠ news feed on unlock. **Soft maybe:** one quiet purpose line under mark — not a publication panel. **Command:** `/impeccable shape` only if product insists on panel (internal voice, not posts) ### P2 — Generic Megaphone mark + Not Solla / Field Desk identity. **Command:** `/impeccable polish` (reuse campaign-logo) ### P3 — Always-on first-access paragraph + Progressive disclosure for returning users. **Command:** `/impeccable distill` or `/impeccable clarify` diff --git a/.impeccable/critique/2026-07-19T23-22-03Z__src-app-campaign-campanha-app-page-tsx.md b/.impeccable/critique/2026-07-19T23-22-03Z__src-app-campaign-campanha-app-page-tsx.md index 043498e7..ca1446ee 100644 --- a/.impeccable/critique/2026-07-19T23-22-03Z__src-app-campaign-campanha-app-page-tsx.md +++ b/.impeccable/critique/2026-07-19T23-22-03Z__src-app-campaign-campanha-app-page-tsx.md @@ -7,23 +7,24 @@ p2_count: 3 timestamp: 2026-07-19T23-22-03Z slug: src-app-campaign-campanha-app-page-tsx --- + Method: dual-agent (A: design review · B: detector + Playwright screenshots) ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 3 | KPIs têm `CampaignDataFreshness`; filas não mostram idade dos itens | -| 2 | Match System / Real World | 3 | Linguagem de núcleo/fila encaixa; **"Lideranças" sem contexto** | -| 3 | User Control and Freedom | 3 | **"Limpar"** em Visitados é ghost sem ícone nem `aria-label` claro | -| 4 | Consistency and Standards | 2 | **Lista de núcleos usa `lg:grid-cols-2`; dashboard geral não** | -| 5 | Error Prevention | 3 | Dashboard read-only; sem riscos destrutivos aqui | -| 6 | Recognition Rather Than Recall | 3 | Visitados ajuda recall; **cores do mapa não são decodificáveis** | -| 7 | Flexibility and Efficiency | 2 | **Coluna única + `max-w-screen-2xl`** desperdiça desktop largo | -| 8 | Aesthetic and Minimalist Design | 2 | **Três subseções vazias nas filas**; cards com muito respiro interno | -| 9 | Error Recovery | 3 | N/A nesta tela | -| 10 | Help and Documentation | 2 | Status de apoio e escala do mapa sem glossário/legenda visual | -| **Total** | | **27/40** | **Acceptable — melhorias significativas antes de sentir "pronto"** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | -------------------------------------------------------------------- | +| 1 | Visibility of System Status | 3 | KPIs têm `CampaignDataFreshness`; filas não mostram idade dos itens | +| 2 | Match System / Real World | 3 | Linguagem de núcleo/fila encaixa; **"Lideranças" sem contexto** | +| 3 | User Control and Freedom | 3 | **"Limpar"** em Visitados é ghost sem ícone nem `aria-label` claro | +| 4 | Consistency and Standards | 2 | **Lista de núcleos usa `lg:grid-cols-2`; dashboard geral não** | +| 5 | Error Prevention | 3 | Dashboard read-only; sem riscos destrutivos aqui | +| 6 | Recognition Rather Than Recall | 3 | Visitados ajuda recall; **cores do mapa não são decodificáveis** | +| 7 | Flexibility and Efficiency | 2 | **Coluna única + `max-w-screen-2xl`** desperdiça desktop largo | +| 8 | Aesthetic and Minimalist Design | 2 | **Três subseções vazias nas filas**; cards com muito respiro interno | +| 9 | Error Recovery | 3 | N/A nesta tela | +| 10 | Help and Documentation | 2 | Status de apoio e escala do mapa sem glossário/legenda visual | +| **Total** | | **27/40** | **Acceptable — melhorias significativas antes de sentir "pronto"** | ## Anti-Patterns Verdict @@ -46,26 +47,31 @@ O dashboard tem ingredientes certos para o Field Desk (fila prioritária, faixa ## Priority Issues ### [P1] Desktop não aproveita largura; ultra-wide deixa vazio à direita + - **Why:** `CampaignPageShell` usa `flex-col gap-8` sem breakpoint grid; `mr-auto max-w-screen-2xl` prende conteúdo à esquerda em monitores largos. - **Fix:** Reflow `GeneralDashboard` em `lg:grid` (ex.: filas + KPIs à esquerda, mapa sticky + eventos à direita), espelhando `NucleusListOverview`. Considerar `mx-auto` ou remover cap em `xl:` quando houver grid de 2 colunas. - **Suggested command:** `/impeccable layout` ### [P1] Filas de ação vazias ocupam espaço sem valor + - **Why:** `QueueSection` sempre renderiza; com tudo zerado o usuário lê três mensagens + três badges "0". - **Fix:** Se todas as filas vazias, um único estado positivo ("Nada pendente — filas em dia"); renderizar subseções só quando `items.length > 0`. - **Suggested command:** `/impeccable quieter` ### [P2] Escala do mapa sem cores + - **Why:** `choroplethFillColor` implementa gradiente rose→vermelho; UI só mostra números em `ChoroplethMapControls`. - **Fix:** Barra de legenda com swatches usando o mesmo ramp; rótulos 0 e máximo. - **Suggested command:** `/impeccable clarify` ### [P2] "Lideranças" sem framing + - **Why:** Linha solta com badges de status + contagem; não fica claro que são contatos de liderança em todos os núcleos por status de apoio. - **Fix:** Card com título + descrição; link para lista filtrada; tooltip/glossário nos status. - **Suggested command:** `/impeccable clarify` ### [P2] Visitados recentemente — bullets e botão Limpar + - **Why:** `
` solto | -| 5 | Error Prevention | 3 | Dashboard read-only; sem riscos destrutivos nesta tela | -| 6 | Recognition Rather Than Recall | 4 | `ChoroplethLegend` + visitados recentes; glossário ainda só em `title` | -| 7 | Flexibility and Efficiency | 2 | Fila prioritária ainda é um clique por núcleo; sem triagem em lote | -| 8 | Aesthetic and Minimalist Design | 3 | Top row 3:2:1 funciona; dois `CampaignMetricStrip` + mapa sem header | -| 9 | Error Recovery | 3 | Empty de liderança com CTA; coordenador sem próximo passo | -| 10 | Help and Documentation | 2 | Status de apoio e estimativa sem affordance touch (`?`/Popover) | -| **Total** | | **32/40** | **Good — fundação sólida; flexibilidade e ajuda ainda abaixo do ideal** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ------------------------------------------------------------------------------------ | +| 1 | Visibility of System Status | 3 | KPIs têm `CampaignDataFreshness`; filas não mostram idade do item na linha | +| 2 | Match System / Real World | 4 | Linguagem de núcleo/fila encaixa; `LeadershipStatusCard` contextualiza status | +| 3 | User Control and Freedom | 4 | `RecentlyVisitedCard` com `aria-label` no limpar; liderança tem CTA no empty | +| 4 | Consistency and Standards | 3 | Dashboard `geral` alinhado ao grid coordenador; empty de eventos ainda é `
` solto | +| 5 | Error Prevention | 3 | Dashboard read-only; sem riscos destrutivos nesta tela | +| 6 | Recognition Rather Than Recall | 4 | `ChoroplethLegend` + visitados recentes; glossário ainda só em `title` | +| 7 | Flexibility and Efficiency | 2 | Fila prioritária ainda é um clique por núcleo; sem triagem em lote | +| 8 | Aesthetic and Minimalist Design | 3 | Top row 3:2:1 funciona; dois `CampaignMetricStrip` + mapa sem header | +| 9 | Error Recovery | 3 | Empty de liderança com CTA; coordenador sem próximo passo | +| 10 | Help and Documentation | 2 | Status de apoio e estimativa sem affordance touch (`?`/Popover) | +| **Total** | | **32/40** | **Good — fundação sólida; flexibilidade e ajuda ainda abaixo do ideal** | ## Anti-Patterns Verdict @@ -49,26 +50,31 @@ O dashboard `geral` saiu da pilha vertical ingênua para um desk operacional: fi ## Priority Issues ### [P2] Triagem em lote ainda ausente na fila prioritária + - **Why:** Cada item “Sem coordenador” é um link isolado; 15 núcleos = 15 idas e voltas. - **Fix:** Multi-select só em `withoutCoordinator` + barra “Atribuir coordenador (N)” reutilizando shell de designação existente. - **Suggested command:** `/impeccable layout` ### [P2] Jargão de domínio opaco no touch + - **Why:** `SupportStatusBadge`, estimativa confirmada vs proposta, métricas do mapa dependem de `title` (hover) — inútil no celular. - **Fix:** `CampaignGlossaryHint` com gatilho `?` (`min-h-11`) em badges e labels de KPI. - **Suggested command:** `/impeccable clarify` ### [P2] Outline de headings pula `h2` em Filas + - **Why:** `h1` → `CardTitle` Filas (não heading) → `h3` nas subfilas → depois `h2` Indicadores — ordem invertida para leitores de tela. - **Fix:** Promover “Filas de ação” a `h2` semântico (`id="action-queues"` já existe). - **Suggested command:** `/impeccable audit` ### [P3] Empty do coordenador sem CTA + - **Why:** Texto explica o bloqueio mas não oferece ação (liderança já tem “Ver meu perfil”). - **Fix:** Espelhar `LeadershipDashboard` empty com `EmptyContent` + CTA. - **Suggested command:** `/impeccable onboard` ### [P3] Recentes compactos escondem timestamp + - **Why:** Modo `compact` põe idade só em `sr-only`; Alex não distingue visita recente de antiga. - **Fix:** Mostrar `text-xs text-muted-foreground` truncado no modo compacto. - **Suggested command:** `/impeccable polish` diff --git a/.impeccable/critique/2026-07-23T21-29-20Z__src-components-campaign-plazalistoverview-tsx.md b/.impeccable/critique/2026-07-23T21-29-20Z__src-components-campaign-plazalistoverview-tsx.md index bc3f78d1..5811cd59 100644 --- a/.impeccable/critique/2026-07-23T21-29-20Z__src-components-campaign-plazalistoverview-tsx.md +++ b/.impeccable/critique/2026-07-23T21-29-20Z__src-components-campaign-plazalistoverview-tsx.md @@ -8,23 +8,24 @@ p3_count: 1 timestamp: 2026-07-23T21-29-20Z slug: src-components-campaign-plazalistoverview-tsx --- + Method: dual-agent (A: c0c0346d-83f2-4aa7-b728-c883635b063e · B: 104c4dcf-5d13-4351-b6fe-db8d2d632179) ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 2 | Número muda com filtros, mas nunca diz que é o cenário Média; mapa pode divergir | -| 2 | Match System / Real World | 2 | “Faixa” e “no conjunto” não nomeiam pessimista–otimista nem o recorte filtrado | -| 3 | User Control and Freedom | 3 | Agregado read-only correto; filtros controlam o conjunto; sem seletor de cenário no strip | -| 4 | Consistency and Standards | 2 | Dashboard: “Votos estimados” + célula própria p/ sem estimativa; lista empacota no meio | -| 5 | Error Prevention | 2 | `—` quando total=0; faixa some se falta um extremo (pós-backfill só central) | -| 6 | Recognition Rather Than Recall | 1 | Exige lembrar A10: default=média; Faixa=P–O; conjunto=filtrado | -| 7 | Flexibility and Efficiency | 2 | Denso p/ Alex; cenário só no mapa / Popover da linha | -| 8 | Aesthetic and Minimalist Design | 3 | Field Desk limpo; ênfase justificada; leve hero-KPI | -| 9 | Error Recovery | 2 | Qualidade do total (`sem estimativa`) enterrada em Declarações | -| 10 | Help and Documentation | 1 | Sem microcopy “Média” / “Pessimista–Otimista” | -| **Total** | | **20/40** | **Acceptable — craft visual ok; informação do cenário fraca** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ----------------------------------------------------------------------------------------- | +| 1 | Visibility of System Status | 2 | Número muda com filtros, mas nunca diz que é o cenário Média; mapa pode divergir | +| 2 | Match System / Real World | 2 | “Faixa” e “no conjunto” não nomeiam pessimista–otimista nem o recorte filtrado | +| 3 | User Control and Freedom | 3 | Agregado read-only correto; filtros controlam o conjunto; sem seletor de cenário no strip | +| 4 | Consistency and Standards | 2 | Dashboard: “Votos estimados” + célula própria p/ sem estimativa; lista empacota no meio | +| 5 | Error Prevention | 2 | `—` quando total=0; faixa some se falta um extremo (pós-backfill só central) | +| 6 | Recognition Rather Than Recall | 1 | Exige lembrar A10: default=média; Faixa=P–O; conjunto=filtrado | +| 7 | Flexibility and Efficiency | 2 | Denso p/ Alex; cenário só no mapa / Popover da linha | +| 8 | Aesthetic and Minimalist Design | 3 | Field Desk limpo; ênfase justificada; leve hero-KPI | +| 9 | Error Recovery | 2 | Qualidade do total (`sem estimativa`) enterrada em Declarações | +| 10 | Help and Documentation | 1 | Sem microcopy “Média” / “Pessimista–Otimista” | +| **Total** | | **20/40** | **Acceptable — craft visual ok; informação do cenário fraca** | ## Anti-Patterns Verdict @@ -36,7 +37,7 @@ Method: dual-agent (A: c0c0346d-83f2-4aa7-b728-c883635b063e · B: 104c4dcf-5d13- ## Overall Impression -O strip está certo em *estrutura* A10 (média grande + faixa secundária, não três KPIs) e no lugar certo (acima da tabela, no recorte filtrado). Falha em *rotular a semântica*: o número hero não diz “Média”, “Faixa” não diz pessimista–otimista, e o mapa acima pode mostrar outro cenário sem o strip confessar o lock em `central`. Em reunião, Marcos não sabe se está olhando chão, caso-base ou teto. +O strip está certo em _estrutura_ A10 (média grande + faixa secundária, não três KPIs) e no lugar certo (acima da tabela, no recorte filtrado). Falha em _rotular a semântica_: o número hero não diz “Média”, “Faixa” não diz pessimista–otimista, e o mapa acima pode mostrar outro cenário sem o strip confessar o lock em `central`. Em reunião, Marcos não sabe se está olhando chão, caso-base ou teto. ## What's Working @@ -47,31 +48,37 @@ O strip está certo em *estrutura* A10 (média grande + faixa secundária, não ## Priority Issues ### [P1] Número grande sem rótulo “Média” + - **Why:** Default A10 é `central`; a UI só diz “Votos estimados no conjunto”. Coordenação pergunta “isso é o otimista?”. - **Fix:** Label ou detail explícito: “Média” / “Cenário média (padrão)”. - **Suggested command:** `/impeccable clarify` ### [P1] “Faixa X–Y” sem pessimista–otimista + - **Why:** Pode ser CI, meta ou goals; conflita com vocabulário A10 já nos forms/mapa. - **Fix:** “Pessimista X · Otimista Y” ou mini `VoteEstimateScenarioStrip` endpoints. - **Suggested command:** `/impeccable clarify` ### [P1] Mapa Cenário vs strip dessincronizado + - **Why:** Mapa (acima) troca P/M/O; strip fica em central sem cue — duas verdades na mesma scroll. - **Fix:** Âncora explícita (“sempre média”) **ou** strip segue o cenário do mapa (estado local compartilhado). - **Suggested command:** `/impeccable layout` ### [P2] `sem estimativa` enterrado em Declarações + - **Why:** Qualidade do hero number some no meio da célula; dashboard já tem célula própria. - **Fix:** Footnote sob o total ou alinhar layout ao dashboard. - **Suggested command:** `/impeccable layout` ### [P2] “No conjunto” subespecificado + - **Why:** Não diz “Praças filtradas”; fácil ler como estadual/escopo total. - **Fix:** “Média nas Praças filtradas” (resolve P1+P2 de naming). - **Suggested command:** `/impeccable clarify` ### [P3] Linguagem visual ≠ linhas da tabela + - **Why:** Linhas usam ScenarioStrip; overview só tipografia. - **Fix:** Strip compacto endpoints no detail. - **Suggested command:** `/impeccable polish` diff --git a/.impeccable/critique/2026-07-23T21-52-39Z__src-components-campaign-plazamappanel-tsx-cenario.md b/.impeccable/critique/2026-07-23T21-52-39Z__src-components-campaign-plazamappanel-tsx-cenario.md index c7d766e0..922decde 100644 --- a/.impeccable/critique/2026-07-23T21-52-39Z__src-components-campaign-plazamappanel-tsx-cenario.md +++ b/.impeccable/critique/2026-07-23T21-52-39Z__src-components-campaign-plazamappanel-tsx-cenario.md @@ -8,23 +8,24 @@ p3_count: 1 timestamp: 2026-07-23T21-52-39Z slug: src-components-campaign-plazamappanel-tsx-cenario --- + Method: dual-agent (A: c3613972-8d1f-41bb-b210-501b0ddc14c9 · B: 8ae72814-5de3-4010-9ebb-7c9d64d8ccec) ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 1 | Ano default 2022: mudar Cenário não pinta o mapa; efeito no overview abaixo do fold | -| 2 | Match System / Real World | 1 | “overview” / “preenchimento” ≠ linguagem de campo; toolbar diz “filtro do mapa” | -| 3 | User Control and Freedom | 3 | Três opções reversíveis; baixo risco | -| 4 | Consistency and Standards | 2 | Mesmo NativeSelect que Ano/Escala, mas escopo de página (não só mapa) | -| 5 | Error Prevention | 1 | Posição convida o modelo errado; disclaimer é pós-fato | -| 6 | Recognition Rather Than Recall | 2 | Labels P/M/O ok; regra “só 2026” exige ler o rodapé | -| 7 | Flexibility and Efficiency | 2 | Sync global é eficiente se entendido; sem atalho Ano→2026 | -| 8 | Aesthetic and Minimalist Design | 2 | Quarto controle + disclaimer xs no estado comum (Ano≠2026) | -| 9 | Error Recovery | 2 | Mapa “não fez nada” sem live region no overview | -| 10 | Help and Documentation | 2 | Hint existe; copy de engenheiro; sempre ligada no first paint | -| **Total** | | **18/40** | **Poor — labels A10 ok; assento + disclaimer quebram o controle** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ----------------------------------------------------------------------------------- | +| 1 | Visibility of System Status | 1 | Ano default 2022: mudar Cenário não pinta o mapa; efeito no overview abaixo do fold | +| 2 | Match System / Real World | 1 | “overview” / “preenchimento” ≠ linguagem de campo; toolbar diz “filtro do mapa” | +| 3 | User Control and Freedom | 3 | Três opções reversíveis; baixo risco | +| 4 | Consistency and Standards | 2 | Mesmo NativeSelect que Ano/Escala, mas escopo de página (não só mapa) | +| 5 | Error Prevention | 1 | Posição convida o modelo errado; disclaimer é pós-fato | +| 6 | Recognition Rather Than Recall | 2 | Labels P/M/O ok; regra “só 2026” exige ler o rodapé | +| 7 | Flexibility and Efficiency | 2 | Sync global é eficiente se entendido; sem atalho Ano→2026 | +| 8 | Aesthetic and Minimalist Design | 2 | Quarto controle + disclaimer xs no estado comum (Ano≠2026) | +| 9 | Error Recovery | 2 | Mapa “não fez nada” sem live region no overview | +| 10 | Help and Documentation | 2 | Hint existe; copy de engenheiro; sempre ligada no first paint | +| **Total** | | **18/40** | **Poor — labels A10 ok; assento + disclaimer quebram o controle** | ## Anti-Patterns Verdict @@ -47,26 +48,31 @@ A10 labels e sync via context estão certos. O bug de UX é estrutural: **Cenár ## Priority Issues ### [P1] Assento na toolbar do mapa implica choropleth quando Ano≠2026 + - **Why:** First paint comum: muda Cenário → mapa igual → sensação de broken. -- **Fix:** Relocar ao overview; **ou** desabilitar/ghost + explicar; **ou** Cenário força Ano→2026; **ou** esconder no mapa quando ≠2026 *e* hospedar o controle onde o efeito é visível. +- **Fix:** Relocar ao overview; **ou** desabilitar/ghost + explicar; **ou** Cenário força Ano→2026; **ou** esconder no mapa quando ≠2026 _e_ hospedar o controle onde o efeito é visível. - **Suggested command:** `/impeccable layout` (ou `/impeccable shape`) ### [P1] Disclaimer em português de engenheiro + - **Why:** “overview” não está na UI; “preenchimento” é jargão de mapa. - **Fix:** Uma linha de resultado (“Muda os totais acima da lista. No mapa, só com Ano 2026.”) — ou matar a linha relocando o controle. - **Suggested command:** `/impeccable clarify` / `/impeccable distill` ### [P2] Feel the action: efeito fora do viewport + - **Why:** Mapa acima; overview/lista abaixo. Em mobile parece no-op. - **Fix:** Highlight/pending no overview; ou co-localizar o controle. - **Suggested command:** `/impeccable animate` + layout ### [P2] Always-show na fila do mapa vs hide -- **Why:** Sync global é racional; *nesta* fila treina o affordance errado. + +- **Why:** Sync global é racional; _nesta_ fila treina o affordance errado. - **Fix:** Não esconder sem relocação; se global, não vestir como filtro do mapa. - **Suggested command:** `/impeccable shape` ### [P3] Densidade Ano / Escala / Cenário / Comparar + - **Why:** Quarto peer + disclaimer wrap em narrow (Casey). - **Suggested command:** `/impeccable quieter` diff --git a/.impeccable/critique/2026-07-24T20-30-52Z__a11-ranking-votos.md b/.impeccable/critique/2026-07-24T20-30-52Z__a11-ranking-votos.md index fc6c1a12..84d89e25 100644 --- a/.impeccable/critique/2026-07-24T20-30-52Z__a11-ranking-votos.md +++ b/.impeccable/critique/2026-07-24T20-30-52Z__a11-ranking-votos.md @@ -6,6 +6,7 @@ p1_count: 2 timestamp: 2026-07-24T20-30-52Z slug: a11-ranking-votos --- + # Critique — A11 posição em votos **Alvos:** `MunicipalityBaselineCard`, `MunicipalityList`, `MunicipalitySortableHead`, `MunicipalityFilters` @@ -13,19 +14,19 @@ slug: a11-ranking-votos ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 3 | Pending/dim ok; sort active mostly chevron — no “ordenado por…” summary | -| 2 | Match System / Real World | 2 | “% da votação” unexplained on list; “Praça” leftovers; seed empty-state | -| 3 | User Control and Freedom | 3 | Limpar is all-or-nothing (sort resets only with full clear) | -| 4 | Consistency and Standards | 2 | Mobile “% da votação” vs desktop “Votos 2022”; card vs table readout order | -| 5 | Error Prevention | 3 | Detail separates dual-% well; list has no equivalent guardrail | -| 6 | Recognition Rather Than Recall | 2 | List % without denominator; definition lives on detail | -| 7 | Flexibility and Efficiency | 3 | Default votos desc is right mesa lens; inactive columns under-afforded | -| 8 | Aesthetic and Minimalist Design | 3 | Restrained desk; quiet secondary lines also hide meaning | -| 9 | Error Recovery | 2 | “—” for missing rank; engineer empty baseline copy | -| 10 | Help and Documentation | 2 | Baseline intro good; list column gives zero definition | -| **Total** | | **25/40** | **Acceptable — vocabulary/consistency is the drag** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | -------------------------------------------------------------------------- | +| 1 | Visibility of System Status | 3 | Pending/dim ok; sort active mostly chevron — no “ordenado por…” summary | +| 2 | Match System / Real World | 2 | “% da votação” unexplained on list; “Praça” leftovers; seed empty-state | +| 3 | User Control and Freedom | 3 | Limpar is all-or-nothing (sort resets only with full clear) | +| 4 | Consistency and Standards | 2 | Mobile “% da votação” vs desktop “Votos 2022”; card vs table readout order | +| 5 | Error Prevention | 3 | Detail separates dual-% well; list has no equivalent guardrail | +| 6 | Recognition Rather Than Recall | 2 | List % without denominator; definition lives on detail | +| 7 | Flexibility and Efficiency | 3 | Default votos desc is right mesa lens; inactive columns under-afforded | +| 8 | Aesthetic and Minimalist Design | 3 | Restrained desk; quiet secondary lines also hide meaning | +| 9 | Error Recovery | 2 | “—” for missing rank; engineer empty baseline copy | +| 10 | Help and Documentation | 2 | Baseline intro good; list column gives zero definition | +| **Total** | | **25/40** | **Acceptable — vocabulary/consistency is the drag** | ## Anti-Patterns Verdict @@ -48,26 +49,31 @@ Default sort by concentration is the right product move. The biggest opportunity ## Priority Issues ### [P1] Label / metric / sort vocabulary collision + - **Why:** Under pressure, header “Votos 2022” vs cell “% da votação” vs mobile Ordenar invites wrong comparisons. - **Fix:** One shared term (e.g. Concentração 2022) across column, Ordenar, and primary readout; secondary = votos · Nº de 435. - **Suggested command:** `/impeccable clarify` ### [P1] Dual-% trap still live on list → detail path + - **Why:** List shows unexplained %; detail introduces local % of válidos — disclaimer one click too late. - **Fix:** Column hint/caption: “% da votação estadual do candidato”; keep local dominance secondary. - **Suggested command:** `/impeccable clarify` ### [P2] Card vs table VotePositionReadout hierarchy diverge + - **Why:** Same data, different story (table prioritizes share; card is middot soup). - **Fix:** Same stack both layouts: concentration → votos · rank. - **Suggested command:** `/impeccable distill` ### [P2] “Praça” + engineer empty state + - **Why:** Remodel is Município; “Rode o seed…” fails closed for staff. - **Fix:** Município language; staff-safe empty (“Sem baseline TSE neste ambiente”). - **Suggested command:** `/impeccable harden` ### [P3] Active sort under-announced for sighted scan + - **Why:** Chevron alone is easy to miss in dense headers. - **Fix:** Active weight + optional “Ordenado por concentração 2022…”. - **Suggested command:** `/impeccable polish` diff --git a/.impeccable/critique/2026-07-24T20-48-41Z__a11-ranking-votos.md b/.impeccable/critique/2026-07-24T20-48-41Z__a11-ranking-votos.md index a5a2b01a..436108e7 100644 --- a/.impeccable/critique/2026-07-24T20-48-41Z__a11-ranking-votos.md +++ b/.impeccable/critique/2026-07-24T20-48-41Z__a11-ranking-votos.md @@ -6,6 +6,7 @@ p1_count: 2 timestamp: 2026-07-24T20-48-41Z slug: a11-ranking-votos --- + # Critique — A11 posição em votos (pós-polish) **Alvos:** BaselineCard, List, SortableHead, Filters @@ -13,19 +14,19 @@ slug: a11-ranking-votos ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 3 | Sort summary ok; dormant chevrons faint | -| 2 | Match System / Real World | 3 | Concentração unified; Praças leftovers in visit/scope | -| 3 | User Control and Freedom | 3 | Limpar nuclear | -| 4 | Consistency and Standards | 3 | Mobile/desktop labels aligned | -| 5 | Error Prevention | 3 | Dual-% taught; cells still noisy | -| 6 | Recognition Rather Than Recall | 3 | Definition in body/cells, not on header | -| 7 | Flexibility and Efficiency | 3 | Default votos desc right | -| 8 | Aesthetic and Minimalist Design | 2 | Per-cell “da votação estadual” + “de 435” | -| 9 | Error Recovery | 3 | Staff-safe empty baseline | -| 10 | Help and Documentation | 3 | Help misplaced (cells vs header) | -| **Total** | | **29/40** | **Good** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ----------------------------------------------------- | +| 1 | Visibility of System Status | 3 | Sort summary ok; dormant chevrons faint | +| 2 | Match System / Real World | 3 | Concentração unified; Praças leftovers in visit/scope | +| 3 | User Control and Freedom | 3 | Limpar nuclear | +| 4 | Consistency and Standards | 3 | Mobile/desktop labels aligned | +| 5 | Error Prevention | 3 | Dual-% taught; cells still noisy | +| 6 | Recognition Rather Than Recall | 3 | Definition in body/cells, not on header | +| 7 | Flexibility and Efficiency | 3 | Default votos desc right | +| 8 | Aesthetic and Minimalist Design | 2 | Per-cell “da votação estadual” + “de 435” | +| 9 | Error Recovery | 3 | Staff-safe empty baseline | +| 10 | Help and Documentation | 3 | Help misplaced (cells vs header) | +| **Total** | | **29/40** | **Good** | ## Anti-Patterns Verdict @@ -46,18 +47,23 @@ Vocabulary polish worked (+4 vs 25). Next jump is density: definitions once on t ## Priority Issues ### [P1] Per-cell “da votação estadual” (owner) + Cell = bare %. Explanation on Concentração header tooltip. → `/impeccable distill` ### [P1] “de 435” per row (owner) + Rank = `12º` only; catalog size once in header tooltip. → `/impeccable distill` ### [P2] Sort summary copy-heavy + Short status only; definition → header. → `/impeccable quieter` / polish ### [P2] Baseline dual-% fork + Demote local dominance. → `/impeccable layout` ### [P3] Dormant chevrons + Praças leftovers + → `/impeccable polish` / clarify ## Persona Red Flags diff --git a/.impeccable/critique/2026-07-24T21-01-02Z__a11-ranking-votos.md b/.impeccable/critique/2026-07-24T21-01-02Z__a11-ranking-votos.md index 823368af..9e719eff 100644 --- a/.impeccable/critique/2026-07-24T21-01-02Z__a11-ranking-votos.md +++ b/.impeccable/critique/2026-07-24T21-01-02Z__a11-ranking-votos.md @@ -6,6 +6,7 @@ p1_count: 1 timestamp: 2026-07-24T21-01-02Z slug: a11-ranking-votos --- + # Critique — A11 (pós density distill) **Data:** 2026-07-24 @@ -13,19 +14,19 @@ slug: a11-ranking-votos ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 3 | Sort status solid | -| 2 | Match System / Real World | 3 | Concentração vocabulary ok | -| 3 | User Control and Freedom | 3 | Limpar nuclear | -| 4 | Consistency and Standards | 3 | Help chrome fights distill | -| 5 | Error Prevention | 3 | Bare cells help | -| 6 | Recognition Rather Than Recall | 3 | Definition on ? not header | -| 7 | Flexibility and Efficiency | 3 | Default votos desc | -| 8 | Aesthetic and Minimalist Design | 3 | Cells good; ? residual | -| 9 | Error Recovery | 3 | Empty baseline ok | -| 10 | Help and Documentation | 2 | Wrong chrome: ? vs hover header | -| **Total** | | **30/40** | **Good** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ------------------------------- | +| 1 | Visibility of System Status | 3 | Sort status solid | +| 2 | Match System / Real World | 3 | Concentração vocabulary ok | +| 3 | User Control and Freedom | 3 | Limpar nuclear | +| 4 | Consistency and Standards | 3 | Help chrome fights distill | +| 5 | Error Prevention | 3 | Bare cells help | +| 6 | Recognition Rather Than Recall | 3 | Definition on ? not header | +| 7 | Flexibility and Efficiency | 3 | Default votos desc | +| 8 | Aesthetic and Minimalist Design | 3 | Cells good; ? residual | +| 9 | Error Recovery | 3 | Empty baseline ok | +| 10 | Help and Documentation | 2 | Wrong chrome: ? vs hover header | +| **Total** | | **30/40** | **Good** | ## Anti-Patterns @@ -44,13 +45,16 @@ Cells landed. Open P1: remove CampaignInfoHint; explanation on header hover/focu ## Priority Issues ### [P1] Owner — no ? button; hover header (validated) + Remove hint chrome; Tooltip on sortable Concentração head. Mobile: no orphan ?. Baseline: same rule. → `/impeccable distill` ### [P2] Limpar nukes sort + → `/impeccable harden` ### [P3] Dormant chevrons after ? dies + → `/impeccable polish` ## Personas diff --git a/.impeccable/critique/2026-07-25T01-04-34Z__omponents-campaign-municipalitygoalaccountcard-tsx.md b/.impeccable/critique/2026-07-25T01-04-34Z__omponents-campaign-municipalitygoalaccountcard-tsx.md index dcc665bf..f59e9b60 100644 --- a/.impeccable/critique/2026-07-25T01-04-34Z__omponents-campaign-municipalitygoalaccountcard-tsx.md +++ b/.impeccable/critique/2026-07-25T01-04-34Z__omponents-campaign-municipalitygoalaccountcard-tsx.md @@ -6,23 +6,24 @@ p1_count: 3 timestamp: 2026-07-25T01-04-34Z slug: omponents-campaign-municipalitygoalaccountcard-tsx --- + Method: dual-agent (A: 92b63fbf-f200-4a00-9cc5-81db3f317b57 · B: 35312920-2be2-4bac-92aa-0fbb62c2a571) ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 3 | Coverage %, deficit text, and provenance ("estimativa da mesa") are all stated plainly; the 0%-coverage `Progress` bar is a near-invisible 4px hairline, understating urgency at the most common early-campaign state. | -| 2 | Match Between System and Real World | 2 | "Teto do campo," "share intracampo," "roll-off," "campo" are coined composites — confirmed by the product's own coordinator calling these "conceitos complicados" *after* this exact tooltip fix shipped (`docs/plans/documentacao-conceitos-campanha.md`). | -| 3 | User Control and Freedom | 3 | Popover/tooltip dismiss cleanly (Escape, click-outside, blur); no traps. | -| 4 | Consistency and Standards | 2 | Two disclosure idioms collide in one card: `CampaignInfoHint` opens-on-click-and-stays-open; the metric `Tooltip` closes-on-click and never opens on click. A user primed by the "?" icon one line above will click a metric next and get nothing, or dismiss an open tooltip. | -| 5 | Error Prevention | 3 | n/a mostly (read-only diagnostics); sane zero/negative fallbacks ("Sem meta definida," "Sem teto do campo projetado..."). | -| 6 | Recognition Rather Than Recall | 2 | Dotted-underline is a fair desktop cue, but on touch there is **no cue at all** — confirmed by both assessments (Radix's own touch-suppression logic, and no tap affordance reachable at 390×844). | -| 7 | Flexibility and Efficiency of Use | 3 | `Tab` reaches every metric and opens its tooltip on focus with a visible ring — solid keyboard path, measured live. | -| 8 | Aesthetic and Minimalist Design | 3 | Restrained, on-brand, correctly dense for a staff surface; undermined live by the tooltip/popover collision covering sibling content (screenshotted at both desktop and 390px). | -| 9 | Error Recovery | 3 | n/a — no error states exercised; fallback copy is clear and non-technical. | -| 10 | Help and Documentation | 2 | Good *density* of contextual help (card popover + 4 inline tooltips), not yet *effective* — field evidence says the explanations didn't resolve confusion, and there's no link to deeper docs yet (that's roadmap E18). | -| **Total** | | **26/40** | **Acceptable — significant improvements needed before users are happy** | +| # | Heuristic | Score | Key Issue | +| --------- | ----------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| 1 | Visibility of System Status | 3 | Coverage %, deficit text, and provenance ("estimativa da mesa") are all stated plainly; the 0%-coverage `Progress` bar is a near-invisible 4px hairline, understating urgency at the most common early-campaign state. | +| 2 | Match Between System and Real World | 2 | "Teto do campo," "share intracampo," "roll-off," "campo" are coined composites — confirmed by the product's own coordinator calling these "conceitos complicados" _after_ this exact tooltip fix shipped (`docs/plans/documentacao-conceitos-campanha.md`). | +| 3 | User Control and Freedom | 3 | Popover/tooltip dismiss cleanly (Escape, click-outside, blur); no traps. | +| 4 | Consistency and Standards | 2 | Two disclosure idioms collide in one card: `CampaignInfoHint` opens-on-click-and-stays-open; the metric `Tooltip` closes-on-click and never opens on click. A user primed by the "?" icon one line above will click a metric next and get nothing, or dismiss an open tooltip. | +| 5 | Error Prevention | 3 | n/a mostly (read-only diagnostics); sane zero/negative fallbacks ("Sem meta definida," "Sem teto do campo projetado..."). | +| 6 | Recognition Rather Than Recall | 2 | Dotted-underline is a fair desktop cue, but on touch there is **no cue at all** — confirmed by both assessments (Radix's own touch-suppression logic, and no tap affordance reachable at 390×844). | +| 7 | Flexibility and Efficiency of Use | 3 | `Tab` reaches every metric and opens its tooltip on focus with a visible ring — solid keyboard path, measured live. | +| 8 | Aesthetic and Minimalist Design | 3 | Restrained, on-brand, correctly dense for a staff surface; undermined live by the tooltip/popover collision covering sibling content (screenshotted at both desktop and 390px). | +| 9 | Error Recovery | 3 | n/a — no error states exercised; fallback copy is clear and non-technical. | +| 10 | Help and Documentation | 2 | Good _density_ of contextual help (card popover + 4 inline tooltips), not yet _effective_ — field evidence says the explanations didn't resolve confusion, and there's no link to deeper docs yet (that's roadmap E18). | +| **Total** | | **26/40** | **Acceptable — significant improvements needed before users are happy** | ## Anti-Patterns Verdict @@ -45,30 +46,35 @@ The card itself is well-crafted and on-brand — restrained, honest about data p ## Priority Issues **[P1] Touch users cannot open the metric tooltips at all.** + - **Why it matters**: PRODUCT.md names "used in the field and on the go" as this surface's defining context, and this exact follow-up exists for comprehension. It's unreachable on the device class that context implies. - **What/evidence**: `@radix-ui/react-tooltip@1.2.8`'s `TooltipTrigger` explicitly ignores touch pointer events and gates focus-open on a pointer-down ref that a tap sets first — confirmed against the installed source, not inference. At 390×844, no tap affordance exists for any of the 4 metrics; the adjacent "Editar votos estimados" control works fine at the same width, so this reads as an oversight, not a deliberate mobile choice. - **Fix**: Add an explicit tap trigger — drop `asChild` for a focusable/clickable element with its own `onClick` toggling open, or give each metric a small click-openable affordance like `CampaignInfoHint`'s. - **Suggested command**: `/impeccable harden` **[P1] Tooltips render on top of the number/coverage block they explain.** + - **Why it matters**: The moment someone seeks clarification is the moment the clarified figure disappears — a direct "one thing at a time" violation at the card's highest-stakes row. - **What/evidence**: Reproduced independently by both assessments via hover, real keyboard focus, and screenshots at 1280×720 and 390×844 — the bubble (Radix collision-flips to `data-side="top"` since the trigger sits near the viewport bottom) fully covers "Cobertura da meta" / the progress bar / "Faltam X votos para a meta" at both widths. - **Fix**: Force collision-safe placement for this usage (`side="top"` with generous `sideOffset` plus bottom padding, or reorder the diagnostic row above the coverage block so there's room for the tooltip to open without overlap). - **Suggested command**: `/impeccable layout` **[P1] Tooltip/popover copy is dense, cross-referential jargon — and the real user already said it didn't help.** -- **Why it matters**: `docs/plans/documentacao-conceitos-campanha.md` quotes the actual coordinator calling these "conceitos complicados" *after* these exact tooltips shipped — the fix under critique didn't fix the problem it was built to fix. + +- **Why it matters**: `docs/plans/documentacao-conceitos-campanha.md` quotes the actual coordinator calling these "conceitos complicados" _after_ these exact tooltips shipped — the fix under critique didn't fix the problem it was built to fix. - **What/evidence**: e.g. the "Teto do campo" explanation is one ~40-word sentence with three technical terms and no break; "Share intracampo"'s explanation requires recalling "Captura"'s definition mid-read, but the two tooltips can never be open at the same time (opening one closes the other) — a genuine working-memory violation. - **Fix**: Split each explanation into a short lead sentence (what it measures) + a visually secondary formula line; bold only the one term each tooltip defines; stop cross-referencing metrics that can't be open simultaneously — state the difference inline instead of by reference. - **Suggested command**: `/impeccable clarify` **[P2] Two incompatible disclosure idioms coexist in one card.** -- **Why it matters**: Breaking Consistency *within* a single component teaches the wrong mental model in real time — a user who just learned "click the small icon" naturally tries clicking a metric next and gets nothing or an unwanted dismissal. + +- **Why it matters**: Breaking Consistency _within_ a single component teaches the wrong mental model in real time — a user who just learned "click the small icon" naturally tries clicking a metric next and gets nothing or an unwanted dismissal. - **What/evidence**: `CampaignInfoHint` = click-to-open-and-stay-open Popover; `GoalAccountMetric` = hover/focus Tooltip that closes on click (Radix default), never opens on click. - **Fix**: Pick one idiom for this card, or make the "click for detail" vs. "hover/focus for definition" visual distinction stronger than dotted-underline vs. circle-icon alone. - **Suggested command**: `/impeccable clarify` **[P3] The 0%-coverage progress bar is nearly invisible.** + - **Why it matters**: Understates urgency exactly when it should read loudest (0% coverage is the most common early-campaign state). - **Fix**: Give the near-zero state deliberate visual weight instead of relying solely on the adjacent "0%" text. - **Suggested command**: `/impeccable polish` @@ -91,6 +97,6 @@ The card itself is well-crafted and on-brand — restrained, honest about data p ## Questions to Consider -- If the coordinator needed a *separate* documentation surface (E18) days after these exact tooltips shipped specifically because they didn't resolve the confusion, is hover/focus disclosure the right mechanism for this density of explanation at all — or does the card need one worked example inline before a glossary page ever ships? +- If the coordinator needed a _separate_ documentation surface (E18) days after these exact tooltips shipped specifically because they didn't resolve the confusion, is hover/focus disclosure the right mechanism for this density of explanation at all — or does the card need one worked example inline before a glossary page ever ships? - "Captura" and "Share intracampo" exist as two numbers whose entire tooltip copy is dedicated to explaining how they differ from each other — should this be one metric with a denominator toggle instead of two numbers that each require reading the other's footnote? -- As E9–E17 add more diagnostic metrics to this row, does the card need a settled disclosure model *now* — before there are 8 metrics fighting over two incompatible idioms instead of 4? +- As E9–E17 add more diagnostic metrics to this row, does the card need a settled disclosure model _now_ — before there are 8 metrics fighting over two incompatible idioms instead of 4? diff --git a/.impeccable/critique/2026-07-25T02-37-03Z__src-components-campaign-municipalitylist-tsx.md b/.impeccable/critique/2026-07-25T02-37-03Z__src-components-campaign-municipalitylist-tsx.md index 6b81b4a9..7a1c4c22 100644 --- a/.impeccable/critique/2026-07-25T02-37-03Z__src-components-campaign-municipalitylist-tsx.md +++ b/.impeccable/critique/2026-07-25T02-37-03Z__src-components-campaign-municipalitylist-tsx.md @@ -6,25 +6,26 @@ p1_count: 3 timestamp: 2026-07-25T02-37-03Z slug: src-components-campaign-municipalitylist-tsx --- + # Critique — B16 Municipality Header Filters Method: dual-agent (A: 8cdcb249-95fe-4f3d-8937-081b10b442bc · B: c641769d-fc5c-4a83-9442-4329cff5cf96) ## Design Health Score -| # | Heuristic | Score | Key Issue | -|---|-----------|-------|-----------| -| 1 | Visibility of System Status | 2 | Control lag until RSC (fixed post-critique: optimistic) | -| 2 | Match System / Real World | 3 | Priority on Município column | -| 3 | User Control and Freedom | 3 | Limpar + Todos clear | -| 4 | Consistency and Standards | 2 | Header vs mobile select duality | -| 5 | Error Prevention | 3 | Constrained options | -| 6 | Recognition Rather Than Recall | 2 | Icon-only funnels (Priority now labeled) | -| 7 | Flexibility and Efficiency | 3 | Column-local filters | -| 8 | Aesthetic and Minimalist Design | 3 | Slim bar succeeds | -| 9 | Error Recovery | 2 | Limpar primary recovery | -| 10 | Help and Documentation | 2 | Filter meanings sparse | -| **Total** | | **25/40** | **Acceptable** | +| # | Heuristic | Score | Key Issue | +| --------- | ------------------------------- | --------- | ------------------------------------------------------- | +| 1 | Visibility of System Status | 2 | Control lag until RSC (fixed post-critique: optimistic) | +| 2 | Match System / Real World | 3 | Priority on Município column | +| 3 | User Control and Freedom | 3 | Limpar + Todos clear | +| 4 | Consistency and Standards | 2 | Header vs mobile select duality | +| 5 | Error Prevention | 3 | Constrained options | +| 6 | Recognition Rather Than Recall | 2 | Icon-only funnels (Priority now labeled) | +| 7 | Flexibility and Efficiency | 3 | Column-local filters | +| 8 | Aesthetic and Minimalist Design | 3 | Slim bar succeeds | +| 9 | Error Recovery | 2 | Limpar primary recovery | +| 10 | Help and Documentation | 2 | Filter meanings sparse | +| **Total** | | **25/40** | **Acceptable** | ## Anti-Patterns Verdict diff --git a/.impeccable/live/config.json b/.impeccable/live/config.json index a5453592..bbe52400 100644 --- a/.impeccable/live/config.json +++ b/.impeccable/live/config.json @@ -1,8 +1,5 @@ { - "files": [ - "src/app/(frontend)/layout.tsx", - "src/app/(campaign)/layout.tsx" - ], + "files": ["src/app/(frontend)/layout.tsx", "src/app/(campaign)/layout.tsx"], "insertBefore": "