Two-step UX-1 flow on the B59 chassis with URL contract ?signalType= and optional ?entryAction= for embedded skip; reuses createMunicipalityListSignalFormAction.
Replace the three-step ?cenario= ritual with one screen aligned to the municipality list popover; plan covers focused shortcuts and confirm-time coherence validation.
Organization stays by product decision (political branching, e.g. SindMed);
the leadership gains `exclusive` (default true) with list badge and form
checkbox, and sector/sectorNotes/consentNote leave the collection, zod,
forms, list filters/sort, invite autofill and redemption.
Staff can adjust municipality expected votes through média→pessimista→otimista steps with shortcuts, coherence warnings, and a single POST on completion.
Drops signalSource/triangulated from municipalityUpdate (migration
simplify_municipality_signal_fields), rewrites signal-type labels for the
field team, and treats any adversary signal as confirmed in E11 (P1
triage 1). Also fixes the stale post-B43 leader-home e2e and lowers a
drifted bypass pin.
- F1: loadMunicipalityScopeFromDocs evita segunda query em municipalityPageData
- F2: computeAllMunicipalityPotentials memoizado por processo
- F3: TooltipProvider movido para o layout de (app)
- F4: DRY nos filtros multi do mobile em MunicipalityFilters
The B46 flex spacer never filled the scrollport because min-h-full did not propagate; h-full min-h-0 plus home-dock groups the thumb zone above bottom nav.
B58 hid the scrollbar but dropped mouse drag-to-scroll; pointer-fine
handlers pan past an 8px threshold while coarse touch keeps native pan-x.
Includes simplify pass (imperative data-dragging, coarse-pointer test)
and pin ratchet for municipalityElectoralBaseline bypass count.
Staff get six launchers with uncovered-municipalities linking to the sem_assessor list; leaders get two with contacts wired to the shared route constant.
Unifies Salvador vs RMS subgroup logic for territory rollups, aggregate class slugs, and the intra-TI capture benchmark so the MAUP-sensitive rule cannot drift across call sites.
Bookmarks the canonical list recorte beside Limpar, syncs via useSyncExternalStore, and matches active URLs with a pure href comparator so the app layout never imports the heavy URL serializer.
Wire CampaignListPendingBoundary/Results on /campanha/atividades/giros so TI navigation matches list pending UX; pin contract in tourRegionPending unit spec.
Research only — no roadmap items, no verticals, no code; validation with the real person gates everything (notebook: .cursor/rules/projects/emendas-mandato.mdc).
After B8 F2 the choropleth already opens each Salvador ZE; drop the textual list and zoneBreakdown from the bundle, keeping the mesh provenance caveat via hasZoneMunicipalities.
Staff sees a Flag + tooltip on the name column and mobile card instead of the destructive “Prioritária” chip, with copy centralized in municipalityLabels.
No product items registered yet — the 2026-07-29 session with the real gestora decides whether the finance track opens; pre-validation P0-P2 assessment lives in the project notebook.
Nothing left from the reviewers scored high enough to earn a roadmap item, so
the four discards are written down with their reasons instead — a discard whose
reason is missing comes back next session dressed as an obvious win. The one
worth keeping is the enrollment toast's third spelling of the failure copy: it
is deliberate, because that toast has no retry affordance and ending the
sentence in "Tente novamente." would be a false instruction.
Three engineering deferrals gained the trigger they lacked (shared HMAC core,
an optional `bodySchema` on the route shell, promoting `postJson`) — all three
are second-call-site abstractions, so the trigger is the third.
Also corrects two statements this delivery falsified: the notebook still said
`postJson` translates `SyntaxError`, which the simplify pass deleted, and the
roadmap's B40 item carried the pre-optimization 130 kB that its own header line
had already restated as 126 kB.
The rebase brought a convention guard that refuses a route.ts exporting POST
outside campaignJsonMutationRoute, and it named all four WebAuthn routes. They
now come from the shell, so the same-origin check is structural rather than
copied, and postJson delegates to postCampaignJson — keeping only what the
ceremonies add on top: the envelope's discriminant decides instead of the
status, and a non-JSON response reads as one sentence while a network failure
still propagates untouched. The two *-options routes have no body, hence
campaignWebAuthnNoBodySchema.