Fixes the unfilled "no-one's-land" holes left when the v0.14 coarsening merged sub-regions into bigger ones — the real problem behind the Moselle (FR) / Kočevje (SI) / Kavadartsi (MK) / Ağcabədi (AZ) holes.
Approach: new scripts/fill-gaps.mjs (npm fill:regions) uses each country's authoritative landmass (public/countries.geo.json, id=ISO_A3) as the reference. For every country it computes gaps = country_landmass − union(that country's regions) — exactly the no-one's-land — and assigns each gap to the nearest region of that country (each gap → one region, so regions never overlap). Sub-25 km² border-precision slivers are skipped; cross-border phantom overhang is clipped away.
Result:
All 1,796 regions are now solid / fully connected (verified: every named region and, globally, 1,793/1,796 collapse to a single connected polygon when their parts are unioned; 0 still fragmented). The added gap pieces touch the existing parts, so the holes are genuinely filled — not new floating fragments.
Total no-one's-land dropped ~3.9M → 63,889 km² (98.4%); the residual is coastline digitization fuzz plus the deliberately-kept KZ-KZY Aral-basin lake (it's water, excluded from the landmass, so it correctly stays a hole).
1,796 regions / all 177 countries / every id+name+parent unchanged; all 83 islands kept; no overlaps; idempotent.
File grew 2.29 → 3.40 MB (the touching pieces are stored as separate parts; a follow-up can dissolve each region to a single polygon to shrink it if the map feels heavy).
Map/LLM contract untouched — this only rewrites public/regions.geo.json geometry. Adds a dataset test (no significant no-one's-land per country + KZ-KZY hole present).
Part of #16
Fixes the unfilled "no-one's-land" holes left when the v0.14 coarsening merged sub-regions into bigger ones — the real problem behind the Moselle (FR) / Kočevje (SI) / Kavadartsi (MK) / Ağcabədi (AZ) holes.
**Approach:** new `scripts/fill-gaps.mjs` (npm `fill:regions`) uses each country's authoritative landmass (`public/countries.geo.json`, `id`=ISO_A3) as the reference. For every country it computes `gaps = country_landmass − union(that country's regions)` — exactly the no-one's-land — and assigns each gap to the nearest region of that country (each gap → one region, so regions never overlap). Sub-25 km² border-precision slivers are skipped; cross-border phantom overhang is clipped away.
**Result:**
- All **1,796 regions are now solid / fully connected** (verified: every named region and, globally, 1,793/1,796 collapse to a single connected polygon when their parts are unioned; 0 still fragmented). The added gap pieces *touch* the existing parts, so the holes are genuinely filled — not new floating fragments.
- Total no-one's-land dropped ~3.9M → 63,889 km² (98.4%); the residual is coastline digitization fuzz plus the deliberately-kept **KZ-KZY Aral-basin lake** (it's water, excluded from the landmass, so it correctly stays a hole).
- **1,796 regions / all 177 countries / every `id`+`name`+`parent` unchanged**; all 83 islands kept; no overlaps; idempotent.
- File grew 2.29 → 3.40 MB (the touching pieces are stored as separate parts; a follow-up can dissolve each region to a single polygon to shrink it if the map feels heavy).
Map/LLM contract untouched — this only rewrites `public/regions.geo.json` geometry. Adds a dataset test (no significant no-one's-land per country + KZ-KZY hole present).
Part of #16
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Part of #16
Fixes the unfilled "no-one's-land" holes left when the v0.14 coarsening merged sub-regions into bigger ones — the real problem behind the Moselle (FR) / Kočevje (SI) / Kavadartsi (MK) / Ağcabədi (AZ) holes.
Approach: new
scripts/fill-gaps.mjs(npmfill:regions) uses each country's authoritative landmass (public/countries.geo.json,id=ISO_A3) as the reference. For every country it computesgaps = country_landmass − union(that country's regions)— exactly the no-one's-land — and assigns each gap to the nearest region of that country (each gap → one region, so regions never overlap). Sub-25 km² border-precision slivers are skipped; cross-border phantom overhang is clipped away.Result:
id+name+parentunchanged; all 83 islands kept; no overlaps; idempotent.Map/LLM contract untouched — this only rewrites
public/regions.geo.jsongeometry. Adds a dataset test (no significant no-one's-land per country + KZ-KZY hole present).Part of #16