The close-delivery debt harvest defers FieldError/unify-forms and E11 query tuning to B63 and a production-volume trigger instead of opening new roadmap IDs.
7.5 KiB
Simplificar modelo de sinal (tipo + texto; sem fonte/triangulado)
Status: entregue em código 2026-07-29
Atualizado em: 2026-07-29
Item do roadmap: docs/roadmap.md (Trilha B, item B62 — UX-1 / C12 sinais)
Impeccable: B — schema + forms existentes (MunicipalitySignalFields, B26, admin); UI nova de escolha = B63
Appetite: ~0,75–1 dia eng; migration drop + zod/collection/UI lista/detail; rename de labels; ajuste E11
Responsável: —
Revisão 2026-07-29 (as-built): entregue conforme o plano, com duas decisões da sessão e dois achados: (1) E11 triage 1 por presença — o usuário decidiu que sinal de adversário registrado lê como confirmado ("eles não vão adicionar sinais improváveis"), divergindo do default "ramo fonte única" abaixo; adversarySignal: { present: true } | null, P1 triage 1, fator único "Sinal de adversário registrado". (2) scrub "broker" = só o modelo de sinal — activity.origin (Pedido de broker) e as strings "broker" do suggestionCatalog (staff-only) ficaram para o gatilho já registrado. Achados da auditoria incorporados: form duplicado em MunicipalityUpdateForm.tsx, readouts municipalityUpdatePageData.ts + MunicipalityUpdateFeed.tsx (detalhe + dossiê), glossário campaignIntelligenceConcepts.ts; migration gerada reemitia ADD VALUE 'adiada' (drift de snapshot da cadeia .json — removido à mão; o snapshot desta migration sara a cadeia). Bônus de gate: e2e campaignMunicipalities "advisor scopes…" obsoleto desde B43 (home liderança → /campanha/contatos, redirect pós-B43) atualizado; pin de bypass do municipalityElectoralBaseline 9→8 (drift pré-existente em main). Gate: 876 unit / 489 int / e2e alvo verde / build; Aikido 0 findings.
Dados → decisão → apresentação
Dados: N/A neste item como superfície nova — remove campos; labels novas alimentam B63 e B26.
Contexto
C12 ✓ tipou municipalityUpdate kind: 'sinal' com signalType, signalSource (obrigatório) e triangulated. B26 ✓ e MunicipalitySignalFields expõem os três. Pedido de produto (2026-07-29, gate confirmado): sinais = só tipo + texto; dropar Fonte e Triangulado; renomear rótulos para militantes PT ~60 anos (sem “broker”).
E11 ✓ lê triangulated em sinais de adversário (municipalityTriggers.ts / suggestionCatalog) — ao dropar, o motor trata presença do sinal como o ramo “fonte única” (ou só “há sinal”), sem segunda dimensão.
Objetivos
-
Migration: remover colunas
signal_sourceetriangulateddemunicipality_update(e enums/admin conforme snapshot Payload);pnpm migrate:create simplify_municipality_signal_fields. -
Zod
municipalityUpdateCreateSchema: parakind: 'sinal', exigirsignalType+body; não exigirsignalSource; removertriangulated. -
Collection
MunicipalityUpdate: dropar fields; ajustarbeforeValidateque hoje exige fonte. -
Labels/descriptions (enum values preservados — sem rewrite de rows):
value label description curta invasaoInvasão Adversário ocupando nosso espaço esfriamentoRede esfriou Aliados pararam de responder / cairam visita_adversarioAdversário apareceu Visita ou agenda dele no município proposta_brokerAlguém pediu algo Liderança/intermediário pediu ou ofereceu outroOutro Fato importante que não encaixa acima -
Atualizar
MunicipalitySignalFields, B26 form, detail/dossier readouts, int tests, seeds se houver. -
E11: remover branch
triangulateddo input de sugestão; copy do catálogo que cita "triangulado" / "fonte única" no eixo de adversário → presença do sinal basta e lê como confirmada (triage 1 — decisão da sessão 2026-07-29); recalibrar texto mínimo; não reabrir E15. -
Sem Consent novo. Sem UI de grid do wizard (isso é B63).
Decisões travadas
- Modelo =
signalType+bodyapenas. Rejeitado: manter fonte/triangulado opcionais “por se acaso” (pedido: simplificar; campos mortos confundem mesa). - Enum values estáveis; só labels/descriptions mudam. Rejeitado: renomear
proposta_broker→proposta_intermediarioneste slice (migration de dados + grep em E11/tests sem ganho de UX). Gatilho: se copy interna/código ainda vazar “broker” em string de usuário após labels — aí rename. - E11 sem dimensão triangulado. Rejeitado: inventar proxy (“texto longo = triangulado”); manter coluna só para o motor.
- i18n: ids
invasao…; copy pt-BR nova.
Questões em aberto
- Textos longos do drawer de info (B63) — quem redige? Opções: A eng com copy provisória no plano B63 | B assessoria. Recomendação: A no ship (o quê / consequências / quando usar em 3–5 frases); B revisa no R6. (assumido)
Abordagem proposta
flowchart LR
Mig["migration DROP fonte/triangulated"] --> Zod["zod + collection"]
Zod --> UI["SignalFields + B26"]
Zod --> E11["triggers/catalog"]
Componentes:
- Migration +
MunicipalityUpdate.ts+municipalityUpdate.tsschema. MunicipalitySignalFields.tsx— select de tipo + textarea; sem checkbox/fonte.municipalityTriggers.ts/suggestionCatalog.ts— dropartriangulateddo tipo de input.- View models de update/dossier — parar de exibir fonte/triangulado.
- Migration: sim (drop columns; sem backfill necessário além de drop).
Dependências
- Dura: C12 ✓. Soft: B26 ✓ (superfície a atualizar). Desbloqueia B63.
Não escopo
- Grid de botões + drawer de info + “Pular” → B63.
- Novos tipos de sinal (Perda de apoio / Novo apoio do rascunho UX-1) — não expandir taxonomia neste item; só renomear os 5 existentes. Gatilho: sessão pedir tipo que não cabe em
outro.
Rabbit holes
- Reescrever taxonomia inteira + migração de valores históricos. Mitigação: labels only.
- Unificar
kindurgente/nota com sinal. Mitigação: fora — C12 já separou.
Adiado com gatilho
- Rename enum
proposta_broker. Revisitar sebrokerainda aparecer em UI/admin após labels (grep pt-BR + admin). - Novos signalType values. Revisitar com evidência de mesa (tipos que caem sempre em
outro). FieldErrordesignalTypeno detalhe (MunicipalityUpdateForm). Gap pré-existente: o form inline não renderiza erro de servidor no select de tipo (a lista B26 já usaMunicipalitySignalFieldscomFieldError). Gatilho: B63 (wizard + unificação dos dois forms de sinal).- Unificar
MunicipalitySignalFields+ bloco inline do detalhe. Duplicação aceitável pós-B62 (só tipo + textarea); gatilho: B63 (3º call site do wizard). - Consulta de existência de sinais no loader E11. Hoje
limit: 0na janela de 28d é barato; se o volume crescer, trocar por agregado/exists — gatilho: fila de sugestões lenta ou >N sinais/dia por município em produção.
Referências
- registro-fundacao.md · registrar-sinal-lista-municipios.md · motor-de-sugestoes.md ·
src/lib/schemas/municipalityUpdate.ts·src/collections/MunicipalityUpdate.ts·MunicipalitySignalFields.tsx·municipalityTriggers.ts - AGENTS.md — migrations;
overrideAccess: false - Impeccable: B — craft compacto nos forms existentes