From f83d2c7704265d297532ec21f9414736a0eee15b Mon Sep 17 00:00:00 2001 From: Rijad Zuzo Date: Sun, 5 Jul 2026 12:52:13 +0200 Subject: [PATCH] docs: mark simulation state phase complete --- docs/BUILD_IN_PUBLIC_PLAN.md | 2 +- docs/LEARNING_ROADMAP.md | 36 +++++----- docs/PROJECT_CONTEXT.md | 28 +++++--- docs/SIMULATION_STATE_SCHEMA.md | 70 +++++++++++++++++++ .../0001-simulation-authority-boundary.md | 11 +-- 5 files changed, 115 insertions(+), 32 deletions(-) create mode 100644 docs/SIMULATION_STATE_SCHEMA.md diff --git a/docs/BUILD_IN_PUBLIC_PLAN.md b/docs/BUILD_IN_PUBLIC_PLAN.md index fbc8cdf..44869d9 100644 --- a/docs/BUILD_IN_PUBLIC_PLAN.md +++ b/docs/BUILD_IN_PUBLIC_PLAN.md @@ -360,7 +360,7 @@ learning roadmap: - deterministic clock and seeded randomness; ✅ - fixed-seed headless scenarios and final-state checksum; ✅ -- versioned serializable NPC, village, and resource records; +- versioned serializable NPC, village, resource, clock, and RNG records; ✅ - resource amount and reservation authority outside scene nodes; - stable action/profession IDs and initial definitions; - separate action selection, execution, target resolution, and visual travel; diff --git a/docs/LEARNING_ROADMAP.md b/docs/LEARNING_ROADMAP.md index cf30951..a754518 100644 --- a/docs/LEARNING_ROADMAP.md +++ b/docs/LEARNING_ROADMAP.md @@ -54,17 +54,21 @@ The gate is complete when the same scenario produces the same checksum without loading `main.tscn`, and loading or unloading a visual does not change authoritative NPC or resource state. -**Current progress:** the first deterministic slice is implemented: +**Current progress:** the first two architecture slices are implemented: - `SimulationClock` advances explicit fixed ticks while preserving remainder; - NPC decisions and visual wander requests use controlled per-NPC random streams derived from an exported simulation seed; - a headless scenario verifies same-seed equality, different-seed divergence, and a final-state checksum without loading `main.tscn`. +- versioned JSON records capture and restore current NPC, village, resource, + clock, and RNG state; +- a save-at-tick-24 continuation test matches an uninterrupted 48-tick + checksum and rejects unsupported schema versions. -The gate remains open. Versioned state records, scene-independent resource -authority, stable definitions, responsibility separation, and visual -load/unload invariance are still required. +The gate remains open. Scene-independent resource authority, stable +definitions, responsibility separation, and visual load/unload invariance are +still required. See [the simulation state schema](SIMULATION_STATE_SCHEMA.md). ## Three vertical slices @@ -611,23 +615,23 @@ Completed foundations: The practical next sequence is: -1. Add versioned serializable NPC, village, and resource state records, - including enough clock and RNG state for deterministic continuation. -2. Move resource amount/reservation authority out of `ResourceNode` scenes. -3. Replace free-form task and profession strings with stable IDs and +1. Move resource amount/reservation authority out of `ResourceNode` scenes and + make unloaded resources remain in state. +2. Replace free-form task and profession strings with stable IDs and definitions. -4. Separate action selection, execution, target resolution, and visual travel; +3. Separate action selection, execution, target resolution, and visual travel; remove decision mutation from `WorldViewManager`. -5. Define active-position synchronization and prove visual unload/reload. -6. Pass the architecture gate's deterministic headless and unloaded-visual exit +4. Define active-position synchronization and prove visual unload/reload. +5. Pass the architecture gate's deterministic headless and unloaded-visual exit tests. -7. Build location-based food storage, inventory, and transactions. -8. Emit structured economic events while making one NPC visibly gather, carry, +6. Build location-based food storage, inventory, and transactions. +7. Emit structured economic events while making one NPC visibly gather, carry, store, retrieve, and eat food. -9. Add versioned save/load before schedules or social state expand. -10. Resume Terrain3D sculpting, runtime integration, and the simulation-garden +8. Add save-slot persistence and explicit schema migrations before schedules + or social state expand. +9. Resume Terrain3D sculpting, runtime integration, and the simulation-garden beauty pass. -11. Add stylized character and profession readability plus the reason +10. Add stylized character and profession readability plus the reason inspector. This order strengthens the simulation while regularly producing visible diff --git a/docs/PROJECT_CONTEXT.md b/docs/PROJECT_CONTEXT.md index 6c015b4..e1bcf4a 100644 --- a/docs/PROJECT_CONTEXT.md +++ b/docs/PROJECT_CONTEXT.md @@ -464,12 +464,14 @@ NpcVisual navigates through the active world │ ├── SimNPC.gd │ ├── SimVillage.gd │ ├── SimulationClock.gd -│ └── SimulationManager.gd +│ ├── SimulationManager.gd +│ └── state/ Versioned simulation-state records ├── tests/ │ ├── deterministic_simulation_test.gd │ ├── flat_map_baseline_test.gd │ ├── jajce_world_scaffold_test.gd -│ └── resource_node_player_parity_test.gd +│ ├── resource_node_player_parity_test.gd +│ └── simulation_state_serialization_test.gd ├── terrain/jajce/ Dedicated Terrain3D seed data and assets ├── tools/ │ └── generate_jajce_terrain_seed.gd @@ -496,14 +498,15 @@ These are expected prototype constraints, not necessarily isolated bugs: - Task names and task-to-activity-marker mappings are duplicated strings. - Temporary activity markers remain for eating, rest, study, and patrol; NPC and player food/wood gathering use `ResourceNode` instances with no fallback. -- Mutable simulation state is not serializable through a defined save schema. -- Simulation randomness is seeded and split into controlled per-NPC streams, - but RNG state is not yet part of a serializable save record. +- Current NPC, village, loaded resource, clock, and RNG state serialize through + schema v1, but there is no save-slot/file UX or backward migration yet. +- Resource records currently mirror loaded ResourceNode state; the scene nodes + still own live amounts and reservations. - An explicit fixed-step clock converts frame delta into simulation ticks, but orchestration still lives on the scene-tree `SimulationManager`. -- Automated coverage includes deterministic same-seed checksum, - player-parity/resource-contention, flat-map, and Jajce scaffold scenarios; - broader gameplay coverage is still missing. +- Automated coverage includes deterministic same-seed and save/restore + continuation checks, player-parity/resource-contention, flat-map, and Jajce + scaffold scenarios; broader gameplay coverage is still missing. - Resources are global floating-point counters rather than items in locations and inventories. - NPCs do not have homes, schedules, possessions, memories, relationships, @@ -713,15 +716,18 @@ Food and wood migration and the deliberately minimal `JajceWorld` scaffold, greybox, navigation spike, and stable-ID placement proof are complete. Do not proceed directly from that proof into open-ended beauty production. -The architecture gate is now the active milestone. Its first slice is complete: +The architecture gate is now the active milestone. Its first two slices are +complete: - explicit fixed-step simulation clock; - seeded per-NPC decision and wander random streams; -- headless fixed-seed scenario with a final-state checksum. +- headless fixed-seed scenario with a final-state checksum; +- versioned JSON records for NPC, village, loaded resource, clock, and RNG + state; +- deterministic save/restore continuation with exact 64-bit RNG preservation. The remaining gate work is: -- versioned serializable NPC, village, and resource state; - data-defined action and profession IDs; - separated action selection, execution, target resolution, and visual travel; - resource amount and reservation authority moved out of scene nodes; diff --git a/docs/SIMULATION_STATE_SCHEMA.md b/docs/SIMULATION_STATE_SCHEMA.md new file mode 100644 index 0000000..e0bb755 --- /dev/null +++ b/docs/SIMULATION_STATE_SCHEMA.md @@ -0,0 +1,70 @@ +# The Steward — Simulation State Schema + +## Current contract + +`SimulationStateRecord` is the versioned JSON boundary for the current +simulation. Schema v1 captures: + +- simulation seed, tick interval, tick count, clock remainder, and elapsed + clock ticks; +- every NPC's identity, needs, attributes, task lifecycle, target, position, + starvation state, and decision RNG stream; +- village resource counters; +- controlled per-NPC wander RNG streams; +- loaded ResourceNode amount, reservation, and enabled state. + +The top-level identity is: + +```json +{ + "schema": "the_steward.simulation", + "schema_version": 1 +} +``` + +Unknown schema versions and structurally incomplete records are rejected. Add +an explicit migration function before accepting a future version; never +silently reinterpret old data as the newest layout. + +## Deterministic continuation + +RNG seeds and internal states are encoded as decimal strings. They are signed +64-bit values and cannot safely pass through every JSON number implementation +without precision loss. Converting them to ordinary JSON numbers caused a +restored simulation to retain the same visible state while silently changing +its future random sequence. + +`tests/simulation_state_serialization_test.gd` protects this contract by: + +1. running a fixed-seed scenario for 48 ticks without interruption; +2. running the same scenario for 24 ticks; +3. serializing and restoring into a fresh manager; +4. running the remaining 24 ticks; +5. requiring the complete final-state checksums to match. + +It also verifies clock remainder, ResourceNode amount/reservation/enabled +round-tripping, and rejection of unsupported schemas. + +## Transitional resource boundary + +Schema v1 can capture and restore loaded `ResourceNode` state, but the scene +node still owns the live amount and reservation. That is transitional support, +not the final authority model. + +The next architecture-gate phase moves those values into scene-independent +resource records. ResourceNode will then bind to a record by stable ID and act +as presentation plus an active-world interaction surface. An unloaded resource +must remain simulated and serializable. + +## Deliberately out of scope + +This phase does not yet provide: + +- save-slot files, metadata, thumbnails, or atomic disk writes; +- backward migrations beyond schema v1; +- inventory, relationship, schedule, or history records; +- a player-facing load flow; +- scene-independent resource authority. + +Those features should build on this boundary rather than inventing parallel +serialization paths. diff --git a/docs/decisions/0001-simulation-authority-boundary.md b/docs/decisions/0001-simulation-authority-boundary.md index 5ba1614..7d11b22 100644 --- a/docs/decisions/0001-simulation-authority-boundary.md +++ b/docs/decisions/0001-simulation-authority-boundary.md @@ -44,10 +44,10 @@ random streams, and no dependency on a loaded gameplay scene. ## Staged migration -1. Add a deterministic clock, seeded random source, and scenario runner. -2. Introduce serializable village, NPC, and resource-state records. -3. Bind `ResourceNode` presentation to resource records instead of owning - authoritative amount and reservation. +1. ✅ Add a deterministic clock, seeded random source, and scenario runner. +2. ✅ Introduce serializable village, NPC, and resource-state records. +3. **Next:** Bind `ResourceNode` presentation to resource records instead of + owning authoritative amount and reservation. 4. Move target choice and reservation coordination out of `WorldViewManager` into an action/target system with an active-world query adapter. @@ -55,6 +55,9 @@ random streams, and no dependency on a loaded gameplay scene. 6. Add versioned save/load before inventories, schedules, or relationships substantially expand mutable state. +Schema v1 and its deterministic continuation contract are documented in +[the simulation state schema](../SIMULATION_STATE_SCHEMA.md). + ## Consequences - Some current prototype APIs are transitional and should not be generalized