docs: consolidate O0+/B68+ and fatia B79→B91

Merge escala-dry B68+ into O0+ (same kimi-k3-low model). Split B79
chassis from drawer search (B91) so B80–B90 unblock without the search half.

Co-authored-by: Francisco Solla <fsolla@users.noreply.github.com>
This commit is contained in:
Cursor Agent 2026-07-31 01:57:16 +00:00
parent e2bc366c10
commit 5700817563
5 changed files with 152 additions and 74 deletions

View file

@ -4,6 +4,8 @@ Conteúdo movido do `AGENTS.md` em 2026-07-30 (fatiamento do paradigma de agente
---
**Recently resolved (2026-07-31):** **Consolidação de Issues (project-status)** — merge **B68+** (#39) → **O0+** (#35) (mesmo `model: kimi-k3-low`); **não** merge D3/D4/D5 (modelos mistos kimi vs composer); **não** merge B53–B55 (já `done`); fatia **B79** → chassis (#15) + **B91** busca no drawer (#76, `depends: [B79]`). Planos: `escala-dry-pos-onda0.md`, `busca-global-bottom-drawer.md`, `chassis-bottom-drawer-acoes-rapidas.md`.
## Known Gaps (as of 2026-07-24 — resolve before relying on this file for onboarding new devs)
Backlog consolidado (bloqueadores, site, campanha, white-label): [`docs/roadmap.md`](docs/roadmap.md).

View file

@ -0,0 +1,84 @@
# Busca global no bottom drawer (mobile)
Status: rascunho
Atualizado em: 2026-07-31
Issue: #76 (B91)
Priority: P1
Model: composer-2.5
Impeccable: C — chrome do drawer (B79); reuso da busca do Início dentro do snap expandido
Appetite: ~0,75–1 dia eng; extrair acoplamento HomeSearch do Início; sem migration
Responsável: —
## Design (Impeccable)
Âncoras: `PRODUCT.md` / `DESIGN.md` · tema `data-theme='campaign'` · shell do drawer em [chassis-bottom-drawer-acoes-rapidas.md](chassis-bottom-drawer-acoes-rapidas.md) (B79).
Na implementação (`work-issue`): craft compacto → critique → polish (superfície já moldada pelo chassis).
Brief compacto:
- **Persona / contexto:** staff no celular, drawer expandido em rota ≠ Início.
- **Job principal:** a mesma busca global do Início (`POST /campanha/home-search`, providers B48–B55) sem sair da página.
- **Estratégia de cor:** Restrained — chrome do drawer.
- **Edit where you see:** não — busca/navegação.
- **Anti-goals:** segunda API de busca; command palette desktop; reinventar debounce/contrato; drawer no Início.
### Wireframe (texto)
```text
┌─ CampaignQuickActionsDrawer (expanded) ─────────────┐
│ ═ handle ═ │
│ [ações B80+ …] │
│ ┌─ Buscar na campanha ────────────────────────────┐ │
│ │ input + results (HomeSearch* reusado) │ │
│ └─────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────┘
Fora: página opaca/interativa (B79); Início sem este item.
```
## Dados → decisão → apresentação
Dados: N/A — hits = providers B48+ já existentes; este item só monta a UI no drawer.
## Contexto
Fatia de **B79** (2026-07-31): o chassis (drawer não-modal + snap + registry + padding) desbloqueia **B80–B90**; a busca embutida era a metade que inchava o guarda-chuva. B79 permanece o dependente duro dos catálogos; este item (B91) depende de B79 e não bloqueia B80–B90.
## Objetivos
- Extrair o mínimo de `CampaignHomeSearch` / `HomeSearchProvider` / results shell para montar fora de `CampaignHomeStaffChrome`.
- No drawer expandido: mesma API, debounce e modo focado do Início.
- Guardrails: sem migration, sem collection, sem Consent, sem server action de escrita.
## Decisões travadas
- **Busca = contrato do Início** (`home-search`). **Rejeitado:** segunda API; omnibox desktop neste item.
- **Depende de B79 (chassis).** Sem drawer montado, não há onde embutir. **Rejeitado:** busca flutuante fora do drawer.
- **Não bloqueia B80–B90.** Catálogos usam o slot de ações do chassis; busca é independente.
## Abordagem proposta
- Depth check: reusar `HomeSearch*` — extrair provider montável no drawer; não duplicar debounce.
- Wire no `CampaignQuickActionsDrawer` (região expandida).
- Pins: unit/int existentes da home-search; smoke mobile do drawer com query.
## Dependências
- Dura: **B79** (chassis + mount). Soft: B47 ✓ / B48–B55 (providers).
## Não escopo
- Catálogos por vertical → B80–B90.
- Chassis / snap / padding → B79.
- Desktop omnibox.
## Rabbit holes
- **Teclado virtual cobrindo a busca no snap.** Mitigação: v1 = padding fixo; Adiado com gatilho iOS.
- **Levantar strip do Início sem medir bundle.** Mitigação: só a busca neste item.
## Referências
- [chassis-bottom-drawer-acoes-rapidas.md](chassis-bottom-drawer-acoes-rapidas.md) (B79)
- `src/components/campaign/dashboard/HomeSearchResultsContext.tsx`
- `src/lib/campaignHomeActions.ts` + `CampaignHomeSearch`

View file

@ -1,10 +1,13 @@
# Chassis do bottom drawer de ações rápidas + busca (mobile)
Status: rascunho
Atualizado em: 2026-07-30
Status: in-progress (Issue #15) — **fatiado 2026-07-31:** busca embutida → **B91**
Atualizado em: 2026-07-31
Issue: #15 (B79)
Priority: P1
Model: composer-2.5
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item **B79** — UX-1 chrome pós-B73)
Impeccable: C — chrome novo em toda rota `(app)` exceto Início e wizards; gesto drag + busca embutida
Appetite: ~1,5–2 dias eng; shell não-modal + snap/drag + slot de ações + reuso da busca global; sem migration
Impeccable: C — chrome novo em toda rota `(app)` exceto Início e wizards; gesto drag + slot de ações
Appetite: ~1–1,5 dia eng; shell não-modal + snap/drag + registry/slot de ações + padding; **sem** busca (B91); sem migration
Responsável: —
## Design (Impeccable)
@ -16,10 +19,10 @@ Na implementação (`implement-roadmap-item`): shape → craft → critique →
Brief compacto:
- **Persona / contexto:** CG/assessor no celular, **fora** do Início — após **B73** a bottom nav some; o ritual de ação+busca só existia no Início; nas outras páginas sobra só o sidebar fechado.
- **Job principal:** ter ações rápidas do contexto da página + a mesma busca global do Início, sem escurecer nem bloquear a página atrás; poder recolher/expandir o drawer para ver mais conteúdo.
- **Job principal:** ter ações rápidas do contexto da página sem escurecer nem bloquear a página atrás; poder recolher/expandir o drawer para ver mais conteúdo. (Busca global no drawer = **B91**.)
- **Estratégia de cor:** Restrained — superfície de chrome (fundo campaign), não modal dramático.
- **Edit where you see:** não neste item — launchers; escrita nos wizards/listas.
- **Anti-goals:** overlay que muda opacidade/`pointer-events` da página; segunda bottom nav de destinos de domínio; FAB flutuante; drawer no Início (já tem dock B65); drawer em `/campanha/acoes/*` (ritual B59/B75); reinventar busca (reusar B47+).
- **Anti-goals:** overlay que muda opacidade/`pointer-events` da página; segunda bottom nav de destinos de domínio; FAB flutuante; drawer no Início (já tem dock B65); drawer em `/campanha/acoes/*` (ritual B59/B75); embutir busca neste item (→ **B91**).
## Dados → decisão → apresentação
@ -30,8 +33,8 @@ Dados: N/A — chrome de navegação/ação; hits da busca = providers B48+ já
Decisão de produto (2026-07-30): com a remoção da bottom nav (**B73**), a navegação mobile frequente fica no Início (ações + busca) e no sidebar (Sheet fechado por padrão, B38 ✓). Nas **demais** páginas falta um atalho de intenção. Solução: **bottom drawer** sempre montado no viewport &lt;`md` (desktop: fora — sidebar + chrome amplo bastam _(assumido)_), com:
1. Strip/catálogo de ações **contextualizadas** pela página atual (catálogos = **B80–B90**).
2. Barra de busca com o **mesmo escopo global** do Início (`POST /campanha/home-search`, providers B48–B55).
3. Gesto: arrastar para cima/baixo para expandir/recolher; tap na borda/handle superior também alterna.
2. Gesto: arrastar para cima/baixo para expandir/recolher; tap na borda/handle superior também alterna.
3. **Busca no drawer** ficou em **B91** (fatia 2026-07-31) — não bloqueia B80–B90.
O `Drawer` shadcn/base-ui já expõe `modal={false}` (não renderiza `DrawerOverlay`) e `snapPoints` — profundidade certa; não inventar segundo sheet.
@ -39,11 +42,11 @@ O `Drawer` shadcn/base-ui já expõe `modal={false}` (não renderiza `DrawerOver
- Componente shell (ex. `CampaignQuickActionsDrawer`) montado no layout `(app)` **só** quando: viewport mobile, actor staff (ou leader nas rotas que o plano B89 pedir), pathname **não** é Início exato e **não** está sob `/campanha/acoes`.
- **Não-modal:** página atrás permanece 100% opaca, scrollável e interativa; o drawer **ocupa** faixa inferior (layout shift / padding do scroll) em vez de cobrir com scrim.
- Snap points mínimos: **collapsed** (handle + talvez 1 linha de peek) e **expanded** (ações + busca); drag e tap no handle/borda superior alternam. Persistência de snap na sessão _(recomendado: `sessionStorage`)_ — Adiado se estourar appetite.
- Slot `actions` (lista já resolvida com `href`s) + slot/região de busca reusando `CampaignHomeSearch` / `HomeSearchContext` / results shell — extrair o necessário para não acoplar ao `CampaignHomeLayout`.
- Contrato de contexto client-safe (ex. `CampaignQuickActionContext`: `municipalitySlug?`, `leadershipId?`, …) + helper que resolve `href` via `wizardActionHref` / atalhos de lista — **B80+** só preenchem o contexto e o catálogo.
- Snap points mínimos: **collapsed** (handle + talvez 1 linha de peek) e **expanded** (ações; região de busca reservada/vazia até B91); drag e tap no handle/borda superior alternam. Persistência de snap na sessão _(recomendado: `sessionStorage`)_ — Adiado se estourar appetite.
- Slot `actions` (lista já resolvida com `href`s). Contrato de contexto client-safe (ex. `CampaignQuickActionContext`: `municipalitySlug?`, `leadershipId?`, …) + helper que resolve `href` via `wizardActionHref` / atalhos de lista — **B80+** só preenchem o contexto e o catálogo.
- Ajuste de padding do `campaign-content-scroll` para a altura do peek (substitui o antigo `pb-24` da bottom nav após B73).
- Guardrails: sem migration, sem collection, sem Consent, sem server action nova de escrita; leader lockdown respeitado (sem omnibox estadual no drawer staff).
- Guardrails: sem migration, sem collection, sem Consent, sem server action nova de escrita; leader lockdown respeitado.
- **Tracer bullet:** drawer montado + registry vazio/stub + padding → merge — isso **desbloqueia B80–B90** sem esperar B91.
## Decisões travadas
@ -51,8 +54,8 @@ O `Drawer` shadcn/base-ui já expõe `modal={false}` (não renderiza `DrawerOver
- **Fora do Início e fora de `/acoes/*`.** Início já tem dock; wizard tem chrome próprio (B75). **Rejeitado:** unificar Início no mesmo drawer (dois docks); drawer dentro do wizard.
- **Só mobile (&lt;`md`).** Desktop/tablet mantêm sidebar + busca do Início quando o usuário volta. **Rejeitado:** drawer em `md+` (ruído; compete com sidebar).
- **Catálogo por página = itens B80–B90**, não hardcode no chassis. O chassis só renderiza o que a rota fornece (via registry pathname→provider ou prop do layout segment). **Rejeitado:** um único catálogo global idêntico ao Início em toda rota (perde o prefill).
- **Busca = mesmo contrato do Início** (`home-search`, debounce, modo focado **dentro do drawer expandido**). **Rejeitado:** segunda API; command palette desktop neste item.
- **i18n:** ids `CampaignQuickActionsDrawer`, `quickActionContext`, `snap`; copy pt-BR (“Buscar na campanha”, aria do handle “Mostrar ações rápidas” / “Ocultar…”).
- **Busca neste item = fora.** Contrato `home-search` no drawer → **B91**. **Rejeitado:** manter busca no escopo do chassis (guarda-chuva que bloqueava 11 P1).
- **i18n:** ids `CampaignQuickActionsDrawer`, `quickActionContext`, `snap`; copy pt-BR (aria do handle “Mostrar ações rápidas” / “Ocultar…”).
## Questões em aberto
@ -69,27 +72,27 @@ flowchart TB
gate -->|não| drawer["CampaignQuickActionsDrawer modal=false"]
drawer --> handle["handle + snap"]
drawer --> actions["ações do registry B80+"]
drawer --> search["HomeSearch* reusado"]
drawer -.->|"B91"| search["HomeSearch* no drawer"]
actions --> wizards["wizardActionHref + context"]
search --> api["POST /campanha/home-search"]
```
Componentes:
- **`CampaignQuickActionsDrawer`** (`src/components/campaign/shell/`): `Drawer` `modal={false}` + `snapPoints` + `showSwipeHandle`; região de ações (reuso visual de `CampaignHomeActionStrip` / botões B44 se couberem no peek) + busca.
- **`CampaignQuickActionsDrawer`** (`src/components/campaign/shell/`): `Drawer` `modal={false}` + `snapPoints` + `showSwipeHandle`; região de ações (reuso visual de `CampaignHomeActionStrip` / botões B44 se couberem no peek); slot/região de busca **opcional** (preenchida em B91).
- **`campaignQuickActionRegistry` / `resolveQuickActionsForPath`** (`src/lib/` client-safe): pathname + role + context → `ResolvedCampaignHomeAction[]` (ou tipo irmão). Contextos ricos entram pelos planos B80+.
- **Extrair busca do acoplamento ao Início** o mínimo necessário (`HomeSearchProvider` montável fora de `CampaignHomeStaffChrome`) — depth check: não duplicar debounce/contrato.
- **`(app)/layout.tsx`**: mount condicional; padding inferior do scroll = altura do peek.
- **Migration:** Sem migration, sem collection, sem server action de escrita.
## Dependências
- Dura: **B73** (remover bottom nav — senão dois chromes inferiores). Soft: **B47 ✓**/B48+ (busca); **B45 ✓**/B44 ✓ (strip/botão); **B60 ✓** (`wizardActionHref` + `?municipio=`).
- Desbloqueia **B80–B90**.
- Desbloqueia **B80–B90** (não exige B91).
- Soft: **B91** (busca no drawer) depende deste chassis.
## Não escopo
- Catálogos e prefills por vertical → **B80–B90**.
- Busca global embutida no drawer → **B91** ([busca-global-bottom-drawer.md](busca-global-bottom-drawer.md)).
- Novos wizards / novas actions de escrita.
- Desktop omnibox global.
- Quadro: **fora do inventário** (decisão de produto 2026-07-30).
@ -108,9 +111,14 @@ Componentes:
## Referências
- `docs/roadmap.md` (UX-1, B73, B79–B90)
- [busca-global-bottom-drawer.md](busca-global-bottom-drawer.md) (B91 — fatia busca)
- `src/components/ui/Drawer.tsx` — `modal={false}` sem overlay
- `src/lib/campaignActionRoutes.ts` — `wizardActionHref`
- `src/lib/campaignHomeActions.ts` + `CampaignHomeActionStrip` / `CampaignHomeSearch`
- `src/lib/campaignHomeActions.ts` + `CampaignHomeActionStrip`
- `src/app/(campaign)/campanha/(app)/layout.tsx` — scroll + chrome
- [remover-bottom-nav-mobile.md](remover-bottom-nav-mobile.md) · [fluxos-acao-primeiro-inicio.md](fluxos-acao-primeiro-inicio.md)
- `PRODUCT.md` / `DESIGN.md` — Field Desk mobile
## Revisões
- **2026-07-31:** Fatia humana — busca → B91; chassis desbloqueia B80–B90 sozinho; tracer bullet = drawer + registry + padding.

View file

@ -1,58 +1,19 @@
# Escala e DRY pós-B68 (sugestões na busca aberta)
Status: rascunho (débito pós-`/simplify` 2026-07-29)
Atualizado em: 2026-07-29
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Fill-ins abertos, **B68+**)
Impeccable: A — perf/estrutura de loader; sem pixel novo
Appetite: ~0,5–0,75 dia eng (F1); F2 cortável
Responsável: —
Status: **absorvido em O0+ (#35)** — 2026-07-31
Atualizado em: 2026-07-31
Issue: #39 (fechada) → fases vivas em [escala-dry-pos-onda0.md](escala-dry-pos-onda0.md) (§ Absorvido de B68+)
Priority: P2
Model: kimi-k3-low
## Dados → decisão → apresentação
## Motivo da absorção
- **Vou apresentar dados?** Não (N/A) — mesmos ~8 hits já mostrados; só muda de onde vêm no primeiro focus.
Consolidação humana (project-status 2026-07-31): mesmo domínio/prio heurístico (escala dry/P2) e **mesmo `model: kimi-k3-low`**. A regra de merge era: só consolidar se a complexidade de modelo não subir — aqui permanece Kimi K3 (simplify/DRY).
## Contexto
Não reabrir este plano; trabalhar as fases B68-F1/F2 no plano consolidado O0+.
**B68 ✓ (2026-07-29)** entrega sugestões de municípios no empty state da busca do Início (`mode: 'suggest'` em `POST /campanha/home-search`). O `/simplify` do fechamento mediu que, para **coordenador/candidato**, cada focus dispara um POST que repete `loadMunicipalityScope` + `loadMunicipalityGoalCoverageBundle` — trabalho que a mesma página já pagou em `loadCampaignHomeSummary` no RSC. `React cache()` não cruza a fronteira RSC ↔ route handler.
## Referência histórica (pré-merge)
O simplify da sessão já aplicou mitigação parcial: o bundle E8 roda só em municípios `priority === 'alta'` (não nas 435 linhas) e `toHomeSearchMunicipalityHit` unificou o shaping dos hits.
O `/simplify` de B68 mediu que, no Início staff (coordenador/candidato), cada focus do empty-state dispara POST que repete `loadMunicipalityScope` + `loadMunicipalityGoalCoverageBundle` já pagos no RSC. Mitigação: embed `initialSuggest` no mesmo request da página.
## Objetivos
- **F1:** primeiro focus no Início staff **não** refaz scope+coverage no POST quando o RSC da página já carregou os insumos — embed `initialSuggest` (ou loader irmão no mesmo `Promise.all` da página) e hidratar `useHomeSearchResultsState` com TTL curto / invalidação ao navegar.
- Sem mudar a política de ranking (assessor = frescor; CG = déficit + frescor).
- Sem migration/collection/Consent.
## Já resolvido no simplify/critique (não reabrir)
- `aria-busy` duplicado (`resultsBusy ?? isDebouncing`).
- Shell de erro sem `errorMessage` nullable intermediário.
- `id` removido do tipo puro do ranker.
- Factory `toHomeSearchMunicipalityHit` nos dois loaders.
- Bundle de cobertura restrito a `priority === 'alta'`.
## Fases
### F1 — RSC embed do suggest (P1 perf)
- Estender `loadCampaignHomeSummary` ou extrair `loadHomeSearchSuggestHits` reutilizável no mesmo request da página (`page.tsx`).
- Passar `initialSuggest` para `CampaignHomeStaffChrome` → `useHomeSearchResultsState({ initialSuggest })`.
- Client: usar payload inicial quando `uiFocused && !query.isActive` e não houver stale/error; POST só para revalidação explícita ou após TTL (opcional v1: só primeiro paint).
### F2 — Comparator compartilhado de déficit (cortável)
- Extrair `compareNullableNumberDesc` + tiebreak hook para `lib/municipalitySort.ts` quando houver 3º call site com política diferente de tiebreak (hoje: B20 nome, B68 frescor, E9 lista).
## Explicitamente fora / Adiado com gatilho
- **Cache client-side / stale-while-revalidate no refocus** — aceito no plano B68 (fetch ao focus); revisitar se sessão reclamar de flash de loading.
- **Unificar constante `8`** (`HOME_SEARCH_SUGGEST_LIMIT` vs `DASHBOARD_PRIORITY_SAMPLE_LIMIT`) — cosmético; mover para `lib/` só se um dos dois mudar.
- **`loadTerritoryOverview` em todo keystroke da busca** — débito adjacente B48 (search path), não B68; gatilho: latência perceptível ao digitar após B49+.
- **Mesclar `loadHomeSearchSuggestions` com `searchHomeMunicipalities`** — dois call sites; extrair só o mapper (já feito).
## Referências
- [sugestoes-busca-vazia-inicio.md](sugestoes-busca-vazia-inicio.md) (B68)
- [`loadHomeSearchSuggestions.ts`](../src/utilities/homeSearch/loadHomeSearchSuggestions.ts)
- [`campaignDashboardData.ts`](../src/utilities/campaignDashboardData.ts) (`loadCampaignHomeSummary`)
- [`HomeSearchResultsContext.tsx`](../src/components/campaign/dashboard/HomeSearchResultsContext.tsx)
Detalhe completo das fases e rabbit holes: ver § Absorvido de B68+ em [escala-dry-pos-onda0.md](escala-dry-pos-onda0.md).

View file

@ -1,8 +1,13 @@
# Escala e DRY pós-Onda 0 (Consent / privacidade / cache)
# Escala e DRY P2 — pós-Onda 0 + pós-B68 (consolidado)
Status: Fase 1 entregue; fases 2–5 pendentes
Atualizado em: 2026-07-19
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Onda 0+, fill-in de engenharia pós-MVP)
Status: Fase 1 (Onda 0 revalidate) entregue; fases 2–5 O0 + F1–F2 B68 pendentes
Atualizado em: 2026-07-31
Issue: #35 (O0+) — absorveu **B68+** (#39) em 2026-07-31 (mesmo `model: kimi-k3-low`)
Priority: P2
Model: kimi-k3-low
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Onda 0+ + Fill-in B68+)
Impeccable: A — perf/estrutura + DRY Consent/cache; sem pixel novo
Appetite: ~1–1,5 dia eng (fases O0 restantes + F1 B68; F2 B68 cortável)
Responsável: —
## Contexto
@ -116,6 +121,24 @@ flowchart TD
- `tests/int/onda0Provision.int.spec.ts` / `campaignMigrationReconciliation.int.spec.ts`
- AGENTS.md — Consent por chave estável, `revalidateGlobal`, naming
## Absorvido de B68+ (2026-07-31)
Plano original: [escala-dry-pos-b68.md](escala-dry-pos-b68.md) (Issue #39 fechada como absorvida). Mesma classe de tarefa (simplify/escala-dry → `kimi-k3-low`); domínio distinto (busca do Início) mas consolidado sob O0+ por decisão humana 2026-07-31.
### Fase B68-F1 — RSC embed do suggest (P1 perf)
- Estender `loadCampaignHomeSummary` ou extrair `loadHomeSearchSuggestHits` reutilizável no mesmo request da página (`page.tsx`).
- Passar `initialSuggest` para `CampaignHomeStaffChrome` → `useHomeSearchResultsState({ initialSuggest })`.
- Client: usar payload inicial quando `uiFocused && !query.isActive` e não houver stale/error; POST só para revalidação explícita ou após TTL (opcional v1: só primeiro paint).
- Sem mudar política de ranking (assessor = frescor; CG = déficit + frescor). Sem migration/collection/Consent.
### Fase B68-F2 — Comparator compartilhado de déficit (cortável)
- Extrair `compareNullableNumberDesc` + tiebreak hook para `lib/municipalitySort.ts` quando houver 3º call site com política diferente de tiebreak (hoje: B20 nome, B68 frescor, E9 lista).
**Já resolvido no simplify B68 (não reabrir):** `aria-busy` duplicado; shell de erro; `id` no ranker; factory `toHomeSearchMunicipalityHit`; bundle E8 só em `priority === 'alta'`.
## Revisões
- **2026-07-31:** Consolidação com B68+ (#39) — mesmo modelo `kimi-k3-low`; fases B68-F1/F2 absorvidas neste plano; Issue #39 fechada.
- **2026-07-19:** Fase 1 entregue — endpoint allowlisted (`posts`, `global_privacy-policy`), `getGlobalCacheTag` exportado, curl no runbook Onda 0 e lembrete no `seed:consent`.