mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 15:13:07 +00:00
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.
95 lines
7.5 KiB
Markdown
95 lines
7.5 KiB
Markdown
# 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](../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_source` e `triangulated` de `municipality_update` (e enums/admin conforme snapshot Payload); `pnpm migrate:create simplify_municipality_signal_fields`.
|
||
- Zod `municipalityUpdateCreateSchema`: para `kind: 'sinal'`, exigir `signalType` + `body`; **não** exigir `signalSource`; remover `triangulated`.
|
||
- Collection `MunicipalityUpdate`: dropar fields; ajustar `beforeValidate` que hoje exige fonte.
|
||
- Labels/descriptions (enum **values** preservados — sem rewrite de rows):
|
||
|
||
| value | label | description curta |
|
||
| ------------------- | ------------------- | ----------------------------------------- |
|
||
| `invasao` | Invasão | Adversário ocupando nosso espaço |
|
||
| `esfriamento` | Rede esfriou | Aliados pararam de responder / cairam |
|
||
| `visita_adversario` | Adversário apareceu | Visita ou agenda dele no município |
|
||
| `proposta_broker` | Alguém pediu algo | Liderança/intermediário pediu ou ofereceu |
|
||
| `outro` | Outro | Fato importante que não encaixa acima |
|
||
|
||
- Atualizar `MunicipalitySignalFields`, B26 form, detail/dossier readouts, int tests, seeds se houver.
|
||
- E11: remover branch `triangulated` do 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` + `body` apenas.** **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_intermediario` neste 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
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
Mig["migration DROP fonte/triangulated"] --> Zod["zod + collection"]
|
||
Zod --> UI["SignalFields + B26"]
|
||
Zod --> E11["triggers/catalog"]
|
||
```
|
||
|
||
Componentes:
|
||
|
||
- Migration + `MunicipalityUpdate.ts` + `municipalityUpdate.ts` schema.
|
||
- `MunicipalitySignalFields.tsx` — select de tipo + textarea; sem checkbox/fonte.
|
||
- `municipalityTriggers.ts` / `suggestionCatalog.ts` — dropar `triangulated` do 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 `kind` urgente/nota com sinal.** **Mitigação:** fora — C12 já separou.
|
||
|
||
## Adiado com gatilho
|
||
|
||
- **Rename enum `proposta_broker`.** Revisitar se `broker` ainda 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`).
|
||
- **`FieldError` de `signalType` no detalhe (`MunicipalityUpdateForm`).** Gap pré-existente: o form inline não renderiza erro de servidor no select de tipo (a lista B26 já usa `MunicipalitySignalFields` com `FieldError`). **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: 0` na 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](registro-fundacao.md) · [registrar-sinal-lista-municipios.md](registrar-sinal-lista-municipios.md) · [motor-de-sugestoes.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
|