docs(decisions): address PR #129 review — D-191 §8 amendment + boundary notes
Blocking PR #129 items 1, 2 (plus polish 16 and 17): - D-191 §8 prose rewritten to match the code. The previous amendment said positions were `{x, y}` objects against a "typically 1024 × 512" grid, but the generator, the six hand-authored templates, and all 2394 procedural seed files ship `[row, col]` integer arrays against a `{"w": 512, "h": 256}` grid. The decision doc is now aligned with reality: positions are `[row, col]`, the storage grid is 512 × 256, and the row-first ordering is called out explicitly so readers can cross-reference NumPy/flood-fill/A*/cost-grid conventions. - §8 now follows the D-094 amendment pattern. The superseded 2026-04-10 prose is preserved verbatim as "Original (superseded)" with a dated Amendment block on top — future readers can see what changed and why instead of silently losing the history. - brands.toml header gains a short Phase 2 boundary note. The 4 anchor brands come from D-189 §5; the additional ~23 brands from D-189 §11 are deliberately deferred to Phase 3 — Phase 2 only needs the demand- node plumbing and V-B01..V-B06 validation exercised end-to-end. - systems-schema.sql `bodies.terrain_reference` comment now pins the repo-root-relative path convention (wiki/star-systems/<slug>/bodies/ <body_id>/heightmap.png) so the three downstream pipelines (populate, atlas generator, client loader) share a documented contract instead of drifting against an unwritten convention.
This commit is contained in:
@@ -710,9 +710,21 @@ Technical foundation decisions that constrain implementation: engine, client-ser
|
||||
- Maps to D-181 signal visibility ladder
|
||||
|
||||
**8. Settlement Data Model**
|
||||
- markers.json is stored in heightmap pixel space — every marker file declares a `grid: { w, h }` header (the heightmap dimensions, typically `1024 × 512`) and every position is `{ x, y }` integer pixels into that grid. This is the canonical storage format used by both the generator and the hand-authored template files (Edict, Vuurkloof, Røros, Cairnside, Estrade). Pixel space is what the heightmap analysis (flood-fill, A* cost grid, city placement) natively operates on; it is deterministic and avoids double-conversion through a projection.
|
||||
- markers.json schema per body: `grid: {w, h}`, `cities` (name, pos `{x,y}`, population_tier, primary_function, gate_terminal, continent_id), `roads` (path polylines as `[{x,y}, ...]`, connects), `railroads` (path polylines, connects), `pois` (name, kind, pos), plus existing rivers/oceans/mountains with names filled
|
||||
- Lat/lon strings are a **display-time derivation**, not a storage format. The atlas UI converts `{x, y}` + `grid: {w, h}` into an equirectangular `lat°N/S, lon°E/W` string for the city data panel and hover tooltips, using the body's radius for any great-circle distances it needs. This keeps the immersive surface without paying conversion cost in the generator, the DB, or the diff churn on hand-authored files.
|
||||
- **Amendment (2026-04-15):** The original §8 (below) described marker positions as lat/lon objects and city records keyed by `population_tier`/`primary_function`/`gate_terminal`/`continent_id`. That shape was aspirational — neither the generator nor the hand-authored templates ever emitted it. Both ended up writing pixel-space row/col arrays against a `512 × 256` storage grid, and PR #129 canonizes that shape so the code and the decision stop drifting. The original prose is preserved immediately below; the current shape follows.
|
||||
- **Original (2026-04-10, superseded):** markers.json schema per body: `cities` (name, lat/lon, population_tier, primary_function, gate_terminal, continent_id), `roads` (path polylines, connects), `railroads` (path polylines, connects), `pois` (name, kind, position), plus existing rivers/oceans/mountains with names filled. Population tier → city count: `floor(log10(pop/1M))`, modified by `settlement_pattern`. Gate terminal POI at largest population center, sometimes scattered to a smaller one. Moons: same depth as planets, scale with population.
|
||||
- **Current canonical format:** markers.json is stored in heightmap pixel space. Every marker file declares a `grid: { w, h }` header — the generator, the 6 hand-authored templates (Lendel, Edict, Vuurkloof, Røros, Cairnside, Estrade), and all 2394 procedural seed files ship `{"w": 512, "h": 256}`. Every position is a two-element **array** `[row, col]` of integer pixels into that grid, where `row ∈ [0, h)` and `col ∈ [0, w)` (row is the first axis to match NumPy convention and the flood-fill / A* / cost-grid code that `tooling/planet-gen/` already runs in). Polyline geometry (`roads[*].path`, `railroads[*].path`, `rivers[*].path`) is `[[row, col], [row, col], ...]`.
|
||||
- **markers.json top-level schema:**
|
||||
- `grid`: `{"w": 512, "h": 256}`
|
||||
- `cities[]`: `{id, name, kind, center: [row, col], population}` — `kind` is `capital` or `city`; `name` is empty when awaiting gemma_naming.py (#833).
|
||||
- `roads[]`: `{id, name, kind, path: [[row, col], …]}` — `kind` is `commercial` by default for generated roads; hand-authored roads use `highway`, `rural`, etc.
|
||||
- `railroads[]`: same shape as `roads[]`; generated default `kind` is `passenger_freight`.
|
||||
- `pois[]`: `{id, name, kind, center: [row, col]}` — generated POIs are `kind: "transit"`; hand-authored POIs use `institutional`, `cultural`, `corporate`, etc.
|
||||
- `rivers[]`: `{id, name, path: [[row, col], …]}`
|
||||
- `oceans[]`: `{id, name, kind, center: [row, col], area_fraction}` where `kind` is `lake` | `sea` | `ocean`.
|
||||
- `mountain_ranges[]`: `{id, name, center: [row, col], peak: [row, col], area_cells}`
|
||||
- Pixel space is what the heightmap analysis (flood-fill, A* cost grid, city placement) natively operates on; it is deterministic and avoids double-conversion through a projection.
|
||||
- Lat/lon strings are a **display-time derivation**, not a storage format. The atlas UI converts `[row, col]` + `grid: {w, h}` into an equirectangular `lat°N/S, lon°E/W` string for the city data panel and hover tooltips, using the body's radius for any great-circle distances it needs. This keeps the immersive surface without paying conversion cost in the generator, the DB, or the diff churn on hand-authored files.
|
||||
- Atlas DB index (`atlas_cities`, `atlas_roads`, `atlas_railroads`, `atlas_pois`, `atlas_rivers`, `atlas_oceans`, `atlas_mountain_ranges`, `atlas_body_grids`) mirrors these scalar fields row-by-row for implant-app and development queries; polyline geometry stays in the JSON files next to the heightmaps.
|
||||
- Population tier → city count: `floor(log10(pop/1M))`, modified by `settlement_pattern`
|
||||
- Gate terminal POI: at largest population center, sometimes scattered to a smaller one
|
||||
- Moons: same depth as planets, scale with population
|
||||
@@ -739,4 +751,4 @@ Technical foundation decisions that constrain implementation: engine, client-ser
|
||||
|
||||
---
|
||||
|
||||
*53 decisions. Last updated: 2026-04-14 (D-191 §8 — markers.json canonical format is pixel space `{x, y}` with a `grid: {w, h}` header; lat/lon is a display-time derivation)*
|
||||
*53 decisions. Last updated: 2026-04-15 (D-191 §8 amendment — markers.json canonical format is pixel space `[row, col]` arrays against a `512 × 256` grid, following the D-094 amendment pattern; lat/lon is a display-time derivation)*
|
||||
|
||||
@@ -167,7 +167,16 @@ CREATE TABLE IF NOT EXISTS bodies (
|
||||
industrial_corridor TEXT, -- MVG, Gate_Corp, DSMC, Prometheus, Agricultural_Syndic
|
||||
|
||||
-- Rendering
|
||||
terrain_reference TEXT, -- heightmap path when authored, NULL otherwise
|
||||
-- terrain_reference: repo-root-relative path to the body's heightmap PNG.
|
||||
-- Convention (enforced by populate_terrain_reference.py and assumed by
|
||||
-- generate_atlas.py and the Godot client's atlas scene loader):
|
||||
-- wiki/star-systems/<system_slug>/bodies/<body_id>/heightmap.png
|
||||
-- where <system_slug> = system_id with spaces replaced by hyphens
|
||||
-- (e.g. "GJ 244A" → "GJ-244A"). NULL means no heightmap has been
|
||||
-- generated for this body yet. The three downstream pipelines
|
||||
-- (populate, atlas generator, client loader) all assume this format —
|
||||
-- changing it requires updating all three sites together.
|
||||
terrain_reference TEXT,
|
||||
screenshot_path TEXT, -- planetary shader screenshot path
|
||||
|
||||
updated_at TEXT DEFAULT (datetime('now'))
|
||||
|
||||
@@ -7,6 +7,13 @@
|
||||
# tâtonnement simulation (D-185: brands consume commodities, not the reverse).
|
||||
# Pricing model and cultural premium curves are Phase 3+ deliverables (D-189).
|
||||
#
|
||||
# Phase 2 boundary: only the 4 anchor brands from D-189 §5 are authored here
|
||||
# (Calloway, VGV, thrds, Bífröst Marmor). The additional ~23 brand corps
|
||||
# listed in D-189 §11 are deliberately deferred to Phase 3 — Phase 2 only
|
||||
# needs the demand-node plumbing + V-B01..V-B06 validation to be exercised
|
||||
# end-to-end. Add new brands to this file; the importer and validators pick
|
||||
# them up without schema changes.
|
||||
#
|
||||
# Fields per [[brand_products]] entry:
|
||||
# brand_product_id Unique slug (corp_id + product slug)
|
||||
# corp_id Must match a slug in wiki/corporations/
|
||||
|
||||
Reference in New Issue
Block a user