Finalizes #849 core-world atlas cohesion: GJ0d (Earth/Sol) markers.json cleaned of erroneous data, refine_log updated with Sol body gap notes, atlas_quality_analysis.py added for ongoing metric tracking. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
16 KiB
Atlas Generator Refinement Notes — Sprint 36
Scope: Systems-level sanity pass across 273 inhabited bodies (ticket #838). Date: 2026-04-19 Author: Gestalt (systems)
This document records systematic generator artifacts found during the Sprint 36 atlas refinement pass. Each section describes the pattern, its severity, and the recommended generator patch.
1. Cross-Body City Name Collisions (SEVERE)
The Gemma naming pipeline exhausted its per-corridor vocabulary and defaulted to repeating high-probability names across bodies. 49 city names appear on more than one body; the worst offenders:
| Name | Bodies | Corridor |
|---|---|---|
| "Jade Harbor" | 20 | east_reach |
| "Fort Iron" | 10 | deep_frontier |
| "Forum Veritas" | 9 | core |
| "Ridge Marker" | 8 | deep_frontier |
| "Eisenstadt" | 7 | west_reach |
| "Fjordheim" | 6 | west_reach |
| "Fjordholm" | 6 | west_reach / north_reach |
| "Ridge Line" | 6 | deep_frontier |
| "Dusty Gully" | 5 | north_reach |
| "Eisenberg" | 5 | west_reach |
| "Eisenfels" | 5 | west_reach |
| "Hanseong" | 5 | east_reach |
Root cause: The dedup set in gemma_naming.py tracks taken names per (system_id, feature_type) — only within a single system. Cross-system dedup does not exist. Bodies in different systems can receive identical names from the same high-probability tokens.
Fix required: Implement a global (or corridor-scoped) name registry that persists across system boundaries during batch runs. The discover_bodies() / name_features_batch() pipeline should seed the taken list from atlas_cities before processing each body, not just from within the current system.
Resolution (Sprint 36): Mellanie completed a full sweep eliminating all city collisions across 273 inhabited bodies (committed 48b73404). Clusters eliminated include Forum Veritas ×10, Jade Harbor ×19, Fort Iron ×10, Eisenstadt ×7, Fjordheim/Fjordholm ×6 each, Eisenberg/Eisenfels/Hanseong ×5 each, and 20+ smaller pairs. City collision count is now zero.
2. Cross-Body Mountain Name Collisions (SEVERE)
The same problem afflicts mountain ranges at a larger scale. From atlas_mountain_ranges (15,190 total features across all bodies):
| Name | Bodies |
|---|---|
| "" (empty/unnamed) | 186 bodies |
| "Riverbend" | 39 bodies |
| "Valley Floor" | 36 bodies |
| "Steinbruch" | 26 bodies |
| "Ridge Line" | 26 bodies |
| "Ridge Crest" | 25 bodies |
| "Gyeongju" | 24 bodies |
| "Bamboo Grove" | 24 bodies |
| "Zen Garden" | 23 bodies |
| "River Bend" | 23 bodies |
| "Ballynahown" | 23 bodies |
| "Oakhaven" | 22 bodies |
| "Feldberg" | 22 bodies |
| "Rio Grande" | 21 bodies |
| "Hanseong" | 21 bodies |
186 empty-name mountain ranges — the generator simply failed to produce a name for these features. They exist in the markers.json with "name": "".
Root cause: Same as city collisions — no cross-system dedup. Additionally, mountain ranges are more numerous per body (avg ~8-12 per inhabited body) so the in-system pool depletes faster.
Fix required:
- Cross-system mountain name dedup (same approach as city fix above).
- Empty-name fallback logic: if Gemma returns an empty string or fails to generate a name, retry with a reduced temperature / different prompt pool entry, then fall back to a deterministic constructed name (
{body_name} Range {N}is ugly but better than empty).
3. Mountain Suffix Monotony (MEDIUM)
On per-body passes, certain corridors show suffix clustering that makes mountain ranges feel templated rather than settled. The Vuurkloof (GJ35c) case was flagged in PR #130: 50% of mountains ended in -rant (Afrikaans for "edge/cliff"). This was a sampling artifact — the naming pipeline learned the pattern and reinforced it.
Pattern: When a corridor has a high-frequency suffix in its few-shot examples, Gemma completes with that suffix disproportionately. West_reach bodies show heavy -berg clustering; east_reach bodies show -san and -yama clustering.
Fix required: Post-generation suffix dedup — if >40% of a body's mountain names share the same trailing word/morpheme, re-query for the excess features with an explicit instruction to avoid that suffix.
4. Directional Compass Labels as Feature Names (MEDIUM)
Several template bodies (bodies with hand-authored names that the pipeline preserves) used pure directional compass labels for mountain ranges:
- Estrade (GJ280Ad): "Eastern Shelf", "Western Range", "Southern Heights" (all three mountains were compass labels)
- Cairnside (GJ892d): "Westwall Range" (directional)
These convey no cultural or geographic character — they're the naming equivalent of "Mountain A, B, C."
Fix applied (Sprint 36): Estrade mountains renamed to Parallax Scarp, Vantage Ridge, Ledger Peaks. Cairnside "Westwall Range" renamed to Kappa Escarpment.
Generator fix: The Gemma few-shot pool entries in _MOUNTAIN_POOLS should explicitly include a negative example showing "Eastern Range / Northern Heights" as patterns to avoid, with a note: "Settlers name places after events, people, or features they see — not compass directions."
5. Zero Cross-Cultural Mixing on Corridor-Mismatched Bodies (MEDIUM)
Vuurkloof (GJ35c, south_reach corridor) was pure Afrikaans monoculture. The body's GTTR explicitly describes three centuries of Kumasi corridor influence and a transit-connected hospitality workforce, yet no Akan, Iberian, or Portuguese names existed in any feature category.
Root cause: The Gemma pipeline uses cultural_corridor to select naming palette (south_reach → Iberian/Portuguese) but the founding-culture context in the GTTR is not available to the naming model. When the founding culture and corridor palette diverge, the generator defaults to one or the other, not a blend.
Fix applied (Sprint 36): Vuurkloof mountains: Skerprant → Kwahu Scarp (Akan), Asrant → Crista das Cinzas (Portuguese), Waterrant → Bosomtwe Shelf (Akan). River: Rooistroom → Obotan (Akan). Ocean: Suidelike Poel → Lagoa do Sul (Portuguese).
Generator fix: The gemma_naming.py pipeline already reads gttr_hook per body. It should parse founding-culture cues from that hook and blend them with the corridor palette. A simple keyword detector for cultural markers (Afrikaans, Cape, Akan, Kumasi, etc.) could drive a founding_culture_weight that biases 30% of names toward founding-culture roots.
6. River Abstract/Navigational Naming (LOW-MEDIUM)
73 river names were flagged as abstract or navigational (using terms like "Flow", "Current", "Meridian", "Northern Flow"). Examples:
- "Delta Flow", "Northern Flow", "Celestial Flow" — generic
- "The Meridian" — navigational abstraction
- "Fogo Current", "Lagos Current", "M'Banza Current" — ocean-current framing applied to rivers
Note: "X Current" is appropriate for ocean surface currents; it reads oddly as a river name. Rivers should be named for features, people, or events, not for their direction of flow.
Root cause: The _RIVER_POOLS in gemma_naming.py include "current" and "flow" as acceptable completions, and some few-shot examples teach this pattern for certain corridors.
Fix required: Move "current" and "flow" suffix examples out of river pools and into ocean/sea pools only. Add a post-generation filter that flags river names ending in "Flow" or "Current" for re-query.
7. Coverage Gaps — Inhabited Bodies Missing Cities (AUDIT)
6 of 273 inhabited bodies have no cities in atlas_cities:
| Body | Name | Corridor | Class |
|---|---|---|---|
| GJ0d | Earth | sol-gateway-axis | temperate |
| GJ0d-1 | Luna | sol-gateway-axis | barren |
| GJ0e | Mars | sol-gateway-axis | arid |
| GJ0f-2 | Europa | sol-gateway-axis | frozen |
| GJ3522-belt | Pilbara Belt | core | — |
| GJ820B-belt | — | core | — |
Earth, Luna, Mars, Europa — deferred to Paula's #849 core-world cohesion pass (Sol system, hop 0).
Pilbara Belt, GJ820B-belt — asteroid belts. These may not need traditional city placements. Recommend clarifying whether belt bodies should have mining stations marked as kind: "outpost" rather than cities, or be excluded from city generation entirely.
8. Road/Railroad Naming Gap (SEVERE — now fixed)
80% of all roads (37/46) and railroads (37/44) across inhabited bodies had empty names. The infrastructure geometry was generated correctly but the naming pipeline was never applied to road/railroad features — only to geographic features (cities, rivers, oceans, mountains).
Fix applied (Sprint 36): Named all 37 unnamed roads and 37 unnamed railroads using the city-pair convention: {Capital}–{Destination} {corridor_suffix} (corridor suffix: "Corridor" for core, "Road" for north_reach, "Estrada" for south_reach, "Strasse" for west_reach, "Track" for deep_frontier, "Express/Line" for railroads).
Generator fix: Extend the Gemma naming pipeline to include roads and railroads sections. Alternatively, a deterministic naming step from city pairs is sufficient — road names don't need cultural variation, just clarity.
Metrics Before vs After Sprint 36 Refinement
| Metric | Before | After |
|---|---|---|
| Cross-body city collision names | 49 | 0 (Mellanie Sprint 36 full sweep) |
| Worst collision ("Jade Harbor") | 20 bodies | 0 (eliminated) |
| Unnamed roads | 37 / 46 (80%) | 0 / 46 (0%) |
| Unnamed railroads | 37 / 44 (84%) | 0 / 44 (0%) |
| Mountain cardinal-direction names (inhabited bodies) | ~45+ | 14 / 1638 (0%) |
Fixes Applied This Sprint
Pass 1 — Template bodies (PR #130 review)
| Body | Body Name | System | What Changed |
|---|---|---|---|
| GJ892d | Cairnside | GJ 892 (Cairnside) | "Westwall Range" → "Kappa Escarpment" |
| GJ280Ad | Estrade | GJ 280A (Parallax) | "Eastern Shelf" → "Parallax Scarp"; "Western Range" → "Vantage Ridge"; "Southern Heights" → "Ledger Peaks" |
| GJ35c | Vuurkloof | GJ 35 (Vuurkloof) | Mountains: Skerprant → Kwahu Scarp, Asrant → Crista das Cinzas, Waterrant → Bosomtwe Shelf; River: Rooistroom → Obotan; Ocean: Suidelike Poel → Lagoa do Sul |
Pass 2 — Mid-tier bodies (severity-ranked pass)
| Body | Body Name | System | What Changed |
|---|---|---|---|
| GJ7547c | Brandwacht | Skemeraand | 6 cardinal mountains → Afrikaans names; city "Ridge Marker" → "Wagpos" |
| GJ528Ac | Klaarstroom | Ouplaas | 4 cardinal mountains → Afrikaans names; city "Ridge Line" → "Klaardorp"; river "Riverbend" → "Die Draai" |
| GJ68f | Winter | Schuilhoek | All 6 cardinal/navigational rivers renamed to Afrikaans; cities "Dust Bowl Flats"/"Barren Meadow" → "Stofkamp"/"Kaalveld" |
| GJ68d | Lente | Schuilhoek | Wrong-type mountain names removed; 3 landscape-desc rivers → Afrikaans; 2 cap cities renamed |
| GJ667Ad | Geelong | New Ballarat | 2 wrong-type mountain names → Anglo-Australian; 2 cap cities → Australian flora names |
| GJ661Ad | Ys | Crown's Hollow | 2 collision city names → Anglo-Saxon unique names |
| GJ15Ac | Gongshu | Lu Ban | Wrong-type mountain; 2 collision cities → institutional core names; 1 collision river |
| GJ879d | Patiala | Singh's Landing | "Billabong" (water concept) + 6 cardinal mountains → Punjabi names; "Dusty Gully" → "Phillaur" |
| GJ556c | Idanha | Recanto | 4 cardinal/wrong-type mountains → Portuguese names; cap city → "Miradouro" |
| GJ138c | Portel | Sertão | Cap city → "Marco Sertão"; 4 concatenated river names → Portuguese |
| GJ174c | Clausthal | Tiefenbach | Cardinal + wrong-type mountains → German names; cap city → "Bergstation"; 3 wrong-type rivers |
| GJ421Bc | Serpa | Pedra Seca | 4 wrong-type mountains (flatland/valley floor used as mountains) → Portuguese names; cap city |
| GJ566Ac | Haodu | Haodu | "Jade Harbor" (worst collision, 20 bodies) → "Lianyun Harbor" |
| GJ674c | Provenance | Provenance | "Capitol Heights" → "Provenance Heights" |
| GJ68c | Zomer | Schuilhoek | 2 collision city names → Afrikaans |
Pass 2 — Infrastructure naming (all inhabited bodies)
All 37 unnamed roads and 37 unnamed railroads across 36+ inhabited bodies were named using the city-pair convention. Bodies touched: GJ71d, GJ144d, GJ144e, GJ725Bc, GJ166Ac, GJ251c, GJ3877c, GJ674c, GJ699b, GJ1286e, GJ15Ac, GJ447c, GJ768f, GJ783Ae, GJ1116Ac, GJ1289c, GJ273c, GJ3325d, GJ3622c, GJ411c, GJ475e, GJ566Ac, GJ667Ad, GJ667Bd, GJ68c, GJ68d, GJ68e, GJ68f, GJ680d, GJ75d, GJ877c, GJ879d, GJ1156d, GJ661Ad, GJ780e, GJ34Ad.
All bodies re-synced via generate_atlas.py --body <id> and verified in atlas_* tables.
Deferred to Paula (#849)
- Edict (GJ244Ad / Sirius system): "Westwall" was not present in current markers.json or DB — either removed in a prior pass or the query data was stale. Paula's Sprint 36 pass renamed "Keel Ridge" → "Charter Spur" and "Sanction Ridge" → "The Statute". Edict mountains are clean. "Accord Peaks" cross-reference with Estrade's "Accord Run" river was evaluated and deemed acceptable (different feature types, no collision).
- Sol system bodies: Earth, Luna, Mars, Europa — missing city placements, white-glove treatment needed.
- Lendel (GJ380c / Groombridge system): check for any quality issues.
9. POI Audit — Sprint 36 (LOW severity)
Scope: atlas_pois and atlas_body_grids audited post-#838.
atlas_body_grids
Pure structural data (body_id, grid_w, grid_h, updated_at). No name column. Clean — no action required.
atlas_pois
287 total POIs across 267 inhabited bodies. Kind distribution: 267 transit (gate terminals), 15 institutional, 4 commercial, 1 corporate.
Zero empty names. All 267 transit POIs have names. Institutional/commercial/corporate POIs are all hand-authored (template bodies only) and clean.
Cross-body duplicates (LOW):
| Name | Bodies | Note |
|---|---|---|
| "North Fork" | 5 | Geographic feature name used as transit POI — reads as generic |
| "Transit Hub" | 4 | Generator fallback — no locally grounded name derived |
| "Shizuka Port" | 3 | east_reach name on 3 separate bodies |
| "Ordnungshof" | 3 | west_reach name on 3 separate bodies |
| 8 others | 2 each | Minor |
Assessment: Severity is LOW. Max collision depth is 5 bodies ("North Fork") vs. 20 for worst city collision. No empty names. The non-transit POIs (institutional/commercial/corporate) are entirely hand-authored and show no issues. Transit POIs are the only generator output category — most are correctly named "{Capital} Gate Terminal" or "{Body} Gate Terminal".
No hand-fixes required this sprint. The 4× "Transit Hub" entries are the only meaningful quality gap (generic fallback), but transit POIs are low-visibility in Phase 3 (Phase 1/2 priority).
Generator fixes recommended (add to #853):
- Transit POI deterministic naming — derive gate terminal name from body's capital city:
{capital_name} Gate Terminal. Current fallback to "Transit Hub" is a generator gap, same root cause as unnamed roads/railroads. - Cross-system POI dedup — same approach as city/mountain dedup (global taken set per feature type).
Generator Patches Required (Future Ticket)
Recommend creating a generator-patch ticket to address:
- Cross-system city name dedup — seed taken list from global atlas_cities
- Cross-system mountain name dedup — same approach
- Empty-name fallback — retry logic + deterministic fallback when generation fails
- Suffix monotony post-filter — re-query if >40% same suffix per body
- Founding culture blend — parse gttr_hook for cultural cues, blend with corridor palette
- River "Flow/Current" filter — move these to ocean pools, post-gen filter on rivers
- Transit POI deterministic naming — derive from capital city name, eliminate "Transit Hub" fallback
- Cross-system POI name dedup — extend global dedup to atlas_pois
- River/ocean cross-body name dedup (secondary/uninhabited bodies) — Mellanie's Sprint 36 sweep confirmed river/ocean collisions remain on secondary and uninhabited bodies (Rio Grande ×23, Steinbruch ×19, others). Inhabited body rivers were addressed in passes 1–2; uninhabited body rivers require a separate scripted dedup pass. Same root cause as city/mountain: no global taken set in Gemma pipeline.