diff --git a/docs/backups/settledreach.db.backup b/docs/backups/settledreach.db.backup index 316b8a9d3..2fd4baa71 100644 Binary files a/docs/backups/settledreach.db.backup and b/docs/backups/settledreach.db.backup differ diff --git a/docs/sprints/sprint-35/client.md b/docs/sprints/sprint-35/client.md new file mode 100644 index 000000000..9de15aeac --- /dev/null +++ b/docs/sprints/sprint-35/client.md @@ -0,0 +1,99 @@ +# Sprint 35: Atlas — Client Tasks + +**Goal:** Launch Phase 3 — open the Atlas implant panel so a player can navigate from the Reach map down to any planetary body and see a heightmap with generated city markers, overlays, and a city data panel linking to the economics monitor. + +**Branch:** `sprint-35/client` +**Agents:** Stig (UI), Tyre (architecture) + +## New Tickets + +| # | Title | Blocked by | +|---|-------|------------| +| #834 | Atlas implant panel — system picker, orbital diagram, body navigation | — | +| #835 | Atlas heightmap viewer — pan/zoom, marker overlay, city data panel | #834 | +| #836 | Atlas overlay system — 9 MVP overlays with visibility tiers | #835 | + +## Key Decisions + +- `decisions/architecture.md` — D-191 (Atlas Phase 3 scope — full UI spec: zoom hierarchy, navigation levels, city data panel, overlay system, MVP completion criteria), D-169 (implant UI component library — compose from `client/ui/implant/`), D-170 (HUD visibility groups — Atlas registers as `implant/map/atlas`, FULLSCREEN mode z=20) +- `decisions/economics.md` — D-181 (signal visibility ladder — maps to which overlays are always-on vs. toggleable vs. locked in #836) + +## Notes + +### #834 — Atlas implant panel: system picker + orbital diagram + body navigation + +New implant app. Register with `HudGroups` as `implant/map/atlas` in FULLSCREEN mode (z=20). The atlas is an extension of `implant/map`, not a separate app — the existing `star_map.gd` registers at `implant/map/starchart`. The atlas adds the next zoom levels downward. + +**Three navigation levels:** +1. **System picker** — reuse the system list from `client/ui/implant/economics_panel.gd`. Searchable scroll list. Selecting a system advances to level 2. `client/ui/star_map.gd` already has a system selection signal; check if it can be reused or if the atlas needs its own. +2. **Orbital diagram** — star at center, bodies arranged by `orbit_index` from `systems.db`. Click a body → level 3. Click a station → mini data panel (name, operator, currency_zone — no drill-down; stations have no heightmap). Back navigation returns to system picker. +3. **Body entry point** — tile/button that opens the heightmap viewer (`#835`). Can be a simple "VIEW ATLAS" button in this ticket; the actual viewer is built in #835. + +Use implant component library throughout: `ImplantPanel`, `ImplantHeader`, `ImplantSeparator`, `ImplantDataRow`, `ImplantTextBlock`. Theme from `client/ui/implant/default_implant.tres`. + +This ticket delivers navigation skeleton only — the heightmap viewer content comes from #835. Build with stub data (empty orbital diagram with system name and body count) so the panel can be tested independently. Data for the orbital diagram lives in `res://data/star_map_data.json` (the same source used by the star map). Check whether `orbit_index` and body type are already in the JSON; extend the generation script (`tooling/generate-star-map-data.py`) if not. + +Add keyboard shortcut and implant nav entry (consistent with how `economics_panel.gd` registers its shortcut). + +### #835 — Atlas heightmap viewer: pan/zoom, marker overlay, city data panel + +Body atlas level. Loaded when a body is selected in #834. + +**Heightmap display:** Load the heightmap PNG as `Texture2D` in a `SubViewportContainer` with pan/zoom. The heightmap path comes from `terrain_reference` in `bodies` data (the `star_map_data.json` should include this after #839 runs on server; if the JSON was generated before #839, re-run `make atlas-generate` to pick up the column). Pan/zoom: mouse drag + scroll wheel, pinch gesture on touchscreen. Clamp to image bounds. + +**MarkerOverlay:** A `Node2D` drawn via `_draw()` on top of the viewport. Renders from `markers.json` per body (path: same directory as the heightmap PNG): +- Cities: filled circles, radius scaled by `population_tier` +- Roads: polylines (solid, thin) +- Railroads: polylines (dashed) +- POIs: diamond shapes +- Named features (rivers, oceans, mountains): labels at centroid + +`markers.json` will be initially empty for most bodies until server's #832 and #833 complete. The overlay must handle empty arrays gracefully — display the bare heightmap if `cities` is empty. + +**City data panel sidebar:** Clicking a city opens a right-side panel (ImplantPanel components) showing: +- City name, population tier, primary function +- Currency zone, Commission presence flag +- Shadow economy zone (broad band from `shadow_economy_intensity`) +- Gate distance (hop count to nearest gate terminal) +- **Economics panel link** — button that calls `HudGroups.open_app("implant/economics")` and triggers an `EconStateQuery` pre-filtered to this body's system node. This is the cross-panel integration point from D-191 criterion 5. + +Blocked by #834 (needs the navigation frame). Can start before #832/#833 complete — build against the empty `markers.json` state; the overlay will auto-populate once the server pipeline runs. + +### #836 — Atlas overlay system: 9 MVP overlays with visibility tiers + +Overlay toggle bar at top-right of the regional view (inside the heightmap viewer scene from #835). + +**Always-on (5):** terrain, infrastructure (roads + rail), named features, gate/spaceport markers, political zones (currency zone color bands) + +**Toggleable (4):** population density heatmap, production zones, shadow economy zones (broad bands from `shadow_economy_intensity`), corporate presence Tier 1 (dots where Tier 1 corps operate) + +**Deferred (visible but locked):** overlays requiring D-181 semi-private or private signals (signals 5–6: `stockpile_weeks`, `production_vs_baseline`). Show these as greyed toggle buttons with a tooltip explaining the unlock requirement ("Requires corporate contact" / "Requires insider access"). + +The deferred overlays are present in the UI per D-191 — they communicate to the player that deeper information exists and is gated. Do not omit them. + +Implementation: each overlay is a separate `Node2D` child of the `MarkerOverlay` container, toggled visible/invisible. The toggle bar is an `HBoxContainer` of `ImplantTabRow`-style buttons. State persists per session (not saved to disk). + +Maps to D-181 signal visibility ladder — always-on overlays use public signals (1–2), toggleable overlays use observable signals (3–4), locked overlays use semi-private/private signals (5–6). + +Blocked by #835 (needs the heightmap viewer and marker overlay infrastructure). + +## Dependency Chain + +``` +#834 (atlas panel — system picker + orbital diagram + body nav) — start here, standalone + → #835 (heightmap viewer — pan/zoom, marker overlay, city data panel) + → #836 (overlay system — 9 MVP overlays) +``` + +`#834` can begin immediately (no server dependency for skeleton). `#835` builds on #834's navigation frame. `#836` builds on #835's MarkerOverlay infrastructure. + +The heightmap viewer (#835) can be built against empty `markers.json` and will auto-populate when the server atlas pipeline (#832, #833) completes — no hard sequencing dependency between server and client work, only a data-availability dependency at test time. + +## PR Workflow + +```bash +tea pr create --repo jpmschweitzer/settled-reach --login schweitz \ + --title "feat(ui): Atlas implant panel — Phase 3 planetary viewer" \ + --description "Sprint 35 client work: atlas navigation panel, heightmap viewer, 9-overlay system" \ + --base main --head sprint-35/client +``` diff --git a/docs/sprints/sprint-35/copy.md b/docs/sprints/sprint-35/copy.md new file mode 100644 index 000000000..a6cb26566 --- /dev/null +++ b/docs/sprints/sprint-35/copy.md @@ -0,0 +1,155 @@ +# Sprint 35: Atlas — Copy Tasks + +**Goal:** Launch Phase 3 — hand-author the atlas quality bar for Lendel and 4-5 core systems, seed the brand layer with canonical brand corp TOML entries and 120-130 archetype templates, and create the wiki glossary as a canonical noun reference for all future authoring. + +**Branch:** `sprint-35/copy` +**Agents:** Mellanie (author), Miri (worldbuilding) + +## New Tickets + +| # | Title | Blocked by | +|---|-------|------------| +| #840 | Wiki glossary — canonical proper nouns, factions, locations, terminology | — | +| #830 | Add Calloway, VGV, thrds, Bífröst Marmor to tier1.toml | — | +| #831 | Author brand_templates.toml — 120-130 archetypes with corridor naming patterns | — | +| #837 | Hand-author atlas templates — Lendel and 4-5 core systems | — | +| #838 | Review and hand-refine generated atlas content across all inhabited bodies | #832 (server), #833 (server) | + +## Key Decisions + +- `decisions/economics.md` — D-189 (brand layer architecture — section 4 naming patterns, section 1 taxonomy, section 11 named brand corps table), D-190 (brand volume calibration — population-relative scale; apply when writing wiki volume figures), D-185 (brands are not commodities — brand corps register as commodity demand nodes), D-175 (corp taxonomy — Tier 1 TOML record fields), D-182 (TOML pipeline — sync rule: wiki corp entries and TOML records must match) +- `decisions/architecture.md` — D-191 (Atlas Phase 3 — markers.json schema, settlement data model, Gemma naming patterns the hand-authored templates must match) +- `decisions/content.md` — D-036 (Sova/Krenn as canonical v0.1 setting), D-093 (Sova district spatial layout), D-095 (Horizon stations) + +## Notes + +### #840 — Wiki glossary + +**Start here.** This ticket is the most urgent: it was triggered by a Sprint 34 copy review incident where "Gatebuilder" was used instead of the canonical "Founders." That kind of drift will recur in Phase 3 authoring at scale. + +Create `wiki/glossary.md`. Canonical sections: +- **Factions:** Concord Assembly, Compact of Westphalia, Commission (full name: ?), Gate Corporation, Syndicate +- **Precursor terms:** Founders (canonical), NOT Gatebuilders (obsolete), NOT Builders, NOT Precursors without qualification +- **Currencies:** Tractus (Assembly), Mark (Compact), Sol (shadow/untracked) +- **Corridors:** inner_corridor, north_reach, east_reach, west_reach, south_reach, frontier — include canonical descriptions +- **Key locations:** Sirius (GJ 244A / S-067, Concord Assembly seat), Groombridge (GJ 380, financial clearing), Lendel (GJ 380c, inner core capital), Sova Transit District (Krenn System, canonical v0.1 setting) +- **Economics terms:** tâtonnement (not tatonnement or tâtonnement), Leontief (capitalized), tractus (currency lowercase when written in prose) +- **Wiki terminology:** planet_class (not biome_summary — D-188 rename), system_id format (GJ catalog strings) + +Format: simple alphabetical list with the canonical form bolded and "NOT [wrong form]" notes where drift has been observed. Keep it practical — this is a quick-reference tool for authors, not an encyclopedia. + +### #830 — Add Calloway, VGV, thrds, Bífröst Marmor to tier1.toml + +The 4 canonical brand corps exist in wiki pages but are missing from `wiki/economics/corporations/tier1.toml`. Add full TOML records for each, per the field schema at the top of that file. + +Key fields to get right (cross-reference D-189 section 11 for confirmed details): +- **Calloway Distillery:** `terroir`, `north_reach`, `premium_spirits` as primary commodity input, `shadow_connections = false`, `gate_energy_dependent = true` +- **Vins de Grand Vide (VGV):** `terroir`, `west_reach`, requires F8V stellar spectrum per D-177 (terroir_locked = true in brand_products — note this constraint here), `premium_spirits` +- **thrds:** `heritage_craft`, `north_reach`, `luxury_textiles` as primary commodity input +- **Bífröst Marmor:** `terroir`, `north_reach` / Compact affiliation, `bloc_affiliation = compact`, `geological_material` as commodity input + +The server team (#827) will author the `brand_products` TOML entries for these corps. Your task is the `tier1.toml` records (corporation identity, behavioral archetype, primary commodities as inputs). Coordinate with Dudley to avoid duplicating data: `tier1.toml` = corp identity; `brands.toml` (server creates) = product records. + +The D-182 sync constraint requires wiki corp pages and TOML records to match. Check that each of the four corps has a wiki page; flag any discrepancy in the PR description. + +### #831 — Author brand_templates.toml + +Create `wiki/economics/archetypes/brand_templates.toml` with approximately 35-40 archetypes × 3 sub-variants = 120-130 template definitions. + +Each template defines (per D-189): +- `brand_category` (one of 8: terroir, heritage_craft, tech_premium, cultural, service_premium, commodity_branded, design_heritage, platform_catalogue) +- `commodity_inputs` with quantity ranges +- `premium_range` +- `scarcity_class` (capped / constrained / scalable / unlimited) +- `value_trajectory` (appreciating / depreciating / timeless) +- `scale_tier` (local / regional / reach-wide) +- `naming_pattern` — corridor-specific per D-189 section 4: + - `north_reach` → British/Australian inflection (surnames, place names, compound nouns) + - `east_reach` → Korean/Japanese patterns + - `west_reach` → German/Dutch/Nordic patterns + - `south_reach` → Portuguese/Swahili patterns + - `inner_corridor` → pan-corridor neutral (no strong cultural inflection) + - `frontier` → founder surname + noun (e.g., "Vasquez Feeds", "Okafor Fabrication") + +These templates feed the server's `generate_brands` pipeline (#829, Sprint 36). The templates are authored content — they define the cultural texture of 10,000 generated minor brands. Quality here directly affects world texture density. + +Archetypes to cover: at minimum 4-5 per `brand_category`, distributed across corridors. Aim for balance: each corridor should have at least 10 templates that feel culturally native. Sub-variants within an archetype should vary on `scale_tier` and `value_trajectory` (e.g., a local terroir brand vs. a regional one vs. a reach-wide budget version of the same category). + +**Volume calibration:** When specifying production volumes or market penetration in template descriptions, apply D-190 population-relative scale. "40M units" without a reference population is not meaningful at Reach scale. Annotate as "40M (west_reach corridor, ~10B addressable)" or similar. + +### #837 — Hand-author atlas templates: Lendel and 4-5 core systems + +Hand-author complete `markers.json` content for Lendel (GJ 380c) and 4-5 other high-visibility systems. These are the quality bar templates — they define what the generator should produce, serve as few-shot examples for Gemma 2 naming prompts, and establish the authoring conventions for Phase 3. + +**markers.json schema** (per D-191 section 8): +```json +{ + "cities": [ + { + "name": "...", + "lat": ..., "lon": ..., + "population_tier": 1-6, + "primary_function": "capital|trade|industrial|port|...", + "gate_terminal": true|false, + "continent_id": "..." + } + ], + "roads": [{"path": [[lat, lon], ...], "connects": ["city_a", "city_b"]}], + "railroads": [{"path": [[lat, lon], ...], "connects": ["city_a", "city_b"]}], + "pois": [{"name": "...", "kind": "...", "lat": ..., "lon": ...}], + "rivers": [...existing geometry..., "name": "..."], + "oceans": [...existing geometry..., "name": "..."], + "mountain_ranges": [...existing geometry..., "name": "..."] +} +``` + +The `rivers`, `oceans`, and `mountain_ranges` arrays already exist in `markers.json` from the planet-gen pipeline — they have geometry but `name: null`. Fill the names and add the cities/roads/rail/POIs. + +**Authoring rules:** +- Validate city placements visually against the heightmap PNG — not in water, not on mountains, reasonable distribution across habitable terrain +- Roads/rail should follow terrain corridors (valleys, coastal plains), not cross water without reason +- Names must be culturally appropriate to the system's corridor (Lendel is inner_corridor/inner_core — pan-corridor neutral) +- Gate terminal: largest city unless lore suggests otherwise +- City count: use `floor(log10(pop / 1_000_000))` as baseline; modify for narrative weight of the system + +**Priority systems to author** (suggest Lendel plus 4 from): Sova (Krenn System — canonical setting, D-036), the Sirius system (Concord Assembly seat, D-144), one Compact system (Mark-zone texture), one frontier system (sparse/rough). Miri to select the remaining 4 based on wiki depth and lore importance. + +These hand-authored files should be checked into `wiki/star-systems/` alongside the heightmap PNGs before the sprint ends — they are consumed by the heightmap viewer (#835) and the Gemma 2 naming pipeline (#833) as few-shot examples. + +### #838 — Review and hand-refine generated atlas content + +**Blocked by #832 and #833 (server).** Begin only after `make atlas-generate` has run and produced `markers.json` output for inhabited bodies. + +Review pass across all 273 inhabited bodies. Focus areas: +- City placements: not in water, not on mountains, reasonable geographic distribution +- Names: culturally appropriate to corridor, no Earth-name leaks (blocklist should catch most, review the rest), no duplicates within a body +- Roads/rail: follow terrain, don't cross water without a logical reason (major trade route, bridge) +- Lore consistency: key systems should have city names that match wiki canon where specified + +Refinements go directly into `markers.json` files. Track which bodies needed correction and what kind — this feedback informs generator tuning for Sprint 36. + +Uninhabited bodies (no cities) get geographic feature names only; focus review effort on the 273 inhabited bodies. + +This ticket may complete in sprint or carry to Sprint 36 depending on pipeline timing — #832 and #833 completing early in the sprint is the prerequisite. + +## Dependency Chain + +``` +#840 (glossary) — start here, standalone, unblocks all future authoring +#830 (brand corps in tier1.toml) — standalone, parallel +#831 (brand_templates.toml) — standalone, parallel +#837 (hand-author atlas templates) — standalone, unblocked; complete before #833 runs (few-shot examples) + +#832 (server) + #833 (server) → #838 (review generated content) +``` + +`#840`, `#830`, `#831`, and `#837` are all unblocked and can run in parallel. Complete `#837` before the server team runs `#833` (the Gemma naming pass uses the hand-authored templates as few-shot examples). `#838` is the end-of-sprint pass once generation completes. + +## PR Workflow + +```bash +tea pr create --repo jpmschweitzer/settled-reach --login schweitz \ + --title "content(atlas): hand-authored templates, brand TOML, wiki glossary" \ + --description "Sprint 35 copy work: Lendel atlas templates, brand corps tier1, brand_templates.toml, glossary" \ + --base main --head sprint-35/copy +``` diff --git a/docs/sprints/sprint-35/joint.md b/docs/sprints/sprint-35/joint.md new file mode 100644 index 000000000..fcb14181f --- /dev/null +++ b/docs/sprints/sprint-35/joint.md @@ -0,0 +1,75 @@ +# Sprint 35: Atlas — Integration and Sprint Proof + +**Goal:** Launch Phase 3 — build the atlas generation pipeline (terrain-aware city placement, Gemma naming), lay the brand layer DB schema, and open the Atlas implant in the client. By end of sprint, a player can open the Atlas, navigate to any inhabited body, and see a heightmap with generated city markers. + +--- + +## Pre-Sprint Checklist + +These must be confirmed before implementation work begins: + +| Item | Owner | Status | +|------|-------|--------| +| `terrain_reference` column exists in `bodies` table | server (Tyre) | Verify schema before #839 | +| `markers.json` schema confirmed (D-191 section 8) | server+copy | Align before #832 and #837 start | +| Gemma 2 (`sr-voice` binary) reachable from `tooling/planet-gen/` | server (Dudley) | Check before #833 | +| Copy completes #837 (hand-authored templates) before server runs #833 | copy+server | Coordinate timing — Gemma needs few-shot examples | +| `brand_products` schema confirmed between server (#827) and copy (#830) | server+copy | Avoid data duplication: `tier1.toml` = corp identity; `brands.toml` = product records | + +--- + +## Cross-Team Dependencies + +``` +Copy #837 (hand-author Lendel + 4 systems) ──► Server #833 (Gemma naming — uses as few-shot examples) +Server #839 (terrain_reference) ──► Server #832 (generate_atlas) ──► Server #833 (Gemma naming) ──► Copy #838 (review) +Server #832/#833 data ──► Client #835 (heightmap viewer — populate markers) +Client #834 (atlas panel nav frame) ──► Client #835 ──► Client #836 (overlays) +``` + +The critical path is: `#839 → #832 → #833 → #838`. Copy should complete `#837` in the first week so server can use those templates in the naming pass. + +--- + +## Sprint Completion Proof + +The sprint is done when all of the following are observable: + +1. **Navigation chain end-to-end:** Open the Atlas implant (keyboard shortcut). Select a system from the picker. Click a planet body. See the heightmap viewer. Back-navigate to system, then to Reach map. All three levels work without error. +2. **Heightmap with markers:** At least one inhabited body (Lendel or Sova) displays city markers, roads, and railroads on the heightmap. City names are non-null. +3. **City data panel:** Click a city marker. A sidebar panel opens showing city name, population tier, currency zone, shadow economy zone, and gate distance. An "Economics" link is present. +4. **Economics cross-link:** Click the economics link in the city data panel. The Economics Monitor opens, pre-filtered to that body's system. (Phase 2 panel, Sprint 34 deliverable — this tests cross-panel navigation.) +5. **Overlays present:** The 9 MVP overlay toggles are visible in the regional view. At least 5 always-on overlays render. 4 locked overlays show greyed-out with tooltip. No errors on toggle. +6. **Brand schema in DB:** `brand_products`, `brand_inputs`, `system_fiscal`, `corp_financial_state`, `corp_lifecycle_events` tables exist in `server/data/systems.db`. The 4 canonical brand corps (Calloway, VGV, thrds, Bífröst) appear as demand nodes. +7. **World seed wired:** Server logs show the econ sim initialized with a non-zero seed value derived from `StartupMessage`. +8. **Wiki glossary live:** `wiki/glossary.md` exists and is linked from wiki index. + +--- + +## Test Plan + +| Test | Method | Who | +|------|--------|-----| +| Atlas navigation (all 3 levels) | Manual: open game, open Atlas, navigate down and back | Hoshe | +| Heightmap pan/zoom + marker overlay | Manual: drag, scroll, verify markers render at correct lat/lon | Hoshe | +| City data panel fields | Manual: click 3+ cities across different systems | Hoshe | +| Economics cross-link | Manual: click link, verify panel opens pre-filtered | Hoshe | +| Overlay toggles | Manual: toggle each of the 4 toggleable overlays, verify greyed state of locked | Hoshe | +| `generate_atlas.py` determinism | Run twice with same seed, diff output — must be identical | Dudley | +| Brand tables in DB | `tooling/db/sqlite-query "SELECT COUNT(*) FROM brand_products"` | Dudley | +| Seed in server log | `grep "econ.*seed" server.log` — must show non-zero value | Dudley | +| TOML sync (D-182) | `make economy-db` must pass without name-mismatch errors after #827 + #830 land | Dudley | + +--- + +## Open Questions to Resolve Early + +None blocking. The Phase 3 design is fully specified in D-191. If the `sr-voice` batch interface needs changes to support the naming prompt format, Dudley should flag that before starting #833 (not a blocker for #832). + +--- + +## Notes + +- `#838` (copy review of generated atlas) may not complete fully within the sprint if the generation pipeline runs late — partial completion is acceptable. Track which bodies were reviewed. +- `#836` (overlay system) is medium priority. If client time is tight, `#834` and `#835` are the critical deliverables — overlays can carry to Sprint 36 if needed. Check with Jeroen before deferring. +- Sprint 36 brand tail: `#828` (author 120-170 notable brands) and `#829` (generate_brands pipeline) are intentionally deferred. They depend on `#827` (schema) + `#831` (templates) completing this sprint. diff --git a/docs/sprints/sprint-35/server.md b/docs/sprints/sprint-35/server.md new file mode 100644 index 000000000..c2ee9ec7e --- /dev/null +++ b/docs/sprints/sprint-35/server.md @@ -0,0 +1,116 @@ +# Sprint 35: Atlas — Server Tasks + +**Goal:** Launch Phase 3 — build the atlas generation pipeline (terrain population, city placement, Gemma naming) and lay the brand layer DB schema, so all inhabited bodies have generated markers and the economics simulation uses world-seeded randomness. + +**Branch:** `sprint-35/server` +**Agents:** Dudley (simulation/tooling), Tyre (architecture) + +## New Tickets + +| # | Title | Blocked by | +|---|-------|------------| +| #826 | Thread world seed from StartupMessage into economy simulation | — | +| #827 | Add brand_products, brand_inputs, system_fiscal schema and Phase 2 demand stubs | — | +| #839 | Batch populate terrain_reference column in systems.db bodies table | — | +| #832 | Build generate_atlas.py — terrain-aware sequential city placement and infrastructure generation | #839 | +| #833 | Gemma 2 batch naming pipeline for atlas geographic features | #832 | + +## Key Decisions + +- `decisions/architecture.md` — D-188 (biome_summary → planet_class rename, affects pipeline scripts), D-191 (Atlas Phase 3 scope — full pipeline spec: city placement algorithm, infrastructure gen, naming, markers.json schema) +- `decisions/economics.md` — D-189 (brand layer architecture — DB schema per section 5), D-190 (brand volume calibration — population-relative scale), D-185 (brands are not commodities — brand corps are commodity demand nodes), D-175 (corp taxonomy — Tier 1 brand corps), D-182 (TOML source of truth — make economy-db extends to brand tables) + +## Notes + +### #826 — Thread world seed into economy simulation + +Small, self-contained. `server/src/simulation/mod.rs` initializes `EconSimResource` with `try_load_economy(0)` — the `0` is a hardcoded seed. Wire in the `world_seed` from `StartupMessage` (received during the IPC handshake). The seed is already available in the simulation startup path; find where `StartupMessage` is handled and thread the value through to `try_load_economy()`. Start here — it unblocks nothing else but is low-risk and closes the Sprint 34 loose end. + +### #827 — Brand layer DB schema and Phase 2 demand stubs + +Per D-189 section 5, add five new tables to `db/schema.sql` (or `server/data/systems-schema.sql` if that is the brand-layer schema file — check which file `make economy-db` reads): + +- `brand_products` — full column list in D-189 section 5 +- `brand_inputs` — `brand_product_id`, `commodity_id`, `quantity` +- `system_fiscal` — `system_id`, `corp_tax_rate`, `collection_efficiency` +- `corp_financial_state` — passive tracking (Phase 2: health metric only) +- `corp_lifecycle_events` — Phase 3 lifecycle state machine (Phase 2: stub table with correct schema) + +Add composite index on `brand_products(corp_id, brand_category)` for UI queries (D-189 section 5). + +Also author `wiki/economics/corporations/brands.toml` (new file) with TOML records for the 4 canonical brand corps: Calloway Distillery, Vins de Grand Vide, thrds, Bífröst Marmor. Each record registers those corps as commodity demand stubs at their home market nodes — they consume generic commodity inputs (per D-185: brands consume commodities, not the reverse). The copy team (#830) is authoring these same entries to `tier1.toml`; coordinate — the brand corps should appear in `tier1.toml` (copy) AND have separate `brand_products` entries (this ticket). Do not duplicate data; confirm the split before writing. + +Extend `make economy-db` to compile brand tables alongside the existing pipeline. Add validation rules V-B01 through V-B05 (defined in the ticket description). + +### #839 — Batch populate terrain_reference + +The `bodies` table in `server/data/systems.db` has a `terrain_reference` column that is NULL for all 273 inhabited bodies. Write a batch script (Python fits alongside the existing `tooling/planet-gen/` scripts) that: + +1. Queries all body rows with NULL `terrain_reference` +2. Constructs the expected wiki heightmap path: `wiki/star-systems/{system_slug}/bodies/{body_id}/heightmap.png` +3. Verifies the file exists +4. Updates the column + +Log any bodies where the heightmap is missing so they can be flagged. This is the prerequisite for `#832` — `generate_atlas.py` reads `terrain_reference` to find the heightmap. Keep the script simple; it's a data population pass, not logic. + +### #832 — Build generate_atlas.py + +New Python pipeline at `tooling/planet-gen/generate_atlas.py`. Reuses `planet_simulation.simulate()` for terrain data. Per D-191 section 3 and 9: + +**Pipeline order:** +1. Load heightmap via `terrain_reference` (populated by #839) +2. Analyze terrain: continent detection (flood-fill), habitability scoring (temperature + moisture + slope), river mouth identification +3. Place cities sequentially: + - Capital first: ~50% at river mouths, scored by habitability + coastal access + flat hinterland + - Rail corridor growth: cities 2-N follow the capital's terrain corridor + - New continent ports at cities 3-4 (cross-continent expansion) +4. Generate infrastructure: A* pathfinding for roads and rail on terrain cost grid, MST network connecting cities +5. Apply quadrant distribution constraint (cities should not all cluster in one area) +6. Apply ±25% noise for variation +7. Compute city count from population: `floor(log10(pop / 1_000_000))`, modified by `settlement_pattern` from systems.db +8. Write `markers.json` per body (schema per D-191 section 8: cities with lat/lon/population_tier/primary_function/gate_terminal/continent_id, roads, railroads, POIs) + +**make target:** `make atlas-generate` — incremental, skips bodies where `markers.json` already populated. Deterministic per seed. + +Naming step is NOT in this ticket — city names will be blank strings in this pass; `#833` fills them. Gate terminal POI: place at largest population center, occasionally scatter to a smaller one (per D-191). + +Existing files to reuse: `tooling/planet-gen/planet_simulation.py`, `tooling/planet-gen/biome_config.py`. The `generate.py` script already calls `_build_markers()` for rivers/oceans/mountains — extend that structure rather than replacing it. + +### #833 — Gemma 2 batch naming pipeline + +Extend `generate_atlas.py` with `tooling/planet-gen/gemma_naming.py` — a batch client for the `sr-voice` binary. Per D-191 and D-191 cross-reference to D-138 (Gemma 2 voice pipeline): + +For each body, send corridor-appropriate naming prompts: +- Prompt context: `planet_class`, `cultural_corridor`, `settlement_pattern`, `atmospheric_tone` + corridor palette +- Name: rivers, oceans, mountain ranges, regions, city names (already placed by #832, just unnamed) +- Naming patterns per D-189: `north_reach` → British/Australian inflection, `east_reach` → Korean/Japanese, `west_reach` → German/Dutch/Nordic, `south_reach` → Portuguese/Swahili, `inner_corridor` → pan-corridor neutral, `frontier` → founder surname + noun + +Post-processing: +- Earth-name blocklist (filter obvious Earth names that slip through) +- Dedup check against full name corpus per body +- Estimated runtime: ~80 min for all 2,394 bodies — make this batch incremental + +This ticket serves dual purpose: Phase 3 content delivery AND a quality test of the Gemma 2 naming pipeline ahead of its broader use. + +The `sr-voice` binary lives in `server/src/voice/` — check existing voice pipeline callers in the codebase for the batch invocation pattern before writing new code. + +## Dependency Chain + +``` +#826 (seed wiring) — standalone, start first (small) + +#827 (brand schema + demand stubs) — standalone, parallel track + +#839 (terrain_reference populate) → #832 (generate_atlas.py) → #833 (Gemma naming) +``` + +`#839 → #832 → #833` are sequential. `#826` and `#827` are fully parallel to the atlas chain. Atlas pipeline is the sprint's critical path. + +## PR Workflow + +```bash +tea pr create --repo jpmschweitzer/settled-reach --login schweitz \ + --title "feat(simulation): atlas generation pipeline and brand schema" \ + --description "Sprint 35 server work: terrain_reference population, generate_atlas.py, Gemma naming, brand DB schema, world seed wiring" \ + --base main --head sprint-35/server +```