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>
23 KiB
title, description, type, status, workshop, agent, round, created
| title | description | type | status | workshop | agent | round | created |
|---|---|---|---|---|---|---|---|
| Round 2 Notes — Generation Cascade Workshop | Compiled Round 2 proposals: consensus, Paula's spatial narrative additions, disagreements, D-record candidates, ticket dependency convergence, and open questions for Round 3 | workshop | active | generation-cascade | qatux | 2 | 2026-04-30 |
Generation Cascade Workshop — Round 2 Notes
Compiled by: Qatux
Source files:
docs/workshops/generation-cascade/gestalt-round2.mddocs/workshops/generation-cascade/tyre-round2.mddocs/workshops/generation-cascade/paula-round2.md
Scope: Spatial pipeline only — from atlas city markers to walkable rendered tiles. Heritage grammar, NPC population, social sites, culture overlays, and #615 are out of scope per lead directive.
Summary
Round 2 achieved strong convergence on implementation order, effort, and the stored-vs-derived boundary. The two key technical open questions from Round 1 (OQ-R1-C and OQ-R1-D) are now resolved by both technical participants independently reaching the same conclusions. Paula introduced three new spatial narrative fields and a naming register system that neither Gestalt nor Tyre addressed — these require Round 3 disposition before Phase 2 can be scoped. Effort estimates converged to ~6–7 days once heritage grammar contamination was removed from Tyre's Round 1 figure.
Out-of-Scope References — Flagged
Two references in the Round 2 files touch heritage or cultural territory. Per scope rules, these are flagged but not incorporated:
-
Paula §5 on #615: Paula references "OQ-R1-B resolved (SocietyProfileRef type)" as a dependency for #615.
SocietyProfileRefis heritage territory (culture file resolution). The reference is used to position #615's unblocking condition, not to reopen heritage design — but the dependency chain Paula describes would require an out-of-scope decision. Not incorporated into consensus. -
Paula §2 — Naming system: The five naming registers themselves (
Commemorative | Functional | Aspirational | Folk | Geographic) are spatial parameters derivable from(DistrictType, WorldTier). The lookup table that maps registers to types is in scope as a spatial decision. However, Paula notes that "the names are drawn from culture pool" for seeded generation — name pools are heritage/cultural territory. The register taxonomy and lookup table are captured here; the name pool population is flagged as out of scope for this workshop.
Consensus Points
1. Effort estimates converged: ~6–7 dev-days
Round 1 gap (Gestalt ~5–7d vs. Tyre ~9d) was caused by heritage grammar contamination in Tyre's estimate. With spatial-only scope:
- Gestalt Round 2: 5.5 days (explicit line-item breakdown)
- Tyre Round 2 revised: 6–7 days (conservative; includes type migration friction)
Gestalt's 5.5d floor represents minimum friction. Tyre's 6–7d includes explicit allowance for String-stub-to-real-type migration surprises during compilation. Paula (§5) explicitly supports the Gestalt floor estimate and Stages 1–2 deferral position.
Converged answer: ~6 days under reasonable conditions. 7–8 days if String-stub migrations surface unexpected breadth.
2. OQ-R1-C resolved: do not extend markers.json
Both Gestalt and Tyre independently reached the same answer:
primary_function,planet_class, andsettlement_patternare read fromsystems.dbbodies table by cross-reference onbody_id.generate_atlas.pydoes not need modification.
- Gestalt: "Do not extend markers.json. Instead, resolve via systems.db cross-reference using body_id... keeps markers.json as a pure spatial-plus-naming store."
- Tyre: "
primary_function,planet_class,settlement_patternare available in systems.db bodies table and do NOT need to be added to markers.json."
Status: RESOLVED. No markers.json schema changes. City decomposition reads systems.db bodies table directly.
3. OQ-R1-D resolved: no pixel-to-sim-tile formula needed
Tyre provided the architectural resolution:
"The atlas grid is a display coordinate system for the atlas UI. It is not a world-space coordinate for the game simulation. The walkable world uses a city-local coordinate system starting at (0, 0)."
Atlas pixel coordinates are UI-only (city dot placement on planetary map). The walkable world uses city-local sim-tile coordinates. Districts in a city are placed at (col × 512, row × 512) sim tiles in city-local space. No conversion from atlas pixels to sim tiles is needed or meaningful.
Gestalt's Round 2 acknowledged the same conclusion: "For the minimum slice, we don't need this — we spawn one district at world origin." Gestalt deferred the multi-city coordinate question to Step 2b / Round 3; Tyre provided the answer: it's city-local grid, not atlas-pixel-derived.
Status: RESOLVED. Atlas coordinates are UI-only. No formula needed. City-local sim-tile coordinates from (0,0).
4. Seed-vs-stored boundary: atlas markers are the last stored layer
Both Gestalt and Tyre independently reached the same boundary definition:
Stored (authored or generated-then-committed):
- Star system and body definitions (wiki + systems.db)
- Economic data, corporations (systems.db economics tables)
- City positions, populations, infrastructure (markers.json + systems.db atlas tables)
- City names (markers.json, Gemma-filled, curated)
- Chunk mutations / DamageOverlay (save file)
Seed-derived (never stored, always re-derived from world_seed):
-
District count and positions per city
-
DistrictSkeleton (all fields)
-
BlockSkeleton per district
-
ChunkData tile grid
-
Building footprints, door positions
-
Gestalt: "At the boundary between atlas markers and city → district decomposition (between Layer 5 and Layer 6)."
-
Tyre: "The boundary is between Layer 4 and Layer 6... markers.json city entries are the stored anchor. Below that, the world is fully deterministic from world_seed."
Status: CONSENSUS. Atlas markers are the last stored layer. Save files store world_seed + markers_snapshot + ChunkMutations only.
5. SeedChain design: FNV-1a child_seed
Tyre proposed the concrete seed derivation mechanism. Gestalt's formula (world_seed XOR fnv1a(city_id) XOR district_index) uses the same approach. Consistent with D-010 (FNV-1a determinism mandate).
Tyre's proposed canonical form:
fn child_seed(parent: u64, discriminant: u64) -> u64 {
let mut h = parent ^ 0xcbf29ce484222325;
for byte in discriminant.to_le_bytes() {
h ^= byte as u64;
h = h.wrapping_mul(0x100000001b3);
}
h
}
district_seed = child_seed(world_seed, district_id)
chunk_seed = child_seed(district_seed, (cx as u64) << 32 | (cy as u64))
Properties: any district or chunk can be generated in isolation without generating neighbors first. Generation is parallelizable. No global state required.
6. Phase 1 minimum scope: Stages 1–2 only
All three participants agree Phase 2 tile generation requires only Stages 1 and 2 of Phase 1. Stages 3–5 are deferred.
- Gestalt: Stages 1–2 mandatory. "Fields deferred: reservations, corridors, social_sites, boundaries, guarantee_audit, zone_palette, society_profile, access_points."
- Tyre: "Stages 3 (reservations), 4 (social sites), and 5 (guarantee audit) are deferred — they produce spatial enrichment but are not required for a walkable tile."
- Paula (§5): "I'd formally support deferring Stages 3–5 until after the first walkable district is demonstrably legible."
7. Implementation order (all three agree)
The five-step sequential dependency chain is consistent across Gestalt and Tyre. Steps cannot be parallelized until Step 3 produces a compilable skeleton:
Step 1: Fix WorldTier enum (0.5d)
└─▶ Step 2a: Single-district decomposition stub (0.5d)
└─▶ Step 3: Phase 1 Stages 1-2 generation (1.5-2d)
├─▶ Step 4: Phase 2 minimal tile generator (1.5d)
│ └─▶ Step 5: Chunk streaming wiring (0.5-1d)
│ └─▶ [MINIMUM VIABLE WALKABLE WORLD]
└─▶ Step 2b: Full city decomposition + district grid (1d, follow-on)
8. GeneratorChunkData type must be upgraded
Both Gestalt and Tyre note that pub type GeneratorChunkData = Vec<bool> cannot carry tile IDs and must become a proper struct. Tyre specifies the form:
pub struct GeneratorChunkData {
pub tiles: Vec<TileEntry>, // 64×64 = 4096 entries
}
pub struct TileEntry {
pub tile_id: TileId,
pub walkable: bool,
}
Gestalt concurs that TileId per cell is needed for zone-tinted floor tiles. The type change is a prerequisite for Phase 2.
9. Existing tickets consensus
All three participants (where they addressed tickets) reached identical positions:
| Ticket | Consensus position |
|---|---|
| #619 | NOT generation-dependent. Phase 4 work. No generation blockers. |
| #694 | NOT generation-dependent. Phase 4 work. No generation blockers. |
| #681 | Add formal blocker behind "Minimum Viable Walkable World" milestone. |
| #682 | Correctly blocked by #681. No changes. |
| #616 | No generation dependency. Can proceed. |
| #156 | Close/supersede. New Phase 2 ticket replaces it. |
| #100 | Close/fold into chunk streaming wiring ticket. |
| #899 | Rescope: Stages 1–2 only. Remove Stage 4–5 from scope. Add dependency on WorldTier fix + new city decomp ticket. |
| #615 | Out of scope per lead directive. No position. |
Paula's Spatial Narrative Proposals — Mapping to Gestalt/Tyre
Paula introduced three new concepts not addressed by Gestalt or Tyre. Each requires Round 3 disposition before it can be confirmed as in-scope for the minimum slice.
Paula Proposal P1: prosperity_index: f32 (new field)
A single 0.0–1.0 scalar on DistrictSkeleton that drives tile decay probability, road width, building density, and green space allocation. Derived from WorldTier + DistrictType + city economic profile from systems.db. No authoring required.
| Prosperity band | Tile decay | Road width | Building density | Green space |
|---|---|---|---|---|
| 0.0–0.2 (subsistence) | 40–60% damaged | Narrow | Very high | None |
| 0.2–0.4 (working) | 20–35% | Narrow-medium | High | Minimal |
| 0.4–0.6 (middle) | 5–20% | Medium | Medium | Small plazas |
| 0.6–0.8 (affluent) | 1–5% | Medium-wide | Lower (setbacks) | Parks |
| 0.8–1.0 (elite) | <1% | Wide/boulevard | Low (wasted space = luxury) | Gardens |
Gestalt/Tyre accommodation: Neither includes prosperity_index in their Stage 1 classification. Adding it is architecturally clean — it's a derived field with the same inputs as other Stage 1 fields. However, it changes Phase 2 tile generation (density-driven building placement is in Tyre's algorithm; Paula's version connects that density to prosperity). Round 3 must decide: is prosperity_index in scope for the minimum slice?
Paula's argument for inclusion: "If prosperity_index and perimeter_treatment aren't on DistrictSkeleton before Phase 2 is implemented, tile generation will produce spaces that are spatially indistinguishable regardless of district type — a simulation fidelity problem that's expensive to retrofit."
Paula Proposal P2: perimeter_treatment: PerimeterTreatment (new field)
New enum on DistrictSkeleton:
Open // no boundary markers; permeable
Fenced // visible boundary, no control
Walled // physical barrier, uncontrolled gaps
Gated // checkpoints on main arteries, open on minor
Checkpoint // all entry points monitored
Derived from DistrictType + WorldTier + prosperity_index. Manifests as boundary marker tiles at access_points in Phase 2.
Gestalt/Tyre accommodation: AccessPoint is already in DistrictSkeleton as a stub (pub type AccessPoint = String). perimeter_treatment extends the access system with political character. Neither Gestalt nor Tyre proposed this field. Round 3 must decide whether this is in scope for the minimum slice.
Paula's argument: "The approach to a district is the first story beat. A player walking toward a Checkpoint district understands access control before entering. No tile variation needed — just the presence of the boundary marker tile."
Paula Proposal P3: political_archetype (authored per city)
Five archetypes for city-level authoring (one field per city in atlas/systems.db):
CompanyTown— one corporation dominates; homogeneous district type distributionAdminCapital— government/institutional core with support districtsFreePort— Transit and MixedUse dominant; contested/heterogeneousContested— two or more factions with visible boundary zonesOrganicGrowth— no dominant power; district types mix without hierarchy
Paula notes this "drives the district type distribution for Layer 6" and is derivable from systems.db economics data for most cities, but named cities warrant sanity-checking. This is "a small authoring task, not a large one."
Gestalt/Tyre accommodation: Neither Gestalt nor Tyre proposed political_archetype. Gestalt's decomposition formula (DistrictType from body.economic_role + city.kind) approximates this without the concept explicitly. Paula's proposal is a named abstraction over the same data. Round 3 must decide whether to formalize this as a named field or keep it implicit in the decomposition formula.
Paula Proposal P4: Naming Registers (in-scope component only)
Paula proposes five naming registers that determine what kind of name a district or street receives:
| Register | Pattern | Typical districts |
|---|---|---|
| Commemorative | Person's/institutional name | Administrative, elite Residential |
| Functional | What happens here | Industrial, Transit, LogisticsHub |
| Aspirational | Abstract positive noun | New Commercial, MixedUse growth |
| Folk | Colloquial/ironic | Old Residential, Backwater |
| Geographic | Terrain feature | Pre-political, oldest settlements |
The register lookup table (DistrictType, WorldTier) → register is a spatial/structural decision — in scope for this workshop. The name pools that populate each register are cultural content — out of scope for this workshop.
Neither Gestalt nor Tyre addressed district naming. Paula's register system adds no new DistrictSkeleton fields but informs Phase 2 street labeling. Round 3 must decide: does the naming register lookup table need to be locked before Phase 2, or is it a post-walkable enhancement?
D-Record Candidates
All candidates identified across the three Round 2 files. Sources attributed.
D-C1: Generation Pipeline Layer Definitions (Gestalt)
Canonical spatial pipeline layer sequence:
| Layer | Name | Input | Output | Storage policy |
|---|---|---|---|---|
| 1–5 | Atlas layers (existing) | Wiki + authored content | systems.db, markers.json | Explicitly stored |
| 6 | City → District decomposition | City entry + systems.db bodies | DistrictPlacement vec | Seed-derived, not stored |
| 7 | Phase 1: DistrictSkeleton | DistrictPlacement | DistrictSkeleton (Stages 1–2) | Seed-derived, not stored |
| 8 | Phase 2: ChunkData fill | BlockSkeleton + district seed | 64×64 TileEntry grid | Seed-derived, cached in session |
| 9 | Chunk streaming | Player position | On-demand Phase 2 call | Architecture |
D-C2: Stored-vs-Derived Transition (Gestalt + Tyre)
Atlas marker data (city positions, populations, road topology, city names) is explicitly stored. Everything at Layer 6 and below is seed-derived at runtime. Save files store: world_seed, markers snapshot hash, and ChunkMutations (player-modified chunks only). Changing generation algorithms between a player's saves is a breaking change requiring migration versioning.
D-C3: Phase 1 Minimum Spatial Scope (Gestalt, confirmed by all)
Phase 1 has two mandatory spatial stages for Phase 2 prerequisite:
- Stage 1 (mandatory): Classification — WorldTier, ComplexityTier, SettingType, DistrictType, LayoutMode, z_levels
- Stage 2 (mandatory): Block grid — 4×4 BlockSkeleton with ZoningType, density_pct, seed
Stages 3–5 (Reservations, Social sites, Guarantee audit) are enrichment — they add value to an already-walkable world but are not prerequisites for walkable tile generation.
D-C4: City → District Decomposition Formula (Gestalt + Tyre)
- District count:
max(1, floor(city.population / 50_000)), log-scaled for large cities, capped at WorldTier ceiling - WorldTier district ceiling: Epicenter → uncapped; Regional → 8; Backwater → 4; Passage → 2; Waypoint → 1
- Capital cities: +1 bonus district
- Domed/cave settlement: fixed 1 district regardless of population
- Seed chain:
district_seed = child_seed(world_seed, district_id)via FNV-1a (D-010) - DistrictType: derived from
body.economic_role+city.kind+ district index within city - Cross-reference source: systems.db bodies table (not markers.json)
D-C5: City-Local Coordinate System for Districts (Tyre)
The atlas coordinate system (512×256 pixel grid) is a UI display system only. The walkable world uses city-local sim-tile coordinates. A city's (row, col) atlas position is used only for rendering the city dot on the planetary map UI. All district geometry is expressed in city-local coordinates: district at grid position (col, row) occupies world origin (col × 512, row × 512) sim tiles. No pixel-to-sim-tile conversion formula exists or is needed.
D-C6: SeedChain Algorithm (Tyre)
All child seeds in the spatial pipeline are derived via FNV-1a from a parent seed and a discriminant:
fn child_seed(parent: u64, discriminant: u64) -> u64 // (FNV-1a body above)
This ensures: any district or chunk can be generated in isolation; generation is parallelizable; no global state required. Complies with D-010 (FNV-1a determinism mandate). Any deviation from SimRng or FNV-1a for randomness in the generation pipeline is prohibited.
D-C7: GeneratorChunkData Type Upgrade (Tyre, confirmed Gestalt)
pub type GeneratorChunkData = Vec<bool> is insufficient — it carries only walkability. It must be replaced with a struct carrying per-tile TileId and pre-computed walkability. Minimum viable tile vocabulary for the spatial pipeline: floor_street, floor_interior, wall (three types). Visual variety and heritage grammar apply tile variation in subsequent phases.
D-C8 (Paula proposal): Spatial Class Legibility Requirements
Three fields are minimum requirements for a district to be narratively legible to a player traversing it without NPC interaction or UI overlay:
prosperity_index: f32— drives tile decay, road width, density, green spaceperimeter_treatment: PerimeterTreatment— enum:Open | Fenced | Walled | Gated | Checkpointlayout_mode: DistrictLayoutMode— political geometry signal (planned power vs. ungoverned growth)
Both prosperity_index and perimeter_treatment are derived from DistrictType + WorldTier + city economic profile. No authoring required for unnamed cities.
Note: D-C8 is proposed by Paula. Gestalt and Tyre did not address these fields. Round 3 must decide whether to adopt, modify, or defer this D-record.
Open Questions for Round 3
Questions resolved in Round 2 are marked CLOSED. New questions are from this round's analysis.
| ID | Question | Source | Status | Priority |
|---|---|---|---|---|
| OQ-R1-A | Heritage root count: 7 vs 10 | Miri R1 | Out of scope | — |
| OQ-R1-B | SocietyProfileRef type | Miri R1 | Out of scope | — |
| OQ-R1-C | City marker schema approach | Miri/Tyre R1 | CLOSED — cross-ref systems.db, no markers.json changes | — |
| OQ-R1-D | Atlas coordinate translation | Tyre R1 | CLOSED — no formula; city-local coords | — |
| OQ-R1-E | Vertical slice effort | Gestalt/Tyre R1 | CLOSED — ~6 days (spatial scope only) | — |
| OQ-R1-F | #615 cascade position | Gestalt/Tyre R1 | CLOSED — out of scope per lead directive | — |
| OQ-R2-1 | Should prosperity_index and perimeter_treatment be added to DistrictSkeleton for the minimum slice, or deferred? |
Paula R2 | Open | HIGH |
| OQ-R2-2 | Should political_archetype be a formal authored field per city, or kept implicit in the decomposition formula? |
Paula R2 | Open | HIGH |
| OQ-R2-3 | Phase 2 tile algorithm: Gestalt's door-per-block-edge vs. Tyre's density-driven rectangle placement. Which is implemented first? | Gestalt/Tyre R2 | Open | HIGH |
| OQ-R2-4 | Step 2b (full N-district city layout): in scope for the minimum slice, or strictly a follow-on ticket? Gestalt: defer. Tyre: includes it in architecture. | Gestalt/Tyre R2 | Open | MEDIUM |
| OQ-R2-5 | Naming register lookup table: is this locked before Phase 2, or post-walkable enhancement? | Paula R2 | Open | MEDIUM |
| OQ-R2-6 | prosperity_index: authored for named cities (Van Maanen's Star capital) or always derived from systems.db? |
Paula R2 | Open | MEDIUM |
| OQ-R2-7 | Naming register table ownership (who authors (DistrictType, WorldTier) → register mapping)? |
Paula R2 | Open | LOW |
Ticket Dependency Graph — Converged
From Gestalt Round 2 §6, corroborated by Tyre's architecture:
NEW: Fix WorldTier enum (generator.rs) [0.5d]
│
├──▶ NEW: City → district decomp — single district (Step 2a) [0.5d]
│ │
│ └──▶ #899 (rescoped): Phase 1 Stages 1-2 only [1.5-2d]
│ │
│ ├──▶ NEW: Phase 2 — minimal chunk tile gen [1.5d]
│ │ │
│ │ └──▶ NEW: Chunk streaming hookup [0.5-1d]
│ │ │
│ │ └──▶ [MINIMUM VIABLE WALKABLE WORLD]
│ │ │
│ │ └──▶ #681 ADD BLOCKER HERE
│ │ └──▶ #682 (already blocked by #681)
│ │
│ └──▶ NEW: Missing DistrictSkeleton fields [0.5d]
│ (vertical_structure, breach_only_zones, derived_analysis as stubs)
│
└──▶ NEW: Full city decomp + district grid (Step 2b, follow-on) [1d]
(not required for minimum slice; unblocks multi-district cities)
New tickets needed (identified across all three participants):
- Fix WorldTier enum in generator.rs
- City → district decomposition — single district (Step 2a)
- #899 rescoped: Phase 1 Stages 1–2 only
- Add missing DistrictSkeleton fields as stubs (Gap C)
- Phase 2 — minimal chunk tile generator (new)
- Chunk streaming → generator wiring (new)
- Full city decomposition + district grid layout (Step 2b, follow-on)
- Close/supersede #156 (Procedural district filler)
- Close/fold #100 (Ungenerated → instantiation)
Notes compiled by Qatux from Round 2 source files. All positions attributed to source participant. No editorial opinions added.