Jeroen's gap catch: T-750 never stated that the seed-to-tile cascade is also what determines the world where the player walks. Now connected in one statement across three homes: D-012 amendment (the founding 'chunks load/unload around the player' driver now concretely = the D-227/D-239 cascade; 3x3 chunk neighborhood minimum, coarser context self-provided by D-255(f) function composition, Atlas interaction never a precondition, byte-identical either way), the matching T-750 deliverable note (in changelog), and a one-truth consumer note on Q-093 for the Phase-5 insert minimap (design deferred, no independent map pipeline expected). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
86 KiB
86 KiB
Open Questions — Architecture
Technical foundation questions: engine, protocols, data structures, performance, save/load.
Q-001: Game engine selection
- Status: Resolved → D-020
Q-006: Multiplayer or single-player only?
- Status: Resolved → D-009
Q-009: Time system
- Status: Resolved → D-031
Q-018: Shadowcasting algorithm selection
- Status: Resolved → D-238
- Question: Which line-of-sight algorithm should be used? Symmetric shadowcasting (Albert Ford) vs recursive shadowcasting. Both are proven but differ in symmetry properties (symmetric: if A sees B, then B sees A) and implementation complexity. Requires benchmarking at 150x150 map scale with 30 entities to validate performance within 100ms tick budget.
- Context: D-011 mandates LOS shadowcasting for fog of perception. Architecture review identified this as unspecified (audit section 2.2). Critical for Sprint 2 perception pipeline.
- Assigned to: Tyre, Dudley
- Source: Architecture Review Audit 2026-02-11
Q-019: Entity ID stability strategy
- Status: Partially resolved → D-041
- Resolution: Server-side:
StableEntityIdcomponent +EntityRegistryresource provides bidirectionalStableId(u64) <-> Entitymapping. StableId assigned once at entity spawn, never changes, persists across save/load. Knowledge graphs reference StableId, not bevy Entity. Client-side mapping (Godot StableId -> scene node lifecycle) remains open. - Remaining: Client-side entity lifecycle management, scene node mapping strategy.
- Date partially resolved: 2026-02-11
- Assigned to: Tyre, Dudley (client-side portion)
- Source: Knowledge Graph & Information Boundaries Workshop
Q-020: Multi-entity collision resolution
- Status: Open
- Question: When two NPCs attempt to move to the same tile on the same tick, what is the resolution policy? Options: first-write-wins (deterministic with system ordering), both fail (conservative), priority-based (e.g., player > NPC, Active tier > Background tier).
- Context: D-012 defines tile collision. WalkabilityMap exists (server/src/simulation/movement.rs) but handles single-entity validation. Architecture review identified multi-entity collision as unspecified.
- Assigned to: Gestalt, Dudley
- Source: Architecture Review Audit 2026-02-11
- Update (2026-07-06, T-1088): data point from the 3D locomotion rig — a strictly no-prediction, interpolate-only client (D-248) needs zero blocked-move handling by construction: the rig chases only server-confirmed positions, so a silently rejected move produces "bump-to-turn" (facing updates, position doesn't, gait keys off render velocity). Whatever resolution policy this question picks, the client presentation layer is already policy-agnostic.
Q-021: Tick budget overflow policy
- Status: Open
- Question: When a simulation tick exceeds the 100ms budget, what happens? Options: (1) slow down real-time and preserve determinism (tick completes fully before next), (2) skip ticks and break determinism, (3) cap work per tick and defer to next tick. Must align with D-010 principle 4 (deterministic simulation).
- Context: D-026 defines 100ms tick budget for Active tier at 10 tps. Architecture review consensus recommendation proposes "slow real-time, don't skip ticks." Needs formal decision.
- Assigned to: Tyre, Dudley
- Source: Architecture Review Audit 2026-02-11
Q-022: NPC pathfinding cache eviction
- Status: Open
- Question: With 80 Active-tier NPCs each caching ~3 pathfinding routes, the cache holds ~240 paths. What is the eviction policy? LRU? Time-based expiration? Fixed size per NPC? How are paths invalidated when walkability changes (doors lock, areas become restricted)?
- Context: Architecture review identified pathfinding as MEDIUM gap (audit section 2.2). Cache management needs specification regardless of algorithm choice.
- Assigned to: Tyre, Dudley
- Source: Architecture Review Audit 2026-02-11
Q-023: Debug visualization scope
- Status: Open
- Question: What information should the debug overlay display? Candidates: LOS rays, pathfinding waypoints, vision cones, information boundary tags (who knows what), tick timing breakdown, spatial partition grid cells. Dev-only tool, or accessible for mod development?
- Context: Architecture review (Troblum) identifies debug visualization as missing operational infrastructure. Needed for debugging perception system, information boundaries, and performance issues.
- Assigned to: Tyre, Stig
- Source: Architecture Review Audit 2026-02-11
Q-029: Save file format design
- Status: Open
- Question: What should the long-term save file format look like? Key considerations:
- Versioning and migration: How do saves survive across game versions? Schema evolution strategy (field additions, renames, removals). Should saves embed a version number and run migrations on load?
- Compression: Raw MessagePack vs compressed (zstd, lz4)? Tradeoff between save/load speed and file size. SaveStateV1 is already MessagePack — does that carry forward?
- Integrity: Checksums or signatures to detect corruption? CRC32 header?
- Metadata header: Should the file have a readable header (game version, save date, play time, character name) that the loading screen can read without deserializing the full save?
- Determinism: D-010 requires deterministic simulation. Can saves capture enough state to resume deterministically, or is approximate resume acceptable?
- Modding: Should the format be documented for mod authors? Does it need extension points?
- Cloud sync: Any considerations for Steam Cloud or similar? File size limits?
- Context: Sprint 19 implements a quick-and-dirty save format (D-085 per-game directories, MessagePack serialization from SaveStateV1). This question tracks the thorough design pass for production quality.
- Assigned to: Tyre, Dudley
- Source: Team Leader directive (Sprint 19 planning)
Q-030: Seed configuration schema
- Status: Open
- Question: What artifact records all randomizer decisions at game start? The wiki-review workshop proposed a
seed-state.yamlcapturing: world seed, character selection, pool draws (Tier 1 modules, FRIEND selection, contraband variant), template assignments, NPC trait rolls, triangle configurations, and entanglement pattern. Ticket T-394 (seed configuration schema design) exists but the design is open. - Assigned to: Tyre, Gestalt
- Source: Wiki Review Workshop + v0.1 Content Scoping Workshop
Q-046: Departure schedule model — departure windows as generator output for docked vessels
- Status: Resolved → D-108 (MobileChunk Specification)
- Resolution:
scheduled_departure: Option<SimTick>inDockedstate is mandatory generator output. Vessels without departure schedules are an error state. TheDockedstruct must includedocked_since: SimTickandscheduled_departure: Option<SimTick>— these fields must be added at implementation time (absent from Tyre's Round 4 canonical struct). - Date resolved: 2026-02-27
- Source: Generator Architecture Workshop (T-562)
- Assigned to: Tyre + Miri
Q-059: PlatformInfo full interface scope
- Status: Resolved → D-141
- Question: What properties should
PlatformInfoexpose beyond power state, memory, and file paths? - Resolution: 23 properties across 7 categories (power, memory, CPU, GPU, platform identity, display, locale), 1 signal (
power_profile_changed), 2 methods (refresh_memory,get_diagnostics). Researched Unity SystemInfo, Unreal FPlatformMisc, SDL3. Skip: GPU VRAM (not available in Godot), CPU frequency, audio devices (AudioManager owns that), network connectivity (single-player), VM detection. Add properties only when a ticket needs them — no stubs.get_diagnostics()returns flat Dictionary for bug reports. - Date raised: 2026-03-13
- Date resolved: 2026-03-13
- Assigned to: Tyre
- Source: Sprint 26 client work (T-646, T-659)
Q-060: Can Surface Deform produce acceptable clothing at extreme body types?
- Status: OPEN
- Question: The Surface Deform batch pipeline runs and produces output, but visual quality at extreme body types (heavy, thin) has not been verified at gameplay or mugshot zoom. Does the clothing mesh hold its shape when Surface Deform stretches it to fit a heavy body?
- Date raised: 2026-03-19
- Source: Quaternius aesthetic spike — clothing pipeline validation
- Cross-reference: D-162
Q-063: Footstep VFX system (Godot Asset Library #4122)
- Status: Open
- Question: Integrate the Footsteps asset (https://godotengine.org/asset-library/asset/4122) into the character visual system. Jeroen wants this in the game. Evaluate: how does it hook into the animation system? Does it work with our toon shader pipeline? Should footstep triggers be animation events or raycast-based?
- Cross-reference: D-149 (3D characters rendered live), D-160 (body segments)
- Update (2026-07-06, T-1088): the hook seam now exists — the locomotion gait machine (
client/scripts/sandbox/locomotion_anim.gd) emitsgait_changed(state)and exposes clip phase viaCharacterVisual.get_animation_player(). The animation-events-vs-raycast decision itself remains open.
Q-064: 3D planet generator for wiki system screenshots
- Status: Resolved — answered by T-779 (Sprint 32)
- Question: Evaluate the Godot 3D Planet Generator (https://github.com/remijean/godot-3d-planet-generator) for generating unique planet visuals per star system in the wiki. Each of the 301 systems could get a procedurally generated planet rendered as a screenshot for its wiki page. Key questions: can we get enough visual variety across 301 systems (different biomes, atmospheres, colors, ring configurations)? Can the generator run headlessly for batch rendering? What's the parameter space — how many distinct-looking planets can it produce? Could the planet configs be seeded from system properties (star class, habitable zone, etc.) for consistency across regenerations?
- Resolution: Pure Python ray-sphere renderer (
spikes/planet-renders/generate_planets.py) replaces the Godot plugin approach. Answers all evaluation criteria: (1) visual variety via planet_class type × body_id seed = 301 distinct renders, (2) fully headless — no Godot required, ~2s for all 7 types, (3) seeded from system properties for reproducibility. Avoids headless Godot rendering complexity. Seedocs/design/planetary-screenshots-spec.md. - Cross-reference: Wiki system pages (docs/wiki/), world generation pipeline
Q-065: Shooting mechanics — Deep RayCast 3D vs Ballistic Penetration System vs server-side
- Status: Open
- Question: Evaluate approaches for projectile/hitscan combat mechanics. Three options: (a) Deep RayCast 3D (https://godotengine.org/asset-library/asset/4464) — penetrating raycasts through multiple objects, chain hits, laser effects. (b) Ballistic Penetration System (https://godotengine.org/asset-library/asset/4356) — physics-based damage reduction through materials (thickness, hardness, penetration depth). (c) Roll our own server-side in Rust/bevy_ecs since combat is server-authoritative. Key question: should hit detection and damage calculation live on the client (these plugins) or the server (D-010 server authority)? Could the client use these for visual feedback (tracer rendering, impact effects) while the server handles the authoritative hit/damage calculation?
- Cross-reference: D-010 (server-authoritative simulation), D-012 (client is a view)
Q-066: PathMesh3D for procedural environment geometry
- Status: Open
- Question: Evaluate PathMesh3D (https://godotengine.org/asset-library/asset/3626) — extrudes 2D profiles along 3D paths at runtime to create meshes. C++ GDExtension, MIT licensed. Potential uses: procedural pipes/cables/wiring in station interiors, rail/track generation, corridor geometry, any environment element that follows a path. Not clear yet where this fits in the pipeline — could be a generator-time tool or a runtime decoration system. Worth investigating when environment procedural generation starts.
- Cross-reference: Generator architecture, environment asset pipeline
Q-067: Vehicle physics for in-world transport
- Status: Open
- Question: Evaluate vehicle physics plugins for player/NPC transport between zones. Two candidates: (a) MAdvanced Vehicle System (https://godotengine.org/asset-library/asset/3697) — full car physics with gearbox, AI traffic, traffic management, lights, sounds, steering wheel support. Godot 4.6, MIT, actively updated. (b) Godot Simple Motorcycle Physics (https://godotengine.org/asset-library/asset/4670) — raycast-based motorcycle, simpler scope. Questions: does the game need driveable vehicles or just NPC traffic? Is vehicle movement client-side physics or server-authoritative? The AI traffic and traffic management in MAdvanced could serve NPC vehicle simulation. Scope for v0.2: probably not, but worth tracking for when districts/zones need inter-zone travel.
- Audit note (2026-06-12, fable-ous.md S-47): T-750's Phase-4 asset-class list names "cars", but this question is open and its own text says "Scope for v0.2: probably not" (and v0.2 is dropped). Answer at least to the level of are vehicle assets a Phase-4 deliverable or Phase-5+: if yes, ticket the asset brief; if no, amend T-750's description to drop cars from the class list. Only vehicle artifact today:
spikes/3dpipeline/models/props/vw_beetle.glb(spike, untracked binary per D-241). - Cross-reference: D-010 (server authority), world generation
Q-068: Procedural terrain generation patterns — chunk loading and noise
- Status: Resolved (2026-06-12) — the seed-deterministic chunked-terrain question this reference was held for shipped in the Phase-4 cascade: T-963 (Layer 0 canonical heightmap), T-953 (Layer 1 topography/drainage/sub-biome), T-955 (Layer 3 settlement placement), all done; chunk streaming follows the D-225/D-227 derive-on-demand model rather than this demo's pattern.
- Question: Block-based 3D Procedural Map Generation Demo (https://godotengine.org/asset-library/asset/2698) — Perlin noise terrain with chunk-based loading/unloading. Not directly usable (block-based, Godot 4.2) but the patterns are relevant: seed-deterministic generation for consistent worlds across sessions, chunk loading within player proximity for memory/performance, terrain type placement from noise values. Reference for when the world generator produces location terrain and the client needs to stream it. The chunk load/unload pattern maps to our simulation tier system (Active → Background → State-saved).
- Cross-reference: Generator architecture, D-097 (simulation tiers), D-096 (chunk loading)
Q-069: GPU cloth simulation for dynamic clothing
- Status: Open
- Question: Evaluate GPU Cloth Simulation (https://godotengine.org/asset-library/asset/4853) — compute shader-based cloth with collisions, turbulence, pinning, inertia. MIT, Godot 4.5. NOT for character clothing (solidify is our look). Best use: environmental dressing — sails on ships, flags, awnings, laundry on lines, market tarps, banners. These are static-anchor cloth meshes that add life to environments without per-body fitting. Evaluate performance cost per cloth instance and max reasonable count per scene.
- Cross-reference: Character visual system, D-152 (LOD tiers), clothing pipeline
Q-070: NobodyWho LLM patterns vs our Rust voice pipeline
- Status: Open (evaluated, not adopted)
- Question: NobodyWho (https://docs.nobodywho.ooo/) is a GDExtension providing in-process LLM inference (llama.cpp) with GGUF models. Evaluated against our existing Gemma 2 voice pipeline in server/src/voice/. Verdict: does not fit D-020 — client-side LLM violates client-as-pure-renderer. Our server-side Rust approach is architecturally correct. Patterns worth adopting: (a) tool calling with grammar-enforced structured output — NPC queries game state via typed function calls, guaranteed parseable. (b) Preemptive context shifting for infinite conversations without truncation. (c) GGUF model flexibility (not locked to Gemma 2). These patterns should be evaluated for integration into the Rust voice pipeline, not as a client-side plugin.
- Cross-reference: D-020 (server authority), server/src/voice/ pipeline, D-010 (determinism)
Q-071: Steam integration template for multiplayer lobbies
- Status: Open (future — Steam/multiplayer stage)
- Question: Two resources for Steam multiplayer: (a) SteamMultiplayerPeer (https://github.com/expressobits/steam-multiplayer-peer) — the actual networking primitive. Implements Godot's MultiplayerPeer interface over Steam networking (relay, NAT traversal, lobbies). This is the building block we'd use. (b) Steam Template (https://godotengine.org/asset-library/asset/3328) — CC0 template wrapping SteamMultiplayerPeer with menu UI, settings, lobby management. Reference for UI patterns. Key architecture question: our server-authoritative model (D-010, D-020) means the dedicated server runs the simulation. SteamMultiplayerPeer could handle client↔server transport (using Steam relay for NAT traversal) rather than raw TCP/WebSocket. This would give us Steam friend invites, lobby discovery, and relay infrastructure for free. Evaluate when multiplayer work begins.
- Cross-reference: D-010 (server authority), D-020 (subprocess IPC), Oscar (networking agent)
Q-072: BitTorrent for P2P asset/mod/world state distribution
- Status: Open (future — multiplayer stage)
- Question: godot-torrent (https://godotengine.org/asset-library/asset/4384) — full BitTorrent protocol as GDExtension, C++ native performance. MIT, Godot 4.5. Potential uses: (a) mod/asset sync between multiplayer clients without central CDN costs — players seed assets to each other. (b) World state distribution — large world snapshots shared P2P rather than server→each-client. (c) DLC/content pack distribution. Key advantage: scales with player count (more players = more seeds = faster). Key risk: NAT traversal, firewall issues, player trust (can you trust torrent-distributed assets?). Would need content verification (hash/signature) to prevent tampering.
- Cross-reference: Oscar (networking), multiplayer architecture, mod support
Q-073: BehaviourToolkit patterns for Rust NPC AI
- Status: Open (reference — implementation is server-side Rust)
- Question: BehaviourToolkit (https://github.com/ThePat02/BehaviourToolkit, https://godotengine.org/asset-library/asset/2333) — FSM, Behaviour Trees, Blackboard Resource, nested composition (BT inside FSM and vice versa). MIT. The plugin itself is GDScript/Godot and lives on the wrong side of D-020 for us. But the patterns are directly applicable to the Rust server NPC simulation: (a) Blackboard pattern — shared key-value state between behaviour nodes without coupling, maps to bevy_ecs components. (b) Nested FSM↔BT composition — our NPC state machines (schedule, mood, relationships, job per D-097) could nest behaviour trees for decision-making within each state. (c) Editor interface patterns — how they visualize/debug behaviour trees could inform our server-side tooling. Study the source for architectural patterns, implement in Rust/bevy_ecs.
- Cross-reference: D-097 (simulation tiers, 4 state machines), Dudley (server developer), NPC behaviour system
Q-074: Screenshot manager for in-game captures and bug reports
- Status: Open
- Question: Two references for improving the existing F12 bug reporter: (a) ScreenshotManager (https://github.com/ASecondGuy/ScreenshotManager) — better screenshot file management, auto-naming, viewport isolation. (b) BugReporter (https://github.com/ASecondGuy/BugReporter) — patterns for attaching system info, game state snapshots, reproduction steps to bug reports. Both from the same author. Evaluate what patterns we can adopt into our existing bug reporter flow.
- Cross-reference:
/bug-reportskill, character creator screenshot system
Q-075: RichText3D for in-world text rendering
- Status: Open
- Question: RichText3D (https://github.com/mszylkowski/rich-text-3d-godot) — renders BBCode to a 3D plane in real time. MIT, performant (renders only on property change, max once per frame). Supports color, bold, italic, images, tables, font size, auto text wrapping. Use cases: in-world signage (shop names, zone labels, directional signs), NPC name/title floating labels, item descriptions on crates/containers, news tickers on station displays, terminal screens. The adjustable resolution (pixels per Godot unit) means text stays readable at our isometric camera angles. Worth evaluating when diegetic UI and in-world text elements are implemented.
- Cross-reference: Diegetic UI design, in-world interaction system
Q-076: DeformableMesh for runtime environment and damage variation
- Status: Open
- Question: DeformableMesh (https://github.com/cloudofoz/godot-deformablemesh) — runtime mesh deformation with SphericalDeformer, SimpleDeformer (bend, twist, taper), and DragDeformer nodes. MIT, Godot 4.0+. Use cases: (a) environmental variety from shared meshes — same pipe asset bent differently per instance, twisted metal in damaged zones, wind-bent vegetation/trees. (b) Damage visualization — crushed containers, warped hull plating, dented surfaces. (c) Procedural variation at generator time — deform base assets to create unique instances without authoring each one. The DragDeformer could also serve interactive manipulation (bending objects during gameplay). Low priority but high variety-per-asset value.
- Cross-reference: Generator architecture, environment asset pipeline, damage system
Q-077: World generation architecture → PROMOTED TO WORKSHOP
- Status: Resolved → D-166 — the promoted workshop ran 2026-03-24 and produced the development cascade (
docs/workshops/world-generation/workshop-outcomes.md); the asset-library references were consolidated into the brief and remain available there. Loop closed 2026-06-12. - Question: Outgrew Q-record format. All references (CityCrafter3D, Chunk Manager, Retro Terrain, Spatial Gardener, GridMapLayer, PathMesh3D, DeformableMesh, Poly Haven) consolidated into the workshop brief.
- Cross-reference:
docs/workshops/world-generation/BRIEF.md
Q-078: God rays for atmospheric lighting
- Status: Open
- Question: SimplestGodRay3D (https://github.com/AguaMineral/SimplestGodRay3D) — drop-in volumetric light shaft effect. Light streaming through station viewports, between buildings in exterior zones, through tree canopy in rural areas. Low implementation effort, high atmosphere value. Evaluate: does it work with our GL compatibility renderer? Performance cost per instance? Compatible with our toon shader aesthetic or does it look too realistic?
- Cross-reference: Lighting design, environment atmosphere
Q-079: GridMapLayer — 2D tile logic driving 3D grid rendering
- Status: Open (high relevance)
- Question: GridMapLayer (https://github.com/Caaz/grid-map-layer) — manages 3D GridMaps through TileMapLayer patterns. MIT, Godot 4.4+. Directly relevant: our server sends 2D tile grid data, the client renders 3D isometric. This plugin bridges that gap — autotiling for 3D tiles using 2D rules, arbitrary subdivisions (2x2+ gridmap tiles per 2D tile), multiple GridTiles per 2D tile (layered grids for collision variation), programmatic tile setting for procedurally generated areas. This could be the rendering layer for server-generated floor plans — the server sends the tile palette + grid, the client uses GridMapLayer with autotiling to render walls, floors, doors with correct 3D tile selection.
- Cross-reference: D-096 (chunk loading), tile rendering pipeline, server→client tile data
- Update (2026-07-06, T-1088 — data point, not a resolution): the locomotion sandbox greybox chose MultiMesh over GridMap because it needs per-instance state (four-state visibility tint via instance COLOR) and per-material shader uniforms (wall cutaway) — GridMap has neither per-cell color nor per-cell shader state, so tint changes would mean MeshLibrary item churn on every LOS change. Counter-case recorded: GridMap + a code-built MeshLibrary + diff-only
set_cell_itempainting is legitimately simpler where per-instance color is not required, and remains the natural Phase-5 candidate for static real-asset geometry (walls/floors with final materials). GridMapLayer's autotiling value proposition is untouched by the greybox's choice.
Q-080: Mod loader architecture reference
- Status: Open (reference — future feature)
- Question: Godot Mod Loader (https://github.com/GodotModding/godot-mod-loader) — community-standard mod loading framework for Godot. Study for architectural patterns: mod discovery and load ordering, dependency resolution between mods, conflict detection, API boundaries (what mods can and can't touch), mod manifest format, hot-reload vs startup-only loading, save compatibility with mods enabled/disabled. We'll roll our own but these patterns are battle-tested across many Godot projects. Key question for our architecture: mods need to work with both the Rust server (gameplay mods, new items, behaviours) AND the Godot client (visual mods, UI mods). The mod loader needs to span both sides of the D-020 boundary.
- Cross-reference: D-020 (client/server split), mod support, Q-072 (BitTorrent for mod distribution)
Q-081: VisionCone3D for client-side fog refinement
- Status: Open (high priority — solves the 2D→3D fog transition problem)
- Question: VisionCone3D (https://github.com/Tattomoosa/VisionCone3D) — 3D vision cone raycasting in Godot. MIT, Godot 4.4+. Proposed architecture: (a) Server does authoritative shadowcasting per D-011/D-015, sends visible chunk list in ObserverSnapshot (coarse grid truth). (b) Client uses VisionCone3D to re-trace locally against actual 3D wall geometry within the server-approved visible area. (c) The client's vision cone output drives 3D fog-of-war rendering with smooth, geometry-following edges instead of tile-stepped boundaries. This solves the stepped edge display issue from communicating visibility as grid chunks — the client refines to sub-tile accuracy using real 3D geometry. No information leak: client can only refine within server-approved visible chunks, never see beyond. The cone configuration mirrors the server's D-015 vision cone (forward/peripheral/blind spot zones). Performance tuning options available per the plugin docs.
- Cross-reference: D-011 (LOS shadowcasting), D-015 (vision cone), D-043–D-049 (fog system), fog_state.gd (current 2D fog implementation)
Q-082: VoronoiShatter for destruction effects
- Status: Open
- Question: VoronoiShatter (https://github.com/robertvaradan/voronoishatter) — procedural Voronoi fracture of 3D meshes into rigidbody pieces. MIT, Godot 4.4+, native GDScript. Convex and concave mesh support, seamless materials, auto rigidbody generation. Use cases: wall breaches during combat, crate/container destruction, station hull damage, environmental destruction. Pure client-side visual effect — server sends "object destroyed," client shatters the mesh locally. The Voronoi pattern gives natural-looking irregular fractures. Could pre-compute shatter patterns at load time for performance, trigger on damage event.
- Companion: Particle Scene Compositor (https://github.com/tvenclovas96/particle-scene-compositor) — spawn scene instances as particles. Destruction fragments + sparks/smoke/dust in one effect. Shatter → fragments fly → each fragment emits particles.
- Cross-reference: Combat system, damage visualization, environment interaction
Q-083: ThemeGen for dynamic insert styling and value-level theming
- Status: Open
- Question: ThemeGen (https://github.com/Inspiaaa/ThemeGen) — themes-as-GDScript-code with semantic colours, reusable styles, theme variations, and live preview in editor. MIT. Directly relevant to dynamic inserts: (a) Value-level theming — common/uncommon/rare items get different colour palettes from the same base layout. (b) Faction-themed inserts — Frost Compact cold blues, Reach Authority golds, derived programmatically from a base theme. (c) Danger/security level indicators — zone inserts shift colour based on threat level. (d) Player customisation — let players pick an insert accent colour, ThemeGen derives the full palette. The code-based approach means themes can be generated from server data (faction ID → theme variation) without authoring each one.
- Cross-reference: Diegetic UI / insert system, Stig (UI developer), Araminta (visual design)
Q-084: Isometric point-and-click navigation pattern
- Status: Open
- Question: Reference: isometric-2d-point-and-click-movement (https://github.com/Domogo/isometric-2d-point-and-click-movement). This is 2D but the interaction pattern applies to our 3D isometric setup: click ground tile → convert screen position to tile coordinate → server pathfinds (A* on tile grid) → client animates character along path. Key problems to solve: (a) mouse→3D isometric tile coordinate conversion (ray from camera through click point to ground plane, accounting for D-148 45° map rotation). (b) Path visualization (preview line showing where character will walk). (c) Click-to-move vs WASD — do we support both? (d) Server roundtrip latency — does the client predict movement or wait for server confirmation? Study for interaction patterns, implement in our 3D stack.
- Design notes: Character stays center-screen, map scrolls around them (not character moving on static map). Character always faces toward mouse cursor — this creates a natural looking-direction that drives the D-015 vision cone direction. Unresolved: what happens visually when walking one direction while looking backward (walk animation vs facing direction conflict — later solve). Latency: 200ms feels instant in web interactions (Jeroen's rule from web design) — if server roundtrip is under 200ms, click-to-move without client prediction may be acceptable. Needs user testing to verify.
- Cross-reference: D-148 (camera angle), D-010 (server authority), D-015 (vision cone facing), navigation/pathfinding
- Update (2026-07-06, T-1088): partially settled. (a) mouse→tile conversion is implemented: camera ray to the y=0 plane,
WorldRoot.to_local()undoing the D-148 rotation,atan2to sim angle (client/scripts/sandbox/mouse_aim_provider.gd— the screen-space angle is NOT a sim angle under 45° rotation + ortho pitch, so the full unproject is mandatory). The facing presentation source is now governed by D-249 ("server feet, client eyes"). (d) is answered by D-248: no client prediction, interpolate-only. Still open here: click-to-move + path preview (WASD-only today), stepped player camera rotation (explicitly requires a new record), and the walk-vs-aim animation split — note the purchased UAL 8-direction walk/jog/crouch sets now make a direction-matched-clip solution tractable (playWalk_Fwd_Letc. relative to facing instead of rotating the body into the path).
Q-085: Portal rendering for spatial transitions and viewports
- Status: Open
- Question: Portal concept — not the Godot plugin (client doesn't need it — transparency handles adjacent rooms, SubViewport handles remote camera feeds). The SERVER needs portal logic: when the shadowcasting/vision cone hits a door opening, visibility extends through it into the next room. Portals are openings in the tile grid that allow raycasts to pass between rooms/zones. Study the plugin (https://github.com/VojtaStruhar/godot-portals-plugin) for the spatial math patterns, implement in Rust server's visibility system. Key: doors open = portal active = vision extends through. Doors closed = wall = vision blocked.
- Cross-reference: D-011 (LOS), D-015 (vision cone), z-level system, information boundary design
Q-086: Day/night cycle — server time driving client lighting
- Status: Open
- Question: Reference: DynamicDayNightCycles (https://github.com/eisclimber/DynamicDayNightCycles). The game time is server-authoritative — server ticks time, sends current time-of-day in ObserverSnapshot. Client renders lighting accordingly. Station interiors: artificial lighting follows schedules (dim at night cycle, full during work shifts). Exterior/rural zones: sun position, sky color, shadow direction from time of day. Station viewports could show star position shifting. NPC schedules already tied to time (D-097 schedule state machine). Key question: how granular is the lighting transition — smooth real-time interpolation or discrete time blocks (morning/afternoon/evening/night)?
- Cross-reference: D-097 (NPC schedules), environment lighting, server game clock
Q-087: Water shader for environment zones
- Status: Open
- Question: Godot Realistic Water (https://github.com/godot-extended-libraries/godot-realistic-water) — water rendering with reflections, refraction, waves. May be too realistic for our toon aesthetic — evaluate whether it can be styled down or if a simpler toon water shader is better. Use cases: docking bay water features, hydroponic farms, waste processing, rural rivers/lakes, rain puddles, port zones, fountains. Question: does toon water need reflections or just stylized wave animation + color? The Retro Terrain reference (Q-077) already handles water tile transitions — this adds the surface rendering. Also check if GL compatibility renderer supports the shader features.
- Cross-reference: Q-077 (world generation / terrain), environment aesthetics, GL compatibility renderer
Q-088: Spatial audio for information-aware sound
- Status: Open
- Question: spatial_audio_player_3d (https://github.com/Danikakes/spatial_audio_player_3d) — 3D spatial audio with occlusion and environmental awareness. Directly tied to the information system: sound carries information. Footsteps through walls = muffled (you know someone's there but not who). Conversation in the next room = faint/unintelligible (partial information). Gunshot echoes in corridors = direction cues. The server already knows which audio events are in hearing range (part of the ObserverSnapshot). The client needs spatial rendering: distance attenuation, wall occlusion, reverb based on room size/material. Also ties into Inigo's audio design specs. Evaluate whether this plugin handles occlusion raycasting or just basic 3D positioning.
- Cross-reference: D-011 (LOS — audio equivalent), Inigo (sound designer), information boundary, audio propagation rules
Q-089: Procedural star rendering for space viewports and star map
- Status: Open
- Question: Godot Starlight (https://github.com/tiffany352/godot-starlight) — procedural starfield rendering. Use cases: (a) Station viewport backgrounds — look out a window, see stars. (b) Star map navigation screen. (c) Docking bay exterior views. (d) Skybox for any exterior/surface zone. Could combine with Q-064 (planet generator) for full space vista — procedural stars + procedural planets visible from station viewports. Seed from system coordinates for consistent views per location.
- Cross-reference: Q-064 (planet generator), station viewport design, star map UI
Q-090: Markov chains for procedural name/text generation in Rust
- Status: Open
- Question: Pattern reference: Markov Machine (https://github.com/BirDt/markov-machine) — Markov chain text generation. Need a Rust crate, not the Godot plugin. Candidates to evaluate:
markovcrate,markov_chaincrate, or hand-roll (Markov chains are ~50 lines of Rust). Use cases: NPC name generation from cultural name pools (train on corridor-specific names, generate plausible new ones), shop/business name generation, procedural signage text, news ticker filler, overheard conversation snippets. Faster and cheaper than LLM for short text that just needs to feel culturally consistent. Could train separate chains per corridor/culture for regional flavor. The existing voice pipeline (Gemma 2) handles dialogue variation — Markov is for the lightweight procedural text that doesn't need semantic coherence. - Cross-reference: Generator architecture, name pools, voice pipeline (server/src/voice/)
Q-091: Event-driven audio system
- Status: Open
- Question: Event Audio (https://github.com/bbbscarter/event-audio-godot) — data-driven event→sound mapping. Game events trigger audio without hardcoded play() calls. Complements Q-088 (spatial audio handles WHERE, this handles WHEN/WHAT). Server sends game events in ObserverSnapshot (door opened, NPC entered, combat started), client maps these to audio via configuration. Inigo's audio design specs define the sound palette — this system is the dispatcher that connects game events to that palette. Evaluate whether we adopt the plugin pattern or build our own event→audio bus.
- Cross-reference: Q-088 (spatial audio), Q-063 (footsteps), Inigo (sound designer), AudioManager autoload
Q-092: Modular settings menu as foundation for T-735
- Status: Open
- Question: Godot Modular Settings Menu (https://github.com/MarkVelez/godot-modular-settings-menu) — composable settings panels for keybinds, audio, video, accessibility. Evaluate as the foundation for epic T-735 (Settings and input system). Instead of building keybind remapper, audio sliders, resolution picker, and controller support from scratch, start from this template and restyle to match our UI aesthetic. Key: the modular approach means we can add/remove panels as features are implemented without restructuring.
- Cross-reference: Epic T-735 (settings/input system), Frame0 wireframe session
Q-093: Tile-based exploration map in player insert (Google Maps for the implant)
- Status: Open (high interest)
- Question: Reference: MapTileProvider (https://github.com/AngryMeenky/MapTileProvider) — lazy-loading tile map provider. Concept: the player's insert has a map that works like Google Maps — pan, zoom, tile-based rendering. Server generates map tiles from ECS exploration data (what the player has seen). Explored areas show room layouts, corridors, points of interest. Unexplored areas are blank/fogged. Zoom levels: room detail → building → district → zone → station overview. Knowledge-graph-driven overlays: NPC last-known positions (if the player tracked them), quest markers, danger zones, faction territories. Map tiles are server-authoritative (can't see what you haven't explored) and cached on the client. The tile pyramid approach means the map scales to any world size without loading everything at once.
- Cross-reference: Information boundary (D-011), insert/minimap UI, knowledge graph (D-041), T-732 (minimap ticket). See also D-255 (body-map-viewer stepped Atlas render architecture, 2026-07-24) — a different system (Phase-4 world-generation Atlas, not the player exploration insert), but its server-authoritative per-step data canvases, tagged-envelope carrier, and client cache tiers are shipped prior art for exactly the tile-pyramid/lazy-load/server-authoritative-cache architecture this question sketches. One-truth note for Phase-5 scoping (D-012 amendment 2026-07-24): the natural expectation is that this map consumes the same seed-to-tile derivation as the walkable world and the Atlas — no independent map pipeline; recorded as a note here, binding design deferred to Phase 5.
Q-094: Chart widgets for economy/market insert UI
- Status: Resolved — deferred to Phase 3+ (player interaction layer)
- Date resolved: 2026-04-05
- Resolution: No player-facing economic UI is in scope for Phase 2. The Phase 2 deliverable is the autonomous simulation ticking on investor screens — no player verbs, no insert UI for market data. Chart widget evaluation (Easy Charts plugin, ThemeGen integration, information boundary application) deferred until Phase 3 when the player interaction layer begins.
- Question: Easy Charts (https://github.com/fenix-hub/godot-engine.easy-charts) — line charts, bar charts, scatter plots, pie charts in Godot. For the insert UI: (a) commodity price history graphs (X4/EVE-style market view), (b) faction reputation trends over time, (c) supply/demand curves per station, (d) character stat progression, (e) economy health indicators. The diegetic justification: the player's implant has market analytics. Data comes from server via ObserverSnapshot (the player only sees market data they have access to — information boundary applies). Evaluate whether this plugin's visual style can be themed to match our insert aesthetic (ThemeGen Q-083 integration).
- Cross-reference: Economy system (X4/EVE inspiration), insert UI, Q-083 (ThemeGen), information boundary, D-181 (signal vocabulary — Phase 3 player access)
Q-098: Persistence of generated river/city mapping outputs
- Status: Resolved — D-225 (atlas layer-stream proxy), 2026-05-23
- Resolution: Resolved against the question's own premise. The viewer does not need a durable store under the LRU: the cascade is deterministic and ~45 ms, so eviction → recompute is acceptable. Baking into
systems.db(option a) is rejected — it bloats the install and makes modded bodies second-class. Decision: lazy compute on demand, served by a mod-first layer-stream proxy that resolves a body's source files (base + mod dirs) and streams the computedLayer1Outputover the existing IPC bridge, backed by the D-203 in-memory LRU (miss → backgroundAnalyzeBody; eviction → recompute). See D-225. The mod-content-catalog corner (mods adding new body rows /terrain_referenceto the binarysystems.db) is spun off to Q-099. - Question: The deterministic cascade can recompute river courses (D8 drainage, D-208) and city placements (economic sim + attractor matching, D-211) from seed at any time, so persisting them is a cost optimization, not a correctness need. But the compute is expensive — recomputing per session or per atlas view is waste. How are these mapping outputs persisted so they are computed once per body and kept? D-203's BodyWorldState cache is an LRU — it evicts (volatile). The fork: (a) build-time bake into
systems.db(D-200 build-time tier — precompute all, ship); (b) lazy compute + persist at runtime (cache DB / savegame — compute on first visit, keep); (c) hybrid. Whatever the answer, the in-memory LRU should sit over a durable store so eviction triggers a cheap reload, not a recompute. - Context: Raised 2026-05-22 looking ahead from the Phase 4 markers strip (T-951). Refines D-200 (three-tier execution) and D-203 (LRU cache). Gates the Atlas layer viewer (T-960), which needs persisted mapping to render without recomputing. Determinism (T-952) guarantees recompute is always a valid fallback.
- Cross-reference: D-200, D-203, D-208, D-211, T-952 (determinism harness), T-960 (atlas viewer)
Q-099: Mod content catalog — body rows / terrain_reference overlay for systems.db
- Status: Open — spun off from D-225 (2026-05-23)
- Question: D-225 resolves mod file resolution (a mod body's source
heightmap.pngis found by searching mod dirs over the base install). But a mod adding a new body also needs that body discoverable: thebodiesrow and itsterrain_referencelive insystems.db, which is binary and source-canonical (D-189) — mods cannot append to it. How does a mod register new bodies (and other DB-resident catalog rows)? Options: a mod manifest the server merges into an in-memory catalog overlay at load; a parallel mod catalog DB layered over thesystems.dbreads; or a documented mod build step. Out of scope for T-960 (base-install resolution ships the viewer); needed before third-party bodies are first-class. - Context: Raised 2026-05-23 from the D-225 mod-first layer-stream proxy design. The proxy makes first-party and mod bodies flow through an identical resolve→compute→stream path given a resolvable source file; this question is the remaining gap — getting a mod's new body into the catalog the resolver consults.
- Cross-reference: D-225, D-189 (systems.db source-canonical), T-960 (atlas viewer — base-install only for now)
Q-100: Biome authority — Python sim vs Rust cascade
- Status: Resolved in principle (Jeroen, 2026-05-25) — implementation detail open. The baked heightmap + reliefmap are deterministic inputs (gameplay never touches them), so the natural world is
f(reliefmap, heightmap, seed)and the cascade derives from the baked artifacts, never independently re-derives. The biome/climate the reliefmap encodes is therefore baked as data the Rust cascade reads (option A below);subbiome::classify's independent re-derivation is reconciled away. Open: exactly which data layers to bake + the Rust read path. - Question: Two independent biome systems exist.
planet_simulation.py(build-time) computes biome from a Whittaker table + sim-derived temperature/moisture and coloursreliefmap.png— the authoritative visual.subbiome::classify(Rust, runtime, D-210) re-derivesSubBiomeVariantfrom proxies (elevation percentile, slope, river-distance moisture, latitude temperature). They diverge — a cold fjord coast readsCoastalLowlandin Rust, which lacks the temperature field. Which is canonical? (A) Python canonical → bake temperature + moisture as additional atlas layers the Rust cascade reads (richer; more storage/pipeline; mod-friendly per D-225); (B) Rust canonical → re-render reliefmaps from cascade output at bake time (simpler; loses the atmospheric sim; regenerates ~267 reliefmaps); (C) keep split (pragmatic; contradicts the dual-artifact principle, D-226). Related sub-fork: the Python river-carve (colours the reliefmap) and the Rust D8 network (D-208) also diverge — the dual artifact requires reconciling them. - Context: Tyre's top integration snag. Blocks the biome axis of D-228 and the dual-artifact reconciliation. Tyre's lean: A long-term, B for Phase 4, with the expansion path designed in.
- Cross-reference: D-228, D-226, D-210, D-208, D-225,
tooling/planet-gen/planet_simulation.py,server/src/atlas/subbiome.rs
Q-101: Refinement / derivation contract — coarse hint → fine geometry + morphology algorithm family
- Status: Resolved 2026-06-07 by D-239
- Resolution: Resolved by the tile-derivation-contract workshop → D-239: a three-carrier refinement chain (
RegionProfile~1 km →ChunkContext64 m →VoxelColumn1 m), pure deterministic functions of(seed, atlas, body-params, position)with no authoring at the derivation layers; a stateless f64-to-voxel domain-warp as the anti-squaring mechanism; 8 morphology families (LavaField · FjordWall · CliffCoast · BraidedDelta · DuneStrand · IncisedGorge · MeanderReach · AlluvialPlain) selected by a gated decision tree over a frozen 17-zone vocabulary; a district-temperature climate primitive (2×2 km, °C, nullable) + separate moisture from which all climate/vegetation/glaciation and a scattered, transient freeze/snow model derive;RIVER_THRESHOLDbecomes a derived per-body-class value; seams prevented at source (gate ordering + build-time matrix), valid geomorphic seams kept sharp + warped. Body-class river-density modulation and D8 flow-direction are folded in. (Ocean/lake mask: derive from the heightmap sea-level threshold per D-239's body-params input.) - Question: How does a coarse, map-scale hint (a ~78 km Layer-1 cell) plus a seed become fine, ~1 m-voxel coherent geometry — deterministically, without squaring — across ~3 scale jumps (78 km cell → ~1 km region → 64 m chunk → 1 m voxel)? Needs: the inter-layer hint+seed→geometry API (Tyre sketched a
RegionHint); a context-driven morphology algorithm family selected by local context (rivers meander in lowlands / incise in mountains; coasts dune / crag / fjord by slope + lithology + glaciation), ≥6 distinct generators (meander, incised gorge, braided delta, dune strand, cliff coast, fjord, mountain pass); integer-only structural decisions (D-010), f64 confined to within-voxel interpolation; clean transitions between adjacent morphology families. Unowned dependency: the ocean/lake mask — D-223 stripped the markers.json polygons that D-209CoastalAccess/LakeShoreextraction referenced, so the mask must instead be derived from the heightmap sea-level threshold or a baked water-bodies layer. Lithology is a required input (promoted load-bearing by the volumetric subsurface, D-227). Also in scope: body-class parameters (hydrosphere, tectonic activity, atmosphere) must modulate river-network density — the effective river threshold — so an arid body and an oceanic body differ in how many rivers, not just where they run (todayRIVER_THRESHOLDis a global constant, Nigel); and river flow direction (upstream/downstream — gates effort vs speed, and feeds the seasonal water model) derives from the D8 network at query time. - Context: The heart of the atlas→tile derivation; surfaces as the cascade builds the region → chunk → voxel layers.
- Cross-reference: D-227, D-228, D-208, D-209, D-223, D-010, D-222
Q-102: Cohesion-matrix algorithm — seam-free continuous variation
- Status: Resolved 2026-07-08 (T-1057) — resolved-in-practice by D-246 + D-228 (with T-1080 / T-1077); no dedicated cohesion-matrix D-record is needed.
- Resolution: All five sub-questions are answered by shipped work, so the cohesion matrix needs no separate decision. (1) noise basis + (2) position-keying + (3) threshold mapping + (4) determinism are exactly D-246's
voxel_mosaic(): an enveloped-fBm value-noise band (the T-1081detail_scattermachinery,[64, 32, 16, 8]m octaves) keyed on absolute world position under a body-globalSeedDomain::VoxelMosaic(never the chunk index — so it is continuous across every chunk/region boundary), whose field value indexes the class palette's cumulative weights to select a micro-habitat (the threshold map), all integer-only per D-010. The precondition that there is something for the field to vary is the D-243 ladder's per-district climate/moisture gradient — T-1080 (meso-scale moisture-gradient fix: a flat body constant became a latitude/elevation/continentality gradient) over T-1077 (the D-243 ladder wiring) — so the noise modulates a real gradient, not a uniform slab. (5) authored linear features composite without bleeding is D-228's categoricalFloorMaterial/Vegetationoverride stack (wild/natural → economic/managed → user): the topmost present layer wins and layers are never blended, so an authored road/plaza/field-edge (economic layer) sits on the continuous wild scatter with a hard categorical edge — D-228's "a straight line must always have a placed cause." Seam-free variation (blended noise) and crisp authored lines (categorical, unblended override) are therefore two distinct mechanisms, not one algorithm — which is precisely why a standalone cohesion-matrix decision is unnecessary. - Question: D-228 mandates that intra-region material / sub-biome scatter come from a global, position-keyed continuous noise field so chunk/region boundaries never read as grid seams, while authored straight lines (roads, plazas) stay crisp. Concretely: the noise basis (value / Perlin / simplex / worley); keying on world position (not chunk index) to stay continuous across boundaries; how material / sub-biome thresholds map onto it; integer-only / determinism (D-010); and how authored linear features composite over the continuous field without bleeding.
- Context: The anti-squaring principle pushed down to the material layer.
- Cross-reference: D-228, D-246, D-227, D-010, D-243; tickets T-1080, T-1077, T-1081, T-1084
Q-103: Tile-mutator op schema
- Status: Open — deferred from D-227 (2026-05-25); re-triaged 2026-07-08 (T-1057) → Phase-5 save-system kickoff.
- Triage (2026-07-08, T-1057): DEFERRED, scope unchanged. The question's own text scopes it to Phase 5+ — it is the save-format op vocabulary, and mutators are D-227's sole persisted state, so it cannot be settled without a concrete save serializer to answer against. Confirmed an empirical non-blocker for the Phase-4 tile-fill spine: T-987 (child of T-959) shipped the Layer-5 shell derivation (
server/src/atlas/shell.rs—Void/Wall/FloorSlab/Roof) with no mutator layer at all — the derive phase is a pure function of(seed, tags, z), andChunkMutations/TileOverridealready exist as the frozen-base overlay a mutator log will later stack on. Revisit at Phase-5 save-system kickoff, where the typed-op-vs-full-override fork, replay ordering / conflict semantics, and cross-re-derivation validity are decided together. - Question: D-227 makes tile mutators the sole persisted state (save =
seed + mutator log). What does one mutator record — a full per-voxel override, or typed ops (Dig,Build(FloorMaterial),Place(object),Destroy(object),SetMaterial)? Typed ops are compact, semantic, replayable, but need a fixed op vocabulary; full overrides are simple but heavier and lose intent. Also: replay ordering / conflict semantics, and confirmation that a position-keyed mutator stays valid across re-derivation (determinism guarantees an identical base — to be pinned). - Context: Needed when the save system is built (Phase 5+).
- Cross-reference: D-227, D-010
Q-104: Floor-index ↔ absolute voxel-z coordinate mapping
- Status: Resolved 2026-05-25 by D-229
- Resolution: Resolved via
FloorExtent { base_floor, floor_count, FloorHeightProfile::{Uniform|Variable} }+ the pure functionsfloor_at_voxel_z/voxel_range_for_floor. - Question: D-227 introduces an absolute physical z coordinate (metres, continuous over the voxel grid) alongside D-110's floor-index addressing (
base_z: i8, a story-counting integer). The two coexist but the bridge is undefined: "the floor atbase_z = -2" → which absolute voxel-z values does it span? With variable-height floors (D-227 — default 3 voxels, a cathedral ~10), the mapping is non-linear (a floor's voxel-z depends on the heights of the floors below it). What is the mapping function, and where is it owned (a per-building floor table? a region floor-height index?)? Needed before anything queries both systems (Phase 5 building interiors / vertical movement). Gap, not contradiction — D-227 and D-110 do not conflict. - Context: Raised in the atlas-derivation workshop (Tyre, Round 2 review of D-227).
- Cross-reference: D-227, D-110, D-049, D-222
Q-105: Region seasonal/clock state — the shared cheap-dynamism source
- Status: Resolved 2026-07-08 (T-1057) by D-253
- Resolution: Resolved by D-253 — a four-term region transient-state model (diurnal · tidal · weather · seasonal, one term per natural clock rate) whose derived surface scalars are temperature(time) (= the T-1078/D-240 static baseline + seasonal + diurnal offsets), water-height(time) (= mean + seasonal + tidal), snow/ice depth, weather, and the crop-cycle phase. The bundle is memoized on the region keyed by clock-bucket, recomputed on bucket rollover, never per tick and never integrated (state =
f(absolute clock, region), so it is drift-free, reproducible per D-010, and gives D-226 frozen-phase inspection for free). Districts/tiles never compute their own phase — they read the region scalars, edge-fuzzed by the D-243 §4 blend, and realize per-tile state by local comparison (flooded iff water-height > tile elevation; snowed via the existing T-1030 scatter band; puddled in T-1081 micro-lows; crop stage from the region phase). D-253 supplies the clock the three shipped punts were forward-contracts to (T-1030 transient freeze/snow depth, T-1082 tidal-flat wet/dry, T-1078 region-clock structure), and is a state model only — the gameplay/rendering consumers are Phase 5+. - Question: D-228 commits to a deliberately cheap, deterministic, region-level seasonal/clock state — computed once per region per phase, inherited by its tiles — from which a family of transient surface conditions derive — all computed from the region's seasonal + tidal + weather phase, none of it stored: flooded tiles (floodplain / tidal-flat / seasonal-river, where the water-height crosses local elevation), snow & ice cover, puddles (weather / rain), weather generally, and the farmland crop cycle (sown → growing → ripe → harvested → fallow). The model must stay "nearly free" — simple deterministic functions of the in-game clock + body/region parameters, no per-tile or per-frame simulation. Open: the exact phase functions — a seasonal term phased by hemisphere (latitude sign), driven by the year clock; a tidal term only when the body has a moon (no satellite → no tide), driven by the lunar/day clock with amplitude from the satellite config; a weather term (shorter-term precipitation → puddles + general conditions); how snow/ice depth, puddles, flood extent, weather, and the crop cycle each read the same state; the snow/ice cover model — D-228 removed
Snow/IcefromTerrainMaterial, so snow/ice are entirely this seasonal cover overlay (permanent only where climate never melts them — poles, glaciers), depth rising/falling with the seasonal phase; determinism (state =f(clock, region)→ reproducible) and its interaction with the cache + the D-226 pause/inspection (a frozen phase for stable inspection); and recompute cadence (per phase-change, not per frame). - Context: Grew from the floodplain dependency — "floodplain is only feasible if water heights move" — into a general cheap-dynamism source. Jeroen's constraints: clock + hemisphere bound, moon-gated tides, computed once per region, simple rules; snow / weather / crop cycle ride the same calculation.
- Cross-reference: D-253 (the resolving model), D-228, D-243 (region = lockdown scale), D-239 §2/§3 (temperature primitive; T-1030 scatter band), D-227, D-226 (dynamic-state inspection), D-010
Q-106: Era-band stacking depth for layered architecture-flavor
- Status: Resolved 2026-05-25 by D-232 (round 3) — the question is dissolved, not answered.
- Question (original): D-232 (round-2 draft) made flavor a three-layer resolution (body × district × era-band). How many era-bands does a settlement produce as a function of
founding_age_years? What is the minimum age-gap between bands? How do the flavor slices differ between bands? - Resolution: The round-3 rewrite of D-232 retired the era-band material-progression entirely. The Reach is post-space-travel throughout — there is no stone→concrete→glass tech ladder, so era is not a flavor-stacking axis. A block's construction era (still derived from distance-to-founding-origin, D-229) reads as maintenance/wear through the condition layer (D-217/D-198); the occasional out-of-vogue building is handled by D-232's deviation system (the "past-vogue holdover" — temporal sibling of the spatial swerve), not by multi-band flavor stacking. So there are no era-bands to count.
- Cross-reference: D-232, D-229, D-217/D-198 (condition — where era's wear lands)
Q-107: Wiki → Atlas content-set consolidation
- Status: Open — raised by Jeroen (2026-05-25)
- Question: The wiki pages live semi-outside game scope yet are piped into Atlas content screens AND are now a generator input (D-232 architecture-flavor distilled from wiki prose). Where authored per-body content lives (frontmatter vs companion file vs a consolidated tree) should follow a consolidation of ALL wiki content — pages + heightmaps + markers + architecture-flavor — into one first-class, baked Atlas content set (the "move it into a
gamedata/subtree" instinct), not a per-feature hack. The generator-facing tables (trait_templates+atlas_body_trait_bias, D-232) are invariant to the source location, so this does not block the fill seam. - Audit note (2026-06-12, fable-ous.md S-52): include a signature materials/crafts structured field (per-system or per-body) in the consolidation scope. Distinctive material canon exists only as prose today — granite dry-stack tradition (
wiki/star-systems/GJ-4053/index.md:22-26), peat-wood carving (GJ-1248/index.md:30), basalt crater farms (GJ-285/index.md:28-38), structural timber (GJ-588/index.md:30-34) — while markers are names-only (D-223) and the structured counterpart is only the 28-template trait catalog + 240 D-237 pins. Consolidating it lets D-232 bias be authored from existing prose instead of re-invented; also feeds the dress-canon registers (Q-121). - Cross-reference: D-232, D-223, D-191 (Atlas/settlement), and the development cascade (Phase 1 wiki + Phase 3 Atlas); Q-121
Q-108: Subterranean / domed / sealed-habitat settlement morphology — does the built-world fill model need a surface-vs-enclosed branch
- Status: Open — raised 2026-05-31 (system-economic-specialization workshop follow-up, via Vuurkloof / GJ 35)
- Question: The economic-built-world fill model (D-233, re-amended by D-237) is implicitly a surface model — it derives a roofed-coverage fraction, an operations-surface remainder, and a concentrate-vs-scatter spread across open ground. But
bodies.settlement_patternalready carries non-surface morphologies for real bodies:underground_concentrated(e.g. Vuurkloof / GJ35c, built into ravine walls),cave,domed,underground_complex(~12+ bodies onunderground_concentratedalone, more across the others). Nothing in the current chain readssettlement_pattern— it is not in the D-199 read-set, not consumed bycity_context_reader, not branched on inskeleton_gen/ D-233 fill. The engine primitives exist (D-110 signedbase_z, theUndergroundComplexreservation, D-106 vertical scale — "a deep mine is an inverted skyscraper"), but no morphology switch connectssettlement_patternto them at the built-world layer. So an enclosed-habitat body like Vuurkloof would currently generate as a surface geothermal town (conduits and exchange stations spread across open ground), contradicting authored lore (underground-concentrated, ravine-wall construction). Does the fill model need a first-class surface-vs-enclosed (subterranean / domed / sealed-habitat) morphology branch, and where does it live — (a)settlement_patternas a hard-gate input to D-233/D-237 fill selecting an enclosed coverage/vocabulary model; (b) a separate morphology layer above D-233 the economic vocabulary plugs into; (c) treat domed/sealed (pressurized surface envelope) as distinct from true subterranean (excavated z-negative)? And how does verticality (D-106/D-110) compose with the coverage model when a settlement is primarily vertical/subsurface, and how doesmorphology_zone(D-228/D-234, terrain-driven street geometry) behave when there is no open street plane? - Context: D-237 inherited D-233's surface assumption; it did not introduce the gap and does not block on it (surface bodies — the majority — are correct today). But enclosed-habitat bodies are authored lore and will read wrong until resolved. Wants its own debate/workshop with Tyre (z-level architecture), Burnelli (coverage model), Miri (which bodies, what they must read as), Araminta (how enclosed interiors are visually distinct). Tracked by ticket T-1018; schedule before the Phase 4 content pass authors built form for enclosed-habitat bodies.
- Cross-reference: D-233 (surface coverage model — would be amended), D-237 (authored specialization layer — inherits the surface assumption), D-199 (read-set — would need
settlement_pattern), D-220 (density / vertical pressure), D-106 (vertical scale), D-110 (signed z-levels), D-228/D-234 (morphology zone / street geometry), D-196 (SettlementClass — orthogonal; this is morphology, not active/ghost)
Q-109: Cascade generation-source dispatch — planetary / station / mod-DLC-forked / save-only
- Status: Open — raised by Jeroen (2026-06-05, during T-957 zone-selection authoring); re-triaged 2026-07-08 (T-1057) → revisit before stations / mods / save-only bodies are prioritized (Phase 5+).
- Triage (2026-07-08, T-1057): DEFERRED. The planetary path is the only live generation source today, so the dispatch discriminator has exactly one branch to route to and nothing yet exercises the fork. The station-only interim is already carved by the D-229 amendment (2026-06-05): T-957's
(ZoningType × economic_role × setting)zone-selection table deliberately excludes the station-only ids (residential_station/extraction_space/port_space/rural_orbital), reserving them for a separate station cascade — so the seam is documented without the dispatcher being built. Revisit before stations, mod/DLC-forked bodies, or save-onlyplayer_basebodies are prioritized (Phase 5+), when the discriminator's home (SettingTypevs a dedicatedGenerationSource), the mod/DLC external-code resolution, and the save-only cache-bypass (aplayer_basebody must never enqueue anAnalyzeBody— D-225/D-203) are decided together with the savegame model. - Question: The generation cascade currently has a single implicit path: every body runs the planetary generator (
run_cascade→ Layers 0–5). But a body'sSettingType(or a siblingGenerationSourcediscriminator) should dispatch at the cascade entry to one of several generation sources: (a) planetary — the default terrain→quarter→tile cascade (T-955/T-956/T-957…); (b) station / orbital — a separate cascade that owns the station-only zone types (residential_station,extraction_space,port_space,rural_orbital) and its own layout model, rather than branching the planetary code (this is why T-957's zone-selection table deliberately excludes those ids — see D-229 amendment 2026-06-05); (c) mod / DLC-forked — a value that routes generation to externally-provided code/templates (a mod or DLC name), so third-party content can supply a body's built form without patching core; (d) save-only /player_base— disables auto-generation entirely and loads the body's built world from a save file (player-constructed bases must persist, not regenerate). Where does this discriminator live — onSettingTypeitself (it already carriesStation/Orbitalvariants) or a dedicatedGenerationSourceenum at therun_cascadeentry? How does the mod/DLC fork resolve to external code (registry? trait object? content-pack manifest?)? And how does save-only compose with the D-203 hot cache and the D-225 compute-on-demand proxy (aplayer_basebody must never enqueue anAnalyzeBody)? - Context: Surfaced while authoring T-957's
(ZoningType × economic_role × setting)zone-selection table:settingis the right tweaker within the planetary path, but it is also the natural dispatch point above it — the two roles are distinct and only the tweaker belongs in T-957. The dispatch is a cross-cutting routing seam above any single layer; capturing it here so T-957 stays scoped to the planetary path. Not blocking — the planetary path is the only live source today. Wants Tyre (cascade architecture) + a look at modding/DLC strategy and the savegame model (Phase 5+) before it's decided. - Cross-reference: D-200 (runtime cascade), D-225 (compute-on-demand proxy — save-only must bypass), D-203 (hot cache), D-229 (zone-selection — excludes station ids for this reason), D-222 (Quarter/spatial tiers), and the development cascade (Phase 5 player control + savegame)
Q-110: Region/chunk physical-scale anchoring — what is a region in metres, and what anchors a heightmap pixel?
- Status: Resolved → D-243 (2026-06-14). A nested absolute-metre containment ladder (voxel→chunk→block→quarter→district→region ~205 km) with a single elastic seam region↔planet (
round(2πR/204.8 km)regions per body). Closest to option (a) full-planet anchoring, sharpened: the ladder tops at the region (the largest hard block, sized to ×100 districts ≈ one weather cell), not the ~1 km RegionProfile (dropped onto the district) — so the elastic count is a sane planetary grid, not millions. The region doubles as the climate/weather/season lockdown scale (feeding Q-105), edge-fuzzed so the grid never shows. D-201 tier-4 "Region"→"Province" disambiguates the vocabulary; the canonical ladder is recorded in CLAUDE.md. - Question: The refinement chain's nominal physical anchors (workshop brief: 78 km L1 cell → ~1 km region → 64 m chunk → 1 m voxel,
docs/workshops/tile-derivation-contract/tile-derivation-contract-workshop-brief.md:19-22) are mutually inconsistent in the implementation, and no record fixes metres-per-heightmap-pixel. Evidence: (1)region_profile.rs:3-4documents ~1 km² regions, ~6,000/body (80×75); (2)derive_all_regions(region_profile.rs:1014-1044) actually tiles the 512×256 L1 working grid at 8 cells/region spanning ±90° latitude — for a planet-scale equirect map an L1 cell is body-relative (~78 km on an Earth-like body), making such a region ~624 km, not 1 km; (3)cascade.rs:235-237claims "8 cells per region on a 128×64 working grid → ~80×32 = ~2,560 regions" — internally inconsistent and inconsistent withheightmap.rsGRID 512×256; (4)chunk_context.rs:137-141assumes a region is 16 chunks ≈ 1.024 km; (5) D-239 §10 asserts "D8 ≈ 152 m/cell" — true only if the whole 512-cell grid spans ~78 km, i.e. one nominal L1 cell, not a planet; (6) D-201's tier-4 "Region" is the 50–500 km Province, colliding with the D-239 ~1 km RegionProfile vocabulary. Voxel/chunk scales are absolute (D-222: 1 m / 64 m) but the heightmap pixel is body-relative — the cascade currently glues them with three contradictory assumptions. Which anchoring model is canonical?- (a) Full-planet anchoring: fix metres/pixel per body from
body_radius_km(D-204):px_m = 2πR/1024. Regions become fixed ~1 km cells whose count varies per body (millions for a planet) — requires lazy region derivation (already the D-225/D-227 model) plus an explicit L1→region resampling stage; the 8-cells-per-region shortcut and the ~6,000/body budget die. - (b) Working-window anchoring: L1–L3 stay planet-equirect; the voxel cascade (region→chunk→voxel) operates on bounded windows (~one 78 km L1 cell) anchored at points of interest (settlements), with fixed metres/pixel inside the window. Matches the brief's chain literally and keeps ~6,000 regions/window; needs a window-addressing scheme in BodyWorldState and a rule for inter-window terrain.
- (c) Body-relative everything: keep pure grid-ratio anchoring (region = L1cell/8, chunk = region/16) and let metre meanings float per body — rejected-shaped: breaks the D-222/D-227 absolute 1 m tile vocabulary, D-239 §9 chokepoint widths, and the budget math.
- (a) Full-planet anchoring: fix metres/pixel per body from
- Context: Blocks metre-precise tuning of the cross-region blend and the landform region-anchoring fix; needed for Atlas scale bars (T-960) and the D-239 §10 ~45 ms/body budget accounting (assumes ~6,000 regions/body). A D-201 amendment is likely required to disambiguate Region-vs-Province vocabulary.
- Cross-reference: D-201, D-202, D-204, D-222, D-225, D-227, D-239 §9/§10, Q-105
Q-111: Live-econ coupling of generation inputs — which inputs refresh from the rolling sim vs stay static-authored?
- Status: Open — surfaced 2026-06-12 during cascade-work grounding
- Question: The generation cascade reads every economic input from static systems.db at build/dispatch time (D-199 read-set via
city_context_reader.rs; D-200 tier-1), while the live economy independently rebuildsEconStateResource— all 7 D-181 signals per (system_id, commodity_id) — every ECON_TICK_RATE (economy.rs:107-120).EconStateResourcehas NO generation consumer (only the IPC bridge + debug command read it). D-227 already names the coupling mechanism — the derived economic base is "recomputed on expiry, and force-evicted on an event (e.g. the player tanks a system's economy)" — but no record fixes the policy. For each generation input, which bucket: (a) static-authored forever (economic_role, founding_age_years, D-237 specializations — authored identity); (b) epoch-refreshed (re-read at save/load or world-epoch boundaries: prosperity_baseline_bps? world_tier? dominant commodity/BulkClass?); (c) live-coupled via D-227 force-eviction + re-derivation (settlement active/ghost flips per D-196, building condition/occupancy per D-217/T-999, road MaintenanceAuthority degradation)? And what is the eviction contract: who emits the event (an EconEvent threshold? storyteller?), which cache tiers evict (BodyWorldState regions/quarters vs chunk/voxel caches), and at what granularity (per-settlement, per-body, per-system)? - Context: T-1007 defers economic_tier derivation "until it earns a use case in the rolling sim" and T-982's dominant-commodity lookup is static build-time — both park fields whose home depends on this answer. T-999 is the only ticketed live-econ→world consumer. D-198 fixed the reverse direction (econ sim never reads spatial layers); this is the forward direction. Per the cascade-first direction (2026-06-12 D-166 amendment: geo → econ-on-world → templates → door contracts → NPC/interiors → gameplay), default-static is acceptable through Phase 4; the answer gates Phase 5+ (a Reach a character travels through must show economic life without invalidating walked terrain) and the save model (D-227).
- Cross-reference: D-181, D-196, D-197, D-198, D-199, D-200, D-217, D-227, D-237; T-999, T-1007, T-982; Q-103 (mutator schema), Q-105 (region clock state)
Q-112: Storyteller engagement scoring — move to bps integer arithmetic or sanction f32?
- Status: Open — filed 2026-06-12 from the fable-ous.md audit (S-04)
- Question:
bps.rs:1-8documents the D-010 convention: fractional values in determinism-sensitive paths are integer basis points, f32 only at the edge. But storyteller anchor selection — which mutates game state via triangle activation — computes engagement scores in f32 (weights 2.0/0.005/8.0 atstoryteller/mod.rs:102-112, f64→f32 cast at:445-446) and sorts bypartial_cmp(:546) with a SimRng tie-break (:550-558). Replay-deterministic on one binary, but contradicts the convention. Separatelygenerator.rs:1086declaresfootprint_radius_km: f32in the Phase-4 CityGenerationContext directly below a field documented "Integer to avoid f32 non-determinism (D-010)"; it is currently a 5.0 stub (D-204 formula deferred,city_context_reader.rs:482). Either record that f32-with-integer-derived-inputs + SimRng tie-break is sanctioned for storyteller scoring, or convert the weights to bps (u32). Forfootprint_radius_km, specify the D-204 formula in integer metres/bps before it lands in the cascade. Note: no dedicated D-record for the integer-discipline convention exists — it lives only in code docs and.clippy.toml; answering this is the natural moment to record it. - Cross-reference: D-010, D-204;
server/src/bps.rs,server/src/storyteller/mod.rs,server/.clippy.toml; Q-113
Q-113: Is cross-platform f32 bit-identity required for saves? (golden vectors are x86_64-only)
- Status: Open — filed 2026-06-12 from the fable-ous.md audit (S-40)
- Question: D-227 reclassified generation determinism as save-critical, but the L1 cascade goldens self-declare x86_64-only f32 sensitivity (
cascade_golden.rs:17-20: "a different architecture could in principle round differently" — slope/elev_pct/downsample paths). If cross-platform bit-identity is required for saves, the remaining f32 L1 paths need the same scaled-integer treatment drainage already has (drainage.rs:4-7). Related gate hygiene: the per-family chunk budget assertion runs only underBUDGET_ASSERT=1(derivation_harness.rs:19-23) and its 5 ms gate is looser than the D-239 §10 stated 2.2–4.2 ms — enable it in a release-mode periodic job and reconcile the figures. - Cross-reference: D-010, D-227, D-239 §10;
server/tests/cascade_golden.rs,server/tests/derivation_harness.rs; Q-112
Q-114: Server-side NPC appearance generation contract — seed+culture+role → CharacterVisualDescriptor
- Status: Open — filed 2026-06-12 from the fable-ous.md audit (S-41); Phase 5/6 work, recorded now so the contract exists before that work starts
- Question: The client rendering architecture (D-159..D-164) is implemented and validated, but no server-side appearance generation exists:
npc/generate.rs:465-535spawns the 10 behavioral axes plus sim-state components with zero visual fields, and the appearance pre-generation worker is an explicit stub (workers/stubs.rs:86: "real implementation pre-generates NPC appearance, inventory, mood").CultureProfile(blueprint.rs) carries speech/behavior modifiers but no visual attributes. The contract to decide: where the descriptor is generated (NpcPrepWorker per the stub's own intent), its inputs (culture register, role, faction, corp employment, prosperity band), its determinism requirement (pure function of EntityRng/SeedChain like every other NPC axis), and that the clientCharacterVisualDescriptorschema is the single source of truth for fields. Companion work: the wire struct (T ticket, Phase 5) and wardrobe assignment (Phase 6); garment policy in Q-115/Q-120/Q-121. - Cross-reference: D-122, D-159..D-164;
server/src/npc/generate.rs,server/src/workers/stubs.rs,client/scripts/rendering/character_visual_descriptor.gd; Q-115, Q-120, Q-121
Q-115: Are garments simulated inventory items or visual-only descriptor fields?
- Status: Open — filed 2026-06-12 from the fable-ous.md audit (S-C2); shapes the Q-114 schema, so answer before Phase-5 appearance work
- Question: Server inventory is a 9-slot CarriedBy grid with no equipment concept (
simulation/inventory.rs:12-36). Visual-only garments (descriptor fields) are cheap and ship with Phase 5. Simulated garments (equip/remove/trade) touch inventory, perception, and economy — but fit the game's thesis: in an asymmetric-information game a uniform is a claim about identity that can be false (disguises, the Workshift HeavyWork exposure-history hook as wearable evidence). Recommendation embedded from the audit: visual-only descriptor in Phase 5, with the descriptor schema reserving item-id compatibility so an equipment-slot upgrade remains an explicit Phase-6 decision rather than a migration. - Cross-reference: D-024 (NPC axes), D-159..D-162;
server/src/simulation/inventory.rs,wiki/corporations/workshift-apparel.md; Q-114, Q-120
Q-123: Believability gate threshold calibration
- Status: Open — filed 2026-06-28 alongside D-245 (the gate names the criteria; this fixes their numbers)
- Question: D-245 makes "the nature layers read alive anywhere" the acceptance gate, screened by five automated necessary-conditions, but leaves the thresholds TBD pending baselines from the T-1083 enforcer. Calibrate, from T-1083's first runs across several habitable bodies × seeds:
- Sampling power — probes per body, number of bodies, number of seeds that constitute "anywhere" (enough that one lucky/unlucky draw is not decisive).
- Non-stationarity — the similarity metric for "two same-class km² differ" (histogram distance / feature-vector cosine) and the minimum dissimilarity that counts as non-repeating; plus a tile-period autocorrelation ceiling (the Netherlands "no two km² alike" rule, made numeric).
- Intra-class variety — minimum distinct micro-features per sampled patch (K), per terrain class (T-1084).
- Relief floor — minimum relief variance, conditioned on the macro terrain's expectation (a plain's floor ≠ a montane floor) (T-1081). (T-1081 landed the metric —
contrast.voxel_relief_m, mean within-district elevation range over a 2 km transect — with a provisional≥ 8 mthreshold and a provisionalVOXEL_RELIEF_SPAN_M = 100(≈22 m mean relief on Arbour/Edict); calibrate both, and make the floor macro-conditioned rather than a single global number. The span is capped low because relief sits on the compressedelev_q/Nbase and clamps at sea level, so it can't grow without artifacts until — also pending — the absolute elevation span moves off that compressed base to a per-body hypsometric model (which sets true relief ceilings and gives the span headroom). T-1081 review notes to fold in: (i) sanity-check theslope_q*3 + elev_qenvelope on a synthetic high-slope body — both terms saturate the same 0–100 cap, so slope's 3× weight contributes little once elev_q is already high (the tectonic-class ridge-sharpening refinement would address this); (ii) the relief transect samples a single diagonal slice — fine for the current isotropic fBm, but revisit if an anisotropic/ridge-aligned field is added.) - Coherence — the vegetation ↔ (moisture / water-distance / slope / aspect) correlation floor; the water-zone-renders-wet check (T-1082); the allowed "impossible combo" set (should be empty). (T-1082 review note: the current 50% "water renders wet" floor is weak for ocean-dominant bodies — calibrate it per zone: post-T-1082 an
OpenOceandistrict should render wet ~100% (Dry is impossible), while a mixed coastal district may legitimately read partial.) Also calibrate the vegetation-present denominator: dividing by all sampled districts (incl. water) makes the criterion structurally unreachable for a 2/3-ocean world — it should be land-relative (exclude water-body districts). - Climate-appropriateness — how "structured-sparse passes / blank fails" is measured on cold/arid bodies, so a frozen world is not failed for being legitimately sparse.
- Pass budget + ratchet — the % of land probes that must pass to ship (budgeted), and the trigger to ratchet advisory → strict (hard push-gate block).
- Cross-reference: D-245 (the gate this calibrates), D-239 §8/§10 (laws + budget), D-227, D-243; tickets T-1083 (enforcer — produces the baselines), T-1079 (epic), T-1080/T-1081/T-1082/T-1084.
65 questions (13 resolved, 1 partially resolved, 51 open). Last updated: 2026-06-28 (Q-123 — believability gate threshold calibration, alongside D-245).