mirror of
https://github.com/fsolla/teqo.git
synced 2026-11-13 23:53:05 +00:00
Document B2 map geometries as-built delivery and helpers.
This commit is contained in:
parent
f04dbe07f9
commit
8e0ee43844
4 changed files with 40 additions and 10 deletions
|
|
@ -11,8 +11,8 @@ alwaysApply: false
|
|||
- **Ciclo 2 entregue, mesclado e deployado (2026-07-18):** A1 território multi-município/bairro, A3 baseline TSE 2022 (modelo + import), B1 overview da lista, C1 compartilhar página e D1 PWA — detalhes no item datado abaixo.
|
||||
- **A2 entregue e mesclado em `main` (2026-07-18):** cadastro estático município↔ZE (`bahiaTseZones`, TSE 2024) + chips opt-in no formulário (`NucleusTerritoryAndZonesFields` / `territorySuggestions`); sem migration. Plano: [`docs/plans/zonas-por-municipio.md`](../../../docs/plans/zonas-por-municipio.md).
|
||||
- **C3 Planos de Ação implementado (2026-07-18):** collection `actionPlan` + vertical `/campanha/planos` (lista com tabs Próximos/Todos/Realizados/Rascunhos, detalhe com tabs Visão geral/Tarefas/Atualizações, forms novo/editar), blocos "Próximos eventos" no overview de núcleos e no dashboard; `startAt` opcional só em rascunho; access por `coordinators`/`leadership`; migration `20260718_222832_add_action_plan`.
|
||||
- **B2 Mapa Fase 1 (geometrias) entregue (2026-07-18):** TopoJSON estático municípios IBGE + TIs por dissolução, `bahiaMunicipalityCodes`, helpers `bahiaGeometries`, script `pnpm build:geometries`. Sem UI (B3). Plano: [`docs/plans/mapa-bahia-geometrias.md`](../../../docs/plans/mapa-bahia-geometrias.md).
|
||||
- **B5 registrado (2026-07-18):** débitos de escala/DRY pós-B2 do `/simplify` (lazy load de geometrias mun/TI + helper `ensureCachedDownload` para CLIs) — plano [`docs/plans/escala-dry-pos-b2.md`](../../../docs/plans/escala-dry-pos-b2.md); F1 preferencialmente com B3; F2 cortável.
|
||||
- **B2 Mapa Fase 1 (geometrias) entregue (2026-07-18):** TopoJSON estático municípios IBGE (`bahia-municipalities.topo.json`, ~132 KB, object `municipalities`) + TIs por dissolução (`bahia-identity-territories.topo.json`, ~15 KB, object `territories`); tabela `bahiaMunicipalityCodes` + `codeForMunicipality` / `municipalityForCode`; helpers `bahiaGeometries` (`getMunicipalityFeature` / `getTerritoryFeature`); script re-executável `pnpm build:geometries` (cache `data/geometries/`, sem DB); testes int de bijeção/cobertura/teto de bytes. Sem migration, sem UI (Leaflet = B3). Plano as-built: [`docs/plans/mapa-bahia-geometrias.md`](../../../docs/plans/mapa-bahia-geometrias.md).
|
||||
- **B5 registrado (2026-07-18):** débitos de escala/DRY pós-B2 do `/simplify` que não entraram no cleanup (lazy load mun/TI + helper `ensureCachedDownload` para `build:geometries` / `db:seed:tse`) — plano [`docs/plans/escala-dry-pos-b2.md`](../../../docs/plans/escala-dry-pos-b2.md); F1 preferencialmente com B3; F2 cortável.
|
||||
- **C7 registrado (2026-07-18):** débitos de escala/DRY pós-C3 do `/simplify` (território/contato compostos, helpers FormData/URL, leituras por aba, RMW/índice) — plano [`docs/plans/escala-dry-pos-c3.md`](../../../docs/plans/escala-dry-pos-c3.md); não bloqueia o MVP da agenda.
|
||||
- Fluxos operacionais cobertos: login isolado, CRUD/arquivo de núcleos por slug, designação de coordenador (`geral`), CRM de lideranças, estimativas sugerir/confirmar com versão UUID, feed de atualizações, convites WhatsApp (`wa.me` + hash de uso único), dashboard com agregados só de núcleos ativos.
|
||||
- Pendência operacional (não de código): Consent `lideranca-autopreenchimento` + lote jurídico LGPD antes de dados reais; smoke pós-deploy Vercel. Ver Onda 0 em [`docs/roadmap.md`](../../../docs/roadmap.md).
|
||||
|
|
@ -93,6 +93,7 @@ alwaysApply: false
|
|||
- Em 2026-07-17, decisão de produto: `Município` e `Bairro` do Núcleo passam a aceitar múltiplas entradas (arrays planos `cities`/`neighborhoods`), e `region` vira `regions` derivado no servidor a partir dos municípios, permitindo cruzar Territórios de Identidade. Bairros exigem município único. Modelo A (arrays planos) escolhido em vez de array estruturado por município. Plano: [`docs/plans/territorio-multi-municipio-bairro.md`](../../../docs/plans/territorio-multi-municipio-bairro.md); item do roadmap: A1.
|
||||
- Em 2026-07-18, decisão de produto (revisão A2): no formulário de território, sugestões cruzadas **opt-in** via chips `{rótulo} +` (município/TI → união de ZEs faltantes; TI → municípios irmãos; ZE → municípios oficiais), em vez do auto-preenchimento forçado + Zonas TSE read-only da versão 2026-07-17 do plano. TI a partir do município continua derivado (A1). Cadastro estático município↔zona (`bahiaTseZones`) permanece. Plano: [`docs/plans/zonas-por-municipio.md`](../../../docs/plans/zonas-por-municipio.md); item do roadmap: A2.
|
||||
- Em 2026-07-18, **A2 entregue e mesclado em `main`:** `src/lib/bahiaTseZones.ts` (TSE 2024 `detalhe_votacao_munzona` BA, fixture `bahia-tse-zones.official.json`, índices módulo `citiesByZone` / `zonesByTerritory`), `territorySuggestions.ts` (`buildTerritorySuggestions` com `outsideZones`), `TerritorySuggestionChips` + `NucleusTerritoryAndZonesFields` no formulário; `TseZoneInput` só controlado (`value`/`onChange`); aviso âmbar opcional para ZE fora do cadastro da geografia; alias `NucleusTerritoryFields` removido; sem migration.
|
||||
- Em 2026-07-18, **B2 entregue (fundação de geometrias do mapa):** malhas IBGE qualidade intermediaria → TopoJSON versionado; TIs por `merge` da composição oficial (não shapefile IDE Bahia); extensão `*.topo.json`; reconciliação de nomes via `canonicalizeMunicipalityName`; script sem guard de banco; cleanup `/simplify` barato no mesmo PR; follow-ups de escala → B5.
|
||||
- Em 2026-07-18, **A1 entregue:** `regions`/`cities`/`neighborhoods` como `text` + `hasMany` (tabela `electoral_nucleus_texts`); migration `20260718_190559_territorio_multi_municipio_bairro` com backfill; filtros da lista permanecem single-select na URL e consultam com `{ equals }` (associação ao array — não o operador substring `contains`); UI de `/campanha` com chips multi + bairros só com 1 município; dashboard e criação de liderança atualizados (`Contact.city` só quando `cities.length === 1`).
|
||||
- O DTO paginado de atualizações contém somente filtro/paginação/feed; a visão geral chama um loader dedicado que busca `limit: 3` e apenas os autores necessários à prévia.
|
||||
- A lista paginada de lideranças seleciona e serializa somente os campos da linha; avaliação interna e dados completos de contato são carregados apenas para a liderança selecionada. O fechamento usa `onCloseAutoFocus` no Sheet e `finalFocus` no Drawer, focaliza a linha de origem (ou o título do Núcleo) antes de navegar para a URL canônica, sem RAF/timeout.
|
||||
|
|
|
|||
16
AGENTS.md
16
AGENTS.md
|
|
@ -40,7 +40,7 @@ Backlog consolidado (bloqueadores, site, campanha, white-label): [`docs/roadmap.
|
|||
3. **`Post`/`Tag` ship the news system, but there is still no `Pages` collection for institutional content.** Partly resolved: the `post`/`tag` collections back the news/publications system, and the home "Últimas notícias" list plus the `/[type]`, `/[type]/[category]`, and article routes are live (see "Posts & Tags" below). Still hardcoded/pending: the home hero heading + subtitle copy (`HomePage` global still exposes only a single `image` field — the text lives in `src/app/(frontend)/(home)/page.tsx`), and there is no `Pages` collection yet for institutional content such as the bio and propostas.
|
||||
4. **Campaign LGPD consent texts are not yet configured in production.** Invites and self-service leadership flows fail closed until an admin creates `Consent.key = 'lideranca-autopreenchimento'` with counsel-approved copy. The C2 supporter registry (merged to `main`, production-blocked) additionally requires `Consent.key = 'apoiador-cadastro'` and `Consent.key = 'apoiador-intencao-voto'` (vote intention is sensitive data) — same fail-closed behavior. All four keys are bundled in the single legal batch of Onda 0 (see deploy checklist).
|
||||
|
||||
**Recently resolved (2026-07-18):** the `/campanha` nuclei MVP shipped (auth/RBAC, nuclei, leaderships, vote estimates, updates, WhatsApp invites, dashboard) with consolidated migration `20260718_010733_consolidate_campaign_schema`. Later the same day, cycle 2 was merged and deployed: multi-municipality/neighborhood territory arrays (migration `20260718_190559_territorio_multi_municipio_bairro`), TSE 2022 election baseline collections + `pnpm db:seed:tse` (migration `20260718_195854_add_election_results`), the filtered nuclei-list overview panel, the nucleus share dialog, and the installable `/campanha` PWA. Still on 2026-07-18, **A2** shipped: static Bahia municipality↔TSE zone map (`src/lib/bahiaTseZones.ts` from TSE 2024 `detalhe_votacao_munzona` BA) plus opt-in territory/zone suggestion chips in the nucleus form (`territorySuggestions`, `NucleusTerritoryAndZonesFields`) — no migration, no forced equality on save. Also the same day: **C2** Cadastro nominal de apoiadores (`supporter` join `Contact`↔campanha with optional `nucleus`, migration `20260718_222656_add_supporter` with `UNIQUE NULLS NOT DISTINCT (contact_id, nucleus_id)`, consent keys `apoiador-cadastro` / `apoiador-intencao-voto` resolved via a generalized `campaignConsent.ts` that fails closed, `/campanha/apoiadores` vertical with list+KPIs/detail/CSV-import wizard; phone required in v1, `lideranca` has no access to the area; production use with real data still waits on Consent keys + legal sign-off). Also the same day: C3 Planos de Ação (`actionPlan` + `/campanha/planos`, migration `20260718_222832_add_action_plan`, blocos "Próximos eventos"). Earlier (2026-07-15): local Postgres via `docker-compose.yml` (Postgres 17, `teqo_test`); Payload migrations baselined; dev/test database guards; `post`/`tag` news routes deployed (see "Posts & Tags" below).
|
||||
**Recently resolved (2026-07-18):** the `/campanha` nuclei MVP shipped (auth/RBAC, nuclei, leaderships, vote estimates, updates, WhatsApp invites, dashboard) with consolidated migration `20260718_010733_consolidate_campaign_schema`. Later the same day, cycle 2 was merged and deployed: multi-municipality/neighborhood territory arrays (migration `20260718_190559_territorio_multi_municipio_bairro`), TSE 2022 election baseline collections + `pnpm db:seed:tse` (migration `20260718_195854_add_election_results`), the filtered nuclei-list overview panel, the nucleus share dialog, and the installable `/campanha` PWA. Still on 2026-07-18, **A2** shipped: static Bahia municipality↔TSE zone map (`src/lib/bahiaTseZones.ts` from TSE 2024 `detalhe_votacao_munzona` BA) plus opt-in territory/zone suggestion chips in the nucleus form (`territorySuggestions`, `NucleusTerritoryAndZonesFields`) — no migration, no forced equality on save. Also the same day: **C2** Cadastro nominal de apoiadores (`supporter` join `Contact`↔campanha with optional `nucleus`, migration `20260718_222656_add_supporter` with `UNIQUE NULLS NOT DISTINCT (contact_id, nucleus_id)`, consent keys `apoiador-cadastro` / `apoiador-intencao-voto` resolved via a generalized `campaignConsent.ts` that fails closed, `/campanha/apoiadores` vertical with list+KPIs/detail/CSV-import wizard; phone required in v1, `lideranca` has no access to the area; production use with real data still waits on Consent keys + legal sign-off). Also the same day: C3 Planos de Ação (`actionPlan` + `/campanha/planos`, migration `20260718_222832_add_action_plan`, blocos "Próximos eventos"). Also the same day: **B2** map foundation — static TopoJSON for Bahia municipalities + identity territories, `bahiaMunicipalityCodes`, helpers in `bahiaGeometries`, re-runnable `pnpm build:geometries` (no migration, no UI; Leaflet is B3). Post-`/simplify` scale follow-ups for that delivery are registered as **B5** (`docs/plans/escala-dry-pos-b2.md`). Earlier (2026-07-15): local Postgres via `docker-compose.yml` (Postgres 17, `teqo_test`); Payload migrations baselined; dev/test database guards; `post`/`tag` news routes deployed (see "Posts & Tags" below).
|
||||
|
||||
## Posts & Tags (news / publications)
|
||||
|
||||
|
|
@ -94,7 +94,7 @@ The first `/campanha` operational cycle is centered on `electoralNucleus`; a Nú
|
|||
|
||||
- **Collections:** `electoralNucleus` (territory, coordinators, TSE zone references, intelligence and vote estimates), `leadership` (unique `Contact`↔nucleus join with support status), `nucleusUpdate` (immutable field reports), and `campaignInvite` (single-use WhatsApp invite hashes). All are in admin group `Campanha`.
|
||||
- **Canonical nucleus URLs:** nuclei use a unique canonical `slug` generated from `name` and route through `/campanha/nucleos/[slug]`. IDs stay internal. Names are immutable after creation so existing shared links remain durable without an alias table.
|
||||
- **Territory:** Bahia is implicit. Since 2026-07-18 nuclei use `hasMany` arrays `regions` / `cities` / `neighborhoods` (plus `locality` / `territoryNotes`), validated against official Bahia identity territories (`src/lib/bahiaTerritories.ts`): `regions` is derived server-side from the selected cities, and neighborhoods require exactly one city. List filters stay single-select and query array membership with `{ equals }`. Migration `20260718_190559_territorio_multi_municipio_bairro` backfilled the old scalar fields (`docs/plans/territorio-multi-municipio-bairro.md`). **A2 (2026-07-18):** static municipality↔TSE zone map in `src/lib/bahiaTseZones.ts` (`tseZonesForCity` / `tseZonesForTerritory` / `citiesForTseZone`); the create/edit form coordinator `NucleusTerritoryAndZonesFields` offers opt-in `{label} +` chips from `buildTerritorySuggestions` (city/TI → missing zones; TI siblings and zone cities → municipalities). Manual `TseZoneInput` stays free (1–999); server validation does not require `tseZones` to match the official set; an amber client advisory may warn when a typed zone is outside the selected geography. Details: `docs/plans/zonas-por-municipio.md`.
|
||||
- **Territory:** Bahia is implicit. Since 2026-07-18 nuclei use `hasMany` arrays `regions` / `cities` / `neighborhoods` (plus `locality` / `territoryNotes`), validated against official Bahia identity territories (`src/lib/bahiaTerritories.ts`): `regions` is derived server-side from the selected cities, and neighborhoods require exactly one city. List filters stay single-select and query array membership with `{ equals }`. Migration `20260718_190559_territorio_multi_municipio_bairro` backfilled the old scalar fields (`docs/plans/territorio-multi-municipio-bairro.md`). **A2 (2026-07-18):** static municipality↔TSE zone map in `src/lib/bahiaTseZones.ts` (`tseZonesForCity` / `tseZonesForTerritory` / `citiesForTseZone`); the create/edit form coordinator `NucleusTerritoryAndZonesFields` offers opt-in `{label} +` chips from `buildTerritorySuggestions` (city/TI → missing zones; TI siblings and zone cities → municipalities). Manual `TseZoneInput` stays free (1–999); server validation does not require `tseZones` to match the official set; an amber client advisory may warn when a typed zone is outside the selected geography. Details: `docs/plans/zonas-por-municipio.md`. **B2 (2026-07-18):** static map geometries — see "Campaign map geometries (B2)" below (Leaflet surfaces are B3).
|
||||
- **Role scope:** `geral` sees/manages all nuclei, assigns coordinators, and confirms estimates; `coordenador` sees assigned nuclei and manages their leaderships, updates, invites, and estimates; `lideranca` sees only nuclei linked through an engaged leadership record, creates own updates, and suggests estimates.
|
||||
- **Sensitive fields:** `leadership.supportStatus`, internal notes, consent notes, and strategic nucleus intelligence are staff-only and are excluded from leadership view models. Revoking `engajado` revokes nucleus access immediately. Dashboard aggregates omit Payload-redacted missing statuses and fail closed on invalid enum values.
|
||||
- **People and consent:** leaderships always reuse `Contact`; multi-collection writes are transactional. Self-service updates accept a strict whitelist derived from the invite token. Campaign consent is looked up only by the stable key `lideranca-autopreenchimento`.
|
||||
|
|
@ -123,6 +123,16 @@ Mobilization events / agenda backing the campaign's field operations (roadmap it
|
|||
- **Access.** `geral` everything; `coordenador` where listed in `coordinators` (may create, auto-included); `lideranca` where `leadership` ∈ engaged — write limited to toggling `tasks.done` and appending `updates`. Domain writes go through `withPayloadTransaction` (`src/utilities/payloadTransaction.ts`).
|
||||
- **UI** `/campanha/planos` — list with tabs Próximos (default) / Todos / Realizados / Rascunhos, filters (kind, territory), cards with kind/status badge + date/time + municipality + TI chip + "Resp:" + task progress; detail with tabs Visão geral / Tarefas / Atualizações (pattern `NucleusTabNav`); new/edit forms. "Próximos eventos" blocks surface on the nuclei list overview and the dashboard.
|
||||
|
||||
## Campaign map geometries (B2)
|
||||
|
||||
Static Bahia map foundation for future Leaflet surfaces (roadmap B2; UI is B3). No migration, collection, Consent, or server action — same static-data pattern as `bahiaTerritories` / `bahiaTseZones`.
|
||||
|
||||
- **Artifacts (committed):** `src/lib/geometries/bahia-municipalities.topo.json` (~132 KB; Topology object `municipalities`, 417 features, `properties: { codarea, name }`) and `src/lib/geometries/bahia-identity-territories.topo.json` (~15 KB; object `territories`, 27 features, `properties: { code, name }`). Soft size budget in tests: ≤ ~600 KB each.
|
||||
- **Code table:** `src/lib/bahiaMunicipalityCodes.ts` — canonical municipality name → IBGE 7-digit `codarea`, plus `codeForMunicipality` / `municipalityForCode`. Fixture `tests/fixtures/bahia-municipality-codes.official.json` + int tests for bijection/coverage.
|
||||
- **Runtime helpers:** `src/lib/bahiaGeometries.ts` — `getMunicipalityFeature` / `getTerritoryFeature`, typed topologies, feature arrays. Eagerly decodes TopoJSON→GeoJSON at module load (lazy split is B5 F1 — prefer with B3).
|
||||
- **Territory polygons:** dissolved from IBGE municipality meshes via `bahiaIdentityTerritoryRecords` (`topojson` `merge`), not the IDE Bahia shapefile (IDE remains provenance/validation reference only).
|
||||
- **Rebuild:** `pnpm build:geometries` (`scripts/build-bahia-geometries.mjs`) downloads IBGE Malhas (qualidade intermediaria) + Localidades, reconciles names with `canonicalizeMunicipalityName`, simplifies/quantizes, emits the artifacts above. Cache under `data/geometries/` (gitignored; override with `GEOMETRIES_CACHE_DIR`). **Does not touch the database** — no `assertLocalDatabase` / no Neon risk. Not part of `pnpm build` or `pnpm dev`. Details: `docs/plans/mapa-bahia-geometrias.md`. Scale/DRY follow-ups from `/simplify`: `docs/plans/escala-dry-pos-b2.md` (B5).
|
||||
|
||||
## Election baseline data (TSE 2022)
|
||||
|
||||
Public TSE 2022 results back the electoral baseline (roadmap item A3; UI lands with A4). Three collections in admin group `Dados Eleitorais`: `electionTally` (per city×zone totals: eligible voters, turnout, valid/blank/null votes), `electionCandidateVote` (nominal votes per candidate×city×zone), and `electionCandidate` (candidate registry with a cross-year `identityKey` hash — no CPF or voter ID is ever persisted). Read access requires an authenticated `campaignUser` or `users` account (`canReadElectionData`); writes are Payload-admin-only, and the import runs via CLI with `overrideAccess: true`.
|
||||
|
|
@ -166,7 +176,7 @@ src/
|
|||
├── collections/ # Users, CampaignUser, CampaignInvite, ElectoralNucleus, Leadership, NucleusUpdate, Supporter, ActionPlan, ElectionTally, ElectionCandidateVote, ElectionCandidate, Media, Petition, Signature, Consent, Contact, Subscription, Post, Tag
|
||||
├── globals/ # Global configs (SiteSettings, HomePage, Metadata)
|
||||
├── components/ # Custom React components (campaign/*, ui from shadcn)
|
||||
├── lib/ # cities.ts, bahiaTerritories.ts, bahiaTseZones.ts, territorySuggestions.ts, formData.ts, zod schemas (lib/schemas/*)
|
||||
├── lib/ # cities.ts, bahiaTerritories.ts, bahiaTseZones.ts, bahiaMunicipalityCodes.ts, bahiaGeometries.ts, geometries/*.topo.json, territorySuggestions.ts, formData.ts, zod schemas (lib/schemas/*)
|
||||
├── utilities/ # campaign*, nucleus*, posts, documents, globals, locks, etc.
|
||||
└── payload.config.ts # Main config
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Escala e DRY pós-B2 (geometrias + scripts CLI)
|
||||
|
||||
Status: rascunho
|
||||
Status: registrado no roadmap (fases pendentes)
|
||||
Atualizado em: 2026-07-18
|
||||
Item do roadmap: [docs/roadmap.md](../roadmap.md) (Trilha B, item B5)
|
||||
Responsável: —
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ Hierarquia TSE: município → (1+) zona → (muitas) seção; a relação munic
|
|||
- **Join por chave estável:**
|
||||
- Municípios: o núcleo guarda `cities[]` (array de nomes, desde A1). Tabela `src/lib/bahiaMunicipalityCodes.ts` (nome canônico → código IBGE de 7 dígitos) + fixture `tests/fixtures/bahia-municipality-codes.official.json` + teste `tests/int/bahiaMunicipalityCodes.int.spec.ts`. Reconciliação IBGE→canônico via `canonicalizeMunicipalityName` (`src/lib/electionResults.ts`).
|
||||
- Territórios: join por `code` (01–27) já presente em `bahiaIdentityTerritoryRecords`; sem tabela extra.
|
||||
- **Helpers:** `src/lib/bahiaGeometries.ts` — `getMunicipalityFeature(codarea)`, `getTerritoryFeature(code)`, topologias tipadas (framework-free para B3).
|
||||
- **Proveniência e versionamento:** cada artefato com cabeçalho/documentação de proveniência (URL, SHA-256 do download de origem), no estilo de `bahiaTerritories.ts` / `bahiaTseZones.ts`.
|
||||
- **Helpers:** `src/lib/bahiaGeometries.ts` — `getMunicipalityFeature(codarea)`, `getTerritoryFeature(code)`, arrays `bahiaMunicipalityFeatures` / `bahiaTerritoryFeatures`, topologias tipadas (`bahiaMunicipalitiesTopology` / `bahiaIdentityTerritoriesTopology`; objects `municipalities` / `territories`). Framework-free para B3. Lookups de código: `codeForMunicipality` / `municipalityForCode` em `bahiaMunicipalityCodes.ts`.
|
||||
- **Proveniência e versionamento:** cabeçalho em `bahiaMunicipalityCodes.ts` + script (URL + SHA-256 dos downloads IBGE), no estilo de `bahiaTerritories.ts` / `bahiaTseZones.ts`.
|
||||
|
||||
## Script de geração (one-off, re-executável)
|
||||
|
||||
- `scripts/build-bahia-geometries.mjs` (`pnpm build:geometries`): baixa IBGE Malhas + Localidades, reconcilia nomes, constrói topologia com `topojson-server` + `topojson-simplify` + `quantize`, dissolve territórios com `topojson-client` `merge`, emite os `*.topo.json`, `bahiaMunicipalityCodes.ts` e o fixture. Cache em `data/geometries/` (gitignored). **Não toca banco** — sem `assertLocalDatabase`. Não roda em build/dev — só quando se atualiza a versão de origem.
|
||||
- `scripts/build-bahia-geometries.mjs` (`pnpm build:geometries`): baixa IBGE Malhas + Localidades (via `downloadToBuffer` de `electionResultsZip.ts`), reconcilia nomes com `canonicalizeMunicipalityName` (só `UnknownMunicipalityError`), constrói topologia com `topojson-server` + `topojson-simplify` (`SIMPLIFY_QUANTILE = 0.35`) + `quantize` (`1e4`), dissolve territórios com `topojson-client` `merge`, emite os `*.topo.json`, `bahiaMunicipalityCodes.ts` e o fixture. Cache em `data/geometries/` (gitignored; `GEOMETRIES_CACHE_DIR`). **Não toca banco** — sem `assertLocalDatabase`. Não roda em build/dev — só quando se atualiza a versão de origem.
|
||||
|
||||
## Leaflet na campanha (B3 — pendente)
|
||||
|
||||
|
|
@ -74,6 +74,21 @@ Hierarquia TSE: município → (1+) zona → (muitas) seção; a relação munic
|
|||
|
||||
**Sequenciamento:** a Fase 1 é independente e paralelizável. A Fase 2 rende mais depois de B1 ✓ (overview) e ganha valor com A4 (baseline no produto). Nenhum dos dois bloqueia B3 — o mapa funciona só com estimativa/nº de núcleos. B5 F1 é dependência suave de qualidade de bundle.
|
||||
|
||||
## Entrega as-built (B2, 2026-07-18)
|
||||
|
||||
| Artefato | Caminho | Notas |
|
||||
| -------- | ------- | ----- |
|
||||
| TopoJSON municípios | `src/lib/geometries/bahia-municipalities.topo.json` | ~132 KB; 417 features; object `municipalities` |
|
||||
| TopoJSON TIs | `src/lib/geometries/bahia-identity-territories.topo.json` | ~15 KB; 27 features; object `territories` (dissolução IBGE) |
|
||||
| Tabela nome→`codarea` | `src/lib/bahiaMunicipalityCodes.ts` | + `codeForMunicipality` / `municipalityForCode` |
|
||||
| Helpers runtime | `src/lib/bahiaGeometries.ts` | `topojson-client` `feature()` + Maps no load do módulo |
|
||||
| Fixture oficial | `tests/fixtures/bahia-municipality-codes.official.json` | evidence SHA + bijeção |
|
||||
| Testes int | `tests/int/bahiaMunicipalityCodes.int.spec.ts`, `tests/int/bahiaGeometries.int.spec.ts` | cobertura 417/27, teto de bytes, nomes de objects via módulo |
|
||||
| Script | `scripts/build-bahia-geometries.mjs` | `pnpm build:geometries`; deps: `topojson-client` (runtime), `topojson-server` / `topojson-simplify` (dev) |
|
||||
| Cache | `data/geometries/` | gitignored |
|
||||
|
||||
**Cleanup `/simplify` já aplicado no PR da Fase 1:** reuso de `downloadToBuffer`; catch só de `UnknownMunicipalityError`; remoção de dead code de codegen (`stableStringifyTopo` enganoso, tipo `BahiaMunicipalityCode` não usado). **Não aplicado (→ B5):** lazy load split mun/TI; helper CLI compartilhado `ensureCachedDownload`.
|
||||
|
||||
## Ciclo seguinte — Zonas TSE como camada (B4)
|
||||
|
||||
Após A2 ✓ + B3. Polígono por dissolução dos municípios membros (abordagem A, default — já validada na Fase 1 para TIs) ou por geocodificação dos endereços das seções → casco (abordagem B, questão em aberto). Ponto representativo por centroide da zona.
|
||||
|
|
@ -103,10 +118,14 @@ Após A2 ✓ + B3. Polígono por dissolução dos municípios membros (abordagem
|
|||
|
||||
## Referências
|
||||
|
||||
- `docs/roadmap.md` (B2 / B3 / B4 na trilha B)
|
||||
- `docs/roadmap.md` (B2 / B3 / B4 / B5 na trilha B)
|
||||
- `docs/plans/escala-dry-pos-b2.md` (follow-ups pós-`/simplify`)
|
||||
- AGENTS.md — seção "Campaign map geometries (B2)"
|
||||
- `src/lib/bahiaTerritories.ts` + `tests/fixtures/bahia-identity-territories.official.json` + `tests/int/bahiaTerritories.int.spec.ts` (padrão a espelhar)
|
||||
- `src/lib/bahiaMunicipalityCodes.ts`, `src/lib/bahiaGeometries.ts`, `src/lib/geometries/*.topo.json`
|
||||
- `src/lib/electionResults.ts` (`canonicalizeMunicipalityName`), `src/lib/electionResultsZip.ts` (`downloadToBuffer`)
|
||||
- `scripts/build-bahia-geometries.mjs`
|
||||
- `tests/int/bahiaMunicipalityCodes.int.spec.ts`, `tests/int/bahiaGeometries.int.spec.ts`
|
||||
- `src/collections/ElectoralNucleus.ts`, `src/utilities/campaignDashboardPageData.ts`, `src/utilities/nucleusViewModels.ts`, `src/utilities/nucleusListOverviewPageData.ts` (agregados a reusar no B3)
|
||||
- `docs/plans/zonas-por-municipio.md` (dependência da camada de Zonas)
|
||||
- `docs/plans/baseline-eleitoral-tse.md` (baseline por zona, consumidor do mapa)
|
||||
|
|
|
|||
Loading…
Reference in a new issue