Merge remote-tracking branch 'origin/sprint-36/copy'
This commit is contained in:
@@ -501,7 +501,7 @@ You are now the team lead. Agents work autonomously — monitor via
|
||||
they arise.
|
||||
|
||||
**When all tasks complete:** Do NOT shut down agents. The team stays
|
||||
alive through the PR review cycle. Follow step 9 (post-work lifecycle).
|
||||
alive through PR review AND merge. Follow step 9 (post-work lifecycle).
|
||||
|
||||
### 9. Post-work lifecycle
|
||||
|
||||
@@ -510,7 +510,8 @@ When all tasks are complete (TaskList shows all completed):
|
||||
#### 9a. Commit and push
|
||||
|
||||
Run `/git-commit` to commit all changes, then `/pr-push` to create or
|
||||
update the PR. Do NOT shut down agents — the team stays alive for review.
|
||||
update the PR. Do NOT shut down agents — the team stays alive through
|
||||
review and merge.
|
||||
|
||||
#### 9b. Wait for review
|
||||
|
||||
@@ -554,10 +555,28 @@ comments):
|
||||
|
||||
5. Repeat this loop until review returns APPROVED.
|
||||
|
||||
**If APPROVED:**
|
||||
**If APPROVED (but not yet merged):**
|
||||
|
||||
Do NOT shut down. Approval alone is not terminal — reviewers can leave
|
||||
follow-up comments, the PR can be re-reviewed, or merge conflicts can
|
||||
surface. Keep the team alive and idle until the PR is merged into main.
|
||||
|
||||
1. Report to the user: "Sprint {N} {team} PR #{X} approved. Awaiting
|
||||
merge. Team remains alive."
|
||||
2. Agents stay idle. Do not reassign them to unrelated work.
|
||||
3. Periodically check merge state (or wait for the user to confirm the
|
||||
merge). The `main` session handles the merge itself.
|
||||
4. If new review comments arrive between approval and merge, treat it
|
||||
as CHANGES_REQUESTED and re-enter the fix loop.
|
||||
5. Once the PR is merged, proceed to 9d.
|
||||
|
||||
#### 9d. Handle merge completion
|
||||
|
||||
When the PR is confirmed merged into main (user confirmation, Gitea
|
||||
state change, or the `main` session reports the merge):
|
||||
|
||||
1. Send `shutdown_request` to all sprint agents.
|
||||
2. Wait for all `shutdown_response` confirmations.
|
||||
3. Call `TeamDelete` to clean up.
|
||||
4. Report: "Sprint {N} {team} complete. PR #{X} approved and ready for
|
||||
merge on main."
|
||||
4. Report: "Sprint {N} {team} complete. PR #{X} merged into main. Team
|
||||
shut down."
|
||||
|
||||
@@ -336,7 +336,9 @@ This domain covers: currency system, commodity taxonomy, shadow economy, corpora
|
||||
- Queryable content: `brand_products JOIN corp_presence` filtered by location and `product_subcategory`; sub-millisecond at 10K+ rows — primary use case alongside economic simulation
|
||||
|
||||
**5. DB Schema**
|
||||
- `brand_products`: `brand_product_id`, `corp_id`, `product_name`, `brand_category` (8 values), `value_trajectory`, `scarcity_class` (`capped` / `constrained` / `scalable` / `unlimited`), `product_subcategory`, `base_premium_multiplier`, `premium_floor`, `origin_system`, `terroir_locked`, `currency_denomination`, `shadow_viable`, `brand_tier` (`halo` / `volume`), `halo_brand_id` (for volume tiers)
|
||||
- `brand_products`: `brand_product_id`, `corp_id`, `product_name`, `brand_category` (8 values), `value_trajectory`, `scarcity_class` (`capped` / `constrained` / `scalable` / `unlimited`), `product_subcategory`, `base_premium_multiplier`, `premium_floor`, `origin_system`, `terroir_locked`, `currency_denomination`, `shadow_viable`, `brand_tier` (`halo` / `volume`), `halo_brand_id` (for volume tiers), `price_tier` (enum — see below)
|
||||
- `price_tier` enum (5 values): `mass` (widely accessible, lowest price point; commodity_branded volume tiers) / `premium` (above-average quality signal; most volume tiers across categories) / `luxury` (aspirational, restricted availability; terroir and design_heritage halos) / `flagship` (pinnacle output, ultra-scarce; Veblen curve inflection; max 1 per brand, lore-grounded scarcity ceiling required) / `institutional` (B2B contract pricing, not market price; service_premium and platform_catalogue)
|
||||
- **Amendment (2026-04-19):** `price_tier` valid values were not defined in the original decision. Locked to the five values above per team decision, Sprint 36.
|
||||
- `brand_inputs`: `brand_product_id`, `commodity_id`, `quantity`
|
||||
- `system_fiscal`: `system_id`, `corp_tax_rate`, `collection_efficiency` (derived from `shadow_economy_intensity`)
|
||||
- `corp_financial_state` + `corp_lifecycle_events` tables for acquisition/startup lifecycle
|
||||
@@ -440,4 +442,4 @@ This domain covers: currency system, commodity taxonomy, shadow economy, corpora
|
||||
|
||||
---
|
||||
|
||||
*19 decisions (D-171–D-187, D-189–D-190), 1 rejected alternative (R-011). Domain: economics. Last updated: 2026-04-10.*
|
||||
*19 decisions (D-171–D-187, D-189–D-190), 1 rejected alternative (R-011). Domain: economics. Last updated: 2026-04-19.*
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
# Atlas Hand-Refine Log — Sprint 36
|
||||
|
||||
Tracks all hand-edits to markers.json files above the batch Gemma 2 pass (#833).
|
||||
Re-run `python3 tooling/planet-gen/atlas_quality_analysis.py` after each entry to verify metrics improved.
|
||||
|
||||
---
|
||||
|
||||
## Sprint 36 — Baseline City Collision Elimination (#838)
|
||||
|
||||
**Date:** 2026-04-19
|
||||
**Scope:** All 273 inhabited bodies — city name cross-body collisions reduced to zero
|
||||
|
||||
### Summary
|
||||
|
||||
Starting from the Forum Veritas / Jade Harbor / Fort Iron collision leaders identified during the #849 analysis pass, performed a systematic sweep across all city name collisions.
|
||||
|
||||
**Result: 0 city name collisions** across all inhabited bodies (was 119 collisions across 15+ distinct names at ×2–×20).
|
||||
|
||||
### Approach
|
||||
|
||||
For each collision cluster: used world proper_name as the city name wherever unique. Where world names collided (same proper_name on two bodies), authored corridor-appropriate alternates. All edits paired with `generate_atlas.py --body` sync.
|
||||
|
||||
### Collision names eliminated and replacement strategy
|
||||
|
||||
| Collision name | Count | Corridor | Strategy |
|
||||
|---|---|---|---|
|
||||
| Forum Veritas | 10 | core | Unique Latin institutional names per body (Tributarium, Velabrum, Tabularium, etc.) |
|
||||
| The Forum Veritas | 2 | core | The Mons Sacer, The Pomerium (mountain ranges) |
|
||||
| Jade Harbor | 19 | east_reach | World-anchored names + corridor-appropriate alts |
|
||||
| Fort Iron | 10 | deep_frontier | World-anchored Germanic/Portuguese names |
|
||||
| Eisenstadt | 7 | west_reach | World-anchored names |
|
||||
| Fjordheim | 6 | west_reach | World-anchored names |
|
||||
| Fjordholm | 6 | west_reach/north_reach | World-anchored names |
|
||||
| Eisenberg | 5 | west_reach | World-anchored names |
|
||||
| Eisenfels | 5 | west_reach | World-anchored names |
|
||||
| Hanseong | 5 | east_reach | World-anchored names (Korean/Vietnamese) |
|
||||
| Ridge Marker | 5 | deep_frontier | World-anchored names |
|
||||
| Mbanza | 4 | south_reach | World-anchored + Lukala for Mbanza-named world |
|
||||
| Ridge Line | 4 | deep_frontier | World-anchored names |
|
||||
| Rio Grande | 4 | south_reach | World-anchored names |
|
||||
| Sakura Bay | 4 | east_reach | World-anchored names |
|
||||
| Steinbruch | 4 | west_reach | World-anchored names |
|
||||
| Zen Garden | 4 | east_reach | World-anchored names |
|
||||
| Dry Creek Station | 3 | north_reach | World-anchored names |
|
||||
| Dusty Creek | 3 | north_reach | World-anchored names |
|
||||
| Dusty Gully | 3 | north_reach | World-anchored names |
|
||||
| Ribeira Grande | 3 | south_reach | World-anchored names |
|
||||
| Serra do Sol | 3 | south_reach | World-anchored names |
|
||||
| Steinbach | 3 | west_reach | World-anchored names |
|
||||
| + 12 more ×2 pairs | 2 each | mixed | World-anchored names |
|
||||
|
||||
### Remaining river/ocean collision issues (not fixed this sprint)
|
||||
|
||||
River and ocean collisions (Rio Grande ×23 rivers, Steinbruch ×19 rivers, Ridge Line ×19 rivers, etc.) affect uninhabited and secondary bodies at scale — these are Gemma 2 template artifacts requiring a dedicated batch-script pass. Not addressed here as #838 scope is inhabited bodies.
|
||||
|
||||
---
|
||||
|
||||
## Sprint 36 — Core-World Cohesion Pass (#849)
|
||||
|
||||
**Analysis date:** 2026-04-19
|
||||
**Analysis script:** `tooling/planet-gen/atlas_quality_analysis.py`
|
||||
|
||||
### Key findings from analysis
|
||||
|
||||
- **Cross-body city collision leader:** "Jade Harbor" on 20 bodies, "Fort Iron" on 10, "Forum Veritas" on 9
|
||||
- **Cross-body river collision leader:** "Rio Grande" on 23 bodies, "Riverbend" on 19 (note: appeared on 18 other bodies from Vethis' perspective)
|
||||
- **Cross-body mountain collision leader:** "Riverbend" (mountain!) on 39 bodies, "Valley Floor" on 36
|
||||
- **Worst generic stem (first word):** `rio` 541×, `ridge` 379×, `the` 344×
|
||||
- **Sol system gap:** Earth, Mars, Luna, Europa have no atlas content (no markers.json files exist) — requires separate sprint with heightmap authoring before atlas content can be placed
|
||||
- **Tau Ceti (GJ71):** Pipeline over-Latinized with "The X" format — high collision rate; corrected below
|
||||
- **Ran (GJ144):** Generic American-West names inappropriate for core corridor world; corrected below
|
||||
|
||||
### Bodies touched
|
||||
|
||||
| Body | System | Reason |
|
||||
|------|--------|--------|
|
||||
| GJ244Ad (Edict) | GJ 244A (Sirius) | "Westwall" collision ×3; hand-authored template otherwise good |
|
||||
| GJ71c (Threshold) | GJ 71 (Tau Ceti) | Capital "Forum Veritas" collision ×8; "Capitolium" collision ×3 |
|
||||
| GJ71d (Arden) | GJ 71 (Tau Ceti) | Multiple "The X" format collisions; river/ocean/mountain fixes |
|
||||
| GJ71d-1 (Verantis) | GJ 71 (Tau Ceti) | Nearly all Latin institutional names collided with other bodies |
|
||||
| GJ144d (Kallast) | GJ 144 (Ran) | Capital city mismatch (tier1.toml says "Kallast", atlas said "Iron Creek"); generic American-West voice wrong for core corridor |
|
||||
| GJ144e (Vethis) | GJ 144 (Ran) | "Riverbend" ×18 collision; "Timberline" ×14; "Flat Ground" ×6; all generic American-West |
|
||||
|
||||
### Changes
|
||||
|
||||
**GJ244Ad (Edict, GJ 244A / Sirius):**
|
||||
- `range_3` "Westwall" → "Sanction Ridge" (institutional-Anglo voice; on-theme for Edict's political character)
|
||||
|
||||
**GJ71c (Threshold, GJ 71 / Tau Ceti):**
|
||||
- `city_0` "Forum Veritas" → "Janua" (Latin: doorway/gate — reinforces world name "Threshold"; unique)
|
||||
- `range_2` "Capitolium" → "Firmamentum" (Latin: vault of heaven — unique)
|
||||
- `range_1` "Pantheon" → "Arcanum" (Latin: sacred/secret place — unique; reduced from ×1 collision)
|
||||
|
||||
**GJ71d (Arden, GJ 71 / Tau Ceti):**
|
||||
- `city_0` "Athenaeum" → "Palaestra" (Greek: place of learning — unique)
|
||||
- `river_0` "The Prefecture" → "The Rostrum" (Roman speaker's platform — unique)
|
||||
- `river_4` "Senate House" → "The Curia" (Roman senate house — unique)
|
||||
- `river_5` "The Tribunal" → "The Decumanus" (main Roman road — unique)
|
||||
- `water_0` "The Pantheon" → "The Augusteum" (unique)
|
||||
- `water_2` "The Lyceum" → "The Porticus" (Roman colonnade — unique)
|
||||
- `range_2` "The Foundation" → "The Substructures" (unique)
|
||||
- `range_3` "The Axiom" → "The Codicil" (legal addendum — unique)
|
||||
- `range_4` "The Citadel" → "The Oppidum" (Latin: fortified town — unique)
|
||||
|
||||
**GJ71d-1 (Verantis, GJ 71 / Tau Ceti — moon):**
|
||||
- `city_0` "The Capitolium" → "Praetorium" (Roman general's quarters — appropriate for outpost moon)
|
||||
- `range_0` "The Basilica" → "The Lateranum" (early Roman basilica site — unique)
|
||||
- `range_1` "The Senate Hall" → "The Curia Magna" (unique)
|
||||
- `range_2` "The Lyceum" → "The Exedra" (semicircular recess for discussion — unique)
|
||||
- `range_3` "The Collegium" → "The Aedes Sacra" (sacred precinct — unique)
|
||||
- `range_4` "The Forum" → "The Macellum" (Roman market — unique)
|
||||
- `range_6` "The Tribunal" → "The Comitium" (Roman popular assembly — unique)
|
||||
- `water_0` "The Pantheon" → "The Pronaos" (temple vestibule — unique)
|
||||
|
||||
**GJ144d (Kallast, GJ 144 / Ran):**
|
||||
- `city_0` "Iron Creek" → "Kallast" (matches tier1.toml `kallast_agrosyndic` settlement; critical consistency fix)
|
||||
- `city_1` "Willow Bend" → "Rán's Landing" (references the Norse sea goddess and system name)
|
||||
- `river_0` "Flatland Stream" → "Rán's Run" (Norse/system reference)
|
||||
- `river_1` "Gap Crossing" → "Aldren Pass" (invented Nordic-Anglo compound; subsequently renamed "Randalfoss" in a later fix pass to eliminate the cross-system Aldren stem collision with GJ380c)
|
||||
- `river_2` "Ridge Fork" → "Scarp Fork" (less generic geological term)
|
||||
- `river_3` "Pine Gulch" → "Timber Keld" (Old Norse: keld = cold spring)
|
||||
- `river_4` "Valley View" → "Ranfall Beck" (system reference + Nordic 'beck' for stream)
|
||||
- `river_5` "Canyon Edge" → "Cliff Leat" (Anglo-Saxon: leat = watercourse)
|
||||
- `water_0` "West Pass" → "Rán Sea" (directional cardinal removed; named for system star)
|
||||
- `range_0` "Sierra Peak" → "Seterfjellet" (Norwegian: summer pasture mountain)
|
||||
- `range_1` "Prairie Bend" → "Kaldmoor Ridge" (Nordic: kald=cold, moor)
|
||||
- `range_2` "Delta Reach" → "Ranholm Escarpment" (Ran + holm = Norse island feature)
|
||||
|
||||
**GJ144e (Vethis, GJ 144 / Ran):**
|
||||
- `city_0` "Prairie View" → "Vethis Station" (world-anchored, appropriate for secondary colony)
|
||||
- `city_1` "Dusty Gulch" → "Ashvale" (Anglo, more dignified)
|
||||
- `city_2` "Stony Creek" → "Kelbridge" (Anglo: bridge over rocky stream)
|
||||
- `city_3` "Iron Pass" → "Irongate" (more distinguished; creates Irongate/Ironside narrative pair)
|
||||
- `river_0` "Riverbend" → "Greywash" (unique; removes ×18 collision — most impactful single fix)
|
||||
- `river_2` "Delta Flow" → "Veth Delta" (world-anchored)
|
||||
- `river_4` "Mesa Run" → "Ironside Run" (narrative hook: references Irongate city)
|
||||
- `water_0` "Canyon View" → "Dusthollow" (unique compound)
|
||||
- `water_1` "Flat Ground" → "The Morlands" (Anglo: moorlands — removes ×6 collision)
|
||||
- `water_2` "High Bluff" → "Ashbluff Sea" (narrative hook: Ashvale/Ashbluff pairing)
|
||||
- `range_0` "Timberline" → "Thorncrests" (removes ×14 collision — second most impactful)
|
||||
- `range_2` "Swift River" → "Strandford Heights" (removes ×2 collision)
|
||||
- `range_3` "Eastern Slope" → "Far Shore Spine" (removes cardinal direction)
|
||||
- `range_5` "Granite Ridge" → "Ashstone Ridge" (completes Ash* thematic cluster)
|
||||
|
||||
### Open gaps flagged
|
||||
|
||||
- **Sol system (GJ 0):** Earth (8.5B), Mars (1.2B), Luna (350M), Europa (30M) have NO markers.json files and NO atlas DB rows. The `wiki/star-systems/GJ-0/` directory exists but has no `bodies/` subdirectory. Sol bodies need heightmap PNGs before atlas content can be placed — this requires pipeline work, not just hand-authoring. Flagged for a future sprint.
|
||||
- **"Jade Harbor" city on 20 bodies:** Widespread collision in generated content. The Gemma batch used this as a fallback east_reach city name. Needs addressing in the batch or a targeted pass across east_reach bodies.
|
||||
- **"Rio Grande" river on 23 bodies:** Portuguese fallback. Fix in the south_reach naming templates or targeted pass.
|
||||
|
||||
*See also: `tooling/planet-gen/refine_log_849.md` for cross-reference arc analysis, per-body audit metrics, and before→after delta across all 13 inhabited targets.*
|
||||
|
||||
---
|
||||
|
||||
*Next refine pass: re-run `atlas_quality_analysis.py` — baseline metrics should show reduced collision counts on GJ71 and GJ144 bodies.*
|
||||
|
||||
---
|
||||
|
||||
## Sprint 36 — Aethelred Name Legacy (GJ251c, #849 follow-up)
|
||||
|
||||
**Date:** 2026-04-19
|
||||
**Scope:** POI name audit — GJ251c (Renaissance, GJ 251 / Groombridge 1618)
|
||||
|
||||
### Observation
|
||||
|
||||
During the #849 cross-reference audit, `poi_0` on GJ251c carries the name **"Aethelred's Gate"** (kind: transit, center [123, 369]).
|
||||
|
||||
The name is intentional. The Lattice Commission survey team that named the Tau Ceti bodies worked in a strict Latin register throughout (GJ71c Threshold: Janua; GJ71d Arden: The Rostrum, The Curia, The Decumanus; GJ71d-1 Verantis: Praetorium). One team member — Aethelred — carried an Anglo-Saxon name that didn't fit the Latin convention. When the #849 pass renamed GJ71c rivers from English institutional titles to Latin equivalents, any English-register memorial from that survey was displaced from Threshold's naming space.
|
||||
|
||||
GJ251c (Renaissance) was surveyed by the same Commission but settled by a mixed Latin/Germanic population: its capital is "Tributarium" (Latin) and its industrial city is "Ruhr" (Germanic). The transit gate naming convention on Renaissance accommodates this mixed register — making it the natural landing point for Aethelred's memorial. Players who compare Threshold's strictly Latin rivers with Renaissance's "Aethelred's Gate" transit POI can infer the survey team's composition and the naming politics of the Lattice Commission.
|
||||
|
||||
### No changes made
|
||||
|
||||
`poi_0: "Aethelred's Gate"` on GJ251c — preserved as-is. No markers.json edits. No DB sync required.
|
||||
@@ -0,0 +1,255 @@
|
||||
# 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:**
|
||||
1. Cross-system mountain name dedup (same approach as city fix above).
|
||||
2. 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):**
|
||||
|
||||
7. **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.
|
||||
8. **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:
|
||||
|
||||
1. **Cross-system city name dedup** — seed taken list from global atlas_cities
|
||||
2. **Cross-system mountain name dedup** — same approach
|
||||
3. **Empty-name fallback** — retry logic + deterministic fallback when generation fails
|
||||
4. **Suffix monotony post-filter** — re-query if >40% same suffix per body
|
||||
5. **Founding culture blend** — parse gttr_hook for cultural cues, blend with corridor palette
|
||||
6. **River "Flow/Current" filter** — move these to ocean pools, post-gen filter on rivers
|
||||
7. **Transit POI deterministic naming** — derive from capital city name, eliminate "Transit Hub" fallback
|
||||
8. **Cross-system POI name dedup** — extend global dedup to atlas_pois
|
||||
9. **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.
|
||||
Binary file not shown.
@@ -72,6 +72,7 @@ CREATE TABLE IF NOT EXISTS brand_products (
|
||||
shadow_viable INTEGER NOT NULL DEFAULT 0,
|
||||
brand_tier TEXT NOT NULL,
|
||||
halo_brand_id TEXT REFERENCES brand_products(brand_product_id),
|
||||
price_tier TEXT,
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
);
|
||||
|
||||
@@ -177,6 +178,7 @@ COLUMN_MIGRATIONS = [
|
||||
("corporations", "behavioral_archetype", "TEXT"),
|
||||
("corporations", "supply_chain_role", "TEXT"),
|
||||
("corporations", "shadow_economy_access", "INTEGER DEFAULT 0"),
|
||||
("brand_products", "price_tier", "TEXT"),
|
||||
]
|
||||
|
||||
|
||||
@@ -743,6 +745,7 @@ VALID_VALUE_TRAJECTORIES = {"appreciating", "depreciating", "timeless"}
|
||||
VALID_SCARCITY_CLASSES = {"capped", "constrained", "scalable", "unlimited"}
|
||||
VALID_BRAND_TIERS = {"halo", "volume"}
|
||||
VALID_CURRENCY_DENOMINATIONS = {"tractus", "mark", "mixed", "sol_adjacent"}
|
||||
VALID_PRICE_TIERS = {"mass", "premium", "luxury", "flagship", "institutional"}
|
||||
|
||||
|
||||
def import_brands(
|
||||
@@ -780,6 +783,7 @@ def import_brands(
|
||||
int(p.get("shadow_viable", False)),
|
||||
p["brand_tier"],
|
||||
p.get("halo_brand_id"),
|
||||
p.get("price_tier"),
|
||||
))
|
||||
|
||||
input_rows = []
|
||||
@@ -797,8 +801,8 @@ def import_brands(
|
||||
value_trajectory, scarcity_class, product_subcategory,
|
||||
base_premium_multiplier, premium_floor, origin_system,
|
||||
terroir_locked, currency_denomination, shadow_viable,
|
||||
brand_tier, halo_brand_id
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
brand_tier, halo_brand_id, price_tier
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)""",
|
||||
product_rows,
|
||||
)
|
||||
conn.executemany(
|
||||
@@ -947,12 +951,15 @@ def validate_brands(conn: sqlite3.Connection) -> list[str]:
|
||||
("scarcity_class", VALID_SCARCITY_CLASSES),
|
||||
("brand_tier", VALID_BRAND_TIERS),
|
||||
("currency_denomination", VALID_CURRENCY_DENOMINATIONS),
|
||||
("price_tier", VALID_PRICE_TIERS),
|
||||
]
|
||||
for column, valid_set in enum_checks:
|
||||
bad = conn.execute(
|
||||
f"SELECT brand_product_id, {column} FROM brand_products"
|
||||
).fetchall()
|
||||
for pid, value in bad:
|
||||
if value is None:
|
||||
continue # nullable columns (e.g. price_tier) may be unset
|
||||
if value not in valid_set:
|
||||
errors.append(
|
||||
f"V-B06: brand_product '{pid}' has {column}='{value}' — "
|
||||
|
||||
@@ -0,0 +1,413 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Generate minimal wiki stub pages for corps in brands.toml that don't yet have wiki pages.
|
||||
|
||||
Usage:
|
||||
python3 tooling/generate_corp_stubs.py [--dry-run]
|
||||
|
||||
In --dry-run mode, prints which stubs would be created without writing any files.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).parent.parent
|
||||
BRANDS_TOML = REPO / "wiki/economics/corporations/brands.toml"
|
||||
CORPS_DIR = REPO / "wiki/corporations"
|
||||
|
||||
# Star system ID -> (proper_name, corridor)
|
||||
SYSTEMS = {
|
||||
"GJ 0": ("Sol", "sol-gateway-axis"),
|
||||
"GJ 1": ("Grünfeld", "west_reach"),
|
||||
"GJ 1002": ("Caparica", "south_reach"),
|
||||
"GJ 1005A": ("Port Desrochers", "east_reach"),
|
||||
"GJ 103": ("Bestevaer", "west_reach"),
|
||||
"GJ 105A": ("Nová Tržnice", "east_reach"),
|
||||
"GJ 1061": ("Crux Station", "south_reach"),
|
||||
"GJ 1075": ("Espinho", "south_reach"),
|
||||
"GJ 1073": ("Mabuhay", "east_reach"),
|
||||
"GJ 107A": ("Tình Yên", "east_reach"),
|
||||
"GJ 1111": ("Zenzele", "south_reach"),
|
||||
"GJ 1116A": ("Mabaso Junction", "north_reach"),
|
||||
"GJ 1116B": ("Kraków Junction", "west_reach"),
|
||||
"GJ 1125": ("Hwaseong", "east_reach"),
|
||||
"GJ 1128": ("Devereux Point", "east_reach"),
|
||||
"GJ 1156": ("Travessia", "south_reach"),
|
||||
"GJ 1230A": ("Uusi Vantaa", "north_reach"),
|
||||
"GJ 1232": ("Gammelstad", "west_reach"),
|
||||
"GJ 1235": ("Knotenpunkt", "deep_frontier"),
|
||||
"GJ 124": ("Hạ Long", "east_reach"),
|
||||
"GJ 1245A": ("Okoro's Claim", "north_reach"),
|
||||
"GJ 1245B": ("Koeberg", "south_reach"),
|
||||
"GJ 1248": ("Haltefenn", "west_reach"),
|
||||
"GJ 127A": ("Dalim", "deep_frontier"),
|
||||
"GJ 127B": ("Echternach", "west_reach"),
|
||||
"GJ 1286": ("Kensho", "core"),
|
||||
"GJ 1289": ("Athabasca", "north_reach"),
|
||||
"GJ 1292": ("Moyale", "north_reach"),
|
||||
"GJ 136": ("Dài Lộ", "east_reach"),
|
||||
"GJ 137": ("Novaya Zarya", "east_reach"),
|
||||
"GJ 138": ("Sertão", "deep_frontier"),
|
||||
"GJ 139": ("Okafor Station", "north_reach"),
|
||||
"GJ 142": ("Leuchtturm", "deep_frontier"),
|
||||
"GJ 144": ("Ran", "core"),
|
||||
"GJ 15A": ("Lu Ban", "core"),
|
||||
"GJ 166A": ("Keid", "core"),
|
||||
"GJ 172": ("Kaelong", "east_reach"),
|
||||
"GJ 17": ("Binh Trang", "east_reach"),
|
||||
"GJ 178": ("Ashfield", "north_reach"),
|
||||
"GJ 183": ("Waterkant", "north_reach"),
|
||||
"GJ 19": ("Solheim", "west_reach"),
|
||||
"GJ 191": ("Kapteyn's Star", "west_reach"),
|
||||
"GJ 194B": ("Pemberton", "north_reach"),
|
||||
"GJ 197": ("Puerto Último", "south_reach"),
|
||||
"GJ 201": ("GJ 201", "deep_frontier"),
|
||||
"GJ 204": ("Pedra Funda", "deep_frontier"),
|
||||
"GJ 205": ("Kurashiki", "east_reach"),
|
||||
"GJ 208": ("Pereira's Rest", "west_reach"),
|
||||
"GJ 2097": ("Nascente", "south_reach"),
|
||||
"GJ 211": ("Encruzilhada", "deep_frontier"),
|
||||
"GJ 213": ("Kaapse Baai", "south_reach"),
|
||||
"GJ 216A": ("Kelburn Crossing", "north_reach"),
|
||||
"GJ 216B": ("Gemini Point", "north_reach"),
|
||||
"GJ 222A": ("Karoo", "south_reach"),
|
||||
"GJ 229": ("Port Mäkelä", "west_reach"),
|
||||
"GJ 231": ("Thorvaldsen's Circuit", "west_reach"),
|
||||
"GJ 234A": ("Carvalhais", "south_reach"),
|
||||
"GJ 244A": ("Sirius", "core"),
|
||||
"GJ 250A": ("Carrington's Post", "north_reach"),
|
||||
"GJ 251": ("Renaissance", "core"),
|
||||
"GJ 268": ("Yeongwol", "east_reach"),
|
||||
"GJ 27": ("Okahandja", "south_reach"),
|
||||
"GJ 273": ("Fremantle", "north_reach"),
|
||||
"GJ 280A": ("Parallax", "core"),
|
||||
"GJ 282A": ("Bout du Chemin", "west_reach"),
|
||||
"GJ 285": ("Fenwick's Lantern", "north_reach"),
|
||||
"GJ 286": ("Weitblick", "deep_frontier"),
|
||||
"GJ 299": ("Várzea", "south_reach"),
|
||||
"GJ 300": ("Dunmore Stillwater", "north_reach"),
|
||||
"GJ 302": ("Lichtbrücke", "west_reach"),
|
||||
"GJ 309": ("Vorposten", "deep_frontier"),
|
||||
"GJ 3135": ("Whitfield Crossing", "east_reach"),
|
||||
"GJ 320": ("Sonnwend", "west_reach"),
|
||||
"GJ 3250": ("Rionegro", "south_reach"),
|
||||
"GJ 325A": ("Purnima", "east_reach"),
|
||||
"GJ 33": ("96 Piscium", "south_reach"),
|
||||
"GJ 3323": ("Entroncamento", "south_reach"),
|
||||
"GJ 3325": ("Calloway Reach", "north_reach"),
|
||||
"GJ 3333": ("Groenland", "west_reach"),
|
||||
"GJ 3379": ("Shenwei", "east_reach"),
|
||||
"GJ 338B": ("Arbour", "core"),
|
||||
"GJ 3454": ("Eisentor", "west_reach"),
|
||||
"GJ 349": ("Randgebiet", "deep_frontier"),
|
||||
"GJ 34A": ("Tanegashima", "north_reach"),
|
||||
"GJ 34B": ("Yongjin", "east_reach"),
|
||||
"GJ 35": ("Vuurkloof", "south_reach"),
|
||||
"GJ 3522": ("Sindri", "core"),
|
||||
"GJ 3533": ("Trung's Crossing", "east_reach"),
|
||||
"GJ 3586": ("Eisfeld", "west_reach"),
|
||||
"GJ 3612": ("Xa Vời", "east_reach"),
|
||||
"GJ 3618": ("Pemberton's Loop", "north_reach"),
|
||||
"GJ 3622": ("Havnfjord", "north_reach"),
|
||||
"GJ 370": ("Traagwater", "west_reach"),
|
||||
"GJ 3728B": ("Jeonnam", "east_reach"),
|
||||
"GJ 3737": ("Nyrheim", "west_reach"),
|
||||
"GJ 380": ("Groombridge", "core"),
|
||||
"GJ 3820": ("Uusi Vantaa", "north_reach"),
|
||||
"GJ 3877": ("Tessera", "core"),
|
||||
"GJ 388": ("The Lantern", "south_reach"),
|
||||
"GJ 393": ("Encrucijada", "south_reach"),
|
||||
"GJ 395": ("Confluent", "west_reach"),
|
||||
"GJ 3991": ("Dunbar", "north_reach"),
|
||||
"GJ 402": ("Prospect Hill", "north_reach"),
|
||||
"GJ 4053": ("Dzimbahwe", "south_reach"),
|
||||
"GJ 406": ("Wolf 359", "north_reach"),
|
||||
"GJ 408": ("Oude Kraal", "north_reach"),
|
||||
"GJ 410": ("Wagtoring", "north_reach"),
|
||||
"GJ 411": ("Lalande", "south_reach"),
|
||||
"GJ 412A": ("Morales' End", "south_reach"),
|
||||
"GJ 412B": ("Korhonen", "east_reach"),
|
||||
"GJ 414A": ("Vindkast", "west_reach"),
|
||||
"GJ 42": ("Langemark", "west_reach"),
|
||||
"GJ 423A": ("Marunong", "east_reach"),
|
||||
"GJ 423B": ("Quilombo", "south_reach"),
|
||||
"GJ 4274": ("Suzhou", "east_reach"),
|
||||
"GJ 4285": ("Lam's Prospect", "east_reach"),
|
||||
"GJ 432A": ("Kaur's Observatory", "east_reach"),
|
||||
"GJ 435": ("Mirante", "south_reach"),
|
||||
"GJ 438": ("Relay 7", "east_reach"),
|
||||
"GJ 442A": ("Torsby", "west_reach"),
|
||||
"GJ 445": ("Jinghu", "east_reach"),
|
||||
"GJ 447": ("Ross 128", "core"),
|
||||
"GJ 449": ("Murakami's Lantern", "east_reach"),
|
||||
"GJ 451A": ("Groombridge 1830", "south_reach"),
|
||||
"GJ 453": ("Freiholt", "west_reach"),
|
||||
"GJ 454": ("Steinfeld", "west_reach"),
|
||||
"GJ 473A": ("Passagem", "south_reach"),
|
||||
"GJ 473B": ("Nkosi's Bridge", "north_reach"),
|
||||
"GJ 475": ("Braemar", "north_reach"),
|
||||
"GJ 482A": ("Dagat", "east_reach"),
|
||||
"GJ 49": ("Dernier Quai", "east_reach"),
|
||||
"GJ 4A": ("Velha Guarda", "south_reach"),
|
||||
"GJ 501B": ("Candeia", "deep_frontier"),
|
||||
"GJ 502": ("Meridian", "west_reach"),
|
||||
"GJ 505A": ("Bergtor", "west_reach"),
|
||||
"GJ 506": ("Dokkum", "west_reach"),
|
||||
"GJ 508A": ("Stilwater", "north_reach"),
|
||||
"GJ 526": ("Neustadt", "west_reach"),
|
||||
"GJ 529": ("Yttermark", "west_reach"),
|
||||
"GJ 532": ("Kettenschmied", "deep_frontier"),
|
||||
"GJ 534": ("Stillvakt", "west_reach"),
|
||||
"GJ 536": ("Retiro", "south_reach"),
|
||||
"GJ 53A": ("Bridgepoint", "east_reach"),
|
||||
"GJ 54": ("Inhambane", "south_reach"),
|
||||
"GJ 54.1": ("Ribeiro's Star", "south_reach"),
|
||||
"GJ 541": ("Chandra Deep", "east_reach"),
|
||||
"GJ 542": ("Kopparhytta", "west_reach"),
|
||||
"GJ 546": ("Eerste Wacht", "deep_frontier"),
|
||||
"GJ 551": ("Proxima", "core"),
|
||||
"GJ 555": ("Tanaka Station", "east_reach"),
|
||||
"GJ 556": ("Recanto", "deep_frontier"),
|
||||
"GJ 559B": ("ACB", "core"),
|
||||
"GJ 566A": ("Haodu", "east_reach"),
|
||||
"GJ 566B": ("Confluência", "south_reach"),
|
||||
"GJ 567": ("Fragua", "south_reach"),
|
||||
"GJ 570A": ("Bastion", "core"),
|
||||
"GJ 575A": ("Ratnagiri", "north_reach"),
|
||||
"GJ 581": ("Rødvik", "west_reach"),
|
||||
"GJ 588": ("Harrowfield", "north_reach"),
|
||||
"GJ 598": ("Helle Wacht", "deep_frontier"),
|
||||
"GJ 601A": ("Ostmark", "west_reach"),
|
||||
"GJ 603": ("Mossbank", "north_reach"),
|
||||
"GJ 615": ("Dunkelholz", "west_reach"),
|
||||
"GJ 624": ("Halvøy", "west_reach"),
|
||||
"GJ 625": ("Songjiang", "east_reach"),
|
||||
"GJ 628": ("Brennan's Drift", "west_reach"),
|
||||
"GJ 631": ("Bakshi Spur", "west_reach"),
|
||||
"GJ 635A": ("Stilmark", "west_reach"),
|
||||
"GJ 635B": ("Clearwater Station", "east_reach"),
|
||||
"GJ 638": ("Greymantle", "north_reach"),
|
||||
"GJ 643": ("Marktfeld", "west_reach"),
|
||||
"GJ 644A": ("Mavela", "south_reach"),
|
||||
"GJ 644C": ("Moçâmedes", "south_reach"),
|
||||
"GJ 653": ("Dunmore", "north_reach"),
|
||||
"GJ 660A": ("Seongho", "east_reach"),
|
||||
"GJ 661A": ("Crown's Hollow", "north_reach"),
|
||||
"GJ 661B": ("Breëvlei", "north_reach"),
|
||||
"GJ 663A": ("Johannsen's Star", "north_reach"),
|
||||
"GJ 664": ("Caldwell Point", "west_reach"),
|
||||
"GJ 667A": ("New Ballarat", "north_reach"),
|
||||
"GJ 667B": ("Kampala Gate", "north_reach"),
|
||||
"GJ 667C": ("Gliese 667", "east_reach"),
|
||||
"GJ 66A": ("p Eridani", "east_reach"),
|
||||
"GJ 66B": ("Voss", "west_reach"),
|
||||
"GJ 67": ("Roça Nova", "south_reach"),
|
||||
"GJ 672": ("Nova Estrada", "deep_frontier"),
|
||||
"GJ 673": ("Lindström Station", "north_reach"),
|
||||
"GJ 674": ("Meridian", "core"),
|
||||
"GJ 675": ("Neugrund", "deep_frontier"),
|
||||
"GJ 680": ("Carnarvon", "north_reach"),
|
||||
"GJ 682": ("Taishan", "east_reach"),
|
||||
"GJ 684A": ("Sonnenkap", "deep_frontier"),
|
||||
"GJ 684B": ("Paso Largo", "deep_frontier"),
|
||||
"GJ 687": ("Matsue", "east_reach"),
|
||||
"GJ 688": ("Aguas Bravas", "south_reach"),
|
||||
"GJ 693": ("Mwangaza", "south_reach"),
|
||||
"GJ 699": ("Barnard's Star", "core"),
|
||||
"GJ 702B": ("Prometheus", "core"),
|
||||
"GJ 706": ("Ngata's Star", "north_reach"),
|
||||
"GJ 716": ("Murchison", "north_reach"),
|
||||
"GJ 71": ("Tau Ceti", "core"),
|
||||
"GJ 713A": ("Samuels Reach", "east_reach"),
|
||||
"GJ 722": ("Skuilplek", "deep_frontier"),
|
||||
"GJ 725B": ("Struve", "core"),
|
||||
"GJ 729": ("Ross 154", "west_reach"),
|
||||
"GJ 737B": ("Punta del Sol", "south_reach"),
|
||||
"GJ 75": ("Enugu", "north_reach"),
|
||||
"GJ 752A": ("Ribeirão", "south_reach"),
|
||||
"GJ 754": ("Miryang", "east_reach"),
|
||||
"GJ 764": ("Nova Roma", "core"),
|
||||
"GJ 768": ("Altair", "south_reach"),
|
||||
"GJ 770": ("Rekohu", "north_reach"),
|
||||
"GJ 771A": ("Alshain", "west_reach"),
|
||||
"GJ 775": ("Randsholm", "west_reach"),
|
||||
"GJ 780": ("Puerto Rivera", "north_reach"),
|
||||
"GJ 783A": ("Aurelius", "core"),
|
||||
"GJ 784": ("Kovács Loop", "east_reach"),
|
||||
"GJ 785": ("Porto Fechado", "south_reach"),
|
||||
"GJ 79": ("Oshima", "east_reach"),
|
||||
"GJ 798": ("Brückenau", "west_reach"),
|
||||
"GJ 807": ("Grenzstein", "west_reach"),
|
||||
"GJ 809": ("Seiðrmaðr", "west_reach"),
|
||||
"GJ 820B": ("Cygni B", "core"),
|
||||
"GJ 825": ("Lacaille", "north_reach"),
|
||||
"GJ 827": ("Solandar", "south_reach"),
|
||||
"GJ 829": ("Posto Avançado", "south_reach"),
|
||||
"GJ 83.1": ("Farol", "south_reach"),
|
||||
"GJ 832": ("Hansestadt", "west_reach"),
|
||||
"GJ 845": ("Cairn", "north_reach"),
|
||||
"GJ 848": ("Shimanami", "east_reach"),
|
||||
"GJ 86": ("Kumasi", "south_reach"),
|
||||
"GJ 860A": ("Kruger 60", "south_reach"),
|
||||
"GJ 860B": ("Changwon", "east_reach"),
|
||||
"GJ 866A": ("EZ Aqr", "east_reach"),
|
||||
"GJ 873": ("Ashworth Junction", "north_reach"),
|
||||
"GJ 875": ("The Narrows", "deep_frontier"),
|
||||
"GJ 876": ("Koskinen's Reach", "north_reach"),
|
||||
"GJ 877": ("Holmgren's Passage", "north_reach"),
|
||||
"GJ 879": ("Singh's Landing", "north_reach"),
|
||||
"GJ 880": ("Holgersen's Landing", "north_reach"),
|
||||
"GJ 884": ("Matamba", "south_reach"),
|
||||
"GJ 887": ("Lacaille", "core"),
|
||||
"GJ 892": ("Cairnside", "deep_frontier"),
|
||||
"GJ 896A": ("Nowa Huta", "south_reach"),
|
||||
"GJ 905": ("Isibaya", "south_reach"),
|
||||
"GJ 908": ("Thornfield Station", "east_reach"),
|
||||
"GJ 909A": ("Tam Giang", "east_reach"),
|
||||
"GJ 92": ("Pollux", "south_reach"),
|
||||
"GJ 95": ("Caledonia's End", "north_reach"),
|
||||
}
|
||||
|
||||
# Brand category -> description template suffix and tags hint
|
||||
CATEGORY_META = {
|
||||
"terroir": ("regional specialty producer", ["terroir", "scarcity_class_rare"]),
|
||||
"heritage_craft": ("heritage craft manufacturer", ["heritage_craft", "artisan"]),
|
||||
"tech_premium": ("precision technology manufacturer", ["tech_premium", "electronics"]),
|
||||
"cultural": ("cultural content producer", ["cultural", "entertainment"]),
|
||||
"service_premium": ("premium service provider", ["service_premium"]),
|
||||
"commodity_branded": ("consumer goods manufacturer", ["commodity_branded", "consumer_goods"]),
|
||||
"design_heritage": ("design and furniture manufacturer", ["design_heritage", "consumer_goods"]),
|
||||
"platform_catalogue": ("media platform and catalogue service", ["platform_catalogue", "entertainment"]),
|
||||
}
|
||||
|
||||
def slug_to_title(slug: str) -> str:
|
||||
"""Convert a slug like 'my-corp-name' to 'My Corp Name'."""
|
||||
return " ".join(w.capitalize() for w in slug.replace("-", " ").split())
|
||||
|
||||
def parse_brands_toml(path: Path) -> dict:
|
||||
"""Parse brands.toml and return dict of corp_id -> {origin_system, brand_category}."""
|
||||
corps = {}
|
||||
current_corp = None
|
||||
current_system = None
|
||||
current_category = None
|
||||
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line == "[[brand_products]]":
|
||||
# Save previous
|
||||
if current_corp and current_system:
|
||||
if current_corp not in corps:
|
||||
corps[current_corp] = {
|
||||
"origin_system": current_system,
|
||||
"brand_category": current_category,
|
||||
}
|
||||
current_corp = None
|
||||
current_system = None
|
||||
current_category = None
|
||||
elif line.startswith("corp_id = "):
|
||||
current_corp = line.split("=", 1)[1].strip().strip('"')
|
||||
elif line.startswith("origin_system = "):
|
||||
current_system = line.split("=", 1)[1].strip().strip('"')
|
||||
elif line.startswith("brand_category = "):
|
||||
current_category = line.split("=", 1)[1].strip().strip('"')
|
||||
|
||||
# Save last
|
||||
if current_corp and current_system:
|
||||
if current_corp not in corps:
|
||||
corps[current_corp] = {
|
||||
"origin_system": current_system,
|
||||
"brand_category": current_category,
|
||||
}
|
||||
|
||||
return corps
|
||||
|
||||
def generate_stub(slug: str, origin_system: str, brand_category: str) -> str:
|
||||
title = slug_to_title(slug)
|
||||
sys_info = SYSTEMS.get(origin_system, (origin_system, "unknown"))
|
||||
sys_name, corridor = sys_info
|
||||
|
||||
cat_meta = CATEGORY_META.get(brand_category, ("commercial enterprise", []))
|
||||
cat_desc, cat_tags = cat_meta
|
||||
|
||||
corridor_currency = "tractus"
|
||||
if corridor in ("west_reach",):
|
||||
corridor_currency = "mark"
|
||||
elif corridor == "core":
|
||||
corridor_currency = "tractus"
|
||||
|
||||
headquarters = f"{sys_name} ({origin_system})"
|
||||
tags_list = [brand_category, corridor, corridor_currency] + cat_tags
|
||||
# Deduplicate while preserving order
|
||||
seen = set()
|
||||
tags = []
|
||||
for t in tags_list:
|
||||
if t not in seen:
|
||||
seen.add(t)
|
||||
tags.append(t)
|
||||
tags_str = "[" + ", ".join(tags) + "]"
|
||||
|
||||
description = f"{title} — {cat_desc} based in {sys_name}, {corridor.replace('_', ' ')}"
|
||||
|
||||
return f"""---
|
||||
title: "{title}"
|
||||
description: "{description}"
|
||||
slug: {slug}
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: {headquarters}
|
||||
tags: {tags_str}
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# {title}
|
||||
|
||||
**Type:** Corporation — {cat_desc.title()}
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — {corridor.replace('_', ' ')} operations
|
||||
**Headquarters:** {headquarters}
|
||||
|
||||
{title} is a {cat_desc} operating out of {sys_name} ({origin_system}). Details to be expanded.
|
||||
"""
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate minimal wiki stub pages for corps in brands.toml."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="Print which stubs would be created without writing any files.",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
|
||||
corps = parse_brands_toml(BRANDS_TOML)
|
||||
print(f"Found {len(corps)} unique corp_ids in brands.toml")
|
||||
if args.dry_run:
|
||||
print("(dry-run — no files will be written)\n")
|
||||
|
||||
created = 0
|
||||
skipped = 0
|
||||
for slug, meta in sorted(corps.items()):
|
||||
stub_path = CORPS_DIR / f"{slug}.md"
|
||||
if stub_path.exists():
|
||||
skipped += 1
|
||||
continue
|
||||
if args.dry_run:
|
||||
print(f" (dry-run) Would create: {slug}.md")
|
||||
else:
|
||||
content = generate_stub(slug, meta["origin_system"], meta["brand_category"])
|
||||
stub_path.write_text(content, encoding="utf-8")
|
||||
print(f" created: {slug}.md")
|
||||
created += 1
|
||||
|
||||
action = "Would create" if args.dry_run else "Created"
|
||||
print(f"\nDone. {action} {created} stubs, skipped {skipped} existing.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,300 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
apply_name_fixes.py — Apply curated name replacements to markers.json files.
|
||||
|
||||
Usage:
|
||||
python3 tooling/planet-gen/apply_name_fixes.py [--dry-run]
|
||||
|
||||
Edits name fields only; all geometry (path, center, area_fraction) is preserved.
|
||||
After running, call generate_atlas.py --body <id> for each body to sync DB.
|
||||
|
||||
Decisions: D-191 (markers.json format, corridor palettes)
|
||||
"""
|
||||
import json
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = (Path(__file__).resolve().parent / ".." / "..").resolve()
|
||||
WIKI = REPO_ROOT / "wiki" / "star-systems"
|
||||
|
||||
DRY_RUN = "--dry-run" in sys.argv
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Name replacement tables per body
|
||||
# Format: { body_dir_key: { "feature_type": { "old_name": "new_name" } } }
|
||||
# feature_type: cities | rivers | oceans | mountain_ranges | pois
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
FIXES: dict[str, dict[str, dict[str, str]]] = {
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# GJ 144 — Ran system
|
||||
# Verified against actual markers.json files (DB is stale).
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Kallast (GJ144d) — 2B pop, agricultural, urban_concentrated, ocean world
|
||||
# Current state (from markers.json): good Nordic naming pass done; residual
|
||||
# lazy/generic oceans remain. Fix: rename remaining generics, add cross-ref
|
||||
# with mountain "Seterfjellet" (ocean → "Seterfjord"), fix POI, and rename
|
||||
# "Aldren Pass" to avoid cross-system collision with Lendel (GJ380c capital
|
||||
# "Aldren" and river "The Aldren").
|
||||
# Narrative hook: "Rán's Landing" city (names the star), "Rán's Run" and
|
||||
# "Ranfall Beck" rivers (shared Rán stem = cross-referencing done). Adding
|
||||
# Seterfjord → Seterfjellet link completes the second cross-reference arc.
|
||||
"GJ-144/bodies/GJ144d": {
|
||||
"rivers": {
|
||||
# Avoid cross-system stem collision with Lendel (GJ380c) "Aldren"
|
||||
"Aldren Pass": "Randalfoss",
|
||||
},
|
||||
"oceans": {
|
||||
# Still generic — large ocean near mountains → name ties to Seterfjellet
|
||||
"Boulder Bluff": "Keldmere",
|
||||
# "High Mesa" for an ocean is nonsensical
|
||||
"High Mesa": "Seterfjord",
|
||||
},
|
||||
"pois": {
|
||||
"Summit Point": "Kallast Gate Terminal",
|
||||
},
|
||||
},
|
||||
|
||||
# Vethis (GJ144e) — 1.2B pop, agricultural, dispersed_rural
|
||||
# Current state: partial naming pass done. Remaining: cardinals (West Bend),
|
||||
# earth-echoes (Blue Ridge), generics (Stone Point, Ironside Run, Golden
|
||||
# Valley, Broad Fork), "Ash" stem overuse (Ashbluff Sea + Ashstone Ridge +
|
||||
# Ashvale = 3 features), "Iron" stem overuse (Irongate + Ironside Run = 2).
|
||||
# Fixes cross-reference existing named features:
|
||||
# Grey- stem: Greywash + Greywash Fork + Greystone Ridge (intentional arc)
|
||||
# Thorn- stem: Thorncrests + Thornrun (mountain visible from river)
|
||||
# Kel- stem: Kelbridge + Kelside Run (river serving the city)
|
||||
# Veth- stem: Vethis + Veth Delta + Veth Mere (planet name echoed in geography)
|
||||
"GJ-144/bodies/GJ144e": {
|
||||
"rivers": {
|
||||
"West Bend": "Greywash Fork", # cardinal → cross-refs Greywash river
|
||||
"Blue Ridge": "Ashvale Beck", # earth-echo → cross-refs Ashvale city
|
||||
"Stone Point": "Thornrun", # generic → cross-refs Thorncrests mtn
|
||||
"Ironside Run": "Kelside Run", # Iron overuse → cross-refs Kelbridge
|
||||
},
|
||||
"oceans": {
|
||||
# Ashbluff Sea: "Ash" prefix already on Ashvale city + Ashstone Ridge mtn
|
||||
"Ashbluff Sea": "Veth Mere", # Ash overuse → cross-refs Veth Delta
|
||||
},
|
||||
"mountain_ranges": {
|
||||
"Golden Valley": "Greymoor Range", # generic → cross-refs Greywash river
|
||||
"Broad Fork": "Keld Spur", # generic → Nordic "keld" (spring)
|
||||
# Ashstone Ridge: "Ash" overuse (Ashvale + Veth Mere rename frees slot)
|
||||
"Ashstone Ridge": "Greystone Ridge", # Ash overuse → cross-refs Greywash
|
||||
},
|
||||
"pois": {
|
||||
"Ridge Crossing": "Vethis Gate Terminal",
|
||||
},
|
||||
},
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# GJ 71 — Tau Ceti system
|
||||
# Verified against actual markers.json files (DB is stale).
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Threshold (GJ71c) — 600M pop, agricultural, urban_concentrated
|
||||
# Fix: replace "Aethelred" (Anglo-Saxon; breaks the all-Latin-personal-name
|
||||
# pattern of the six rivers: Octavius, Septimus, Quintus, Valeria, Marcus).
|
||||
# Narrative: All six rivers named after the original Commission survey team.
|
||||
"GJ-71/bodies/GJ71c": {
|
||||
"rivers": {
|
||||
"Aethelred": "Gaius",
|
||||
},
|
||||
},
|
||||
|
||||
# Arden (GJ71d) — 500M pop, agricultural, dispersed_rural
|
||||
# Fix cross-body stem duplicates:
|
||||
# "Concordia Hall" city → exact stem match with GJ71c ocean "Concordia"
|
||||
# "Basilica Nova" river → exact name match with GJ71c POI "Basilica Nova"
|
||||
# GJ71d-1 has been independently updated — Forum Major no longer conflicts.
|
||||
# Capital "Palaestra" and other names are clean — keep.
|
||||
"GJ-71/bodies/GJ71d": {
|
||||
"cities": {
|
||||
"Concordia Hall": "The Praxis", # Concordia = GJ71c sea
|
||||
},
|
||||
"rivers": {
|
||||
"Basilica Nova": "Via Principia", # exact match = GJ71c POI name
|
||||
},
|
||||
},
|
||||
|
||||
# Verantis (GJ71d-1) — 20M pop, transit moon of Arden
|
||||
# Already updated in a prior pass (capital=Praetorium, mountains all
|
||||
# renamed to unique Latin institutional names). No changes needed.
|
||||
# "GJ-71/bodies/GJ71d-1": {}, # skip
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# GJ 244A — Sirius system
|
||||
# Verified against actual markers.json files (DB matches).
|
||||
# Note: "Westwall" flagged by Gestalt does NOT appear in Edict markers.json
|
||||
# or DB — either already removed in a prior pass or Gestalt saw stale data.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Edict (GJ244Ad) — 400M pop, hand-authored template + #833 derived features
|
||||
# Hand-authored core is clean (Mandate, Station Edict, Founder's Range,
|
||||
# Accord Peaks, Veto Spur, Concord Assembly Archive, all POIs). Fixes
|
||||
# target only #833-generated features that don't match the political-legal
|
||||
# naming vocabulary of Edict.
|
||||
# Narrative hook: the legal/institutional vocabulary — Mandate, Accord, Veto,
|
||||
# Concord, Statute, Charter — all reference governance and founding documents.
|
||||
# Arcs established: Concord- (ocean + POI), Charter- (mountain + ocean),
|
||||
# Veil- (ocean + POI cross-ref to Veil Institute Survey Station).
|
||||
"GJ-244A/bodies/GJ244Ad": {
|
||||
"mountain_ranges": {
|
||||
# "Keel" is a nautical term — wrong vocabulary for a political world
|
||||
"Keel Ridge": "Charter Spur", # charter = Edict's founding document
|
||||
# "Sanction" fits but "Ridge" suffix is lazy
|
||||
"Sanction Ridge": "The Statute", # distinctive; drops generic suffix
|
||||
},
|
||||
"oceans": {
|
||||
# Cardinal direction names; replace with Edict-vocabulary terms
|
||||
"Upper Shelf": "Veil Shelf", # cross-refs Veil Institute Survey Station
|
||||
"Southern Melt": "Concord Mere", # cross-refs Concord Assembly Archive POI
|
||||
"Eastern Tarn": "Charter Tarn", # cross-refs mountain "Charter Spur"
|
||||
},
|
||||
},
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# GJ 380 — Groombridge system
|
||||
# Verified against actual markers.json files.
|
||||
# Hand-authored template is clean: Aldren (capital) + The Aldren (river) +
|
||||
# Aldren Exchange (POI) is an INTENTIONAL arc — do not touch.
|
||||
# "Meridian Risk HQ" POI is a corporation proper noun — not geography.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Lendel (GJ380c) — 900M pop, hand-authored template + #833 derived features
|
||||
# Two #833-generated features with lazy suffixes. British-Isles naming
|
||||
# vocabulary: Lendel, Aldren, Sethvale, Caldenmere, Rethain Sea.
|
||||
# "Durneth Beck" cross-refs Durneth Range (the major mountain range near
|
||||
# the river's source area). "Tember Spine" keeps the "Tember" stem but
|
||||
# drops the lazy "Ridge" suffix.
|
||||
"GJ-380/bodies/GJ380c": {
|
||||
"rivers": {
|
||||
"Pale Run": "Durneth Beck", # lazy → cross-refs Durneth Range; beck=British stream
|
||||
},
|
||||
"mountain_ranges": {
|
||||
"Tember Ridge": "Tember Spine", # lazy Ridge → Spine (distinctive; not in lazy list)
|
||||
},
|
||||
},
|
||||
|
||||
# -----------------------------------------------------------------------
|
||||
# GJ 699 — Barnard's Star system
|
||||
# Verified against actual markers.json files.
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
# Verada (GJ699b) — 1.9B pop, hop-0, dense urban world
|
||||
# Major problem: rivers and ocean names use urban civic vocabulary
|
||||
# (Grandview Square, Meridian City, Metropolitan Square) — these are
|
||||
# neighborhood-planning names, not geographic features. Rivers especially
|
||||
# cannot be named "Grandview Square" or "Meridian City". Oceans have
|
||||
# district-style names that duplicate on sibling bodies.
|
||||
# Strategy: keep Verada's civic-density character in CITY names, but
|
||||
# give geographic features geographic names that cross-reference the cities.
|
||||
# Arcs: Capitol- (city + river + ocean), Haven/Port- (city + ocean),
|
||||
# Meridian- (river + ocean), Prospect- (ocean), Sterling- (lake).
|
||||
"GJ-699/bodies/GJ699b": {
|
||||
"rivers": {
|
||||
# "Grandview Square" is a plaza, not a river name
|
||||
"Grandview Square": "Verada Reach", # planet name + geographic; Reach = stretch of river
|
||||
# "Meridian City" is a city name used for a river
|
||||
"Meridian City": "The Meridian", # drop civic suffix; becomes proper river name
|
||||
# "Summit View" is lazy
|
||||
"Summit View": "Capitol Beck", # cross-refs Capitol Heights capital city
|
||||
},
|
||||
"oceans": {
|
||||
# "Terrace" is an architectural term — wrong for a large ocean
|
||||
"Prospect Terrace": "Prospect Sea", # keep Prospect, fix suffix
|
||||
# "Metropolitan Square" is a plaza name for an ocean
|
||||
"Metropolitan Square": "Haven Sea", # cross-refs Port Haven city
|
||||
# Exact dup of GJ699b-1 mountain "Central District"
|
||||
"Central District": "Meridian Sound", # cross-refs The Meridian river
|
||||
# "Plaza" is civic architecture, not a lake feature
|
||||
"Liberty Plaza": "Capitol Mere", # cross-refs Capitol Heights capital
|
||||
# "Sterling Heights" — "Heights" is wrong for a lake; dupes GJ699b-1 mountain
|
||||
"Sterling Heights": "Sterling Pool", # keep Sterling, fix suffix
|
||||
},
|
||||
},
|
||||
|
||||
# Verada's moon (GJ699b-1) — uninhabited transit moon
|
||||
# All 8 mountains are named after urban street addresses (Grandview Avenue,
|
||||
# Harmony Boulevard, Beacon Street, etc.) — this is entirely wrong for
|
||||
# mountain ranges. The fix renames them to geological/geographic terms that
|
||||
# cross-reference Verada's institutional vocabulary (as if settlers looked
|
||||
# down at Verada and named the moon's peaks after the institutions below).
|
||||
# The largest range (Verada Scarp, was "Grandview Avenue") takes the planet
|
||||
# name directly.
|
||||
"GJ-699/bodies/GJ699b-1": {
|
||||
"mountain_ranges": {
|
||||
"Grandview Avenue": "Verada Scarp", # largest range; named after parent body
|
||||
"Central District": "Barnard Heights", # names the star; distinct from all Verada names
|
||||
"Harmony Boulevard": "Keystone Scarp", # cross-refs Keystone Junction on Verada
|
||||
"Capitol Heights": "Tribunal Spur", # cross-refs Tribunal Tower on Verada
|
||||
"Meridian Plaza": "Zenith Spine", # cross-refs Zenith Station on Verada
|
||||
"Liberty Square": "Ironwood Spur", # cross-refs Ironwood Borough on Verada
|
||||
"Metropolitan Way": "Consulate Scarp", # cross-refs Consulate Way on Verada
|
||||
"Beacon Street": "Prefecture Spur", # cross-refs Prefecture Hall on Verada
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Helpers
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
def apply_fixes(body_key: str, fixes: dict[str, dict[str, str]]) -> bool:
|
||||
"""Load markers.json for body_key, apply name fixes, write back. Returns True on change."""
|
||||
parts = body_key.split("/")
|
||||
path = WIKI / Path(*parts) / "markers.json"
|
||||
|
||||
if not path.exists():
|
||||
print(f" SKIP {body_key}: markers.json not found at {path}")
|
||||
return False
|
||||
|
||||
with open(path) as f:
|
||||
markers = json.load(f)
|
||||
|
||||
changed = False
|
||||
section_map = {
|
||||
"cities": "cities",
|
||||
"rivers": "rivers",
|
||||
"oceans": "oceans",
|
||||
"mountain_ranges": "mountain_ranges",
|
||||
"pois": "pois",
|
||||
}
|
||||
|
||||
for section, name_map in fixes.items():
|
||||
feature_list = markers.get(section_map[section], [])
|
||||
for feature in feature_list:
|
||||
old_name = feature.get("name", "")
|
||||
if old_name in name_map:
|
||||
new_name = name_map[old_name]
|
||||
if old_name != new_name:
|
||||
print(f" [{section}] '{old_name}' → '{new_name}'")
|
||||
feature["name"] = new_name
|
||||
changed = True
|
||||
|
||||
if changed and not DRY_RUN:
|
||||
with open(path, "w") as f:
|
||||
json.dump(markers, f, indent=2)
|
||||
print(f" Written: {path}")
|
||||
elif changed and DRY_RUN:
|
||||
print(f" (dry-run) Would write: {path}")
|
||||
else:
|
||||
print(f" No changes for {body_key}")
|
||||
|
||||
return changed
|
||||
|
||||
|
||||
def main():
|
||||
print(f"\nApplying name fixes{'(dry-run)' if DRY_RUN else ''}\n")
|
||||
for body_key, fixes in FIXES.items():
|
||||
print(f"=== {body_key} ===")
|
||||
apply_fixes(body_key, fixes)
|
||||
print()
|
||||
print("Done.\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,388 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
atlas_cohesion_audit.py — Quality analysis script for atlas atlas_* tables.
|
||||
|
||||
Runs a set of SQL queries against server/data/systems.db atlas_* tables to
|
||||
identify names that need hand-refining:
|
||||
|
||||
1. Stem duplicates within a system (same root token, different bodies)
|
||||
2. Cross-feature same-body near-duplicates (e.g. Aureus River + Aureus Range)
|
||||
3. Cardinal direction density per body (Western X / Northern X patterns)
|
||||
4. Generic / lazy outputs (Great %, Hilly %, Sector %, The %)
|
||||
5. Empty or single-character names
|
||||
6. Earth-echo concentration in a given system
|
||||
|
||||
Usage:
|
||||
python3 tooling/planet-gen/atlas_cohesion_audit.py
|
||||
python3 tooling/planet-gen/atlas_cohesion_audit.py --system GJ 144
|
||||
python3 tooling/planet-gen/atlas_cohesion_audit.py --body GJ144d
|
||||
|
||||
Decisions: D-191 (atlas pipeline, corridor palettes, markers.json format)
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import sqlite3
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = (Path(__file__).resolve().parent / ".." / "..").resolve()
|
||||
DB_PATH = REPO_ROOT / "server" / "data" / "systems.db"
|
||||
|
||||
CARDINALS = ("North", "South", "East", "West", "Northern", "Southern",
|
||||
"Eastern", "Western", "Upper", "Lower", "Far", "Kita", "Minami",
|
||||
"Higashi", "Nishi")
|
||||
|
||||
LAZY_PATTERNS = (
|
||||
"Great %", "Hilly %", "Sector %", "Flat %", "High %",
|
||||
"Big %", "Little %", "Low %", "Deep %", "Old %",
|
||||
"% Bluff", "% View", "% Gulch",
|
||||
"Flatland %", "Prairie %", "Desert %", "Canyon %",
|
||||
"% Crossing", "% Bend", "% Fork", "% Run", "% Creek",
|
||||
"% Point", "% Pass", "% Peak", "% Ridge", "% Stream",
|
||||
"% Ground", "% Slope", "% Mesa",
|
||||
)
|
||||
|
||||
EARTH_ECHOES = (
|
||||
"Manchester", "London", "Paris", "Berlin", "Madrid",
|
||||
"Sierra Nevada", "Blue Ridge", "Appalachian",
|
||||
"Route %", "Highway %", "Interstate %",
|
||||
"New York", "Los Angeles", "Chicago",
|
||||
"Timberline", "Riverbend", "Greenfield",
|
||||
"Stony Creek", "Iron Creek", "Pine Gulch", "Valley View",
|
||||
)
|
||||
|
||||
|
||||
def get_conn(db_path: Path) -> sqlite3.Connection:
|
||||
conn = sqlite3.connect(str(db_path))
|
||||
conn.row_factory = sqlite3.Row
|
||||
return conn
|
||||
|
||||
|
||||
def section(title: str) -> None:
|
||||
print(f"\n{'='*70}")
|
||||
print(f" {title}")
|
||||
print('='*70)
|
||||
|
||||
|
||||
def run_all_features_for_body(conn, body_id: str) -> list[tuple[str, str]]:
|
||||
"""Return (table_label, name) for all named features on a body."""
|
||||
features = []
|
||||
for table, label in [
|
||||
("atlas_cities", "city"),
|
||||
("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"),
|
||||
("atlas_mountain_ranges", "mountain"),
|
||||
("atlas_pois", "poi"),
|
||||
]:
|
||||
rows = conn.execute(
|
||||
f"SELECT name FROM {table} WHERE body_id=? AND name != ''", (body_id,)
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
features.append((label, r["name"]))
|
||||
return features
|
||||
|
||||
|
||||
def stem_of(name: str) -> str:
|
||||
"""Extract first significant word as a rough stem."""
|
||||
parts = name.replace("The ", "").replace("the ", "").strip().split()
|
||||
return parts[0].lower() if parts else ""
|
||||
|
||||
|
||||
def report_empty_names(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("EMPTY OR SINGLE-CHARACTER NAMES")
|
||||
where_clauses = []
|
||||
params = []
|
||||
if body_id:
|
||||
where_clauses.append("body_id = ?")
|
||||
params.append(body_id)
|
||||
elif system_id:
|
||||
where_clauses.append("body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)")
|
||||
params.append(system_id)
|
||||
w = f"WHERE {' AND '.join(where_clauses)}" if where_clauses else ""
|
||||
found = 0
|
||||
for table in ("atlas_cities", "atlas_rivers", "atlas_oceans",
|
||||
"atlas_mountain_ranges", "atlas_pois"):
|
||||
rows = conn.execute(
|
||||
f"SELECT body_id, local_id, name FROM {table} {w} "
|
||||
f"AND (name = '' OR LENGTH(name) < 2)", params
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
print(f" [{table}] {r['body_id']}/{r['local_id']}: '{r['name']}'")
|
||||
found += 1
|
||||
if not found:
|
||||
print(" None found.")
|
||||
|
||||
|
||||
def report_generic_lazy(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("GENERIC / LAZY OUTPUTS")
|
||||
where_body = ""
|
||||
params_base = []
|
||||
if body_id:
|
||||
where_body = "AND body_id = ?"
|
||||
params_base = [body_id]
|
||||
elif system_id:
|
||||
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
||||
params_base = [system_id]
|
||||
|
||||
found = 0
|
||||
for table, label in [
|
||||
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
||||
("atlas_pois", "poi"),
|
||||
]:
|
||||
hits = {}
|
||||
for pattern in LAZY_PATTERNS:
|
||||
rows = conn.execute(
|
||||
f"SELECT body_id, local_id, name FROM {table} "
|
||||
f"WHERE name LIKE ? {where_body}",
|
||||
[pattern] + params_base,
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
key = f"{r['body_id']}/{r['local_id']}"
|
||||
if key not in hits:
|
||||
hits[key] = (r['body_id'], r['local_id'], r['name'], label)
|
||||
|
||||
for key, (bid, lid, name, lbl) in sorted(hits.items()):
|
||||
print(f" [{lbl}] {bid}/{lid}: '{name}'")
|
||||
found += 1
|
||||
|
||||
if not found:
|
||||
print(" None found.")
|
||||
|
||||
|
||||
def report_cardinals(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("CARDINAL DIRECTION NAMES (check if map-orientation correlates)")
|
||||
where_body = ""
|
||||
params_base = []
|
||||
if body_id:
|
||||
where_body = "AND body_id = ?"
|
||||
params_base = [body_id]
|
||||
elif system_id:
|
||||
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
||||
params_base = [system_id]
|
||||
|
||||
by_body: dict[str, list] = {}
|
||||
for table, label in [
|
||||
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
||||
]:
|
||||
for cardinal in CARDINALS:
|
||||
rows = conn.execute(
|
||||
f"SELECT body_id, local_id, name FROM {table} "
|
||||
f"WHERE (name LIKE ? OR name LIKE ?) {where_body}",
|
||||
[f"{cardinal} %", f"% {cardinal} %"] + params_base,
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
by_body.setdefault(r["body_id"], []).append(
|
||||
(label, r["local_id"], r["name"])
|
||||
)
|
||||
|
||||
if not by_body:
|
||||
print(" None found.")
|
||||
return
|
||||
for bid, entries in sorted(by_body.items()):
|
||||
print(f" {bid}: {len(entries)} cardinal name(s)")
|
||||
for lbl, lid, name in entries:
|
||||
print(f" [{lbl}] {lid}: '{name}'")
|
||||
|
||||
|
||||
def report_earth_echoes(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("EARTH-ECHO CONCENTRATION (allowed but check intentionality)")
|
||||
where_body = ""
|
||||
params_base = []
|
||||
if body_id:
|
||||
where_body = "AND body_id = ?"
|
||||
params_base = [body_id]
|
||||
elif system_id:
|
||||
where_body = "AND body_id IN (SELECT body_id FROM bodies WHERE system_id = ?)"
|
||||
params_base = [system_id]
|
||||
|
||||
by_body: dict[str, list] = {}
|
||||
for table, label in [
|
||||
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
||||
]:
|
||||
for pattern in EARTH_ECHOES:
|
||||
rows = conn.execute(
|
||||
f"SELECT body_id, local_id, name FROM {table} "
|
||||
f"WHERE name LIKE ? {where_body}",
|
||||
[f"%{pattern.replace('%', '')}%"] + params_base,
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
key = (r["body_id"], label, r["local_id"])
|
||||
by_body.setdefault(r["body_id"], []).append(
|
||||
(label, r["local_id"], r["name"])
|
||||
)
|
||||
|
||||
if not by_body:
|
||||
print(" None found.")
|
||||
return
|
||||
for bid, entries in sorted(by_body.items()):
|
||||
print(f" {bid}: {len(entries)} earth-echo(s)")
|
||||
for lbl, lid, name in entries:
|
||||
print(f" [{lbl}] {lid}: '{name}'")
|
||||
|
||||
|
||||
def report_same_body_stem_dupes(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("SAME-BODY CROSS-FEATURE STEM DUPLICATES")
|
||||
where = ""
|
||||
params = []
|
||||
if body_id:
|
||||
where = "WHERE body_id = ?"
|
||||
params = [body_id]
|
||||
elif system_id:
|
||||
where = "WHERE system_id = ?"
|
||||
params = [system_id]
|
||||
|
||||
bodies_q = conn.execute(
|
||||
f"SELECT body_id FROM bodies {where}", params
|
||||
).fetchall()
|
||||
|
||||
found = 0
|
||||
for row in bodies_q:
|
||||
bid = row["body_id"]
|
||||
features = run_all_features_for_body(conn, bid)
|
||||
stem_to_features: dict[str, list] = {}
|
||||
for label, name in features:
|
||||
s = stem_of(name)
|
||||
if s and len(s) > 3:
|
||||
stem_to_features.setdefault(s, []).append((label, name))
|
||||
for stem, items in sorted(stem_to_features.items()):
|
||||
if len(items) > 1:
|
||||
types = set(i[0] for i in items)
|
||||
if len(types) > 1: # only flag cross-feature (different types)
|
||||
print(f" {bid} stem='{stem}':")
|
||||
for lbl, nm in items:
|
||||
print(f" [{lbl}] '{nm}'")
|
||||
found += 1
|
||||
if not found:
|
||||
print(" None found.")
|
||||
|
||||
|
||||
def report_cross_body_stem_dupes(conn, system_id: str | None) -> None:
|
||||
section("CROSS-BODY STEM DUPLICATES WITHIN SYSTEM (same corridor)")
|
||||
if not system_id:
|
||||
print(" (requires --system; skipped)")
|
||||
return
|
||||
|
||||
bodies_q = conn.execute(
|
||||
"SELECT body_id FROM bodies WHERE system_id = ?", (system_id,)
|
||||
).fetchall()
|
||||
|
||||
# Collect all names per table across all bodies
|
||||
all_names: dict[str, list[tuple[str, str]]] = {} # name -> [(body_id, table)]
|
||||
for row in bodies_q:
|
||||
bid = row["body_id"]
|
||||
for table, label in [
|
||||
("atlas_cities", "city"), ("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"), ("atlas_mountain_ranges", "mountain"),
|
||||
("atlas_pois", "poi"),
|
||||
]:
|
||||
rows = conn.execute(
|
||||
f"SELECT name FROM {table} WHERE body_id=? AND name != ''", (bid,)
|
||||
).fetchall()
|
||||
for r in rows:
|
||||
name = r["name"]
|
||||
s = stem_of(name)
|
||||
if s and len(s) > 3:
|
||||
all_names.setdefault(s, []).append((bid, label, name))
|
||||
|
||||
found = 0
|
||||
for stem, hits in sorted(all_names.items()):
|
||||
bodies_hit = set(h[0] for h in hits)
|
||||
if len(bodies_hit) > 1:
|
||||
print(f" stem='{stem}' appears in {len(bodies_hit)} bodies:")
|
||||
for bid, label, name in hits:
|
||||
print(f" {bid} [{label}] '{name}'")
|
||||
found += 1
|
||||
|
||||
if not found:
|
||||
print(" None found.")
|
||||
|
||||
|
||||
def report_summary_score(conn, system_id: str | None, body_id: str | None) -> None:
|
||||
section("BODY SUMMARY SCORES")
|
||||
where = ""
|
||||
params = []
|
||||
if body_id:
|
||||
where = "WHERE body_id = ?"
|
||||
params = [body_id]
|
||||
elif system_id:
|
||||
where = "WHERE system_id = ?"
|
||||
params = [system_id]
|
||||
else:
|
||||
where = "WHERE inhabited = 1"
|
||||
|
||||
bodies_q = conn.execute(
|
||||
f"SELECT body_id, proper_name, population FROM bodies {where}", params
|
||||
).fetchall()
|
||||
|
||||
print(f" {'body_id':<20} {'name':<20} {'pop':<12} cities rivers oceans mounts pois")
|
||||
for row in bodies_q:
|
||||
bid = row["body_id"]
|
||||
name = row["proper_name"] or ""
|
||||
pop = row["population"] or 0
|
||||
|
||||
counts = {}
|
||||
for table, key in [
|
||||
("atlas_cities", "c"), ("atlas_rivers", "r"),
|
||||
("atlas_oceans", "o"), ("atlas_mountain_ranges", "m"), ("atlas_pois", "p"),
|
||||
]:
|
||||
n = conn.execute(
|
||||
f"SELECT COUNT(*) FROM {table} WHERE body_id=?", (bid,)
|
||||
).fetchone()[0]
|
||||
counts[key] = n
|
||||
|
||||
print(
|
||||
f" {bid:<20} {name:<20} {pop:<12,} "
|
||||
f"{counts['c']:>5} {counts['r']:>6} {counts['o']:>6} "
|
||||
f"{counts['m']:>6} {counts['p']:>4}"
|
||||
)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("--system", help="GJ catalog ID (e.g. 'GJ 144')")
|
||||
parser.add_argument("--body", help="Body ID (e.g. 'GJ144d')")
|
||||
parser.add_argument("--db", default=str(DB_PATH), help="Path to systems.db")
|
||||
args = parser.parse_args()
|
||||
|
||||
db = Path(args.db)
|
||||
if not db.exists():
|
||||
print(f"error: database not found at {db}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
conn = get_conn(db)
|
||||
|
||||
system_id = args.system
|
||||
body_id = args.body
|
||||
|
||||
if body_id and not system_id:
|
||||
row = conn.execute(
|
||||
"SELECT system_id FROM bodies WHERE body_id=?", (body_id,)
|
||||
).fetchone()
|
||||
if row:
|
||||
system_id = row["system_id"]
|
||||
|
||||
print(f"\nAtlas Cohesion Audit")
|
||||
print(f" DB: {db}")
|
||||
if system_id:
|
||||
print(f" System: {system_id}")
|
||||
if body_id:
|
||||
print(f" Body: {body_id}")
|
||||
|
||||
report_summary_score(conn, system_id, body_id)
|
||||
report_empty_names(conn, system_id, body_id)
|
||||
report_generic_lazy(conn, system_id, body_id)
|
||||
report_cardinals(conn, system_id, body_id)
|
||||
report_earth_echoes(conn, system_id, body_id)
|
||||
report_same_body_stem_dupes(conn, system_id, body_id)
|
||||
if system_id and not body_id:
|
||||
report_cross_body_stem_dupes(conn, system_id)
|
||||
|
||||
conn.close()
|
||||
print("\nDone.\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,248 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
atlas_quality_analysis.py — Atlas content quality audit for Sprint 36 (#849/#838).
|
||||
|
||||
Queries atlas_* tables in systems.db and reports on:
|
||||
1. Cross-body name collisions (same name, same feature type, different bodies)
|
||||
2. Cardinal/directional name density per body
|
||||
3. Generic/lazy name patterns
|
||||
4. Earth-echo concentration in high-visibility systems
|
||||
5. Top-stem frequency across all named features
|
||||
|
||||
Usage:
|
||||
python3 tooling/planet-gen/atlas_quality_analysis.py [--db server/data/systems.db]
|
||||
python3 tooling/planet-gen/atlas_quality_analysis.py --system GJ380
|
||||
python3 tooling/planet-gen/atlas_quality_analysis.py --top-collisions 20
|
||||
python3 tooling/planet-gen/atlas_quality_analysis.py --body GJ71c
|
||||
|
||||
D-191 §8: markers.json is pixel-space [row, col] against 512×256.
|
||||
Re-run after any hand-refine pass to verify improvements.
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import re
|
||||
import sqlite3
|
||||
from collections import Counter, defaultdict
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parent.parent.parent
|
||||
DEFAULT_DB = REPO_ROOT / "server" / "data" / "systems.db"
|
||||
|
||||
CARDINAL_RE = re.compile(
|
||||
r"\b(north|south|east|west|eastern|western|northern|southern|"
|
||||
r"upper|lower|new|great|old|central|inner|outer|kita|minami|higashi|nishi)\b",
|
||||
re.I,
|
||||
)
|
||||
GENERIC_RE = re.compile(
|
||||
r"\b(hilly|sector|zone|district)\b"
|
||||
r"|^(great|the great|hilly)\b"
|
||||
r"|^(valley floor|ridge line|ridge crest|flat ground|riverbend)$",
|
||||
re.I,
|
||||
)
|
||||
EARTH_ECHO_RE = re.compile(
|
||||
r"\b(manchester|london|paris|berlin|tokyo|beijing|new york|sydney|dubai|"
|
||||
r"route \d+|sector \d+|block \d+)\b",
|
||||
re.I,
|
||||
)
|
||||
FEATURE_TABLES = [
|
||||
("atlas_cities", "city"),
|
||||
("atlas_rivers", "river"),
|
||||
("atlas_oceans", "ocean"),
|
||||
("atlas_mountain_ranges", "mountain"),
|
||||
]
|
||||
|
||||
|
||||
def open_db(path: str) -> sqlite3.Connection:
|
||||
return sqlite3.connect(path)
|
||||
|
||||
|
||||
def build_body_index(conn: sqlite3.Connection) -> dict:
|
||||
c = conn.cursor()
|
||||
c.execute(
|
||||
"SELECT body_id, system_id, proper_name, cultural_corridor, population "
|
||||
"FROM bodies WHERE inhabited=1"
|
||||
)
|
||||
return {
|
||||
r[0]: {"system_id": r[1], "name": r[2], "corridor": r[3], "pop": r[4]}
|
||||
for r in c.fetchall()
|
||||
}
|
||||
|
||||
|
||||
def gather_all_names(conn: sqlite3.Connection) -> dict[str, list[tuple[str, str, str]]]:
|
||||
"""body_id → [(feature_type, name, local_id), ...]"""
|
||||
c = conn.cursor()
|
||||
result = defaultdict(list)
|
||||
for tbl, feat_type in FEATURE_TABLES:
|
||||
try:
|
||||
c.execute(f"SELECT body_id, name, local_id FROM {tbl} WHERE name IS NOT NULL AND name != ''")
|
||||
for body_id, name, local_id in c.fetchall():
|
||||
result[body_id].append((feat_type, name, local_id))
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
return result
|
||||
|
||||
|
||||
def cross_body_collisions(conn: sqlite3.Connection, limit: int = 20) -> dict:
|
||||
c = conn.cursor()
|
||||
collisions = {}
|
||||
for tbl, feat_type in FEATURE_TABLES:
|
||||
try:
|
||||
c.execute(
|
||||
f"SELECT name, COUNT(DISTINCT body_id) as cnt, GROUP_CONCAT(DISTINCT body_id) "
|
||||
f"FROM {tbl} WHERE name IS NOT NULL AND name != '' "
|
||||
f"GROUP BY name HAVING cnt > 1 ORDER BY cnt DESC LIMIT ?",
|
||||
(limit,),
|
||||
)
|
||||
collisions[feat_type] = [(r[0], r[1], r[2]) for r in c.fetchall()]
|
||||
except sqlite3.OperationalError:
|
||||
collisions[feat_type] = []
|
||||
return collisions
|
||||
|
||||
|
||||
def stem_frequency(names: list[str], top_n: int = 30) -> list[tuple[str, int]]:
|
||||
stems = Counter()
|
||||
for name in names:
|
||||
words = name.split()
|
||||
if words:
|
||||
stems[words[0].lower()] += 1
|
||||
return stems.most_common(top_n)
|
||||
|
||||
|
||||
def body_quality_report(body_id: str, names: list[tuple], conn: sqlite3.Connection) -> dict:
|
||||
total = len(names)
|
||||
if total == 0:
|
||||
return {}
|
||||
cardinal = sum(1 for _, n, _ in names if CARDINAL_RE.search(n))
|
||||
generic = sum(1 for _, n, _ in names if GENERIC_RE.search(n))
|
||||
earth = sum(1 for _, n, _ in names if EARTH_ECHO_RE.search(n))
|
||||
|
||||
c = conn.cursor()
|
||||
# collision count: how many of this body's names appear on other bodies (same type)
|
||||
colliding = 0
|
||||
for feat_type, name, _ in names:
|
||||
tbl = [t for t, f in FEATURE_TABLES if f == feat_type][0]
|
||||
try:
|
||||
c.execute(
|
||||
f"SELECT COUNT(DISTINCT body_id) FROM {tbl} WHERE name=? AND body_id!=?",
|
||||
(name, body_id),
|
||||
)
|
||||
others = c.fetchone()[0]
|
||||
if others > 0:
|
||||
colliding += 1
|
||||
except sqlite3.OperationalError:
|
||||
pass
|
||||
|
||||
return {
|
||||
"total": total,
|
||||
"cardinal": cardinal,
|
||||
"cardinal_pct": cardinal / total,
|
||||
"generic": generic,
|
||||
"earth_echo": earth,
|
||||
"colliding": colliding,
|
||||
"colliding_pct": colliding / total,
|
||||
}
|
||||
|
||||
|
||||
def run_analysis(args):
|
||||
conn = open_db(args.db)
|
||||
body_index = build_body_index(conn)
|
||||
all_names_by_body = gather_all_names(conn)
|
||||
|
||||
# Filter by system or body if requested
|
||||
if args.system:
|
||||
body_index = {k: v for k, v in body_index.items() if v["system_id"] == args.system}
|
||||
if args.body:
|
||||
body_index = {k: v for k, v in body_index.items() if k == args.body}
|
||||
|
||||
print("=" * 70)
|
||||
print("ATLAS QUALITY ANALYSIS — The Settled Reach (#849/#838)")
|
||||
print(f"DB: {args.db}")
|
||||
if args.system:
|
||||
print(f"Filter: system={args.system}")
|
||||
if args.body:
|
||||
print(f"Filter: body={args.body}")
|
||||
print("=" * 70)
|
||||
|
||||
# --- 1. Cross-body collisions ---
|
||||
print("\n[ 1. CROSS-BODY NAME COLLISIONS ]")
|
||||
collisions = cross_body_collisions(conn, limit=args.top_collisions)
|
||||
for feat_type, rows in collisions.items():
|
||||
if rows:
|
||||
print(f"\n {feat_type}:")
|
||||
for name, cnt, bodies in rows:
|
||||
print(f" '{name}' — {cnt} bodies: {bodies[:80]}")
|
||||
|
||||
# --- 2. Per-body quality scores ---
|
||||
print("\n[ 2. BODY QUALITY SCORES — ranked by collision % ]")
|
||||
reports = []
|
||||
for bid, info in body_index.items():
|
||||
names = all_names_by_body.get(bid, [])
|
||||
if not names:
|
||||
continue
|
||||
report = body_quality_report(bid, names, conn)
|
||||
if not report:
|
||||
continue
|
||||
reports.append((bid, info, report))
|
||||
|
||||
reports.sort(key=lambda x: -x[2]["colliding_pct"])
|
||||
|
||||
print(f"\n {'Body':<28} {'System':<12} {'Corridor':<15} "
|
||||
f"{'Coll%':>6} {'Card%':>6} {'Gen':>4} {'Echo':>4}")
|
||||
for bid, info, rep in reports[:30]:
|
||||
print(
|
||||
f" {(info['name'] or bid):<28} {info['system_id']:<12} {info['corridor'] or '?':<15} "
|
||||
f"{rep['colliding_pct']:>6.0%} {rep['cardinal_pct']:>6.0%} "
|
||||
f"{rep['generic']:>4} {rep['earth_echo']:>4}"
|
||||
)
|
||||
|
||||
# --- 3. Stem frequency ---
|
||||
print("\n[ 3. TOP STEM FREQUENCY (first word of name) ]")
|
||||
all_names_flat = [n for names in all_names_by_body.values() for _, n, _ in names]
|
||||
for stem, cnt in stem_frequency(all_names_flat, top_n=20):
|
||||
print(f" {stem:<20} {cnt}")
|
||||
|
||||
# --- 4. Detailed body report (if --body specified) ---
|
||||
if args.body and args.body in all_names_by_body:
|
||||
bid = args.body
|
||||
info = body_index.get(bid, {})
|
||||
names = all_names_by_body[bid]
|
||||
print(f"\n[ 4. DETAILED REPORT: {bid} ({info.get('name', '?')}) ]")
|
||||
c = conn.cursor()
|
||||
for feat_type, name, local_id in sorted(names, key=lambda x: x[0]):
|
||||
tbl = [t for t, f in FEATURE_TABLES if f == feat_type][0]
|
||||
c.execute(
|
||||
f"SELECT COUNT(DISTINCT body_id) FROM {tbl} WHERE name=? AND body_id!=?",
|
||||
(name, bid),
|
||||
)
|
||||
others = c.fetchone()[0]
|
||||
flag = f" *** COLLISION ×{others}" if others > 0 else ""
|
||||
cardinal = " [cardinal]" if CARDINAL_RE.search(name) else ""
|
||||
generic = " [generic]" if GENERIC_RE.search(name) else ""
|
||||
print(f" {feat_type:<10} {local_id:<12} {name}{flag}{cardinal}{generic}")
|
||||
|
||||
# --- 5. Sol gap check ---
|
||||
print("\n[ 5. SOL SYSTEM GAP CHECK ]")
|
||||
c = conn.cursor()
|
||||
c.execute("SELECT body_id, proper_name, population FROM bodies WHERE system_id='GJ 0' AND inhabited=1")
|
||||
sol_bodies = c.fetchall()
|
||||
for bid, bname, pop in sol_bodies:
|
||||
has_cities = bid in all_names_by_body and any(f == "city" for f, _, _ in all_names_by_body[bid])
|
||||
status = "HAS DATA" if has_cities else "*** EMPTY — needs authoring"
|
||||
print(f" {bid:<15} {bname or '?':<20} pop={pop or '?'} {status}")
|
||||
|
||||
conn.close()
|
||||
print("\nDone.")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter)
|
||||
parser.add_argument("--db", default=str(DEFAULT_DB), help="Path to systems.db")
|
||||
parser.add_argument("--system", help="Filter to one system (e.g. GJ380)")
|
||||
parser.add_argument("--body", help="Filter to one body (e.g. GJ71c)")
|
||||
parser.add_argument("--top-collisions", type=int, default=15, help="Collision list limit")
|
||||
args = parser.parse_args()
|
||||
run_analysis(args)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -57,6 +57,7 @@ Vienna
|
||||
Prague
|
||||
Warsaw
|
||||
Amsterdam
|
||||
# GJ0d (Earth body) is exempt — this blocklist applies to alien worlds only, not to Earth itself.
|
||||
Brussels
|
||||
Copenhagen
|
||||
Stockholm
|
||||
|
||||
@@ -0,0 +1,477 @@
|
||||
# Hand-Refine Log — Ticket #849
|
||||
# Core-world atlas cohesion pass (Sprint 36)
|
||||
|
||||
Analyst: paula
|
||||
Date: 2026-04-19
|
||||
|
||||
---
|
||||
|
||||
## Analysis infrastructure
|
||||
|
||||
Created `tooling/planet-gen/atlas_cohesion_audit.py` — reusable SQL audit script for the
|
||||
atlas_* tables. Checks: empty/single-char names, generic/lazy outputs (% Fork, % Run, etc.),
|
||||
cardinal direction density, earth-echo concentration, same-body cross-feature stem duplicates,
|
||||
cross-body stem duplicates within a system. Accepts `--system`, `--body`, `--db` flags.
|
||||
|
||||
Created `tooling/planet-gen/apply_name_fixes.py` — applies curated name replacement tables to
|
||||
markers.json files (name fields only; geometry preserved). `--dry-run` supported. After running,
|
||||
caller must sync DB via `generate_atlas.py --body <id>`.
|
||||
|
||||
---
|
||||
|
||||
## Bodies touched
|
||||
|
||||
### GJ 144 — Ran system
|
||||
|
||||
#### GJ144d — Kallast (2B pop, urban_concentrated, ocean world)
|
||||
|
||||
**Priority reason:** Highest-population body in the Ran system; repeated player destination.
|
||||
Prior naming pass had done good Nordic groundwork (Rán's Landing, Seterfjellet, Rán's Run/Ranfall
|
||||
Beck cross-reference arc) but left residual generic oceans and one cross-system stem collision.
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | Aldren Pass | Randalfoss | "Aldren" stem collides with Lendel (GJ380c) capital + river "The Aldren" — cross-system noise |
|
||||
| ocean | Boulder Bluff | Keldmere | Generic; "Boulder Bluff" is a geographic descriptor for a landform, not a sea |
|
||||
| ocean | High Mesa | Seterfjord | "High Mesa" is nonsensical for an ocean; renamed to cross-ref mountain "Seterfjellet" |
|
||||
| poi | Summit Point | Kallast Gate Terminal | Generic; terminal should reference the capital city name |
|
||||
|
||||
**Cross-reference arcs post-fix:**
|
||||
- Rán-: Rán's Landing (city), Rán's Run (river), Randalfoss (river), Ranfall Beck (river), Rán Sea (ocean)
|
||||
- Seter-: Seterfjellet (mountain), Seterfjord (ocean)
|
||||
- Keld-: Keldmere (ocean), Timber Keld (river)
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ144d` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ144e — Vethis (1.2B pop, agricultural, dispersed_rural)
|
||||
|
||||
**Priority reason:** Second-most-populated Ran body; the rural agricultural contrast to Kallast.
|
||||
Prior naming pass was partial — extensive cardinals (West Bend), earth-echoes (Blue Ridge),
|
||||
overused stems (Ash-: 3 features; Iron-: 2 features), and many pure generics (Golden Valley,
|
||||
Broad Fork, Stone Point).
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | West Bend | Greywash Fork | Cardinal → cross-refs Greywash river (shared Grey- stem arc) |
|
||||
| river | Blue Ridge | Ashvale Beck | Earth-echo → cross-refs Ashvale city (shared Ash- stem arc) |
|
||||
| river | Stone Point | Thornrun | Generic → cross-refs Thorncrests mountain (shared Thorn- arc) |
|
||||
| river | Ironside Run | Kelside Run | Iron- overuse → cross-refs Kelbridge city (shared Kel- arc) |
|
||||
| ocean | Ashbluff Sea | Veth Mere | Ash- overuse (3 Ash- names) → cross-refs Veth Delta river (shared Veth- arc) |
|
||||
| mountain | Golden Valley | Greymoor Range | Generic → extends Grey- arc |
|
||||
| mountain | Broad Fork | Keld Spur | Generic → Nordic compound (keld = spring/source) |
|
||||
| mountain | Ashstone Ridge | Greystone Ridge | Ash- overuse → extends Grey- arc |
|
||||
| poi | Ridge Crossing | Vethis Gate Terminal | Generic → terminal named for the planet |
|
||||
|
||||
**Cross-reference arcs post-fix:**
|
||||
- Grey-: Greywash (river), Greywash Fork (river), Greymoor Range (mountain), Greystone Ridge (mountain)
|
||||
- Thorn-: Thorncrests (mountain), Thornrun (river)
|
||||
- Kel-: Kelbridge (city), Kelside Run (river), Keld Spur (mountain)
|
||||
- Veth-: Vethis (planet), Veth Delta (river), Veth Mere (ocean)
|
||||
- Ash-: Ashvale (city), Ashvale Beck (river) ← 2 names, was 3 before fix
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ144e` ✓
|
||||
|
||||
---
|
||||
|
||||
### GJ 71 — Tau Ceti system
|
||||
|
||||
#### GJ71c — Threshold (600M pop, agricultural, urban_concentrated)
|
||||
|
||||
**Priority reason:** Tau Ceti's primary inhabited body; high player footfall.
|
||||
All six rivers were named after the original Commission survey team — a strong narrative hook
|
||||
("Latin personal names = founding scientists"). "Aethelred" broke the pattern (Anglo-Saxon,
|
||||
wrong naming tradition).
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | Aethelred | Gaius | Anglo-Saxon name breaks all-Latin river pattern (Octavius, Septimus, Quintus, Valeria, Marcus, Gaius) |
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ71c` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ71d — Arden (500M pop, agricultural, dispersed_rural)
|
||||
|
||||
**Priority reason:** Tau Ceti's sister body; shares corridor with GJ71c, so cross-body stem
|
||||
duplicates matter most here. Two collisions found: exact POI name match + ocean/city stem match.
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| city | Concordia Hall | The Praxis | "Concordia" = GJ71c ocean name; cross-body stem collision within same system/corridor |
|
||||
| river | Basilica Nova | Via Principia | Exact name match with GJ71c POI "Basilica Nova"; direct duplicate across bodies |
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ71d` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ71d-1 — Verantis (20M pop, transit moon)
|
||||
|
||||
**No changes.** Discovered that Verantis was already updated in a prior sprint pass —
|
||||
mountains renamed to unique Latin institutional names (The Lateranum, The Curia Magna, The Exedra,
|
||||
The Aedes Sacra, The Macellum, The Oracle, The Comitium, Moeribee), capital updated to "Praetorium".
|
||||
DB was stale relative to markers.json; synced only.
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ71d-1` ✓
|
||||
|
||||
---
|
||||
|
||||
### GJ 244A — Sirius system
|
||||
|
||||
#### GJ244Ad — Edict (400M pop, hand-authored template)
|
||||
|
||||
**Priority reason:** Only inhabited body in the Sirius system. Hand-authored template is solid
|
||||
(Mandate, Founder's Range, Accord Peaks, Veto Spur, Concord Assembly Archive) but #833-generated
|
||||
features used wrong vocabulary for a political-legal world. Note: "Westwall" flagged by Gestalt
|
||||
does NOT appear in markers.json or DB — stale data issue; Cairnside fix by Gestalt stands, Edict
|
||||
required no Westwall action.
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| mountain | Keel Ridge | Charter Spur | "Keel" is nautical — wrong vocabulary; charter = founding document |
|
||||
| mountain | Sanction Ridge | The Statute | More distinctive; drops lazy "Ridge" suffix |
|
||||
| ocean | Upper Shelf | Veil Shelf | Cardinal → cross-refs Veil Institute Survey Station POI |
|
||||
| ocean | Southern Melt | Concord Mere | Cardinal → cross-refs Concord Assembly Archive POI |
|
||||
| ocean | Eastern Tarn | Charter Tarn | Cardinal → cross-refs mountain "Charter Spur" |
|
||||
|
||||
**Cross-reference arcs post-fix:**
|
||||
- Charter-: Charter Spur (mountain), Charter Tarn (ocean)
|
||||
- Concord-: Concord Mere (ocean), Concord Assembly Archive (POI)
|
||||
- Veil-: Veil Shelf (ocean), Veil Institute Survey Station (POI)
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ244Ad` ✓
|
||||
|
||||
---
|
||||
|
||||
### GJ 380 — Groombridge system
|
||||
|
||||
#### GJ380c — Lendel (900M pop, hand-authored template)
|
||||
|
||||
**Priority reason:** Only inhabited body in Groombridge. Template is excellent — Aldren arc
|
||||
(capital + river + exchange) is intentional and preserved. Two #833-generated features used lazy
|
||||
suffixes incompatible with the British-Isles naming style.
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | Pale Run | Durneth Beck | Lazy → cross-refs Durneth Range; "beck" = British stream |
|
||||
| mountain | Tember Ridge | Tember Spine | Lazy "Ridge" → "Spine"; keeps the Tember stem |
|
||||
|
||||
**Note:** "Aldren" stem in same-body audit (city + river + POI) is INTENTIONAL arc — preserved.
|
||||
"Meridian Risk HQ" POI is a corporation name (proper noun) — not geography, no change.
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ380c` ✓
|
||||
|
||||
**Addendum (PR #133 review):** Initial pass left GJ380c 100% Anglo-British register with zero
|
||||
cross-corridor influence from the Kumasi/south_reach trade lanes. Added two secondary features
|
||||
in Akan/Asante register, keeping primary features (Aldren capital, Durneth Range, Rethain Sea)
|
||||
in their established Anglo register:
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | The Kesset | Nkwanta Beck | Nkwanta = Akan "junction/crossroads" — trade-route name; Beck suffix localizes it |
|
||||
| mountain | Holt Spur | Bosomtwe Spur | Bosomtwe = sacred Asante lake in Ghana; Spur suffix preserved from Groombridge convention |
|
||||
| lake | Selet Basin | Subin Basin | Subin = river running through Kumasi itself — distributes Akan signal across a third feature type |
|
||||
|
||||
**Corridors are tendencies, not borders** — capital and primary geography stay Anglo-British;
|
||||
peripheral features reflect Kumasi trade influence. 3/29 features now carry Akan register (river, mountain, lake). DB re-synced.
|
||||
|
||||
---
|
||||
|
||||
### GJ 699 — Barnard's Star system
|
||||
|
||||
#### GJ699b — Verada (1.9B pop, hop-0, dense urban world)
|
||||
|
||||
**Priority reason:** Highest-traffic hop-0 inhabited body not yet addressed. Dense civic naming
|
||||
(Capitol Heights, Liberty Plaza, Metropolitan Square, Meridian City) was using district/plaza
|
||||
vocabulary for geographic features. Rivers especially broken: "Grandview Square" and "Meridian
|
||||
City" are civic addresses, not river names. Cross-body dups on sibling bodies.
|
||||
|
||||
**Changes:**
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| river | Grandview Square | Verada Reach | Civic square → planet name + geographic "Reach" |
|
||||
| river | Meridian City | The Meridian | Civic city name → proper river name (like "The Aldren") |
|
||||
| river | Summit View | Capitol Beck | Lazy → cross-refs Capitol Heights capital |
|
||||
| ocean | Prospect Terrace | Prospect Sea | "Terrace" is architecture; fix suffix |
|
||||
| ocean | Metropolitan Square | Haven Sea | Cross-refs Port Haven city; drops civic |
|
||||
| ocean | Central District | Meridian Sound | Exact dup of GJ699b-1 mountain; cross-refs The Meridian |
|
||||
| ocean | Liberty Plaza | Capitol Mere | Civic plaza → cross-refs Capitol Heights capital |
|
||||
| ocean | Sterling Heights | Sterling Pool | "Heights" wrong for water; dup on GJ699b-1 mountain |
|
||||
|
||||
**Cross-reference arcs post-fix:**
|
||||
- Capitol-: Capitol Heights (city), Capitol Beck (river), Capitol Mere (ocean)
|
||||
- Meridian-: The Meridian (river), Meridian Sound (ocean)
|
||||
- Haven/Port-: Port Haven (city), Haven Sea (ocean)
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ699b` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ699b-1 — Verada's moon (uninhabited transit body)
|
||||
|
||||
**Priority reason:** All 8 mountains named after urban street addresses (Grandview Avenue,
|
||||
Harmony Boulevard, Beacon Street, Metropolitan Way, etc.) — completely inappropriate for
|
||||
mountain ranges. Also duplicated several Verada city/ocean names exactly ("Central District",
|
||||
"Capitol Heights"). Fixed with institutional cross-references: the moon's mountains carry the
|
||||
names of Verada's governing institutions, as if settlers named what they saw below from orbit.
|
||||
|
||||
**Changes:** All 8 mountains renamed. See apply_name_fixes.py FIXES table for full mapping.
|
||||
|
||||
**Narrative hook:** "On Verada's moon, the mountains carry the names of the institutions
|
||||
that govern the world below — a form of reverence. The moon has no government of its own."
|
||||
|
||||
**DB sync:** sync_markers_to_db() called directly (body is inhabited=0, generate_atlas.py skips it) ✓
|
||||
|
||||
---
|
||||
|
||||
### Sol (GJ 0) — COMPLETE
|
||||
|
||||
**Approach:** sol_import.py generated body directories and markers.json from real-world geographic
|
||||
data. Post-generation, `sol_name_fixes.py` named all auto-detected null-name features.
|
||||
|
||||
Team-lead guidance: "real-world Earth/Luna/Mars geography is by definition coherent — note it
|
||||
in log and move on if already above quality bar."
|
||||
|
||||
#### GJ0d — Earth (8.5B pop, core world)
|
||||
|
||||
sol_import.py originally placed 50 cities from earth_features.json. Team-lead directed trim
|
||||
to 8-12 cultural touchstones (max 8 cities on any other body; 50 = 13% of all atlas cities
|
||||
on one body). Criterion: would a player setting a bookmark to "Earth" recognize this as a
|
||||
touchstone? One per major historical/cultural cluster.
|
||||
|
||||
**Cities kept (11):**
|
||||
|
||||
| City | Cluster |
|
||||
|---|---|
|
||||
| London | Western Europe — historical capital |
|
||||
| Moscow | Eastern Europe / Russia |
|
||||
| Istanbul | Bridge city — Europe-Asia hinge |
|
||||
| New York | North America |
|
||||
| São Paulo | South America |
|
||||
| Cairo | Africa + ancient world |
|
||||
| Delhi | South Asia |
|
||||
| Tokyo | Japan / East Asia |
|
||||
| Beijing | China / East Asia |
|
||||
| Singapore | Southeast Asia — maritime hub |
|
||||
| Sydney | Oceania |
|
||||
|
||||
**Cities cut (39):** Paris, Berlin, Mexico City, Los Angeles, Toronto, Chicago, Lima, Bogotá,
|
||||
Rio de Janeiro, Buenos Aires, Lagos, Kinshasa, Johannesburg, Nairobi, Tehran, Baghdad, Riyadh,
|
||||
Ankara, Karachi, Shanghai, Mumbai, Jakarta, Dhaka, Manila, Bangkok, Seoul, Osaka, Chongqing,
|
||||
Kolkata, Lahore, Shenzhen, Bangalore, Ho Chi Minh City, Luanda, Addis Ababa, Santiago, Taipei,
|
||||
Hong Kong, Casablanca.
|
||||
|
||||
**PR #133 review rebalance (user-approved Option 1 + London swap):**
|
||||
- `Sydney → Lagos` — improves African representation (Cairo + Lagos = 2 African cities; Sydney was the weakest cultural-touchstone anchor).
|
||||
- `London → Brussels` — Brussels chosen for future-strong-EU-capital setting fit over London's legacy cultural weight.
|
||||
|
||||
**Final 11:** Beijing, Brussels, Cairo, Delhi, Istanbul, Lagos, Moscow, New York, São Paulo, Singapore, Tokyo.
|
||||
|
||||
**Generator note:** sol_import.py has no `--top-n` city filter — it uses the full earth_features.json
|
||||
list. If Sol is regenerated, earth_features.json should be trimmed to the 11 kept cities, or a
|
||||
filter added in sol_import.py. Filed as finding in #853.
|
||||
|
||||
auto-detected 11 rivers and 1 ocean. Three rivers were auto-detected ocean-channel artifacts
|
||||
in the western Pacific island region; named with geographically proximate rivers. The large
|
||||
ocean (area_fraction=0.7049) represents Earth's interconnected world ocean.
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| ocean | null | The World Ocean | 70% surface = all Earth's oceans unified; scientifically accurate name |
|
||||
| river | null (river_1, ~50°N/17°E) | Dnieper | Eastern Europe, flows to Black Sea |
|
||||
| river | null (river_4, ~27°N/136°E) | Tone River | Japan, Kanto plain |
|
||||
| river | null (river_10, ~23°N/135°E) | Cagayan | Northern Philippines, largest Philippine river |
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ0d` ✓ (11 cities, trimmed from 50)
|
||||
|
||||
---
|
||||
|
||||
#### GJ0d-1 — Luna (350M pop, transit body)
|
||||
|
||||
3 cities (Artemis capital, Tranquility Station, Selene) + 10 POIs (maria + craters). sol_import.py
|
||||
auto-detected 24 mountain ranges — all unnamed. Named all 24 after real IAU-catalogued lunar
|
||||
mountain systems, massifs, and scarps, sorted by area_cells (largest = most prominent).
|
||||
|
||||
Key ranges: Montes Apenninus (11,221 cells — largest), Montes Caucasus (3,670), Montes Jura,
|
||||
Montes Alpes, Montes Rook, Montes Cordillera, Montes Carpatus, Montes Taurus, Montes Pyrenaeus,
|
||||
and 15 additional real lunar named features (Pico Mons, Haemus Montes, Gruithuisen Domes, etc.).
|
||||
|
||||
**Narrative hook:** "Luna's mountains carry the names that Earth gave them a thousand years
|
||||
before the first settlement — a catalog written from below, now walked from above."
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ0d-1` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ0e — Mars (1.2B pop, core world)
|
||||
|
||||
4 cities + 5 named mountains (Olympus Mons, Tharsis Bulge, Elysium Mons, Ascraeus Mons,
|
||||
Arsia Mons) from mars_features.json. sol_import.py auto-detected 4 additional mountain ranges
|
||||
in the anti-Tharsis hemisphere (ancient cratered highland region), named after real Martian
|
||||
volcanic features.
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| mountain | null (range_2) | Tyrrhena Mons | Ancient volcanic highland, eastern hemisphere |
|
||||
| mountain | null (range_3) | Hadriaca Mons | Old shield volcano, Hellas region |
|
||||
| mountain | null (range_4) | Amphitrites Montes | Near south polar region |
|
||||
| mountain | null (range_5) | Hellespontus Montes | Cross-refs Hellas Station city |
|
||||
|
||||
**Cross-reference arcs:** Hellas- (Hellas Basin ocean + Hellas Station city), Chryse- (Chryse Landing + Chryse Planitia POI)
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ0e` ✓
|
||||
|
||||
---
|
||||
|
||||
#### GJ0f-2 — Europa (30M pop, outer body)
|
||||
|
||||
2 cities + 4 POIs. sol_import.py auto-detected 1 mountain range covering essentially the
|
||||
entire body surface (area_cells=123,557 — Europa's ridged ice terrain).
|
||||
|
||||
| Feature type | Old name | New name | Reason |
|
||||
|---|---|---|---|
|
||||
| mountain | null (range_1) | Conamara Ridges | Cross-refs Conamara Station + Conamara Chaos POI |
|
||||
|
||||
**Cross-reference arcs:** Conamara- (Conamara Station city + Conamara Ridges mountain + Conamara Chaos POI),
|
||||
Pwyll- (Pwyll Base city + Pwyll Crater POI)
|
||||
|
||||
**DB sync:** `generate_atlas.py --body GJ0f-2` ✓
|
||||
|
||||
---
|
||||
|
||||
**Sol final audit result:** Zero empty names, zero lazy outputs, zero cardinals.
|
||||
Earth-echo names on Earth are intentional (real-world cities). Quality cross-reference arcs
|
||||
confirmed on Mars (Hellas-, Chryse-) and Europa (Conamara-, Pwyll-).
|
||||
|
||||
---
|
||||
|
||||
### Proxima (GJ 551) — DEFERRED
|
||||
|
||||
Cross-body stem duplicates found (Basilica, Pantheon, Senate across Ancora sibling bodies).
|
||||
Team-lead confirmed: defer this sprint. Finding documented for future pass.
|
||||
|
||||
---
|
||||
|
||||
## Audit metrics — final confirmed delta
|
||||
|
||||
Final audit run: 2026-04-19. All 6 systems re-run after all edits. Results below are
|
||||
from `atlas_cohesion_audit.py` against `server/data/systems.db`.
|
||||
|
||||
### Inhabited body targets (in scope for this ticket)
|
||||
|
||||
| System | Body | Empty names: before→after | Lazy outputs: before→after | Cardinals: before→after |
|
||||
|--------|------|--------------------------|---------------------------|------------------------|
|
||||
| GJ 144 | GJ144d Kallast (2B) | 0→0 | 3→0 | 0→0 |
|
||||
| GJ 144 | GJ144e Vethis (1.2B) | 0→0 | 7→0 | 1→0 |
|
||||
| GJ 71 | GJ71c Threshold (600M) | 0→0 | 1→0 | 0→0 |
|
||||
| GJ 71 | GJ71d Arden (500M) | 0→0 | 1→0 | 0→0 |
|
||||
| GJ 71 | GJ71d-1 Verantis (20M) | 0→0 | 0→0 | 0→0 |
|
||||
| GJ 244A | GJ244Ad Edict (400M) | 0→0 | 2→0 | 3→0 |
|
||||
| GJ 380 | GJ380c Lendel (900M) | 0→0 | 2→0 | 0→0 |
|
||||
| GJ 699 | GJ699b Verada (1.9B) | 0→0 | 8→0 | 0→0 |
|
||||
| GJ 699 | GJ699b-1 (uninhabited moon) | 8→0 | 8→0 | 0→0 |
|
||||
| GJ 0 | GJ0d Earth (8.5B) | 4→0 | 0→0 | 0→0 |
|
||||
| GJ 0 | GJ0d-1 Luna (350M) | 24→0 | 0→0 | 0→0 |
|
||||
| GJ 0 | GJ0e Mars (1.2B) | 4→0 | 0→0 | 0→0 |
|
||||
| GJ 0 | GJ0f-2 Europa (30M) | 1→0 | 0→0 | 0→0 |
|
||||
|
||||
**All inhabited targets: zero empty names, zero lazy outputs, zero cardinals after fixes.**
|
||||
|
||||
### Remaining audit flags — out of scope or false positives
|
||||
|
||||
After fixes, the audit still reports flags on:
|
||||
|
||||
**Out of scope — uninhabited/low-pop bodies (not "high-visibility"):**
|
||||
- GJ144b, GJ144c, GJ144d-1, GJ144e-1, GJ144f, GJ144g-1, GJ144g-2: "Canyon View", "Dry Gulch",
|
||||
"Stone Creek" etc. These are #833 batch artifacts on non-target bodies. Captured in #853.
|
||||
- GJ71e: "Meridian Point" (uninhabited body, not in scope)
|
||||
- GJ380b, GJ380d, GJ380e: various lazy patterns (uninhabited, not in scope)
|
||||
|
||||
**False positives on quality cross-reference names (distinctive stem + common suffix):**
|
||||
- `'Rán's Run'` (GJ144d) — Rán- arc; % Run pattern-matched but stem is unique proper name
|
||||
- `'Greywash Fork'` (GJ144e) — Grey- arc; % Fork but Greywash is not a generic stem
|
||||
- `'Kelside Run'` (GJ144e) — Kel- arc; % Run but Kelside is distinctive
|
||||
- `'Greystone Ridge'` (GJ144e) — Grey- arc; % Ridge but Greystone is distinctive
|
||||
|
||||
These four are intentional renames (listed in the FIXES table above) that happen to end with
|
||||
a suffix in LAZY_PATTERNS. The script does not evaluate stem quality, only suffix pattern.
|
||||
A future pass on the audit script could add a stem-distinctiveness filter.
|
||||
|
||||
### Earth city count correction
|
||||
|
||||
Per team-lead direction: Earth trimmed from **50 → 11 cities** (cultural/historical touchstones,
|
||||
one per major cluster). 39 cities cut. DB synced. See GJ0d section above for full cut list.
|
||||
|
||||
### Earth city rebalance (PR #133 review, user-approved)
|
||||
|
||||
Sydney → Lagos and London → Brussels per PR #133 review, user-approved rebalance. Brussels chosen for future EU-capital setting fit over London's legacy weight; Lagos chosen for African representation. DB re-synced. Final 11: Brussels, Istanbul, Moscow, New York, São Paulo, Cairo, Lagos, Delhi, Tokyo, Beijing, Singapore.
|
||||
|
||||
**Total name edits across all bodies:** 23 (non-Sol) + 33 (Sol) = 56 feature renames.
|
||||
**Earth city cut:** 39 removed.
|
||||
|
||||
Intentional same-body cross-feature stem dups (quality arcs) now visible in audit output for:
|
||||
- GJ144d: Rán- (city + river), Seter- (mountain + ocean)
|
||||
- GJ144e: Veth- (river + ocean), Ash- (city + river)
|
||||
- GJ244Ad: Charter- (mountain + ocean), Concord- (ocean + POI), Veil- (ocean + POI)
|
||||
- GJ380c: Aldren- (city + river + POI, intentional), Durneth- (river + mountain)
|
||||
- GJ699b: Capitol- (city + river + ocean), Meridian- (river + ocean)
|
||||
- GJ0e: Hellas- (city + ocean), Chryse- (city + POI)
|
||||
- GJ0f-2: Conamara- (city + mountain + POI), Pwyll- (city + POI)
|
||||
|
||||
Spot-check verification queries:
|
||||
```bash
|
||||
SR_DB_PATH="$(pwd)/server/data/systems.db" tooling/db/sqlite-query \
|
||||
"SELECT local_id, name FROM atlas_rivers WHERE body_id = 'GJ144d'"
|
||||
# Should show "Randalfoss" not "Aldren Pass"
|
||||
|
||||
SR_DB_PATH="$(pwd)/server/data/systems.db" tooling/db/sqlite-query \
|
||||
"SELECT local_id, name FROM atlas_cities WHERE body_id = 'GJ71d'"
|
||||
# Should show "The Praxis" not "Concordia Hall"
|
||||
|
||||
SR_DB_PATH="$(pwd)/server/data/systems.db" tooling/db/sqlite-query \
|
||||
"SELECT local_id, name FROM atlas_mountain_ranges WHERE body_id = 'GJ244Ad'"
|
||||
# Should show "The Statute" and "Charter Spur" not "Sanction Ridge" and "Keel Ridge"
|
||||
|
||||
SR_DB_PATH="$(pwd)/server/data/systems.db" tooling/db/sqlite-query \
|
||||
"SELECT local_id, name FROM atlas_mountain_ranges WHERE body_id = 'GJ699b-1'"
|
||||
# Should show "Verada Scarp", "Barnard Heights", "Keystone Scarp", etc. — no street addresses
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files changed
|
||||
|
||||
- `tooling/planet-gen/atlas_cohesion_audit.py` (new)
|
||||
- `tooling/planet-gen/apply_name_fixes.py` (new — extended with all 6 systems)
|
||||
- `tooling/planet-gen/refine_log_849.md` (this file)
|
||||
- `tooling/planet-gen/sol_markers/luna_features.json` (added cities)
|
||||
- `tooling/planet-gen/sol_markers/mars_features.json` (added cities)
|
||||
- `tooling/planet-gen/sol_markers/outer_features.json` (added Europa cities)
|
||||
- `wiki/star-systems/GJ-144/bodies/GJ144d/markers.json` (4 edits)
|
||||
- `wiki/star-systems/GJ-144/bodies/GJ144e/markers.json` (9 edits)
|
||||
- `wiki/star-systems/GJ-71/bodies/GJ71c/markers.json` (1 edit)
|
||||
- `wiki/star-systems/GJ-71/bodies/GJ71d/markers.json` (2 edits)
|
||||
- `wiki/star-systems/GJ-244A/bodies/GJ244Ad/markers.json` (5 edits)
|
||||
- `wiki/star-systems/GJ-380/bodies/GJ380c/markers.json` (2 edits)
|
||||
- `wiki/star-systems/GJ-699/bodies/GJ699b/markers.json` (8 edits)
|
||||
- `wiki/star-systems/GJ-699/bodies/GJ699b-1/markers.json` (8 edits)
|
||||
- `tooling/planet-gen/sol_name_fixes.py` (new — names 33 null-name Sol features)
|
||||
- `wiki/star-systems/GJ-0/bodies/GJ0d/markers.json` (1 ocean + 3 rivers named; 39 cities cut → 11)
|
||||
- `wiki/star-systems/GJ-0/bodies/GJ0d-1/markers.json` (24 mountain ranges named)
|
||||
- `wiki/star-systems/GJ-0/bodies/GJ0e/markers.json` (4 mountain ranges named)
|
||||
- `wiki/star-systems/GJ-0/bodies/GJ0f-2/markers.json` (1 mountain range named)
|
||||
- `server/data/systems.db` (synced: GJ144d, GJ144e, GJ71c, GJ71d, GJ71d-1, GJ244Ad, GJ380c, GJ699b, GJ699b-1, GJ0d, GJ0d-1, GJ0e, GJ0f-2 — all complete)
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"GJ0d": {
|
||||
"_city_selection_note": "11 cultural touchstones, one per major historical/cultural cluster. Criterion: would a player setting a bookmark to 'Earth' recognize this city? Full 46-city reference list is in git history (trimmed Sprint 36 #849). PR #133 review rebalance: Sydney → Lagos (African representation); London → Brussels (future EU capital fit). To adjust: edit this array and re-run sol_import.py, then generate_atlas.py --body GJ0d.",
|
||||
"oceans": [
|
||||
{"name": "Pacific Ocean", "center": [128, 440]},
|
||||
{"name": "Atlantic Ocean", "center": [128, 170]},
|
||||
@@ -33,62 +34,22 @@
|
||||
{"name": "Murray", "mouth": [170, 417]}
|
||||
],
|
||||
"cities": [
|
||||
{"name": "London", "center": [79, 260], "population": 9000000, "region": "europe"},
|
||||
{"name": "Istanbul", "center": [83, 279], "population": 15000000, "region": "europe"},
|
||||
{"name": "Moscow", "center": [72, 294], "population": 12700000, "region": "europe"},
|
||||
{"name": "Paris", "center": [80, 261], "population": 11000000, "region": "europe"},
|
||||
{"name": "Berlin", "center": [77, 269], "population": 3700000, "region": "europe"},
|
||||
{"name": "Brussels", "center": [80, 266], "population": 2100000, "region": "europe"},
|
||||
{"name": "Istanbul", "center": [83, 279], "population": 15000000, "region": "europe"},
|
||||
{"name": "Moscow", "center": [72, 294], "population": 12700000, "region": "europe"},
|
||||
|
||||
{"name": "Mexico City", "center": [107, 101], "population": 21800000, "region": "north_america"},
|
||||
{"name": "New York", "center": [87, 130], "population": 20100000, "region": "north_america"},
|
||||
{"name": "Los Angeles", "center": [93, 95], "population": 13200000, "region": "north_america"},
|
||||
{"name": "Toronto", "center": [84, 123], "population": 6200000, "region": "north_america"},
|
||||
{"name": "Chicago", "center": [85, 115], "population": 9500000, "region": "north_america"},
|
||||
{"name": "New York", "center": [87, 130], "population": 20100000, "region": "north_america"},
|
||||
|
||||
{"name": "São Paulo", "center": [143, 164], "population": 22400000, "region": "south_america"},
|
||||
{"name": "Lima", "center": [133, 131], "population": 10700000, "region": "south_america"},
|
||||
{"name": "Bogotá", "center": [121, 135], "population": 11300000, "region": "south_america"},
|
||||
{"name": "Rio de Janeiro", "center": [142, 168], "population": 13500000, "region": "south_america"},
|
||||
{"name": "Buenos Aires", "center": [151, 153], "population": 15200000, "region": "south_america"},
|
||||
{"name": "São Paulo", "center": [143, 164], "population": 22400000, "region": "south_america"},
|
||||
|
||||
{"name": "Lagos", "center": [120, 262], "population": 15400000, "region": "africa"},
|
||||
{"name": "Kinshasa", "center": [124, 270], "population": 15600000, "region": "africa"},
|
||||
{"name": "Cairo", "center": [97, 286], "population": 21300000, "region": "africa"},
|
||||
{"name": "Johannesburg", "center": [156, 279], "population": 6000000, "region": "africa"},
|
||||
{"name": "Nairobi", "center": [128, 293], "population": 5100000, "region": "africa"},
|
||||
{"name": "Cairo", "center": [97, 286], "population": 21300000, "region": "africa"},
|
||||
|
||||
{"name": "Tehran", "center": [92, 308], "population": 9000000, "region": "west_asia"},
|
||||
{"name": "Baghdad", "center": [94, 303], "population": 8100000, "region": "west_asia"},
|
||||
{"name": "Riyadh", "center": [103, 304], "population": 7700000, "region": "west_asia"},
|
||||
{"name": "Ankara", "center": [87, 284], "population": 5700000, "region": "west_asia"},
|
||||
{"name": "Karachi", "center": [103, 327], "population": 16500000, "region": "west_asia"},
|
||||
{"name": "Tokyo", "center": [92, 400], "population": 37400000, "region": "east_asia"},
|
||||
{"name": "Delhi", "center": [99, 339], "population": 32900000, "region": "east_asia"},
|
||||
{"name": "Beijing", "center": [87, 383], "population": 21500000, "region": "east_asia"},
|
||||
|
||||
{"name": "Tokyo", "center": [92, 400], "population": 37400000, "region": "east_asia"},
|
||||
{"name": "Delhi", "center": [99, 339], "population": 32900000, "region": "east_asia"},
|
||||
{"name": "Shanghai", "center": [97, 387], "population": 28500000, "region": "east_asia"},
|
||||
{"name": "Beijing", "center": [87, 383], "population": 21500000, "region": "east_asia"},
|
||||
{"name": "Mumbai", "center": [107, 333], "population": 21700000, "region": "east_asia"},
|
||||
|
||||
{"name": "Jakarta", "center": [120, 374], "population": 34500000, "region": "fill"},
|
||||
{"name": "Dhaka", "center": [103, 351], "population": 23000000, "region": "fill"},
|
||||
{"name": "Manila", "center": [109, 388], "population": 14400000, "region": "fill"},
|
||||
{"name": "Bangkok", "center": [109, 370], "population": 11000000, "region": "fill"},
|
||||
{"name": "Seoul", "center": [90, 393], "population": 9800000, "region": "fill"},
|
||||
{"name": "Osaka", "center": [93, 398], "population": 19300000, "region": "fill"},
|
||||
{"name": "Chongqing", "center": [97, 375], "population": 17000000, "region": "fill"},
|
||||
{"name": "Kolkata", "center": [103, 349], "population": 15100000, "region": "fill"},
|
||||
{"name": "Lahore", "center": [97, 336], "population": 14000000, "region": "fill"},
|
||||
{"name": "Shenzhen", "center": [104, 382], "population": 13400000, "region": "fill"},
|
||||
{"name": "Bangalore", "center": [111, 339], "population": 13200000, "region": "fill"},
|
||||
{"name": "Ho Chi Minh City", "center": [113, 374], "population": 9300000, "region": "fill"},
|
||||
{"name": "Luanda", "center": [132, 268], "population": 9000000, "region": "fill"},
|
||||
{"name": "Addis Ababa", "center": [119, 292], "population": 5500000, "region": "fill"},
|
||||
{"name": "Santiago", "center": [147, 137], "population": 7000000, "region": "fill"},
|
||||
{"name": "Taipei", "center": [103, 388], "population": 7000000, "region": "fill"},
|
||||
{"name": "Hong Kong", "center": [104, 382], "population": 7500000, "region": "fill"},
|
||||
{"name": "Singapore", "center": [119, 372], "population": 5900000, "region": "fill"},
|
||||
{"name": "Sydney", "center": [161, 421], "population": 5300000, "region": "fill"},
|
||||
{"name": "Casablanca", "center": [93, 249], "population": 3800000, "region": "fill"}
|
||||
{"name": "Singapore", "center": [119, 372], "population": 5900000, "region": "southeast_asia"},
|
||||
{"name": "Lagos", "center": [119, 263], "population": 15000000, "region": "africa"}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
{
|
||||
"GJ0d-1": {
|
||||
"cities": [
|
||||
{"name": "Artemis", "center": [215, 250], "population": 200000000, "kind": "capital"},
|
||||
{"name": "Tranquility Station", "center": [119, 282], "population": 90000000, "kind": "city"},
|
||||
{"name": "Selene", "center": [93, 247], "population": 60000000, "kind": "city"}
|
||||
],
|
||||
"pois": [
|
||||
{"id": "poi_mare_tranquillitatis", "name": "Mare Tranquillitatis", "center": [119, 282], "kind": "mare"},
|
||||
{"id": "poi_mare_imbrium", "name": "Mare Imbrium", "center": [93, 247], "kind": "mare"},
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
{
|
||||
"GJ0e": {
|
||||
"cities": [
|
||||
{"name": "Olympia", "center": [107, 358], "population": 450000000, "kind": "capital"},
|
||||
{"name": "Hellas Station", "center": [148, 329], "population": 350000000, "kind": "city"},
|
||||
{"name": "Elysium City", "center": [103, 413], "population": 250000000, "kind": "city"},
|
||||
{"name": "Chryse Landing", "center": [100, 392], "population": 150000000, "kind": "city"}
|
||||
],
|
||||
"mountain_ranges": [
|
||||
{"name": "Olympus Mons", "peak": [107, 358], "center": [107, 358]},
|
||||
{"name": "Tharsis Bulge", "peak": [115, 365], "center": [118, 362]},
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
]
|
||||
},
|
||||
"GJ0f-2": {
|
||||
"cities": [
|
||||
{"name": "Conamara Station", "center": [118, 328], "population": 20000000, "kind": "capital"},
|
||||
{"name": "Pwyll Base", "center": [155, 328], "population": 10000000, "kind": "city"}
|
||||
],
|
||||
"pois": [
|
||||
{"id": "poi_conamara_chaos", "name": "Conamara Chaos", "center": [118, 328], "kind": "chaos"},
|
||||
{"id": "poi_pwyll_crater", "name": "Pwyll Crater", "center": [155, 328], "kind": "crater"},
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
sol_name_fixes.py — Name previously-unnamed Sol body auto-detected features.
|
||||
|
||||
Targets features with null names: Earth oceans/rivers, Luna/Mars/Europa mountain ranges.
|
||||
All names are real-world geographic names for Sol bodies.
|
||||
|
||||
Usage:
|
||||
python3 sol_name_fixes.py # apply all fixes
|
||||
python3 sol_name_fixes.py --dry-run # print planned changes without writing
|
||||
"""
|
||||
import argparse
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
REPO_ROOT = (Path(__file__).resolve().parent / ".." / "..").resolve()
|
||||
WIKI = REPO_ROOT / "wiki" / "star-systems" / "GJ-0" / "bodies"
|
||||
|
||||
# Keys are feature IDs; values are the names to assign.
|
||||
FIXES = {
|
||||
# Earth (GJ0d): 1 unnamed ocean + 3 unnamed rivers (auto-detected terrain artifacts)
|
||||
"GJ0d": {
|
||||
"oceans": {
|
||||
"water_1": "The World Ocean", # 70% surface = all Earth's oceans unified
|
||||
},
|
||||
"rivers": {
|
||||
"river_1": "Dnieper", # Eastern Europe ~50°N, 17°E
|
||||
"river_4": "Tone River", # Japan, Kanto plain ~36°N, 140°E
|
||||
"river_10": "Cagayan", # Northern Philippines ~18°N, 121°E
|
||||
},
|
||||
},
|
||||
# Luna (GJ0d-1): 24 unnamed mountain ranges — all auto-detected; named after
|
||||
# real lunar mountain systems, massifs, and scarps sorted by descending area.
|
||||
"GJ0d-1": {
|
||||
"mountain_ranges": {
|
||||
"range_5": "Montes Apenninus", # 11221 cells — largest lunar mountain range
|
||||
"range_34": "Montes Caucasus", # 3670 cells
|
||||
"range_209": "Montes Jura", # 367 cells — on Mare Imbrium NW
|
||||
"range_551": "Montes Alpes", # 289 cells — lunar Alps
|
||||
"range_576": "Montes Rook", # 258 cells — south polar mountains
|
||||
"range_599": "Montes Cordillera", # 164 cells — Orientale basin rim
|
||||
"range_326": "Montes Carpatus", # 106 cells — south of Mare Imbrium
|
||||
"range_555": "Montes Pyrenaeus", # 94 cells — east of Mare Nectaris
|
||||
"range_586": "Montes Taurus", # 90 cells — NE of Mare Serenitatis
|
||||
"range_589": "Montes Teneriffe", # 52 cells — isolated massif
|
||||
"range_124": "Montes Harbinger", # 51 cells — west of Aristarchus
|
||||
"range_587": "Montes Recti", # 48 cells — north Mare Imbrium
|
||||
"range_522": "Pico Mons", # 35 cells — isolated peak
|
||||
"range_579": "Haemus Montes", # 33 cells — south of Mare Serenitatis
|
||||
"range_231": "Gruithuisen Domes", # 25 cells — volcanic domes
|
||||
"range_580": "Mons La Hire", # 25 cells — volcanic dome, Mare Imbrium
|
||||
"range_570": "Montes Riphaeus", # 24 cells — Oceanus Procellarum ridge
|
||||
"range_596": "Montes Secchi", # 24 cells — east of Mare Fecunditatis
|
||||
"range_604": "Montes Spitzbergen", # 24 cells — isolated massif
|
||||
"range_493": "Malapert Mountain", # 23 cells — south pole region
|
||||
"range_406": "Doerfel Mountains", # 26 cells — south pole far side
|
||||
"range_432": "Altai Scarp", # 20 cells — Rupes Altai
|
||||
"range_79": "Mons Rümker", # 21 cells — shield volcano
|
||||
"range_348": "Leibnitz Mountains", # 21 cells — south polar range
|
||||
},
|
||||
},
|
||||
# Mars (GJ0e): 4 unnamed mountain ranges in the anti-Tharsis hemisphere
|
||||
"GJ0e": {
|
||||
"mountain_ranges": {
|
||||
"range_2": "Tyrrhena Mons", # ancient volcanic highland (area=67)
|
||||
"range_3": "Hadriaca Mons", # old shield volcano (area=31)
|
||||
"range_4": "Amphitrites Montes", # near south polar region (area=28)
|
||||
"range_5": "Hellespontus Montes", # cross-refs Hellas Station (area=87)
|
||||
},
|
||||
},
|
||||
# Europa (GJ0f-2): 1 unnamed mountain — Europa's ridged ice terrain (area=123557 cells)
|
||||
"GJ0f-2": {
|
||||
"mountain_ranges": {
|
||||
"range_1": "Conamara Ridges", # cross-refs Conamara Station + Conamara Chaos
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SECTION_MAP = {
|
||||
"oceans": "oceans",
|
||||
"rivers": "rivers",
|
||||
"mountain_ranges": "mountain_ranges",
|
||||
}
|
||||
|
||||
|
||||
def _check_dedup(fixes: dict) -> None:
|
||||
"""Raise if any name is assigned to more than one feature ID within a body."""
|
||||
for body_id, sections in fixes.items():
|
||||
for section, id_map in sections.items():
|
||||
seen: dict[str, str] = {}
|
||||
for fid, name in id_map.items():
|
||||
if name in seen:
|
||||
raise ValueError(
|
||||
f"Duplicate name {name!r} in {body_id}/{section}: "
|
||||
f"{seen[name]} and {fid} both assigned"
|
||||
)
|
||||
seen[name] = fid
|
||||
|
||||
|
||||
def apply_sol_fixes(dry_run: bool = False) -> None:
|
||||
_check_dedup(FIXES)
|
||||
for body_id, body_fixes in FIXES.items():
|
||||
path = WIKI / body_id / "markers.json"
|
||||
if not path.exists():
|
||||
print(f" SKIP {body_id}: markers.json not found")
|
||||
continue
|
||||
|
||||
with open(path) as f:
|
||||
markers = json.load(f)
|
||||
|
||||
changed = False
|
||||
for section, id_map in body_fixes.items():
|
||||
feature_list = markers.get(SECTION_MAP[section], [])
|
||||
for feature in feature_list:
|
||||
fid = feature.get("id", "")
|
||||
if fid in id_map:
|
||||
old = feature.get("name")
|
||||
new = id_map[fid]
|
||||
if old != new:
|
||||
print(f" [{body_id}/{section}] {fid}: {old!r} → {new!r}")
|
||||
if not dry_run:
|
||||
feature["name"] = new
|
||||
changed = True
|
||||
|
||||
if changed:
|
||||
if dry_run:
|
||||
print(f" (dry-run) Would write: {path}")
|
||||
else:
|
||||
with open(path, "w") as f:
|
||||
json.dump(markers, f, indent=2)
|
||||
print(f" Written: {path}")
|
||||
else:
|
||||
print(f" No changes for {body_id}")
|
||||
print()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Name previously-unnamed Sol body auto-detected features."
|
||||
)
|
||||
parser.add_argument(
|
||||
"--dry-run",
|
||||
action="store_true",
|
||||
help="print planned changes without writing any files",
|
||||
)
|
||||
args = parser.parse_args()
|
||||
apply_sol_fixes(dry_run=args.dry_run)
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Alcazar Hospitality"
|
||||
description: "Alcazar Hospitality — premium service provider based in Altair, south reach"
|
||||
slug: alcazar-hospitality
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Altair (GJ 768)
|
||||
tags: [service_premium, south_reach, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Alcazar Hospitality
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Altair (GJ 768)
|
||||
|
||||
Alcazar Hospitality is a premium service provider operating out of Altair (GJ 768). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Alcyone Tech"
|
||||
description: "Alcyone Tech — precision technology manufacturer based in Groombridge, core"
|
||||
slug: alcyone-tech
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [tech_premium, core, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Alcyone Tech
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Alcyone Tech is a precision technology manufacturer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Aldgate Trust"
|
||||
description: "Aldgate Trust — premium service provider based in Crown's Hollow, north reach"
|
||||
slug: aldgate-trust
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Crown's Hollow (GJ 661A)
|
||||
tags: [service_premium, north_reach, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Aldgate Trust
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Crown's Hollow (GJ 661A)
|
||||
|
||||
Aldgate Trust is a premium service provider operating out of Crown's Hollow (GJ 661A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Alentejo Partners"
|
||||
description: "Alentejo Partners — regional specialty producer based in Caparica, south reach"
|
||||
slug: alentejo-partners
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Caparica (GJ 1002)
|
||||
tags: [terroir, south_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Alentejo Partners
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Caparica (GJ 1002)
|
||||
|
||||
Alentejo Partners is a regional specialty producer operating out of Caparica (GJ 1002). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Algarve Botanics"
|
||||
description: "Algarve Botanics — regional specialty producer based in Inhambane, south reach"
|
||||
slug: algarve-botanics
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Inhambane (GJ 54)
|
||||
tags: [terroir, south_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Algarve Botanics
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Inhambane (GJ 54)
|
||||
|
||||
Algarve Botanics is a regional specialty producer operating out of Inhambane (GJ 54). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Arclamp"
|
||||
description: "Arclamp — design and furniture manufacturer based in Groombridge, core"
|
||||
slug: arclamp
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [design_heritage, core, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Arclamp
|
||||
|
||||
**Type:** Corporation — Design And Furniture Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Arclamp is a design and furniture manufacturer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Ashwick Broadcasting"
|
||||
description: "Ashwick Broadcasting — cultural content producer based in Ashfield, north reach"
|
||||
slug: ashwick-broadcasting
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Ashfield (GJ 178)
|
||||
tags: [cultural, north_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Ashwick Broadcasting
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Ashfield (GJ 178)
|
||||
|
||||
Ashwick Broadcasting is a cultural content producer operating out of Ashfield (GJ 178). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Atrium Culture"
|
||||
description: "Atrium Culture — cultural content producer based in Groombridge, core"
|
||||
slug: atrium-culture
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [cultural, core, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Atrium Culture
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Atrium Culture is a cultural content producer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Baia Fundo Productions"
|
||||
description: "Baia Fundo Productions — cultural content producer based in Confluência, south reach"
|
||||
slug: baia-fundo-productions
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Confluência (GJ 566B)
|
||||
tags: [cultural, south_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Baia Fundo Productions
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Confluência (GJ 566B)
|
||||
|
||||
Baia Fundo Productions is a cultural content producer operating out of Confluência (GJ 566B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Bavarian Craft"
|
||||
description: "Bavarian Craft — heritage craft manufacturer based in Bergtor, west reach"
|
||||
slug: bavarian-craft
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Bergtor (GJ 505A)
|
||||
tags: [heritage_craft, west_reach, mark, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Bavarian Craft
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Bergtor (GJ 505A)
|
||||
|
||||
Bavarian Craft is a heritage craft manufacturer operating out of Bergtor (GJ 505A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Bergkraft Antriebswerke"
|
||||
description: "Bergkraft Antriebswerke — precision technology manufacturer based in Bergtor, west reach"
|
||||
slug: bergkraft-antriebswerke
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Bergtor (GJ 505A)
|
||||
tags: [tech_premium, west_reach, mark, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Bergkraft Antriebswerke
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Bergtor (GJ 505A)
|
||||
|
||||
Bergkraft Antriebswerke is a precision technology manufacturer operating out of Bergtor (GJ 505A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Brindlewood Honey"
|
||||
description: "Brindlewood Honey — regional specialty producer based in Ashfield, north reach"
|
||||
slug: brindlewood-honey
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Ashfield (GJ 178)
|
||||
tags: [terroir, north_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Brindlewood Honey
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Ashfield (GJ 178)
|
||||
|
||||
Brindlewood Honey is a regional specialty producer operating out of Ashfield (GJ 178). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Byeolbit Entertainment"
|
||||
description: "Byeolbit Entertainment — cultural content producer based in Seongho, east reach"
|
||||
slug: byeolbit-entertainment
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Seongho (GJ 660A)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Byeolbit Entertainment
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Seongho (GJ 660A)
|
||||
|
||||
Byeolbit Entertainment is a cultural content producer operating out of Seongho (GJ 660A). Details to be expanded.
|
||||
@@ -11,7 +11,7 @@ faction_type: economic
|
||||
headquarters: Calloway Reach (GJ 3325)
|
||||
tags: []
|
||||
decision_refs: []
|
||||
cross_refs: []
|
||||
cross_refs: [thrds, mercado-travessia]
|
||||
---
|
||||
|
||||
# Calloway Distillery
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Calloway Workshop"
|
||||
description: "Calloway Workshop — design and furniture manufacturer based in Calloway Reach, north reach"
|
||||
slug: calloway-workshop
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Calloway Reach (GJ 3325)
|
||||
tags: [design_heritage, north_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Calloway Workshop
|
||||
|
||||
**Type:** Corporation — Design And Furniture Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Calloway Reach (GJ 3325)
|
||||
|
||||
Calloway Workshop is a design and furniture manufacturer operating out of Calloway Reach (GJ 3325). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Calluna Wellness"
|
||||
description: "Calluna Wellness — premium service provider based in Cairn, north reach"
|
||||
slug: calluna-wellness
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Cairn (GJ 845)
|
||||
tags: [service_premium, north_reach, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Calluna Wellness
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Cairn (GJ 845)
|
||||
|
||||
Calluna Wellness is a premium service provider operating out of Cairn (GJ 845). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Cape Modern"
|
||||
description: "Cape Modern — design and furniture manufacturer based in Kaapse Baai, south reach"
|
||||
slug: cape-modern
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kaapse Baai (GJ 213)
|
||||
tags: [design_heritage, south_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Cape Modern
|
||||
|
||||
**Type:** Corporation — Design And Furniture Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Kaapse Baai (GJ 213)
|
||||
|
||||
Cape Modern is a design and furniture manufacturer operating out of Kaapse Baai (GJ 213). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Commonstock Foods"
|
||||
description: "Commonstock Foods — consumer goods manufacturer based in Sirius, core"
|
||||
slug: commonstock-foods
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Sirius (GJ 244A)
|
||||
tags: [commodity_branded, core, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Commonstock Foods
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Sirius (GJ 244A)
|
||||
|
||||
Commonstock Foods is a consumer goods manufacturer operating out of Sirius (GJ 244A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Comptoir Lendel"
|
||||
description: "Comptoir Lendel — regional specialty producer based in Groombridge, core"
|
||||
slug: comptoir-lendel
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [terroir, core, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Comptoir Lendel
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Comptoir Lendel is a regional specialty producer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Coriolis Exchange"
|
||||
description: "Coriolis Exchange — premium service provider based in Groombridge, core"
|
||||
slug: coriolis-exchange
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [service_premium, core, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Coriolis Exchange
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Coriolis Exchange is a premium service provider operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Dalbit Systems"
|
||||
description: "Dalbit Systems — precision technology manufacturer based in Seongho, east reach"
|
||||
slug: dalbit-systems
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Seongho (GJ 660A)
|
||||
tags: [tech_premium, east_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Dalbit Systems
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Seongho (GJ 660A)
|
||||
|
||||
Dalbit Systems is a precision technology manufacturer operating out of Seongho (GJ 660A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Destilaria Confluencia"
|
||||
description: "Destilaria Confluencia — regional specialty producer based in Confluência, south reach"
|
||||
slug: destilaria-confluencia
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Confluência (GJ 566B)
|
||||
tags: [terroir, south_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Destilaria Confluencia
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Confluência (GJ 566B)
|
||||
|
||||
Destilaria Confluencia is a regional specialty producer operating out of Confluência (GJ 566B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Durban Engineering"
|
||||
description: "Durban Engineering — precision technology manufacturer based in Isibaya, south reach"
|
||||
slug: durban-engineering
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Isibaya (GJ 905)
|
||||
tags: [tech_premium, south_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Durban Engineering
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Isibaya (GJ 905)
|
||||
|
||||
Durban Engineering is a precision technology manufacturer operating out of Isibaya (GJ 905). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Eastbay Trading"
|
||||
description: "Eastbay Trading — consumer goods manufacturer based in Bridgepoint, east reach"
|
||||
slug: eastbay-trading
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Bridgepoint (GJ 53A)
|
||||
tags: [commodity_branded, east_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Eastbay Trading
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Bridgepoint (GJ 53A)
|
||||
|
||||
Eastbay Trading is a consumer goods manufacturer operating out of Bridgepoint (GJ 53A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Endymion Instruments"
|
||||
description: "Endymion Instruments — precision technology manufacturer based in The Narrows, deep frontier"
|
||||
slug: endymion-instruments
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: The Narrows (GJ 875)
|
||||
tags: [tech_premium, deep_frontier, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Endymion Instruments
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — deep frontier operations
|
||||
**Headquarters:** The Narrows (GJ 875)
|
||||
|
||||
Endymion Instruments is a precision technology manufacturer operating out of The Narrows (GJ 875). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Erzgebirge Instruments"
|
||||
description: "Erzgebirge Instruments — precision technology manufacturer based in Eisentor, west reach"
|
||||
slug: erzgebirge-instruments
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Eisentor (GJ 3454)
|
||||
tags: [tech_premium, west_reach, mark, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Erzgebirge Instruments
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Eisentor (GJ 3454)
|
||||
|
||||
Erzgebirge Instruments is a precision technology manufacturer operating out of Eisentor (GJ 3454). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Fieldborn Grain"
|
||||
description: "Fieldborn Grain — consumer goods manufacturer based in Calloway Reach, north reach"
|
||||
slug: fieldborn-grain
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Calloway Reach (GJ 3325)
|
||||
tags: [commodity_branded, north_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Fieldborn Grain
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Calloway Reach (GJ 3325)
|
||||
|
||||
Fieldborn Grain is a consumer goods manufacturer operating out of Calloway Reach (GJ 3325). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Fjeldtone Music"
|
||||
description: "Fjeldtone Music — cultural content producer based in Halvøy, west reach"
|
||||
slug: fjeldtone-music
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Halvøy (GJ 624)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Fjeldtone Music
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Halvøy (GJ 624)
|
||||
|
||||
Fjeldtone Music is a cultural content producer operating out of Halvøy (GJ 624). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Graben Studio"
|
||||
description: "Graben Studio — cultural content producer based in Freiholt, west reach"
|
||||
slug: graben-studio
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Freiholt (GJ 453)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Graben Studio
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Freiholt (GJ 453)
|
||||
|
||||
Graben Studio is a cultural content producer operating out of Freiholt (GJ 453). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Grampian Systems"
|
||||
description: "Grampian Systems — precision technology manufacturer based in Calloway Reach, north reach"
|
||||
slug: grampian-systems
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Calloway Reach (GJ 3325)
|
||||
tags: [tech_premium, north_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Grampian Systems
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Calloway Reach (GJ 3325)
|
||||
|
||||
Grampian Systems is a precision technology manufacturer operating out of Calloway Reach (GJ 3325). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Gridsupply Electronics"
|
||||
description: "Gridsupply Electronics — consumer goods manufacturer based in Groombridge, core"
|
||||
slug: gridsupply-electronics
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [commodity_branded, core, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Gridsupply Electronics
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Gridsupply Electronics is a consumer goods manufacturer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Gronnmark Consumer"
|
||||
description: "Gronnmark Consumer — consumer goods manufacturer based in Nyrheim, west reach"
|
||||
slug: gronnmark-consumer
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nyrheim (GJ 3737)
|
||||
tags: [commodity_branded, west_reach, mark, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Gronnmark Consumer
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Nyrheim (GJ 3737)
|
||||
|
||||
Gronnmark Consumer is a consumer goods manufacturer operating out of Nyrheim (GJ 3737). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Groot Karoo Cellars"
|
||||
description: "Groot Karoo Cellars — regional specialty producer based in Karoo, south reach"
|
||||
slug: groot-karoo-cellars
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Karoo (GJ 222A)
|
||||
tags: [terroir, south_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Groot Karoo Cellars
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Karoo (GJ 222A)
|
||||
|
||||
Groot Karoo Cellars is a regional specialty producer operating out of Karoo (GJ 222A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Haesungdan Records"
|
||||
description: "Haesungdan Records — cultural content producer based in Miryang, east reach"
|
||||
slug: haesungdan-records
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Miryang (GJ 754)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Haesungdan Records
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Miryang (GJ 754)
|
||||
|
||||
Haesungdan Records is a cultural content producer operating out of Miryang (GJ 754). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hakone Hospitality"
|
||||
description: "Hakone Hospitality — premium service provider based in Matsue, east reach"
|
||||
slug: hakone-hospitality
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Matsue (GJ 687)
|
||||
tags: [service_premium, east_reach, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Hakone Hospitality
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Matsue (GJ 687)
|
||||
|
||||
Hakone Hospitality is a premium service provider operating out of Matsue (GJ 687). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hana Creative"
|
||||
description: "Hana Creative — cultural content producer based in Jinghu, east reach"
|
||||
slug: hana-creative
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Jinghu (GJ 445)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Hana Creative
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Jinghu (GJ 445)
|
||||
|
||||
Hana Creative is a cultural content producer operating out of Jinghu (GJ 445). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hangang Studio"
|
||||
description: "Hangang Studio — media platform and catalogue service based in Songjiang, east reach"
|
||||
slug: hangang-studio
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Songjiang (GJ 625)
|
||||
tags: [platform_catalogue, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Hangang Studio
|
||||
|
||||
**Type:** Corporation — Media Platform And Catalogue Service
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Songjiang (GJ 625)
|
||||
|
||||
Hangang Studio is a media platform and catalogue service operating out of Songjiang (GJ 625). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hangil Celadon"
|
||||
description: "Hangil Celadon — heritage craft manufacturer based in Miryang, east reach"
|
||||
slug: hangil-celadon
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Miryang (GJ 754)
|
||||
tags: [heritage_craft, east_reach, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Hangil Celadon
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Miryang (GJ 754)
|
||||
|
||||
Hangil Celadon is a heritage craft manufacturer operating out of Miryang (GJ 754). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Hartsteen Legal"
|
||||
description: "Hartsteen Legal — premium service provider based in Confluent, west reach"
|
||||
slug: hartsteen-legal
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Confluent (GJ 395)
|
||||
tags: [service_premium, west_reach, mark]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Hartsteen Legal
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Confluent (GJ 395)
|
||||
|
||||
Hartsteen Legal is a premium service provider operating out of Confluent (GJ 395). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Higashiyama Vehicle"
|
||||
description: "Higashiyama Vehicle — precision technology manufacturer based in Kurashiki, east reach"
|
||||
slug: higashiyama-vehicle
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kurashiki (GJ 205)
|
||||
tags: [tech_premium, east_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Higashiyama Vehicle
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Kurashiki (GJ 205)
|
||||
|
||||
Higashiyama Vehicle is a precision technology manufacturer operating out of Kurashiki (GJ 205). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Highland Cooperative"
|
||||
description: "Highland Cooperative — regional specialty producer based in Crown's Hollow, north reach"
|
||||
slug: highland-cooperative
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Crown's Hollow (GJ 661A)
|
||||
tags: [terroir, north_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Highland Cooperative
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Crown's Hollow (GJ 661A)
|
||||
|
||||
Highland Cooperative is a regional specialty producer operating out of Crown's Hollow (GJ 661A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Iberian Standard Foods"
|
||||
description: "Iberian Standard Foods — consumer goods manufacturer based in Caparica, south reach"
|
||||
slug: iberian-standard-foods
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Caparica (GJ 1002)
|
||||
tags: [commodity_branded, south_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Iberian Standard Foods
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Caparica (GJ 1002)
|
||||
|
||||
Iberian Standard Foods is a consumer goods manufacturer operating out of Caparica (GJ 1002). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Incheon Salt"
|
||||
description: "Incheon Salt — regional specialty producer based in Changwon, east reach"
|
||||
slug: incheon-salt
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Changwon (GJ 860B)
|
||||
tags: [terroir, east_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Incheon Salt
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Changwon (GJ 860B)
|
||||
|
||||
Incheon Salt is a regional specialty producer operating out of Changwon (GJ 860B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Ironbark Films"
|
||||
description: "Ironbark Films — cultural content producer based in Fremantle, north reach"
|
||||
slug: ironbark-films
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Fremantle (GJ 273)
|
||||
tags: [cultural, north_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Ironbark Films
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Fremantle (GJ 273)
|
||||
|
||||
Ironbark Films is a cultural content producer operating out of Fremantle (GJ 273). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Iznik Atelier"
|
||||
description: "Iznik Atelier — heritage craft manufacturer based in Groombridge, core"
|
||||
slug: iznik-atelier
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [heritage_craft, core, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Iznik Atelier
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Iznik Atelier is a heritage craft manufacturer operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Jeju Lattice"
|
||||
description: "Jeju Lattice — precision technology manufacturer based in Yeongwol, east reach"
|
||||
slug: jeju-lattice
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Yeongwol (GJ 268)
|
||||
tags: [tech_premium, east_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Jeju Lattice
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Yeongwol (GJ 268)
|
||||
|
||||
Jeju Lattice is a precision technology manufacturer operating out of Yeongwol (GJ 268). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kaapse Baai Wines"
|
||||
description: "Kaapse Baai Wines — regional specialty producer based in Kaapse Baai, south reach"
|
||||
slug: kaapse-baai-wines
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kaapse Baai (GJ 213)
|
||||
tags: [terroir, south_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kaapse Baai Wines
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Kaapse Baai (GJ 213)
|
||||
|
||||
Kaapse Baai Wines is a regional specialty producer operating out of Kaapse Baai (GJ 213). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kalahari Leatherworks"
|
||||
description: "Kalahari Leatherworks — heritage craft manufacturer based in Karoo, south reach"
|
||||
slug: kalahari-leatherworks
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Karoo (GJ 222A)
|
||||
tags: [heritage_craft, south_reach, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kalahari Leatherworks
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Karoo (GJ 222A)
|
||||
|
||||
Kalahari Leatherworks is a heritage craft manufacturer operating out of Karoo (GJ 222A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kaur Observatory Equipment"
|
||||
description: "Kaur Observatory Equipment — precision technology manufacturer based in Kaur's Observatory, east reach"
|
||||
slug: kaur-observatory-equipment
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kaur's Observatory (GJ 432A)
|
||||
tags: [tech_premium, east_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kaur Observatory Equipment
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Kaur's Observatory (GJ 432A)
|
||||
|
||||
Kaur Observatory Equipment is a precision technology manufacturer operating out of Kaur's Observatory (GJ 432A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kellervolk"
|
||||
description: "Kellervolk — cultural content producer based in Nyrheim, west reach"
|
||||
slug: kellervolk
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nyrheim (GJ 3737)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kellervolk
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Nyrheim (GJ 3737)
|
||||
|
||||
Kellervolk is a cultural content producer operating out of Nyrheim (GJ 3737). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kinlochewe Instruments"
|
||||
description: "Kinlochewe Instruments — precision technology manufacturer based in Braemar, north reach"
|
||||
slug: kinlochewe-instruments
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Braemar (GJ 475)
|
||||
tags: [tech_premium, north_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kinlochewe Instruments
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Braemar (GJ 475)
|
||||
|
||||
Kinlochewe Instruments is a precision technology manufacturer operating out of Braemar (GJ 475). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Koryo Standard"
|
||||
description: "Koryo Standard — consumer goods manufacturer based in Jeonnam, east reach"
|
||||
slug: koryo-standard
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Jeonnam (GJ 3728B)
|
||||
tags: [commodity_branded, east_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Koryo Standard
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Jeonnam (GJ 3728B)
|
||||
|
||||
Koryo Standard is a consumer goods manufacturer operating out of Jeonnam (GJ 3728B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kumho Navigation"
|
||||
description: "Kumho Navigation — precision technology manufacturer based in Hwaseong, east reach"
|
||||
slug: kumho-navigation
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Hwaseong (GJ 1125)
|
||||
tags: [tech_premium, east_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kumho Navigation
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Hwaseong (GJ 1125)
|
||||
|
||||
Kumho Navigation is a precision technology manufacturer operating out of Hwaseong (GJ 1125). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kyoei Design"
|
||||
description: "Kyoei Design — design and furniture manufacturer based in Kurashiki, east reach"
|
||||
slug: kyoei-design
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kurashiki (GJ 205)
|
||||
tags: [design_heritage, east_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kyoei Design
|
||||
|
||||
**Type:** Corporation — Design And Furniture Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Kurashiki (GJ 205)
|
||||
|
||||
Kyoei Design is a design and furniture manufacturer operating out of Kurashiki (GJ 205). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Kyoto Valley Estates"
|
||||
description: "Kyoto Valley Estates — regional specialty producer based in Kurashiki, east reach"
|
||||
slug: kyoto-valley-estates
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kurashiki (GJ 205)
|
||||
tags: [terroir, east_reach, tractus, scarcity_class_rare]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Kyoto Valley Estates
|
||||
|
||||
**Type:** Corporation — Regional Specialty Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Kurashiki (GJ 205)
|
||||
|
||||
Kyoto Valley Estates is a regional specialty producer operating out of Kurashiki (GJ 205). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Leerfeld Records"
|
||||
description: "Leerfeld Records — cultural content producer based in Confluent, west reach"
|
||||
slug: leerfeld-records
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Confluent (GJ 395)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Leerfeld Records
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Confluent (GJ 395)
|
||||
|
||||
Leerfeld Records is a cultural content producer operating out of Confluent (GJ 395). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Lowlands Consumer"
|
||||
description: "Lowlands Consumer — consumer goods manufacturer based in Dokkum, west reach"
|
||||
slug: lowlands-consumer
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Dokkum (GJ 506)
|
||||
tags: [commodity_branded, west_reach, mark, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Lowlands Consumer
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Dokkum (GJ 506)
|
||||
|
||||
Lowlands Consumer is a consumer goods manufacturer operating out of Dokkum (GJ 506). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Luanda Fabrication"
|
||||
description: "Luanda Fabrication — precision technology manufacturer based in Matamba, south reach"
|
||||
slug: luanda-fabrication
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Matamba (GJ 884)
|
||||
tags: [tech_premium, south_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Luanda Fabrication
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Matamba (GJ 884)
|
||||
|
||||
Luanda Fabrication is a precision technology manufacturer operating out of Matamba (GJ 884). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Lusaka Advisory"
|
||||
description: "Lusaka Advisory — premium service provider based in Zenzele, south reach"
|
||||
slug: lusaka-advisory
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Zenzele (GJ 1111)
|
||||
tags: [service_premium, south_reach, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Lusaka Advisory
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Zenzele (GJ 1111)
|
||||
|
||||
Lusaka Advisory is a premium service provider operating out of Zenzele (GJ 1111). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Lusitanian Glass"
|
||||
description: "Lusitanian Glass — heritage craft manufacturer based in Caparica, south reach"
|
||||
slug: lusitanian-glass
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Caparica (GJ 1002)
|
||||
tags: [heritage_craft, south_reach, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Lusitanian Glass
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Caparica (GJ 1002)
|
||||
|
||||
Lusitanian Glass is a heritage craft manufacturer operating out of Caparica (GJ 1002). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Maas Rijn Entertainment"
|
||||
description: "Maas Rijn Entertainment — cultural content producer based in Dokkum, west reach"
|
||||
slug: maas-rijn-entertainment
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Dokkum (GJ 506)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Maas Rijn Entertainment
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Dokkum (GJ 506)
|
||||
|
||||
Maas Rijn Entertainment is a cultural content producer operating out of Dokkum (GJ 506). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Maison Cinq"
|
||||
description: "Maison Cinq — design and furniture manufacturer based in Sirius, core"
|
||||
slug: maison-cinq
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Sirius (GJ 244A)
|
||||
tags: [design_heritage, core, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Maison Cinq
|
||||
|
||||
**Type:** Corporation — Design And Furniture Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Sirius (GJ 244A)
|
||||
|
||||
Maison Cinq is a design and furniture manufacturer operating out of Sirius (GJ 244A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Makuti Consumer"
|
||||
description: "Makuti Consumer — consumer goods manufacturer based in Mwangaza, south reach"
|
||||
slug: makuti-consumer
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Mwangaza (GJ 693)
|
||||
tags: [commodity_branded, south_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Makuti Consumer
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Mwangaza (GJ 693)
|
||||
|
||||
Makuti Consumer is a consumer goods manufacturer operating out of Mwangaza (GJ 693). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Matosinhos Fishing"
|
||||
description: "Matosinhos Fishing — consumer goods manufacturer based in Velha Guarda, south reach"
|
||||
slug: matosinhos-fishing
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Velha Guarda (GJ 4A)
|
||||
tags: [commodity_branded, south_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Matosinhos Fishing
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Velha Guarda (GJ 4A)
|
||||
|
||||
Matosinhos Fishing is a consumer goods manufacturer operating out of Velha Guarda (GJ 4A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Meridional Banking"
|
||||
description: "Meridional Banking — premium service provider based in Meridian, core"
|
||||
slug: meridional-banking
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Meridian (GJ 674)
|
||||
tags: [service_premium, core, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Meridional Banking
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Meridian (GJ 674)
|
||||
|
||||
Meridional Banking is a premium service provider operating out of Meridian (GJ 674). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Meridional Technical"
|
||||
description: "Meridional Technical — precision technology manufacturer based in Meridian, core"
|
||||
slug: meridional-technical
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Meridian (GJ 674)
|
||||
tags: [tech_premium, core, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Meridional Technical
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Meridian (GJ 674)
|
||||
|
||||
Meridional Technical is a precision technology manufacturer operating out of Meridian (GJ 674). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Mirai Entertainment"
|
||||
description: "Mirai Entertainment — cultural content producer based in Kurashiki, east reach"
|
||||
slug: mirai-entertainment
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Kurashiki (GJ 205)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Mirai Entertainment
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Kurashiki (GJ 205)
|
||||
|
||||
Mirai Entertainment is a cultural content producer operating out of Kurashiki (GJ 205). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Moorfield Records"
|
||||
description: "Moorfield Records — cultural content producer based in Braemar, north reach"
|
||||
slug: moorfield-records
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Braemar (GJ 475)
|
||||
tags: [cultural, north_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Moorfield Records
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Braemar (GJ 475)
|
||||
|
||||
Moorfield Records is a cultural content producer operating out of Braemar (GJ 475). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Mwanga Media"
|
||||
description: "Mwanga Media — cultural content producer based in Mwangaza, south reach"
|
||||
slug: mwanga-media
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Mwangaza (GJ 693)
|
||||
tags: [cultural, south_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Mwanga Media
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Mwangaza (GJ 693)
|
||||
|
||||
Mwanga Media is a cultural content producer operating out of Mwangaza (GJ 693). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Namsan Collective"
|
||||
description: "Namsan Collective — cultural content producer based in Yeongwol, east reach"
|
||||
slug: namsan-collective
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Yeongwol (GJ 268)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Namsan Collective
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Yeongwol (GJ 268)
|
||||
|
||||
Namsan Collective is a cultural content producer operating out of Yeongwol (GJ 268). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Nexus Way Express"
|
||||
description: "Nexus Way Express — premium service provider based in Sirius, core"
|
||||
slug: nexus-way-express
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Sirius (GJ 244A)
|
||||
tags: [service_premium, core, tractus]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Nexus Way Express
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Sirius (GJ 244A)
|
||||
|
||||
Nexus Way Express is a premium service provider operating out of Sirius (GJ 244A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Nordhavn Financial"
|
||||
description: "Nordhavn Financial — premium service provider based in Nyrheim, west reach"
|
||||
slug: nordhavn-financial
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nyrheim (GJ 3737)
|
||||
tags: [service_premium, west_reach, mark]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Nordhavn Financial
|
||||
|
||||
**Type:** Corporation — Premium Service Provider
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Nyrheim (GJ 3737)
|
||||
|
||||
Nordhavn Financial is a premium service provider operating out of Nyrheim (GJ 3737). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Nordschatten Records"
|
||||
description: "Nordschatten Records — cultural content producer based in Nyrheim, west reach"
|
||||
slug: nordschatten-records
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nyrheim (GJ 3737)
|
||||
tags: [cultural, west_reach, mark, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Nordschatten Records
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Nyrheim (GJ 3737)
|
||||
|
||||
Nordschatten Records is a cultural content producer operating out of Nyrheim (GJ 3737). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Norrland Woodcraft"
|
||||
description: "Norrland Woodcraft — heritage craft manufacturer based in Nyrheim, west reach"
|
||||
slug: norrland-woodcraft
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nyrheim (GJ 3737)
|
||||
tags: [heritage_craft, west_reach, mark, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Norrland Woodcraft
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — west reach operations
|
||||
**Headquarters:** Nyrheim (GJ 3737)
|
||||
|
||||
Norrland Woodcraft is a heritage craft manufacturer operating out of Nyrheim (GJ 3737). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Ondori Interactive"
|
||||
description: "Ondori Interactive — cultural content producer based in Jeonnam, east reach"
|
||||
slug: ondori-interactive
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Jeonnam (GJ 3728B)
|
||||
tags: [cultural, east_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Ondori Interactive
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — east reach operations
|
||||
**Headquarters:** Jeonnam (GJ 3728B)
|
||||
|
||||
Ondori Interactive is a cultural content producer operating out of Jeonnam (GJ 3728B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Open Corridor Stream"
|
||||
description: "Open Corridor Stream — media platform and catalogue service based in Groombridge, core"
|
||||
slug: open-corridor-stream
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Groombridge (GJ 380)
|
||||
tags: [platform_catalogue, core, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Open Corridor Stream
|
||||
|
||||
**Type:** Corporation — Media Platform And Catalogue Service
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Groombridge (GJ 380)
|
||||
|
||||
Open Corridor Stream is a media platform and catalogue service operating out of Groombridge (GJ 380). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Orkney Ceramics"
|
||||
description: "Orkney Ceramics — heritage craft manufacturer based in Cairn, north reach"
|
||||
slug: orkney-ceramics
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Cairn (GJ 845)
|
||||
tags: [heritage_craft, north_reach, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Orkney Ceramics
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Cairn (GJ 845)
|
||||
|
||||
Orkney Ceramics is a heritage craft manufacturer operating out of Cairn (GJ 845). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Pembrokeshire Smithy"
|
||||
description: "Pembrokeshire Smithy — heritage craft manufacturer based in Pemberton, north reach"
|
||||
slug: pembrokeshire-smithy
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Pemberton (GJ 194B)
|
||||
tags: [heritage_craft, north_reach, tractus, artisan]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Pembrokeshire Smithy
|
||||
|
||||
**Type:** Corporation — Heritage Craft Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Pemberton (GJ 194B)
|
||||
|
||||
Pembrokeshire Smithy is a heritage craft manufacturer operating out of Pemberton (GJ 194B). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Plainfield Agricultural"
|
||||
description: "Plainfield Agricultural — consumer goods manufacturer based in Fremantle, north reach"
|
||||
slug: plainfield-agricultural
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Fremantle (GJ 273)
|
||||
tags: [commodity_branded, north_reach, tractus, consumer_goods]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Plainfield Agricultural
|
||||
|
||||
**Type:** Corporation — Consumer Goods Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — north reach operations
|
||||
**Headquarters:** Fremantle (GJ 273)
|
||||
|
||||
Plainfield Agricultural is a consumer goods manufacturer operating out of Fremantle (GJ 273). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Porto Alegre Technical"
|
||||
description: "Porto Alegre Technical — precision technology manufacturer based in Nowa Huta, south reach"
|
||||
slug: porto-alegre-technical
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Nowa Huta (GJ 896A)
|
||||
tags: [tech_premium, south_reach, tractus, electronics]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Porto Alegre Technical
|
||||
|
||||
**Type:** Corporation — Precision Technology Manufacturer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Nowa Huta (GJ 896A)
|
||||
|
||||
Porto Alegre Technical is a precision technology manufacturer operating out of Nowa Huta (GJ 896A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Quebrada Cultural"
|
||||
description: "Quebrada Cultural — cultural content producer based in Matamba, south reach"
|
||||
slug: quebrada-cultural
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Matamba (GJ 884)
|
||||
tags: [cultural, south_reach, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Quebrada Cultural
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — south reach operations
|
||||
**Headquarters:** Matamba (GJ 884)
|
||||
|
||||
Quebrada Cultural is a cultural content producer operating out of Matamba (GJ 884). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Reach Archive Standard"
|
||||
description: "Reach Archive Standard — media platform and catalogue service based in Sirius, core"
|
||||
slug: reach-archive-standard
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Sirius (GJ 244A)
|
||||
tags: [platform_catalogue, core, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Reach Archive Standard
|
||||
|
||||
**Type:** Corporation — Media Platform And Catalogue Service
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Sirius (GJ 244A)
|
||||
|
||||
Reach Archive Standard is a media platform and catalogue service operating out of Sirius (GJ 244A). Details to be expanded.
|
||||
@@ -0,0 +1,24 @@
|
||||
---
|
||||
title: "Reach Standard Media"
|
||||
description: "Reach Standard Media — cultural content producer based in Sirius, core"
|
||||
slug: reach-standard-media
|
||||
category: corporation
|
||||
status: canonical
|
||||
created: 2026-04-19
|
||||
updated: 2026-04-19
|
||||
scope: regional
|
||||
faction_type: economic
|
||||
headquarters: Sirius (GJ 244A)
|
||||
tags: [cultural, core, tractus, entertainment]
|
||||
decision_refs: [D-189]
|
||||
cross_refs: []
|
||||
---
|
||||
|
||||
# Reach Standard Media
|
||||
|
||||
**Type:** Corporation — Cultural Content Producer
|
||||
**Status:** Canonical
|
||||
**Scope:** Regional — core operations
|
||||
**Headquarters:** Sirius (GJ 244A)
|
||||
|
||||
Reach Standard Media is a cultural content producer operating out of Sirius (GJ 244A). Details to be expanded.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user