diff --git a/.cursor/rules/projects/nucleos-eleitorais.mdc b/.cursor/rules/projects/nucleos-eleitorais.mdc index e2ba6694..fff2f038 100644 --- a/.cursor/rules/projects/nucleos-eleitorais.mdc +++ b/.cursor/rules/projects/nucleos-eleitorais.mdc @@ -7,7 +7,7 @@ alwaysApply: false ## Status -- **Sync roadmap × sessão de campo (2026-07-24):** os achados da sessão real do CG (2026-07-23, `docs/CUSTOMER.md`) foram incorporados ao roadmap e aos planos de inteligência — âncora da mesa = **% da própria votação** (A11 entrega a lente; E9/E10/B13 expõem ao lado de LQ/captura); piso 150 mil resolve a meta inicial de E8; O6 vira **E16 dossiê do município** + gap **G11 emendas por município**; O7 confirma C12 não cortável; E13 rebaixado na fila de corte ("perna" é a restrição dominante); gatilho de D3 reformulado (deltas do ZAP não absorvidos pelo fluxo sede-digita/C12); FD2 absorvido por R6; O8 "ilhas isoladas" em A validar. **Decisão de produto: E4 reaberto como E4R** — seed único via script das planilhas de `docs/sheets/` (arquivo com espaços = canônico de estratégia; underscore = referência Salvador; v1 só `voteGoals`/`priority`, sem PII; Salvador pulado com relatório). Novos itens: **E4R** (janela 1, não cortável), **A11**, **E17 tabela TI no Início** (pedido do candidato; primeira fatia de E12). Planos novos: `import-planilha-projecao.md`, `ranking-votos-municipio.md`, `tabela-ti-inicio.md`, `dossie-municipio.md`. +- **Sync roadmap × sessão de campo (2026-07-24):** os achados da sessão real do CG (2026-07-23, `docs/CUSTOMER.md`) foram incorporados ao roadmap e aos planos de inteligência — âncora da mesa = **% da própria votação** (A11 entrega a lente; E9/E10/B13 expõem ao lado de LQ/captura); piso 150 mil resolve a meta inicial de E8; O6 vira **E16 dossiê do município** + gap **G11 emendas por município**; O7 confirma C12 não cortável; E13 rebaixado na fila de corte ("perna" é a restrição dominante); gatilho de D3 reformulado (deltas do ZAP não absorvidos pelo fluxo sede-digita/C12); FD2 absorvido por R6; O8 "ilhas isoladas" em A validar. **Decisão de produto: E4 reaberto como E4R** — seed único via script das planilhas de `docs/sheets/` (arquivo com espaços = canônico de estratégia; underscore = referência Salvador; v1 só `voteGoals`/`priority`, sem PII; Salvador pulado com relatório). Novos itens: **E4R** (janela 1, não cortável), **A11**, **E17 tabela TI no Início** (pedido do candidato; primeira fatia de E12), **B14 município mais próximo** (geolocalização → atalho no Início staff; prompt 1×/sessão; client-only). Planos novos: `import-planilha-projecao.md`, `ranking-votos-municipio.md`, `tabela-ti-inicio.md`, `dossie-municipio.md`, `municipio-mais-proximo.md`. - **DEPLOY EM PRODUÇÃO REALIZADO (2026-07-23).** A cadeia destrutiva da remodelagem (`20260721_020109_remodel_municipalities` → `20260723_200000_remodel_municipalities` + `20260723_202000_reconcile_municipality_remodel`) foi aplicada em produção pelos builds Vercel de 2026-07-23 (deploys production READY dos commits `a7b8f1b`/`c7a1b74`/`59868a9`). **Este item supersede toda menção "deploy pendente" nas entradas abaixo.** Pendências operacionais: smoke pós-deploy + onboarding do time (Onda 0 §2/§4 em [`docs/roadmap.md`](../../../docs/roadmap.md)); hold de PII real segue no lote jurídico. - **Hardening de engenharia entregue e em produção (2026-07-23, Fases 0–6):** (0) access lockdown — `users`/`signature`/`subscription`/`consent` admin-only, escrita de CMS (`post`/`tag`/`media`/`petition`) admin-only, gates de rota do leader em `demandas*`/`planos*`, `createLeaderSupporter` com escopo correto, `candidate` tratado como staff irrestrito em todas as superfícies; (1) tooling gate — knip no CI (`.github/workflows/ci.yml`, mirror GitHub), `pnpm lint --max-warnings=0`, ban `as never` (helpers `hookFilledCreateData`/`stub`), tsconfig consolidado + `noUnusedLocals`, ~12 módulos mortos deletados; (2) caching — artefato TSE commitado (`pnpm build:election-aggregates` → `src/lib/electionAggregates/`, loader `bahiaElectionAggregates.ts`), `unstable_cache` com tag `election-tse` nos loaders de eleições, `loadMunicipalityScope` (React `cache()`) dedupe dashboard+mapa+lista; (3) pending honesto — bug de revalidação do toggle de tarefa, `CampaignListPendingBoundary` esmaecendo resultados, transição no compare do mapa, mapa do dashboard + abas do detalhe em Suspense; (4) state scoping — hover do mapa isolado em `MunicipalityMapSelection`, provider de cenário estreitado, `LeaderContactForm` extraído como ilha cliente; (5) estrutura — `campaignAccess` dividido em `src/utilities/access/*` (re-export preservado), `supporterImport.ts` separado, `runStaffEntityMutation` + `runCampaignRedirectFormAction` dedupando twins e 4 ladders de formActions, rename `PLAZA_*`→`MUNICIPALITY_*` concluído; (6) docs + regra `.cursor/rules/engineering-standards.mdc`. Tracker: [`docs/IMPROVE-CODE-QUALITY-PLAN.md`](../../../docs/IMPROVE-CODE-QUALITY-PLAN.md) · ledger: [`docs/TECH-DEBT.md`](../../../docs/TECH-DEBT.md) · mapa de testes: [`docs/TESTING.md`](../../../docs/TESTING.md). - **Remodelagem Municípios entregue em código (2026-07-23; deploy pendente — migrações `20260723_200000_remodel_municipalities` + `20260723_202000_reconcile_municipality_remodel` são destrutivas para a vertical campanha).** Decisões pós-reunião 2026-07-23: rename Praça→Município (`municipality`, `/campanha/municipios`); **435** entradas (Camaçari única; Salvador 19 zonas); role `candidate` (visão irrestrita); demandas staff-only; leader lockdown (ferramenta de contatos de apoiadores); dobradinhas (`stateDeputy`); mapa no Início (dashboard). Plano-mestre: [`remodelagem-municipios.md`](../../../docs/plans/remodelagem-municipios.md) (substitui `remodelagem-pracas.md`). diff --git a/docs/plans/municipio-mais-proximo.md b/docs/plans/municipio-mais-proximo.md new file mode 100644 index 00000000..3b51e05c --- /dev/null +++ b/docs/plans/municipio-mais-proximo.md @@ -0,0 +1,133 @@ +# B14 — Município mais próximo (acesso rápido por geolocalização) + +Status: rascunho +Atualizado em: 2026-07-24 +Item do roadmap: [docs/roadmap.md](../roadmap.md) (Demais itens abertos, B14; superfície de coordenação) +Impeccable: B — encaixe no dashboard staff (`/campanha`), sem rota nova +Appetite: ~1 dia eng; artefato estático de centroides + ilha cliente no Início; sem migration, sem collection, sem Consent +Responsável: — + +## Design (Impeccable) + +Âncoras: `PRODUCT.md` (princípios 2 — clareza sob pressão — e 8 — Feel the action) / `DESIGN.md` (register `product`; Field Desk) · tema `data-theme='campaign'` · precedente de ilha client-side [`RecentlyVisitedCard`](../plans/visitados-recentemente.md). + +Na implementação (`implement-roadmap-item`): craft compacto → critique → polish. + +Brief compacto: + +- **Persona / contexto:** assessor ou CG em campo (telefone, deslocamento entre municípios), abrindo o Início sob pressão de tempo — precisa chegar na ficha do município onde está sem digitar na lista. +- **Job principal:** com um toque, abrir o município operacional mais próximo da localização atual. +- **Estratégia de cor:** Restrained — card/atalho sóbrio ao lado de "Visitados recentemente", sem mapa embutido nem badge de GPS gamificado. +- **Edit where you see:** não — só leitura/navegação (atalho); sem mutação de dados. +- **Anti-goals:** segundo mapa; lista "próximos N" tipo Places; sync de localização no servidor; prompt de permissão em loop; superfície para `leader` (lockdown). + +## Dados → decisão → apresentação + +- **Vou apresentar dados?** Sim, superfície neste item — um resultado geo (município mais próximo ± distância opcional), não série/KPI eleitoral. +- **Decisões desbloqueadas:** + - Staff (assessor/CG/candidato): "abrir agora a ficha do município em que estou (ou o mais próximo no meu escopo)?" +- **Forma escolhida:** **número + contexto mínimo** (nome do município + CTA "Abrir" + distância relativa opcional, ex. "~8 km") — **por quê:** uma decisão, um destino; degrau mais pobre que resolve. **Rejeitado:** mapa de proximidade (já há mapa no Início com outro job); ranking dos 5 mais próximos (ruído); chart/gauge. +- **Profile:** geo pontual → 1 entidade do catálogo (ou lista filtrada Salvador); tamanho típico = 1 sugestão; absoluto (km) só como contexto de confiança, não como KPI. +- **Anti-goals de dado:** sem telemetria de posição; sem choropleth de "densidade de visitas"; sem % estadual. + +Self-check dados: 5/5. + +## Contexto + +O Início staff já oferece mapa, KPIs, filas curtas e **Visitados recentemente** (histórico local). Em deslocamento, o atalho que falta é "onde estou → ficha do município". O catálogo tem 435 unidades (`municipalityCatalog.ts`); Salvador é 19 Municípios-zona com o mesmo IBGE — a proximidade por centroide de município IBGE não desambigua ZE. Geolocalização é API do browser (`navigator.geolocation`); a posição **não precisa** ir ao servidor se o matching for client-side sobre um artefato de centroides. + +Decisão de produto (2026-07-24, pedido explícito): sugerir acesso rápido ao município mais próximo e, **uma vez por sessão**, pedir automaticamente a permissão de localização se ainda não houver. + +## Objetivos + +- No dashboard staff (`/campanha`), card/atalho **"Município mais próximo"** (ou copy equivalente) com link para `/campanha/municipios/[slug]` (ou lista filtrada quando a cidade for multi-zona). +- **Uma vez por sessão de aba:** se a permissão de geolocalização ainda não estiver concedida/negada de forma estável, disparar automaticamente o pedido do browser; marcar em `sessionStorage` que o prompt automático já ocorreu (não repetir na mesma sessão). +- Se a permissão já estiver `granted`, resolver a posição sem prompt e mostrar a sugestão. +- Se `denied` / indisponível / fora da Bahia / sem match no escopo: card ausente ou estado curto com CTA manual "Usar minha localização" (sem loop de prompt). +- Matching **só no cliente**; coordenadas nunca enviadas a server actions/API Payload. +- Filtrar candidatos ao **escopo de acesso** do ator (advisor: só municípios administrados; coordinator/candidate: catálogo completo do que a UI já enxerga). +- Sem migration, sem collection, sem server action de escrita, sem nova chave `Consent`. +- Staff only; `leader` permanece no `LeaderContactsPanel` (sem mudança). + +## Decisões travadas + +- **Client-only + artefato de centroides (sem modelo no servidor).** Posição fica no browser; nearest = Haversine (ou equivalente) sobre centroides IBGE commitados. Análogo a visitados recentes. **Rejeitado:** POST de lat/lng ao servidor (PII de localização + Consent + superfície de abuso); reverse-geocode comercial (custo/vendor); PostGIS (fora de escopo do AGENTS.md sem query espacial real). +- **Prompt automático no máximo 1× por sessão (`sessionStorage`).** Cumpre o pedido de produto sem martelar o usuário a cada navegação no Início. Chave estável: `teqo:campaign:geo-prompted-session`. **Rejeitado:** prompt a cada mount do card; `localStorage` "nunca mais perguntar" como único gate (impediria retry legítimo em sessão nova após o usuário mudar a permissão no SO). +- **Sem `Consent` / sem lote jurídico.** Tratamento local da própria localização do usuário autenticado, sem transmissão — mesmo racional de visitados. **Rejeitado:** chave `Consent` só para UX de GPS (multiplica lead time jurídico sem dado no servidor). +- **Malha de matching = município IBGE (417), depois mapear ao catálogo operacional.** Centroides por `ibgeCode`; entradas `kind: 'municipio'` 1:1; entradas `kind: 'zona'` (Salvador) **não** recebem ZE automática na v1 — se o mais próximo for Salvador, CTA para `/campanha/municipios?q=Salvador` (ou filtro equivalente já existente). **Rejeitado:** escolher ZE aleatória/primeira; inventar centroides de zona sem polígonos (B8 F2). +- **Staff only no Início.** Leader lockdown intacto. **Rejeitado:** expor municípios ao leader via atalho geo. +- **i18n e naming:** identificadores em inglês (`NearestMunicipalityCard`, `municipalityCentroids`, `findNearestMunicipality`, `sessionGeoPrompt`, `PROMPT_SESSION_KEY`); strings visíveis em pt-BR ("Município mais próximo", "Abrir", "Usar minha localização"). + +## Questões em aberto + +- **Posição no Início: acima dos KPIs, junto a Recentes, ou sob o mapa?** **Opções:** A) imediatamente sob o header (máxima descoberta em campo) | B) ao lado/abaixo de `RecentlyVisitedCard` (família de atalhos) | C) sob o mapa. **Recomendação:** **B** — agrupa atalhos de navegação sem competir com o hero espacial do mapa; em mobile, card curto acima de Recentes. _(assumido — validar no craft/critique)_ +- **Mostrar distância em km?** **Opções:** sempre | só se < limiar | nunca. **Recomendação:** mostrar quando a precisão/resolução for confiável (ex. < 50 km do centroide); omitir se o usuário parecer fora da BA (e aí não sugerir). +- **Limiar "fora da Bahia"?** **Recomendação:** se o nearest > ~80–100 km do ponto, tratar como fora do teatro e não sugerir (evita "Abrir Mucugê" com usuário em SP). Valor exato no craft com fixture. + +## Abordagem proposta + +```mermaid +flowchart LR + Topo["bahia-municipalities.topo.json
(B2, commitado)"] + Build["pnpm build:municipality-centroids
(CLI, sem DB)"] + Artifact["src/lib/municipalityCentroids/
bahia-municipality-centroids.json"] + Scope["Dashboard RSC
slugs acessíveis do ator"] + Card["NearestMunicipalityCard
(client island)"] + Geo["Geolocation + Permissions
+ sessionStorage prompt flag"] + Match["findNearestMunicipality
(Haversine puro)"] + Link["Link → /campanha/municipios/..."] + + Topo --> Build --> Artifact + Scope --> Card + Artifact --> Card + Card --> Geo --> Match --> Link +``` + +Componentes: + +- **`pnpm build:municipality-centroids`** (`scripts/build-municipality-centroids.mjs`): lê o TopoJSON já commitado (ou IBGE Localidades se for mais estável — preferir TopoJSON para zero rede no rebuild), emite centroides `{ [ibgeCode]: { lat, lng } }` em `src/lib/municipalityCentroids/`; snapshot/int test de cobertura vs `bahiaMunicipalityCodes` / catálogo (padrão do artefato TSE). **Não** entra em `pnpm build` de deploy. +- **`src/lib/municipalityCentroids.ts`** (loader client-safe do JSON) + **`src/lib/municipalityProximity.ts`** (puro): `haversineKm`, `findNearestByIbgeCode(lat, lng, candidates)`, `resolveCatalogTargets(ibgeCode)` → slug único ou `{ kind: 'salvadorZones', listHref }`. +- **`NearestMunicipalityCard`** (`src/components/campaign/`, `'use client'`): + - Props: `{ accessible: { slug, name, ibgeCode, kind }[] }` (mínimo necessário; sem docs Payload inteiros). + - No mount: lê `sessionStorage` flag; consulta `navigator.permissions` quando disponível; se ainda não prompted na sessão e estado ≠ `granted`/`denied` estável, chama `getCurrentPosition` **uma vez** e seta a flag; se `granted`, resolve silencioso. + - Hidratação segura (estado inicial vazio/`null` até o efeito — sem mismatch). + - CTA principal = `Link` shadcn/`Button`; pending honesto enquanto `getCurrentPosition` resolve (Feel the action); erro/negado → CTA manual sem re-prompt automático. +- **Encaixe** em `CampaignDashboard.tsx` (junto a `RecentlyVisitedCard`); página `page.tsx` já restringe staff vs leader — passar só a lista acessível derivada de `getCampaignDashboardData` / scope já carregado (`loadMunicipalityScope` / view). +- **Sem migration, sem collection, sem server action de escrita.** + +## Dependências + +- Nenhuma dura de outro item aberto. Reusa B2 (TopoJSON), catálogo `municipalityCatalog.ts`, shells do dashboard, padrão client-storage de visitados. +- **Suave:** **B8 F2** (polígonos das ZE de Salvador) — quando existir, permite point-in-polygon para desambiguar ZE; até lá, lista filtrada Salvador. + +## Não escopo + +- Geolocalização para `leader` / ferramenta de contatos. +- Enviar ou armazenar posição no servidor / analytics. +- Navegação turn-by-turn, ranking dos N mais próximos, mapa de "perto de mim". +- Matching por seção eleitoral ou bairro (fora de escopo AGENTS; B8 F2 é zona Salvador apenas). +- Pedir permissão em outras rotas além do Início staff (v1). + +## Rabbit holes + +- **Point-in-polygon no client com TopoJSON completo.** Explode bundle e conflita com lazy do mapa (B5). **Mitigação:** só centroides (~poucos KB); polígonos ficam no path do mapa. +- **"Completar" Salvador por ZE sem malha.** Chute de ZE erra operação de campo. **Mitigação:** lista filtrada até B8 F2. +- **Abstração genérica de "location services".** Um card, um helper. **Mitigação:** sem provider/context até 3º call site. +- **Consent/RIPD por precaução.** Sem dado no servidor não há lote jurídico. **Mitigação:** boundary explícito no plano; se no futuro houver sync, aí sim Consent + defer. + +## Adiado com gatilho + +- **Desambiguação Salvador ZE por ponto-em-polígono.** Revisitar quando: **B8 F2** entregue (polígonos no mapa). +- **Atalho também na lista `/campanha/municipios`.** Revisitar quando: evidência de uso no Início (campo pede o mesmo atalho na lista). +- **Lembrar última sugestão em `sessionStorage` para paint imediato.** Revisitar quando: critique acusar flash/vazio perceptível no card. + +## Referências + +- `docs/roadmap.md` (B14; Demais itens abertos; grafo; cortes) +- [visitados-recentemente.md](visitados-recentemente.md) — precedente client-storage + card no dashboard +- [poligonos-pracas-zona.md](poligonos-pracas-zona.md) — B8 F2 (gatilho Salvador ZE) +- [mapa-bahia-geometrias.md](mapa-bahia-geometrias.md) — TopoJSON fonte dos centroides +- `src/components/campaign/CampaignDashboard.tsx`, `RecentlyVisitedCard.tsx`, `src/utilities/recentVisits.ts` +- `src/lib/municipalityCatalog.ts`, `src/lib/bahiaMunicipalityCodes.ts`, `src/lib/geometries/bahia-municipalities.topo.json` +- `PRODUCT.md` / `DESIGN.md` — Field Desk, clareza sob pressão, Feel the action +- AGENTS.md — leader lockdown, naming, sem PostGIS sem query espacial, artefatos commitados via script (não no `pnpm build`) diff --git a/docs/roadmap.md b/docs/roadmap.md index cc5b4672..d0d88b54 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,6 +1,6 @@ # Roadmap — Teqo -Atualizado em: 2026-07-24 (janela 1 vigente — convenções até 05/08; foco: smoke pós-deploy, E4R→A11/E17 na semana de onboarding, R6, E8; sincronizado com a sessão de campo de 2026-07-23 — [CUSTOMER.md](CUSTOMER.md)) +Atualizado em: 2026-07-24 (B14 município mais próximo por geolocalização no Início; janela 1 vigente — convenções até 05/08; foco: smoke pós-deploy, E4R→A11/E17 na semana de onboarding, R6, E8) Registro canônico dos **próximos** planos e débitos. Histórico de entregas: resumo abaixo + planos em [`docs/plans/`](plans/) + notebook [`.cursor/rules/projects/nucleos-eleitorais.mdc`](../.cursor/rules/projects/nucleos-eleitorais.mdc). @@ -81,6 +81,7 @@ O discovery literatura→persona→entrevista ([relatório aprovado](research/re - **D4** envio 1:1 pela sessão do ator · depende de D3 · [plano](plans/whatsapp-envio-liderancas.md) - **D5** inbox da própria sessão → rascunhos (`municipalityUpdate`/demanda) com humano no loop · depende de D3 · [plano](plans/whatsapp-sugestao-atualizacoes.md) - **R6** critique/polish visual da vertical remodelada (ciclo /impeccable completo por superfície; smoke visual coordenador feito em 2026-07-21) · absorve os débitos de produto/UX remanescentes de FD2 ([field-desk-ux-pos-critique.md](plans/field-desk-ux-pos-critique.md)): glossário inline (O3 — hipótese ainda sem evidência), triagem em lote, empty states de coordenador · gatilho: antes de 16/08 +- **B14** município mais próximo (geolocalização → atalho no Início staff) · pede permissão **1× por sessão** se ainda não concedida; matching client-side sobre centroides IBGE; Salvador multi-zona → lista filtrada até B8 F2 · ~1d · Janela 1–2 · sem deps duras · cortável · [plano](plans/municipio-mais-proximo.md) ### Fill-ins abertos @@ -111,6 +112,7 @@ flowchart TD D3 --> D5["D5 WA → rascunhos"] D4 -.thread.-> D5 B8F2["B8 F2 Polígonos
zonas de Salvador"] + B14n["B14 Município mais próximo"] E4R["E4R Import planilha
(seed estratégia)"] A11n["A11 Posição em votos"] E17n["E17 Tabela TI no Início"] @@ -149,13 +151,14 @@ flowchart TD A6 -.dobradinha.-> E13i C2prod -.dados reais.-> E11i E11i -.decisões acumuladas.-> E15i + B8F2 -.ZE Salvador.-> B14n ``` -Paralelizáveis agora: **E4R → A11/E17** (semana de onboarding, sem deps), **E8** (A10 ✓ e remodelagem em produção), **C12** (paralelo a E8), **E16** (compõe o existente), fill-ins (O0+, RS+). **D3** só após smoke + folga e só se o fluxo sede-digita (C12) não absorver os deltas do ZAP (não compete com E8/E9). +Paralelizáveis agora: **E4R → A11/E17** (semana de onboarding, sem deps), **E8** (A10 ✓ e remodelagem em produção), **C12** (paralelo a E8), **E16** (compõe o existente), **B14** (atalho geo no Início; soft B8 F2 só para ZE Salvador), fill-ins (O0+, RS+). **D3** só após smoke + folga e só se o fluxo sede-digita (C12) não absorver os deltas do ZAP (não compete com E8/E9). ### Sequência por janela (só pendentes) -**Janela 1 — agora → 05/08 (convenções):** smoke pós-deploy em produção + onboarding do time (Onda 0 §2/§4), com **E4R → A11/E17** na semana de onboarding (quadro seedado + a lente da mesa prontos quando o time logar); gate de adoção: sinal Little Hire — ≥1 update espontâneo até 30/07, cobrança da tabela dispensada (planilhas já em `docs/sheets/`) — acompanhamento em [IMPROVE-APP-PLAN.md](IMPROVE-APP-PLAN.md); **R6** critique/polish; **E8** pode começar em paralelo; Onda 0 jurídica em paralelo (externa). +**Janela 1 — agora → 05/08 (convenções):** smoke pós-deploy em produção + onboarding do time (Onda 0 §2/§4), com **E4R → A11/E17** na semana de onboarding (quadro seedado + a lente da mesa prontos quando o time logar); gate de adoção: sinal Little Hire — ≥1 update espontâneo até 30/07, cobrança da tabela dispensada (planilhas já em `docs/sheets/`) — acompanhamento em [IMPROVE-APP-PLAN.md](IMPROVE-APP-PLAN.md); **R6** critique/polish; **E8** pode começar em paralelo; **B14** (atalho geo) se sobrar folga de campo no onboarding; Onda 0 jurídica em paralelo (externa). **Janela 2 — 05/08 → 16/08 (pré-propaganda):** C2 dados reais assim que o jurídico liberar; **E8** conta da cadeira → **E9** fila de alocação, com **C12** registro-fundação em paralelo (migrations cedo, longe do congelamento); **E16** dossiê do município (pedido O6 — compõe o existente, melhora com E8); D2 se sobrar folga. @@ -167,7 +170,7 @@ Paralelizáveis agora: **E4R → A11/E17** (semana de onboarding, sem deps), **E **Não cortáveis:** Onda 0 (jurídico/Consent); **E4R** seed da planilha (Big Hire — o quadro nasce vazio sem ele); C2 dados reais; assimetria declarado×estimado (relação de campo); **E8**+**E9**+**C12** (a conta da cadeira, a fila e o registro ex-ante são o mínimo de "inteligência, não planilha" — e C12 é irrecuperável se não registrar durante a campanha). -**Cortes seguros** (se o prazo apertar, nesta ordem): **D5** inbox→rascunhos (manter registro manual + `wa.me`); **D4** envio bridge (manter `wa.me`); **D3** fundação do canal (atalho `wa.me` continua); **E12** camada TI (rollup manual por lista; **E17** já dá a leitura regional básica no Início); **E13** planejador de giros (rebaixado na fila de corte em 2026-07-24: "perna"/agenda é a restrição dominante nomeada em campo — cortar só depois de E12; agenda segue manual com J-A/J-B como guia); **E15** backtest (pós-eleição por definição — cortar = perder o aprendizado 2030); **E11** motor v1 (manter fila E9 sem sugestões); **B13** símbolo proporcional (manter quantis/LQ como escala); **E14** níveis (manter `priority` alta/normal); **B8 F2** polígonos (mapa continua agregado no município; manter F1 bairros); **D2** push (adiar); **A6**; **A11**/**E17** (baratos e sem deps — cortar só em último caso); **E16** dossiê (último dos extras — pedido explícito de campo); débitos/fill-ins. +**Cortes seguros** (se o prazo apertar, nesta ordem): **D5** inbox→rascunhos (manter registro manual + `wa.me`); **D4** envio bridge (manter `wa.me`); **D3** fundação do canal (atalho `wa.me` continua); **E12** camada TI (rollup manual por lista; **E17** já dá a leitura regional básica no Início); **E13** planejador de giros (rebaixado na fila de corte em 2026-07-24: "perna"/agenda é a restrição dominante nomeada em campo — cortar só depois de E12; agenda segue manual com J-A/J-B como guia); **E15** backtest (pós-eleição por definição — cortar = perder o aprendizado 2030); **E11** motor v1 (manter fila E9 sem sugestões); **B13** símbolo proporcional (manter quantis/LQ como escala); **E14** níveis (manter `priority` alta/normal); **B8 F2** polígonos (mapa continua agregado no município; manter F1 bairros); **D2** push (adiar); **A6**; **B14** município mais próximo (lista/busca e Recentes continuam); **A11**/**E17** (baratos e sem deps — cortar só em último caso); **E16** dossiê (último dos extras — pedido explícito de campo); débitos/fill-ins. ## Bloqueadores atuais