docs: establish simulation architecture gate

This commit is contained in:
2026-07-04 19:55:30 +02:00
parent 0900022558
commit 83fc258afc
7 changed files with 288 additions and 56 deletions
+49 -24
View File
@@ -9,6 +9,10 @@ The immediate visual goal is to replace the flat prototype presentation with a
small, attractive, watchable environment while preserving the working NPC small, attractive, watchable environment while preserving the working NPC
simulation, player controls, UI, task lifecycle, and navigation behavior. simulation, player controls, UI, task lifecycle, and navigation behavior.
This is a scoped visual-production plan. Milestone order and architecture gates
are owned by [the learning roadmap](LEARNING_ROADMAP.md); simulation authority
is governed by [ADR 0001](decisions/0001-simulation-authority-boundary.md).
Before runtime terrain integration, food and wood should migrate from abstract Before runtime terrain integration, food and wood should migrate from abstract
zones to actual finite world objects according to zones to actual finite world objects according to
[the ResourceNode migration plan](RESOURCE_NODE_MIGRATION.md). This prevents the [the ResourceNode migration plan](RESOURCE_NODE_MIGRATION.md). This prevents the
@@ -62,9 +66,9 @@ Main
└── UI └── UI
``` ```
The player and `WorldViewManager` reference the task markers through exported The player and `WorldViewManager` still reference non-resource activity markers
`NodePath` values. `NpcVisual` relies on the navigation map to reach those through exported `NodePath` values. `NpcVisual` relies on the navigation map to
markers. reach both those markers and ResourceNode interaction points.
Replacing the ground without respecting those references would break behavior Replacing the ground without respecting those references would break behavior
that already works. that already works.
@@ -89,9 +93,7 @@ Main
│ │ └── ResourceNodes │ │ └── ResourceNodes
│ │ ├── BerryBush instances │ │ ├── BerryBush instances
│ │ └── Tree instances │ │ └── Tree instances
│ ├── LegacyTaskMarkers temporary migration fallback │ ├── LegacyTaskMarkers temporary non-resource activities
│ │ ├── FarmZone fallback only
│ │ ├── ForestZone fallback only
│ │ ├── FoodZone │ │ ├── FoodZone
│ │ ├── GuardZone │ │ ├── GuardZone
│ │ ├── StudyZone │ │ ├── StudyZone
@@ -250,7 +252,7 @@ This becomes both a regression reference and excellent before/after material.
There is a reproducible baseline showing the existing flat prototype and its There is a reproducible baseline showing the existing flat prototype and its
working behaviors. working behaviors.
### Systems prerequisite — Migrate food and wood targets ### Systems prerequisite — Migrate food and wood targets ✅ complete
Implement and validate the first ResourceNodes on the current flat map before Implement and validate the first ResourceNodes on the current flat map before
moving the playable runtime onto Terrain3D: moving the playable runtime onto Terrain3D:
@@ -263,7 +265,7 @@ moving the playable runtime onto Terrain3D:
- extraction after work completion; - extraction after work completion;
- depletion and replanning; - depletion and replanning;
- actual extracted amount applied to the village; - actual extracted amount applied to the village;
- zone fallback with visible warnings. - player interaction through the same extraction contract.
Keep the other task zones temporarily. Rest, eating, study, and patrol will Keep the other task zones temporarily. Rest, eating, study, and patrol will
eventually use activity, storage, or workstation targets rather than pretending eventually use activity, storage, or workstation targets rather than pretending
@@ -335,6 +337,29 @@ The final navigation bake still happens after terrain and props stabilize.
One static frame contains the ridge landmark, roofs, river/waterfall, and One static frame contains the ridge landmark, roofs, river/waterfall, and
village work area. A test agent can traverse the intended task loop. village work area. A test agent can traverse the intended task loop.
### Systems gate — Harden simulation authority
After the scaffold, greybox, and navigation spike prove the world shape, pause
visual production and complete the mandatory architecture gate from the
learning roadmap:
- deterministic clock and seeded randomness;
- fixed-seed headless scenarios and final-state checksum;
- versioned serializable NPC, village, and resource 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;
- explicit active-position synchronization.
Do not solve this by moving simulation ownership into `JajceWorld`. The
environment remains a presentation and active-world query surface.
### Exit condition
The same scenario produces the same result without `main.tscn`; unloading a
visual does not change authoritative state; current resource and movement
behavior still pass regression tests.
### Phase 3 — Establish the beauty baseline ### Phase 3 — Establish the beauty baseline
Add only the highest-value presentation: Add only the highest-value presentation:
@@ -366,7 +391,7 @@ Once the world composition is stable:
2. Disable or remove the old flat world only after the new instance is present. 2. Disable or remove the old flat world only after the new instance is present.
3. Place or move bushes and trees under 3. Place or move bushes and trees under
`JajceWorld/WorldObjects/ResourceNodes` while preserving stable IDs. `JajceWorld/WorldObjects/ResourceNodes` while preserving stable IDs.
4. Reconnect remaining player and `WorldViewManager` fallbacks to markers under 4. Reconnect only remaining non-resource activity markers under
`JajceWorld/LegacyTaskMarkers`. `JajceWorld/LegacyTaskMarkers`.
5. Bake navigation for the new walkable area. 5. Bake navigation for the new walkable area.
6. Test each existing task from multiple spawn positions. 6. Test each existing task from multiple spawn positions.
@@ -538,25 +563,25 @@ The follow-up milestone is complete when:
- cinematic and debug views can show the same real scenario; - cinematic and debug views can show the same real scenario;
- a repeatable public-demo clip shows an autonomous cause and consequence; - a repeatable public-demo clip shows an autonomous cause and consequence;
- performance and navigation regressions are measured and documented. - performance and navigation regressions are measured and documented.
- the mandatory architecture gate passes before final beauty integration.
## Immediate implementation order ## Immediate implementation order
1. Capture the current flat-map baseline. 1. Capture the current flat-map baseline.
2. Implement and validate ResourceNodes on the flat map. 2. Treat ResourceNode migration and player parity as complete.
3. Migrate food and wood; keep remaining zones as logged fallbacks. 3. Create `JajceWorld.tscn` and dedicated Terrain3D data.
4. Create `JajceWorld.tscn`. 4. Create `JajceLookdev.tscn` and its beauty camera.
5. Create dedicated Terrain3D data under `terrain/jajce/`. 5. Greybox the ridge, river valley, terraces, and waterfall drop.
6. Create `JajceLookdev.tscn` and its beauty camera. 6. Place ResourceNodes with stable IDs and only required activity markers.
7. Sculpt the ridge, river valley, terraces, and waterfall drop. 7. Block out the fortress, houses, mill, and bridge.
8. Place ResourceNodes and only the still-required legacy markers. 8. Run the early navigation spike.
9. Block out the fortress, houses, mill, and bridge. 9. Pass the mandatory architecture gate before beauty production.
10. Run the early navigation spike. 10. Establish terrain materials, lighting, water, mist, and foliage.
11. Establish terrain materials, lighting, water, mist, and foliage. 11. Capture “Jajce Lookdev 01.”
12. Capture “Jajce Lookdev 01.” 12. Instance `JajceWorld` into `main.tscn`.
13. Instance `JajceWorld` into `main.tscn`. 13. Reconnect activity markers, rebake navigation, and run regression scenarios.
14. Reconnect fallbacks, rebake navigation, and regression-test the simulation. 14. Add profession/readability presentation and the reason inspector.
15. Add profession/readability presentation. 15. Capture “Simulation Garden 01.”
16. Capture “Simulation Garden 01.”
Do not start with GIS data, a full city, a large asset pack, or more NPC Do not start with GIS data, a full city, a large asset pack, or more NPC
mechanics. The next proof is a beautiful stage for the systems that already mechanics. The next proof is a beautiful stage for the systems that already
+62 -15
View File
@@ -28,6 +28,31 @@ Each milestone should produce five outcomes:
Do not advance because files exist. Advance when the exit test passes. Do not advance because files exist. Advance when the exit test passes.
The current implementation has completed ResourceNode migration through player
parity. Next, build only the minimal Jajce scaffold and navigation proof, then
pass the architecture gate below before beauty production or broader simulation
features. See [ADR 0001](decisions/0001-simulation-authority-boundary.md).
## Mandatory architecture gate
This gate sits between the first Jajce terrain/navigation proof and substantial
beauty work, inventories, schedules, relationships, or population growth.
It requires:
- an explicit deterministic simulation clock;
- controlled, seedable random streams;
- a headless fixed-seed scenario runner and final-state checksum;
- versioned serializable records for current NPC, village, and resource state;
- authoritative resource amounts and reservations outside scene nodes;
- stable action/profession IDs and initial definitions;
- separate action selection, execution, target resolution, and visual travel;
- an active-world adapter for navigation facts and NPC position synchronization.
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.
## Three vertical slices ## Three vertical slices
The long-term vision contains three major risks. Validate them separately before The long-term vision contains three major risks. Validate them separately before
@@ -207,7 +232,8 @@ The staged replacement of abstract task zones begins with
- ownership, storage, reservations, and transactions; - ownership, storage, reservations, and transactions;
- production recipes; - production recipes;
- world interaction points; - world interaction points;
- consistency and invariant testing. - consistency and invariant testing;
- structured economic events as authoritative facts.
### Build ### Build
@@ -226,9 +252,12 @@ Include:
- abstract transfer for distant agents; - abstract transfer for distant agents;
- reservation and cancellation; - reservation and cancellation;
- spoilage only if it improves the initial loop; - spoilage only if it improves the initial loop;
- player participation in the same resource rules. - player participation in the same resource rules;
- structured gather, transfer, consume, deny, and depletion events carrying
stable actor, target, location, and resource IDs.
Add wood only after the food chain is coherent. Wood extraction already exists. Do not build a deeper wood production chain
until the food chain is coherent.
### Reusable artifact ### Reusable artifact
@@ -548,26 +577,44 @@ At the end of each milestone, evaluate the system against this checklist:
- Does it expose reason/debug information? - Does it expose reason/debug information?
- Do measurements justify its complexity? - Do measurements justify its complexity?
- Has at least one real gameplay feature exercised the API? - Has at least one real gameplay feature exercised the API?
- Does persistent authority remain valid when its presentation node is absent?
- Can an active visual synchronize position without becoming the sole owner of
location state?
Do not extract a plugin solely because a system might be reusable. Prefer a Do not extract a plugin solely because a system might be reusable. Prefer a
clear internal module until multiple real consumers establish a stable API. clear internal module until multiple real consumers establish a stable API.
## Recommended implementation order from the current repository ## Recommended implementation order from the current repository
Completed foundations:
- finite food and wood `ResourceNode` instances;
- NPC target selection, reservation, depletion, and authoritative yield;
- player parity through the same extraction contract;
- navigation-failure recovery and an initial headless contention scenario.
The practical next sequence is: The practical next sequence is:
1. Add simulation controls and an NPC reason inspector. 1. Capture a reproducible flat-map baseline.
2. Add finite berry bushes and trees through the first `ResourceNode`. 2. Create only the minimal `JajceWorld` scaffold, terrain greybox, navigation
3. Migrate food target selection, reservation, depletion, and actual yield. spike, and stable-ID resource-placement proof.
4. Introduce an explicit deterministic simulation clock and seed. 3. Begin the architecture gate with deterministic clock/randomness, a headless
5. Replace remaining free-form task strings with action IDs/definitions. scenario runner, final-state checksums, and serializable state records.
6. Separate action selection, action execution, and visual travel. 4. Move resource amount/reservation authority out of `ResourceNode` scenes.
7. Migrate wood and give the player the same extraction contract. 5. Replace free-form task and profession strings with stable IDs and
8. Build the first location-based food storage/inventory. definitions.
9. Make one NPC visibly gather, carry, store, retrieve, and eat food. 6. Separate action selection, execution, target resolution, and visual travel;
10. Build the first attractive Terrain3D simulation-garden layout. remove decision mutation from `WorldViewManager`.
11. Add simple stylized characters and profession readability. 7. Define active-position synchronization and prove visual unload/reload.
12. Add save/load before the mutable world state becomes substantially larger. 8. Pass the architecture gate's deterministic headless and unloaded-visual exit
tests.
9. Build location-based food storage, inventory, and transactions.
10. Emit structured economic events while making one NPC visibly gather, carry,
store, retrieve, and eat food.
11. Add versioned save/load before schedules or social state expand.
12. Resume the attractive Terrain3D simulation-garden beauty pass.
13. Add stylized character and profession readability plus the reason
inspector.
This order strengthens the simulation while regularly producing visible This order strengthens the simulation while regularly producing visible
progress suitable for public development updates. progress suitable for public development updates.
+48 -10
View File
@@ -2,9 +2,11 @@
> Agent-facing context for understanding the project quickly. > Agent-facing context for understanding the project quickly.
> >
> Snapshot basis: repository state after commit `b8752f8`, July 2026. Treat the > Snapshot basis: repository state after commit `0900022`, July 2026. Treat the
> code as the source of truth when this document and the implementation differ. > code as the source of truth when this document and the implementation differ.
See the [documentation map](README.md) for the authority and scope of each plan.
## Quick orientation ## Quick orientation
**The Steward** is currently a small Godot prototype for an embodied village **The Steward** is currently a small Godot prototype for an embodied village
@@ -358,9 +360,11 @@ creation, and some gameplay API responsibilities.
`WorldViewManager` bridges simulation data to visible NPC nodes. It: `WorldViewManager` bridges simulation data to visible NPC nodes. It:
- instantiates `NpcVisual` scenes; - instantiates `NpcVisual` scenes;
- maps task strings to world markers; - resolves resource nodes, random wander targets, and remaining activity
markers;
- writes the selected ResourceNode ID onto the NPC as a transitional behavior;
- sends targets to visuals; - sends targets to visuals;
- reports arrival back to `SimulationManager`; - reports arrival and navigation failure back to `SimulationManager`;
- applies visual death state. - applies visual death state.
### `player/npc/NpcVisual.gd` ### `player/npc/NpcVisual.gd`
@@ -376,7 +380,8 @@ creation, and some gameplay API responsibilities.
### `player/player.gd` and `player/camera_rig.gd` ### `player/player.gd` and `player/camera_rig.gd`
These implement camera-relative character movement, physical interaction These implement camera-relative character movement, physical interaction
proximity checks, mouse capture, and the elevated follow camera. proximity checks, ResourceNode harvesting, mouse capture, and the elevated
follow camera.
### `world/ui/ui.gd` ### `world/ui/ui.gd`
@@ -500,6 +505,26 @@ Use four conceptual layers:
Do not make the simulation core depend on `Node3D`, scene paths, animation, Do not make the simulation core depend on `Node3D`, scene paths, animation,
physics frames, or a currently loaded map. physics frames, or a currently loaded map.
The authoritative-boundary decision is recorded in
[ADR 0001](decisions/0001-simulation-authority-boundary.md). The current
`ResourceNode` state and `WorldViewManager` target selection are transitional,
not patterns to extend into inventories, schedules, or relationships.
### Authority and active-world adapters
Persistent mutable state belongs in versioned, serializable simulation records.
Systems mutate those records. Godot nodes:
- present nearby records;
- expose active-world interaction transforms and navigation results;
- translate player input into simulation commands;
- synchronize active position through an explicit adapter;
- never become the only owner of a persistent amount, reservation, action, or
identity.
Target selection may consume facts supplied by the active world, but the
presentation bridge must not author an NPC's decision or persistent target.
### Stable identity ### Stable identity
Every persistent entity should eventually have a stable ID: Every persistent entity should eventually have a stable ID:
@@ -649,14 +674,25 @@ The project has two interleaved tracks.
Every major systems milestone should produce a shareable visual behavior. Every Every major systems milestone should produce a shareable visual behavior. Every
visual milestone should support or reveal actual simulation state. visual milestone should support or reveal actual simulation state.
## Immediate milestone: the simulation garden ## Immediate milestone: scaffold, architecture gate, then simulation garden
Before integrating Terrain3D into the playable runtime, migrate food and wood Food and wood migration on the flat test map is complete. The next visual step
from abstract zones to finite resource nodes on the current flat test map. This is a deliberately minimal `JajceWorld` scaffold, greybox, navigation spike, and
keeps target-selection and resource-conservation debugging separate from terrain resource-placement proof. Do not proceed directly from that proof into
and navigation changes. open-ended beauty production.
The next coherent visual slice should then aim for: After the scaffold proves terrain and navigation, complete the architecture
gate:
- deterministic clock and controlled random source;
- fixed-seed headless scenarios with final-state checksums;
- 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;
- explicit synchronization of active NPC position.
The coherent visual slice can then aim for:
- one attractive valley section; - one attractive valley section;
- six named villagers; - six named villagers;
@@ -713,6 +749,8 @@ These remain part of the vision, not the next implementation target.
11. Use Conventional Commits. 11. Use Conventional Commits.
12. Update these documents when a decision materially changes the vision, 12. Update these documents when a decision materially changes the vision,
architecture, milestones, or current-state description. architecture, milestones, or current-state description.
13. Follow the authority order in [the documentation map](README.md); do not
let a focused visual or migration plan silently redefine system ownership.
## Definition of “reusable for the future game” ## Definition of “reusable for the future game”
+30
View File
@@ -0,0 +1,30 @@
# Documentation map
The project uses a small hierarchy so overlapping plans do not become competing
sources of truth.
1. [`PROJECT_CONTEXT.md`](PROJECT_CONTEXT.md) is the canonical description of
the vision, current implementation, target architecture, and active
constraints.
2. [`LEARNING_ROADMAP.md`](LEARNING_ROADMAP.md) owns milestone order,
architecture gates, reusable-system exit tests, and intentionally deferred
work.
3. [`BUILD_IN_PUBLIC_PLAN.md`](BUILD_IN_PUBLIC_PLAN.md) owns the scoped Jajce
visual slice. It must respect the architecture gates in the learning
roadmap.
4. [`RESOURCE_NODE_MIGRATION.md`](RESOURCE_NODE_MIGRATION.md) is a focused
migration plan. Phases 14 are complete; its Phase 5 hands world placement to
the visual-slice plan.
5. [`decisions/`](decisions/) contains durable architectural decisions,
including consequences and revisit conditions.
When documents disagree:
- code and tests describe current behavior;
- the newest accepted decision record governs architecture;
- `PROJECT_CONTEXT.md` governs product intent;
- `LEARNING_ROADMAP.md` governs what should be built next;
- focused plans govern only their stated scope.
Update the smallest relevant set of documents after a decision or milestone.
Do not copy full status tables into every plan.
+14 -7
View File
@@ -112,7 +112,7 @@ type proves what is actually common.
## Fit with the current code ## Fit with the current code
The existing flow is: Before this migration, the flow was:
```text ```text
SimNPC chooses a task string SimNPC chooses a task string
@@ -124,7 +124,7 @@ SimNPC chooses a task string
-> SimVillage applies a hard-coded task result -> SimVillage applies a hard-coded task result
``` ```
The migrated flow should become: The migrated flow is:
```text ```text
SimNPC chooses an action SimNPC chooses an action
@@ -139,15 +139,16 @@ SimNPC chooses an action
-> reservation is released -> reservation is released
``` ```
During migration: Current target behavior:
```text ```text
gather_food -> prefer matching ResourceNode -> fallback FarmZone gather_food -> matching ResourceNode -> recover/wander when unavailable
gather_wood -> prefer matching ResourceNode -> fallback ForestZone gather_wood -> matching ResourceNode -> recover/wander when unavailable
other tasks -> existing zones other tasks -> existing zones
``` ```
Fallbacks should log clearly so accidental reliance on zones is visible. Food and wood zone fallback was deliberately removed to preserve resource
conservation.
## Repository-specific file layout ## Repository-specific file layout
@@ -472,6 +473,12 @@ authoritative-yield rules.
### Phase 5 — Jajce world placement ### Phase 5 — Jajce world placement
This phase is a bounded handoff to
[the build-in-public visual plan](BUILD_IN_PUBLIC_PLAN.md), not permission for
open-ended environment polish. Complete the scaffold, placement, and navigation
proof, then pass the learning roadmap's architecture gate before the beauty
baseline.
- place bushes and trees as real world objects in `JajceWorld`; - place bushes and trees as real world objects in `JajceWorld`;
- keep their IDs stable; - keep their IDs stable;
- validate interaction points against terrain and navigation; - validate interaction points against terrain and navigation;
@@ -516,7 +523,7 @@ At minimum, exercise:
7. NPC dies while working; 7. NPC dies while working;
8. navigation fails; 8. navigation fails;
9. node is disabled while reserved; 9. node is disabled while reserved;
10. fallback zone is used because no matching node exists; 10. no matching node causes recovery without zone production; ✅ implemented
11. player and NPC contend for the same source; ✅ automated 11. player and NPC contend for the same source; ✅ automated
12. duplicate node IDs are detected. 12. duplicate node IDs are detected.
@@ -0,0 +1,73 @@
# ADR 0001: Serializable simulation state is authoritative
- **Status:** Accepted
- **Date:** 2026-07-04
## Context
The prototype correctly separates `SimNPC` from `NpcVisual`, but authority is
still split across simulation records and scene nodes:
- `ResourceNode` owns remaining amount and reservations;
- `WorldViewManager` resolves targets and writes the chosen target ID onto an
NPC;
- `SimulationManager` combines time, orchestration, action completion, player
commands, and event publication;
- the visual position of an active NPC can diverge from its stored simulation
position.
This is workable for one loaded flat map. It does not support reliable
save/load, unloaded locations, deterministic replay, simulation fidelity
changes, or a large data-only population.
## Decision
Persistent mutable gameplay state will move into versioned, serializable
records owned by a `WorldState`-style simulation model.
- Definitions contain immutable action, profession, need, item, and location
data.
- State records contain people, resources, inventories, reservations,
locations, current actions, and later relationships and history.
- Systems are the only layer that authoritatively mutates those records.
- Godot world nodes present records and provide active-world facts such as
interaction transforms, navigation results, collision, and animation.
- Presentation adapters may submit commands and query results, but may not
choose actions or directly author persistent state.
- References between records use stable IDs, never `Node`, `NodePath`, or scene
ownership.
- Active-world position must synchronize through an explicit adapter so
unloading a visual does not erase or redefine the NPC's location.
The simulation core must be runnable headlessly with a fixed clock, controlled
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.
4. Move target choice and reservation coordination out of
`WorldViewManager` into an action/target system with an active-world query
adapter.
5. Split action selection, execution, and presentation travel.
6. Add versioned save/load before inventories, schedules, or relationships
substantially expand mutable state.
## Consequences
- Some current prototype APIs are transitional and should not be generalized
as final architecture.
- The Jajce scaffold may proceed far enough to validate terrain, navigation,
and world-object placement, but beauty production pauses at the architecture
gate.
- New persistent features must define their state record and save behavior.
- Headless scenarios become the preferred regression surface for simulation
rules.
## Revisit when
Revisit this decision only if measured prototype work shows that a different
authority model materially simplifies deterministic persistence and simulation
LOD without coupling rules to loaded scenes.
+12
View File
@@ -0,0 +1,12 @@
# Architecture decisions
Decision records capture choices that should survive individual implementation
plans. Use the next sequential number and include:
- context and problem;
- decision;
- consequences;
- staged migration, if needed;
- conditions for revisiting the decision.
Do not create records for routine edits or choices that are still exploratory.