- Add 3 Terrain3D texture assets (limestone, valley grass, warm soil)
- Sculpt initial Terrain3D heightmap with ridge, valley, waterfall drop
- Replace plain water with emissive-tinged material
- Add foam mesh, mist spheres, and procedural sky with valley fog
- Add 10 StylizedTree instances around village perimeter
- Enable directional light shadows with extended cascade range
- Add tree height snapping to terrain surface
- Add refined scaffold tests for material count, terrain height, foliage, sky, fog
- Add terrain texture PNGs and StylizedTree.tscn scene
- Add generate_jajce_terrain.gd tool
- Update ACTION_SYSTEM_ARCHITECTURE.md to describe the active-position
contract and visual lifecycle proof
- Mark BUILD_IN_PUBLIC_PLAN.md systems-gate section complete
- Mark LEARNING_ROADMAP.md architecture-gate section complete and
renumber post-gate implementation sequence
- Update PROJECT_CONTEXT.md immediate-milestone section to reflect
completed gate and next food-loop milestone
- Update SIMULATION_STATE_SCHEMA.md with NPCStateRecord v2 details
- Update ADR 0001 checklist to mark active-position sync done
- NpcVisual emits position_changed signal during _physics_process
- SimulationManager.synchronize_npc_position() writes active position
into SimNPC state on movement, arrival, and navigation failure
- WorldViewManager forwards position_changed and syncs before
despawn/reload
- SimNPC stores travel_target_position and has_travel_target as
versioned state; NPCStateRecord v2 persists them with v1 migration
- WorldViewManager.spawn_npc_visual() resumes travel for traveling NPCs
via SimulationManager.request_current_travel()
- WorldViewManager.despawn_npc_visual() syncs position before removal
- WorldViewManager.reload_npc_visual() spawns a visual from persisted
state without rerolling target selection
- tests/npc_visual_lifecycle_test.gd proves unload/reload preserves
action, target, reservation, position, RNG state, and checksum
- simulation_state_serialization_test adds legacy v1 NPC migration test
that does not invent an active travel target
BUILD_IN_PUBLIC_PLAN.md:
- Mark systems gate items deterministic clock and headless checksum
as complete; remaining gate work stays flagged as in-progress
- Rename TaskZone references to ActivityMarkers for consistency
LEARNING_ROADMAP.md:
- Add architecture gate progress note: first deterministic slice
(SimulationClock, seeded streams, headless checksum) is implemented
- Update recommended implementation order to reflect shifted priorities
PROJECT_CONTEXT.md:
- Note that farm and forest markers have been deleted from main.tscn
- Update activity marker description (4 remaining: guard/study/rest/food)
- Add SimulationClock.gd and deterministic_simulation_test.gd to repo map
- Update technical debt: randomness is now seeded but RNG state is not
yet serialized; clock is explicit but orchestration still lives on scene tree
- Gate status updated with completed first-slice summary
RESOURCE_NODE_MIGRATION.md:
- Mark Phase 4b (player parity) complete
- Phase 6 renamed from 'remove zone model' to 'replace activity markers'
with progress note: TaskZone container and FarmZone/ForestZone deleted
- Update divergences to note farm/forest scene nodes have been removed
Replace implicit randomness with seeded per-NPC RandomNumberGenerator
streams so the same seed always produces the same scenario outcome.
- Add SimulationClock (RefCounted): explicit fixed-step clock that
converts frame delta into simulation ticks while preserving sub-tick
remainder; replaces raw _process tick_timer accumulation
- Add simulation_seed export (int=1337) to SimulationManager; drive
per-NPC RNG streams via seed + npc_id + stream_id derivation
(stream 0=init, stream 1=wander)
- Add get_wander_offset(npc_id) to SimulationManager so wander targets
are deterministic per seed; WorldViewManager calls it instead of
local randf_range()
- Add get_state_snapshot() and get_state_checksum() to SimulationManager
for headless verification and future save/load
- Convert SimNPC/SimVillage const DEBUG_LOGS to instance var debug_logs
so headless tests can silence output without recompilation
- Pass RandomNumberGenerator through SimNPC._init() instead of using
global randf_range() for hunger/energy/position/scoring noise
- Remove obsolete farm_zone and forest_zone exports from
WorldViewManager and their marker/tree scene children from main.tscn;
NPC gather tasks use ResourceNode exclusively
- Rename TaskZone container to ActivityMarkers in main.tscn and update
all scene paths (player, WVM, tests) to match
- Add headless deterministic_simulation_test.gd: verifies clock
accuracy, same-seed equality, different-seed divergence, and
24-tick scenario checksum without loading main.tscn
RESOURCE_NODE_MIGRATION.md:
- Add progress overview table with per-phase completion status
- Document key divergences from original plan (zone fallback removal,
navigation_failed signal, stale-path prevention, duplicate detection)
- Add bug log table (11 bugs found and fixed during implementation)
- Mark completed phases 1-3 with checkmarks
- Split phase 4 into 4a (wood, done) and 4b (player parity, not started)
- Replace flat implementation order with checkable table
- Update definition-of-done with per-criterion status
PROJECT_CONTEXT.md:
- Advance snapshot commit reference from e30d208 to b8752f8
- Note that gather_food/gather_wood now use ResourceNode instances
- Explain zone marker status (player use only, NPCs use nodes)
- Update runtime flow diagram with navigation_failed pathway
- Add resource_nodes/ to repository map
- Update technical debt entries to reflect current state
NpcVisual:
- Add navigation_failed(sim_id) signal distinct from arrived_at_target
so the simulation layer can distinguish genuine arrival from failure
- Replace integer stuck_counter with delta-based stuck_time and
exported stuck_timeout (1.5s) for frame-rate-independent detection
- Add path_request_id / path_pending mechanism to reject stale
async path results when a new target is set or NPC dies
- On empty path or stuck movement, emit navigation_failed instead
of arriving; only emit arrived_at_target when truly close to target
- Reduce arrival_distance back to 0.6 now that navigation_failure
is properly signalled (no longer needed as a workaround)
- clamp arrival_distance reference in apply_dead_visual_state
SimNPC:
- Remove retry_count (replaced by navigation_failed signal pathway)
- Move last_task assignment from set_task() to task completion in
SimulationManager so it reflects the task that actually finished
SimulationManager:
- Add notify_npc_navigation_failed(): release reservation, record
last_task, send NPC to wander for 2s, emit task_changed signal
- Add notify_npc_target_unavailable() as public alias of above
- Guard extraction with node.reserved_by == npc.id to prevent
stale/illegitimate extraction when reservation is lost
- Guard fallback zone task completion (apply_npc_task) so it only
fires for non-resource tasks (gather_food/wood with no target
silently skip instead of applying zone values)
- Remove retry_count safety net (fully replaced by signal pipeline)
WorldViewManager:
- Connect navigation_failed signal in spawn_npc_visual()
- Skip target assignment for empty/idle/dead task states
- When no resource node available for gather_food/wood, call
notify_npc_target_unavailable() so NPC wanders instead of idling
- Add _on_npc_visual_navigation_failed handler delegating to
SimulationManager.notify_npc_navigation_failed()
- Remove retry_count references
- Push error and disable node when duplicate node_id is registered
to prevent silent conflict during find_available()
- Use interaction_point.global_position instead of self.global_position
in find_available() so distance is measured to the marker NPCs
actually navigate toward
Phase 3 of ResourceNode migration:
- Add apply_resource_delta to SimVillage for clean resource changes
- Extract from reserved ResourceNode on task completion instead of
hard-coded apply_npc_task for gather_food/gather_wood
- Detect depleted/unavailable targets on arrival and replan
Phase 1-2 of the ResourceNode migration plan:
- Create ResourceNode class (world/resource_nodes/) with extraction,
reservation, nearest-available selection, and debug label
- Place 4 resource instances in main.tscn (2 berry bushes, 2 trees)
- Add target_id to SimNPC for tracking which node an NPC is using
- Add set_npc_target_id and release_npc_reservation to SimulationManager
with cleanup on task change, completion, and death
- Update WorldViewManager to query available ResourceNodes first,
falling back to zone markers with a logged warning