Files
settled-reach/docs/workshops/generation-cascade/gestalt-round1.md
T
jpmschweitzerandClaude Opus 4.6 42ee1f0a0e docs(workshops): generation cascade workshop — 4 rounds, D-194 through D-218
Four-round workshop (Gestalt, Tyre, Paula, Burnelli-Sheldon, Miri)
mapping the full generation pipeline from planetary heightmap to
walkable tile. 25 D-records produced. Ticket dependency chain for
Tier 0-4 implementation identified.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-05-03 20:18:17 +02:00

20 KiB
Raw Blame History

title, description, type, status, workshop, agent, round, created
title description type status workshop agent round created
Gestalt — Round 1: Systems Inventory Pipeline inventory from the systems design perspective: layer states, system interactions, economics integration, and ticket dependency analysis workshop active generation-cascade gestalt 1 2026-04-30

Generation Cascade — Round 1: Gestalt Inventory

Focus: System interactions across pipeline layers. Where does economics enter? Where do social sites, NPC population, and zone palettes enter? What's the minimum viable viewable world? What tickets formally block the right work?


Pipeline Inventory — Layer by Layer

Overview

Layer Name Status Input Output Key Code
1 Galaxy / System definitions DONE Wiki markdown frontmatter systems.db (star_systems, bodies) tooling/economy-db/import_economics.py
2 Planetary terrain simulation DONE Body definition (planet_class, biome) Elevation/temp/moisture/water grids (in-memory) tooling/planet-gen/planet_simulation.py
3 Atlas markers (city placement) DONE Terrain grids + systems.db (population, settlement_pattern) markers.json (cities, roads, rail, rivers, mountains, POIs) tooling/planet-gen/generate_atlas.py
4 City naming DONE markers.json (empty name fields) + cultural_corridor markers.json (named cities and features) tooling/planet-gen/gemma_naming.py
5 Economics layer DONE Wiki TOMLs + brand templates + Rust binary systems.db (corps, brands, supply chains, trade flows) tooling/economy-db/import_economics.py
6 City → District decomposition MISSING City entry from markers.json (position, population, kind) N district stubs with WorldTier/ComplexityTier/SettingType Nothing exists
7 Phase 1: DistrictSkeleton generation STUB District classification from Layer 6 Filled DistrictSkeleton (block grid, reservations, social sites, zone palette) server/src/simulation/generator.rs — types only
8 Society profile resolution PARTIAL cultural_corridor + heritage roots from body/system SocietyProfileRef → cultural behavioral inputs #679 (done) but not wired to DistrictSkeleton
9 Phase 2: ChunkData tile generation MISSING DistrictSkeleton Phase 1 output Filled 64×64 tile grid (WalkabilityMap + tile types) Nothing connects generator to tile data
10 Heritage grammar application MISSING SocietyProfileRef + zone palette + chunk skeleton Culturally modified tile layout HeritageGrammarOverlay not implemented
11 NPC population (Phase 2) PARTIAL DistrictSkeleton.society_profile + social_sites NpcManifest → NPC pool with triangle assignments Triangle/template system is FULL (#107, #108 done); NpcManifest seeding from skeleton is missing
12 Chunk streaming to generator hookup STUB Player position → on-demand load request Generator-filled ChunkData delivered to WalkabilityMap chunk_streaming.rs — load/unload works but calls static v0.1 data, not generator

Layer Details

Layer 15: What's Done

These layers are genuinely complete and pipeline-capable. Layer 3 (atlas generator) deserves particular attention — it does real terrain-aware computation: continent flood-fill, habitability scoring, river mouth detection, A* road routing, MST rail generation. The output is rich and the data is in systems.db. The atlas is the last fully-working pipeline layer.

The economics layer (Layer 5) is likewise complete: corporations, brands, supply chains, trade flows, fiscal systems are all in systems.db. There is no code bridging this data downstream to district/zone generation yet.

Layer 6: City → District Decomposition — MISSING (Critical Gap)

This is the first entirely missing layer. The atlas produces city markers (position, population, kind: capital/city, economic_role). Converting a city into N districts with appropriate classifications requires:

  • Population tier → district count formula (e.g. population ÷ 50,000 per district, min 1)
  • city.kind + body.economic_role → DistrictType assignments
  • body.planet_class + city position → SettingType (Urban/Agricultural/Maritime/etc.)
  • system WorldTier → ComplexityTier ceiling

No ticket formally covers this. #899 (District skeleton generator — Phase 1) assumes this decomposition as a prerequisite input but does not scope it. This layer needs its own ticket.

Layer 7: Phase 1 DistrictSkeleton — STUB, with a Critical Data Model Discrepancy

server/src/simulation/generator.rs has a complete DistrictSkeleton struct with all fields the workshop designed. Types compile. But:

  1. No generation logic exists. Every field that requires reasoning (block grid ZoningType assignments, social site placement, reservation generation, zone palette selection) has stub type aliases:

    • ZoneDefinition = String
    • SocietyProfileRef = String
    • DistrictContext = String
    • Era = String
    • AccessPoint = String
    • GuaranteeAuditResult = String
  2. WorldTier enum does not match the workshop decision. The code has:

    enum WorldTier { Peripheral, Connected, Core }
    

    The workshop (D-READY-2, workshop-outcomes.md) locked:

    enum WorldTier { Epicenter, Regional, Backwater, Passage, Waypoint }
    

    This is a blocker. #899 cannot be implemented correctly against the current enum. Must be fixed before any generation logic touches WorldTier.

Layer 8: Society Profile Resolution — Partial

Ticket #679 (location-to-culture resolution system) is done. This means we can resolve cultural_corridor → heritage_root for any location. But this output is not yet wired into DistrictSkeleton.society_profile. The SocietyProfileRef field is a String stub — the culture system exists but isn't connected to the generation path.

This is a wiring gap, not a design gap. Relatively cheap to fix once Phase 1 generation logic exists.

Layer 9: Phase 2 ChunkData Tile Generation — MISSING (Critical Gap)

This is the other critical missing layer. chunk_streaming.rs has a solid streaming architecture — load/unload around player position works correctly. But walkability.load_chunk(coord) creates empty chunks; it doesn't call any generator.

The v0.1 world tiles come from YAML files authored by hand (#577) — server/data/locations/. The generator never produces tiles. There is no pipeline from DistrictSkeleton → actual walkable tile data.

For Phase 2 to work:

  • ChunkData needs a tile layer (beyond the walkability bool grid)
  • A generator function must take BlockSkeleton + DistrictSkeleton and fill a 64×64 tile grid
  • chunk_streaming.rs needs to call this generator on ZLevelLoadState::Ungenerated chunks

Existing pre-workshop tickets (#100 "Ungenerated → instantiation", #156 "Procedural district filler", #160 "Tier 3 procedural generator") pre-date the confirmed architecture. They need re-scoping against DistrictSkeleton/ChunkData.

Layer 10: Heritage Grammar — MISSING

HeritageGrammarOverlay is designed (D-READY-9 from workshop) but no Rust type exists. This is Phase 2+ — it applies at chunk fill time. Not a blocker for the minimum viable slice, but it IS what makes tiles culturally distinguishable.

Layer 11: NPC Population — Partial (More Done Than Expected)

The triangle system (server/src/simulation/triangle.rs) is substantially implemented — the workshop brief calls it "stubs" but the file is extensive: template schemas, triangle escalation tick system, NPC spawn patterns. Intra-template (#107) and cross-template (#108) triangle generation are both done.

What's missing is the Phase 2 pipeline connection: NpcManifest seeding from DistrictSkeleton.society_profile + social_sites. But the machinery to run NPCs once they're spawned exists. This means NPC population is a wiring problem, not a design or implementation gap.

Layer 12: Chunk Streaming Hookup — Stub

chunk_streaming.rs has the right architecture for v0.3+ on-demand loading (commented explicitly in the file: "For v0.3+, the generator fills newly loaded chunks with terrain data"). The radius=8 default covers the entire v0.1 district, so nothing unloads. The system is ready for the generator hookup; it just needs the generator to exist.


System Interactions Analysis

Economics Layer → Generation Pipeline

The economics layer is rich but its connections downstream are all implicit data, no code.

Economics Output Where It Should Enter Current State
bodies.economic_role (Agriculture/Refining/Transit/etc.) Layer 6: district decomposition → DistrictType Not wired
bodies.cultural_corridor Layer 8: society profile → SocietyProfileRef #679 done but not wired to skeleton
Corporation presence in system Phase 1: DistrictSkeleton zone_palette modifiers (FactionModifier) ZoneDefinition is a String stub
Supply chain density Phase 1: DistrictType (Commercial/Industrial/Logistics) weighting No connection
Brand presence Phase 2 / Heritage grammar: signage, storefronts HeritageGrammarOverlay not implemented
Trade flow volume WorldTier assignment (high-traffic → higher tier) No connection

Key design principle for Round 2: The economics → generation bridge should be explicit in Layer 6. When we decompose a city into districts, the economic_role should directly drive DistrictType proportions:

  • economic_role=Agriculture → mostly Agricultural setting + Industrial blocks for processing
  • economic_role=Refining → Industrial + Specialized
  • economic_role=Transit → Transit + Commercial + Logistics

This is a systems design decision that should produce D-records.

Where Social Sites, NPC Population, and Zone Palettes Enter

System Entry Layer Entry Mechanism Current State
Zone palettes Phase 1 (Layer 7) DistrictSkeleton.zone_palette (Vec) ZoneDefinition = String stub
Social sites Phase 1 (Layer 7) DistrictSkeleton.social_sites (Vec) SocialSitePlacement struct exists; no generation code fills it
NPC pool Phase 2 (Layer 11) NpcManifest seeded from society_profile NpcManifest not yet a type; society_profile is a String
Triangle assignments Phase 1 (Layer 7) DistrictSkeleton.social_sites[i].triangles No generation code
Heritage grammar Phase 2 (Layer 10) HeritageGrammarOverlay applied at chunk fill time Not implemented

Critical ordering constraint: Zone palettes must be determined at Phase 1 before chunk tiles can be generated in Phase 2. Social sites must be placed before NPC positions can be assigned. The dependency chain inside Phase 1 is:

Classification (WorldTier, ComplexityTier, SettingType)
  → Block grid assignment (ZoningType per block)
    → Zone palette selection (economics + era + culture)
      → Social site placement (template + block assignment)
        → Triangle assignment (TrianglePurpose per site)
          → Guarantee audit (3-tier checks)

The Phase 2 chain continues:

DistrictSkeleton (immutable)
  → ChunkData tile fill (floor/wall/zone tile types)
    → Heritage grammar overlay (cultural modifier)
      → NpcManifest instantiation (society_profile → NPC pool)
        → Triangle → NPC assignments (existing triangle system)

Minimum Viable "Viewable World"

The thinnest vertical slice from heightmap to rendered tiles:

Inputs available now: One city entry from markers.json (position, population, kind). Body's planet_class, economic_role, cultural_corridor from systems.db.

Minimum code to write:

  1. Layer 6 stub: Fixed formula n_districts = max(1, population / 50_000). Assign one SettingType from planet_class. Assign WorldTier from system lookup. Output: N (WorldTier, ComplexityTier, SettingType) tuples.

  2. Layer 7 minimal: Generate DistrictSkeleton with real block grid. Simple deterministic ZoningType assignment from DistrictType (e.g. Commercial district → mostly Commercial blocks, some Mixed). No social sites. No reservations. No guarantee audit. Zone palettes as named constants only.

  3. Layer 9 minimal: For each BlockSkeleton, fill 4 chunks (2×2) with simple tile layout: exterior walls + floor interior + one door per edge. No rooms, no objects, no heritage grammar. Pure structural.

  4. Wiring: In chunk_streaming.rs, on load_chunk() when no YAML data exists, call the Phase 2 generator instead of returning empty. The existing tilemap renderer already handles ChunkData.

What this produces: A player standing in a procedurally-generated city block. Walls are walls. Floor is floor. No cultural character. No NPCs. No social sites. But it's walkable, streaming, and fully pipeline-driven — which is what the cascade deliverable requires.

Estimated effort for minimum viable slice: ~57 dev-days of focused server work (Layer 6: 0.5 days, Layer 7 minimal: 2 days, Layer 9 minimal: 2 days, wiring: 1 day, WorldTier enum fix: 0.5 days).


Ticket Dependency Chain

Current State of Referenced Tickets

Ticket Title Status Current Blockers My Assessment
#897 Generation pipeline cascade (this workshop) backlog Active; blocks #899
#899 District skeleton generator — Phase 1 backlog #897 Correct scope, but misses Layer 6 and WorldTier fix
#615 Tycoon small business owner starting state backlog Game content design, not generation-dependent
#616 Broad economic verb vocabulary design backlog Pure content design, no generation dependency
#619 Full character customisation backlog Phase 4 cosmetic UI, NOT generation-dependent
#681 Apartment generator logic (server) backlog #615, #679(done) Needs cascade blocker: Phase 1 skeleton + cultural context
#682 Apartment visual rendering (client) backlog #681 Correct — blocked by #681
#694 Character creation screen backlog #685(done) Phase 4 UI, NOT generation-dependent

Character and Apartment Work: What Actually Needs Blocking

#619 (Character customization) and #694 (Character creation screen): These are cosmetic UI tickets for Phase 4 (Player Control Scheme). Character visual appearance is independent of world generation. These should NOT be formally blocked behind generation pipeline work. The player needs to look like something before the world needs to be generated. Do not add generation blockers here.

#681 (Apartment generator): This IS generation-dependent and needs additional blockers. The apartment:

  • Lives in a building in a district → needs that district's zone context
  • Uses cultural context → #679 done, but the wiring to DistrictSkeleton is not done
  • Uses economic position → #615 (tycoon starting state) is a real dependency

Recommended: add formal blocker on #681 behind Phase 1 district skeleton working. The apartment generator cannot produce culturally-appropriate tile layouts without knowing the district's society_profile and zone_palette.

#682 (Apartment visual rendering): Correctly blocked by #681. No changes needed.

New Tickets Needed

Priority Ticket Scope Blocked By
Blocker Fix WorldTier enum — Peripheral/Connected/Core → Epicenter/Regional/Backwater/Passage/Waypoint Rename enum values in generator.rs to match workshop-locked decision #897
Critical Layer 6: City → District decomposition Convert atlas city markers to district count + classification stubs None (can start after WorldTier fix)
Critical Phase 2: Basic chunk tile generator Fill 64×64 chunk from BlockSkeleton: walls + floor, no rooms #899
High Connect chunk_streaming to Phase 2 generator On load_chunk() for Ungenerated chunks, invoke Phase 2 generator Phase 2 chunk tile generator
High Wire society profile to DistrictSkeleton Connect #679 location-to-culture output → DistrictSkeleton.society_profile #899
Medium Re-scope #156 (Procedural district filler) Align pre-workshop ticket to DistrictSkeleton architecture Phase 2 chunk tile generator
Medium Re-scope #100 (Ungenerated → instantiation) Align to chunk_streaming + Phase 2 on-demand fill pattern Phase 2 chunk tile generator

Formal Cascade Blocker Chain

#897 (this workshop — D-records)
  └─▶ WorldTier enum fix
  └─▶ Layer 6: City → District decomposition (new ticket)
       └─▶ #899 Phase 1 DistrictSkeleton generation
            └─▶ Phase 2: Basic chunk tile generator (new ticket)
                 └─▶ Connect chunk_streaming to generator (new ticket)
                      └─▶ Wire society profile to skeleton (new ticket)
                           └─▶ #681 Apartment generator (ADD formal block here)
                                └─▶ #682 Apartment visual rendering
                                
#694 Character creation screen — NOT in this chain (Phase 4 UI work)
#619 Character customization — NOT in this chain (Phase 4 cosmetic work)
#616 Verb vocabulary — NOT in this chain (content design)
#615 Tycoon starting state — feeds #681, not generation pipeline

Key Flags for Round 2 Discussion

1. WorldTier enum mismatch is a hard blocker

Before #899 can be correctly implemented, WorldTier in generator.rs must be renamed. This is a small code change but touches a core enum — it needs a D-record confirming the canonical values before the rename happens, to prevent the same drift occurring again.

2. The apartment generator dependency chain is currently incomplete

#681 is blocked only by #615 and #679. It should also be blocked by Phase 1 district skeleton generation. The apartment exists in a district — without district skeleton generation working, we can't produce the zone context that makes an apartment feel culturally appropriate vs. just a random room.

3. Layer 6 (City → District decomposition) has no ticket

This is the first link in the chain from atlas markers to walkable tiles, and it has no ticket and no code. Without it, #899 has no valid input. New ticket needed before #899 can be effectively scoped.

4. Phase 2 tile generation is the real gate on "viewable world"

Phase 1 skeletons are useful for planning and NPC/economic pre-computation. But the cascade deliverable is "walkable generated world" — that requires Phase 2 tile generation. The thinnest slice that produces rendered tiles requires Phase 2, even if that Phase 2 is initially just "floor tiles inside block boundaries, wall tiles at edges." The existing rendering pipeline will handle it.

5. The economics layer is rich and available — use it at Layer 6

We have economic_role, cultural_corridor, trade flow data, corporation presence — all in systems.db. Layer 6 (city → district decomposition) is the natural integration point where this data should shape district character. The design principle: economics drives district type; culture drives zone palette; both come from systems.db data that already exists.


Summary Table

Gap Severity Effort Notes
WorldTier enum mismatch Blocker 0.5 days Rename enum values, update all references
Layer 6: City → District decomposition Critical 0.51 day New ticket, no design gaps just missing code
Phase 1 generation logic Critical ~23 days #899, blocked by this workshop's D-records
Phase 2 chunk tile generator Critical ~2 days New ticket, blocked by #899
Chunk streaming → generator hookup High ~1 day New ticket
Society profile → skeleton wiring High 0.5 days Design done (#679), wiring only
Heritage grammar overlay (Rust type + logic) Medium ~34 days Phase 2+, not on critical path for minimum slice
NpcManifest seeding from skeleton Medium ~1 day Machinery exists, connection missing
Guarantee audit implementation Low ~2 days Can defer until Phase 1 generation is stable