diff --git a/docs/ECONOMIC_EVENTS.md b/docs/ECONOMIC_EVENTS.md new file mode 100644 index 0000000..8a6f888 --- /dev/null +++ b/docs/ECONOMIC_EVENTS.md @@ -0,0 +1,53 @@ +# The Steward — Economic Event Stream + +## Current contract + +Every successful food movement creates one `EconomicEventRecord`: + +```text +resource_extracted +storage_deposited +storage_withdrawn +item_consumed +``` + +Each record contains a monotonically increasing event ID, event type, +simulation tick, actor ID, source ID, destination ID, item ID, and transferred +amount. Actor `-1` identifies a player-triggered extraction until persistent +player identity is introduced. + +Events are immutable facts about completed transfers. They do not perform the +transaction and are not replayed to reconstruct current state. Resource, +inventory, and storage records remain authoritative. + +## Persistence and determinism + +`SimulationStateRecord` schema v3 stores the ordered event stream and +`next_event_id`. Schema v1 and v2 saves migrate to an empty stream beginning at +ID zero. Parsing rejects duplicate event IDs and a next ID that could collide +with restored history. + +The food-loop regression verifies this chain: + +```text +bush -> NPC inventory -> village pantry -> NPC inventory -> consumed +``` + +It checks event order, stable IDs, exact quantities, conservation, and +save/restore continuity. + +## Presentation + +`npc_inventory_changed` is a transient presentation signal. The active +`NpcVisual` shows a small food sack whenever its authoritative inventory +contains food. A newly loaded visual derives the same state directly from the +NPC record, so unloading presentation does not lose the fact. + +## Deliberate limits + +The stream is currently kept in full for the small simulation garden. Before +large populations or long-running worlds, add measured retention, +archival/summary rules, and query indexes. Denied attempts, depletion, +witnesses, secrecy, causal links, and memories belong in later event/history +slices; they should extend this record family without making prose +authoritative. diff --git a/docs/FOOD_STORAGE_ARCHITECTURE.md b/docs/FOOD_STORAGE_ARCHITECTURE.md index d66511f..63d8618 100644 --- a/docs/FOOD_STORAGE_ARCHITECTURE.md +++ b/docs/FOOD_STORAGE_ARCHITECTURE.md @@ -30,6 +30,11 @@ world only when consumed. The village pantry has stable ID `village_pantry`. Storage and NPC inventory are included in versioned state and deterministic checksums. +Successful extraction, deposit, withdrawal, and consumption also append +structured economic facts. See [the economic event stream](ECONOMIC_EVENTS.md). +Active NPCs display a small food sack while their authoritative inventory +contains food; this is presentation derived from state, not a second inventory. + ## Failure behavior Transactions apply the amount actually available: @@ -46,13 +51,14 @@ replans on its next idle tick. This slice contains one pantry and one carried item type. It does not yet add: -- visible carried props; - player inventory; - storage reservations or access capacity; - multiple households or ownership; - spoilage, item quality, weight, or stack definitions; -- structured transaction/history events; - an authored StorageNode scene beyond the current pantry marker. +Economic transfer events exist, but event retention, denial/depletion facts, +witnesses, and social interpretation are deliberately deferred. + Those should extend the transaction boundary rather than mutate counters directly. diff --git a/docs/LEARNING_ROADMAP.md b/docs/LEARNING_ROADMAP.md index 70aef51..8c76f6e 100644 --- a/docs/LEARNING_ROADMAP.md +++ b/docs/LEARNING_ROADMAP.md @@ -637,17 +637,20 @@ Completed after the architecture gate: - location-based pantry state, NPC-carried food, and explicit deposit/withdraw/consume transactions; -- a headless conservation scenario covering the complete food loop. +- a headless conservation scenario covering the complete food loop; +- deterministic structured economic events for extraction, deposit, + withdrawal, and consumption; +- persisted event identity/history and a visible carried-food prop derived + from NPC inventory. The practical next sequence is: -1. Emit structured economic events while making one NPC visibly gather, carry, - store, retrieve, and eat food. -2. Add save-slot persistence and explicit schema migrations before schedules +1. Add save-slot persistence, validation, and explicit migration fixtures + before schedules or social state expand. -3. Resume Terrain3D sculpting, runtime integration, and the simulation-garden +2. Resume Terrain3D sculpting, runtime integration, and the simulation-garden beauty pass. -4. Add stylized character and profession readability plus the reason +3. 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 4a3ff65..8e4eafc 100644 --- a/docs/PROJECT_CONTEXT.md +++ b/docs/PROJECT_CONTEXT.md @@ -737,11 +737,12 @@ architecture gate are complete: - authoritative active position and persisted travel destinations; - checksum-invariant NPC visual unload/reload with reservation preservation. -The location-based food loop is now complete at simulation level: gathering -creates carried food, depositing fills the pantry, withdrawal retrieves one -unit, and eating consumes it. The next systems milestone is structured -transaction events and visible carrying/readability. Bounded Terrain3D -look-development can resume alongside that presentation work. +The location-based food loop is complete and traceable: gathering creates +carried food, depositing fills the pantry, withdrawal retrieves one unit, and +eating consumes it. Each successful transfer creates a persisted structured +event, and active NPCs visibly carry food through presentation derived from +their inventory. The next systems milestone is save-slot persistence and +validation. Bounded Terrain3D look-development can resume alongside it. The coherent visual slice can then aim for: diff --git a/docs/README.md b/docs/README.md index f4d5609..75ac985 100644 --- a/docs/README.md +++ b/docs/README.md @@ -16,6 +16,7 @@ sources of truth. migration plan. Phases 1–4 are complete; its Phase 5 hands world placement to the visual-slice plan. 5. [`ACTION_SYSTEM_ARCHITECTURE.md`](ACTION_SYSTEM_ARCHITECTURE.md), + [`ECONOMIC_EVENTS.md`](ECONOMIC_EVENTS.md), [`FOOD_STORAGE_ARCHITECTURE.md`](FOOD_STORAGE_ARCHITECTURE.md), [`SIMULATION_DEFINITIONS.md`](SIMULATION_DEFINITIONS.md), and [`SIMULATION_STATE_SCHEMA.md`](SIMULATION_STATE_SCHEMA.md) document the diff --git a/docs/RESOURCE_NODE_MIGRATION.md b/docs/RESOURCE_NODE_MIGRATION.md index 4b02c7e..c5092d8 100644 --- a/docs/RESOURCE_NODE_MIGRATION.md +++ b/docs/RESOURCE_NODE_MIGRATION.md @@ -529,7 +529,9 @@ complete. The former `FoodZone` is now `PantryMarker` backed by simulation-owned `StorageStateRecord` state and explicit deposit/withdraw transactions. A -dedicated authored StorageNode presentation is still pending. +dedicated authored StorageNode presentation is still pending. Successful food +transfers now emit serializable economic events, and an active NPC visibly +carries food between source, pantry, and consumption. **Exit:** temporary activity markers and task-to-marker mapping are deleted, not merely unused. diff --git a/docs/SIMULATION_STATE_SCHEMA.md b/docs/SIMULATION_STATE_SCHEMA.md index 1096838..8725308 100644 --- a/docs/SIMULATION_STATE_SCHEMA.md +++ b/docs/SIMULATION_STATE_SCHEMA.md @@ -3,7 +3,7 @@ ## Current contract `SimulationStateRecord` is the versioned JSON boundary for the current -simulation. Schema v1 captures: +simulation. The current world schema is v3 and captures: - simulation seed, tick interval, tick count, clock remainder, and elapsed clock ticks; @@ -13,13 +13,15 @@ simulation. Schema v1 captures: - controlled per-NPC wander RNG streams; - scene-independent resource state plus the definition facts needed while its ResourceNode is unloaded. +- pantry contents, carried NPC inventory, the ordered economic event stream, + and its next stable event ID. The top-level identity is: ```json { "schema": "the_steward.simulation", - "schema_version": 1 + "schema_version": 3 } ``` @@ -62,6 +64,12 @@ StorageStateRecord entries; world-schema v1 migrates legacy village food into the stable `village_pantry` record. Parsed storage values are canonicalized so save/restore continuation retains byte-stable checksums. +SimulationStateRecord v3 adds ordered `EconomicEventRecord` entries and +`next_event_id`. World schemas v1 and v2 migrate explicitly to an empty event +stream. Event records use stable source/destination/item IDs, reject invalid or +duplicate IDs, and preserve deterministic ordering across save/restore. See +[the economic event stream](ECONOMIC_EVENTS.md). + ## Resource authority `SimulationManager` owns `ResourceStateRecord` instances independently of the @@ -84,8 +92,8 @@ definition from a matching presentation node when one becomes available. 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; +- migrations older than the explicitly supported world schemas v1 and v2; +- player inventory, relationship, schedule, or social-memory records; - a player-facing load flow; - save-slot persistence for scene-independent resource state.