feat: add bounded npc memory retention

This commit is contained in:
Rijad Zuzo
2026-07-12 01:10:10 +02:00
parent 9a479ba182
commit 99b8146f75
17 changed files with 945 additions and 126 deletions
+7 -1
View File
@@ -76,7 +76,9 @@ events into `RelationshipSystem`. When an NPC arrives beside a worker at the
same non-storage activity site, the manager may transfer one direct known fact
and applies its consequence only to that newly informed listener. It exposes
knowledge, provenance, relationship, and cause queries without moving social
authority into UI.
authority into UI. After consequences are known, it protects current causal
facts, enforces the recent-memory cap, and runs age review from authoritative
simulation ticks.
### VillageEconomy
@@ -101,6 +103,10 @@ authority into UI.
legacy, with a stable source NPC ID for direct communication;
- permits one performed/witnessed fact to cross one co-located social hop, but
does not relay communicated or ambiguous legacy facts;
- orders communication by lasting relationship relevance, then acquisition
recency;
- retains current relationship causes and at most three other recent facts per
NPC, expiring day-old recent facts at deterministic review boundaries;
- captures evidence only when the event happens, never from current positions
during restore;
- answers deterministic known-event and knower queries without formatting
+3 -2
View File
@@ -15,7 +15,7 @@ SimulationClock
-> ActionTargetResolver resolves a stable target ID
-> VillageEconomy performs inventory/storage transactions
-> SimulationEventLog records completed facts
-> EventKnowledgeSystem records actor/nearby knowledge and bounded transfers
-> EventKnowledgeSystem records, ranks, transfers, and retains bounded knowledge
-> RelationshipSystem applies evidence-gated social consequences
-> WorldViewManager presents travel and NPC state
-> ActiveWorldAdapter supplies loaded-world positions/capacity
@@ -34,7 +34,8 @@ would otherwise obscure that lifecycle:
history queries, and rate calculations;
- `simulation/knowledge/EventKnowledgeSystem.gd` owns per-NPC references to
known objective events, immutable acquisition provenance, proximity witnesses
at record time, and one-hop direct fact transfer;
at record time, one-hop direct fact transfer, and deterministic recent-fact
retention;
- `simulation/relationships/RelationshipSystem.gd` owns directed relationship
queries, event-driven trust changes, and deterministic social tie-breaking;
- `simulation/persistence/` owns save-slot file safety;
+7 -2
View File
@@ -695,11 +695,16 @@ Completed:
can hear one direct fact from a nearby worker at the same non-storage
activity; the inspector names the speaker, the original event is not
replayed, and heard facts do not cascade yet.
23. Bounded memory retention: acquisition time now drives fact recency; current
relationship causes remain lasting while each NPC keeps only three other
recent facts. A deterministic daily-sized review fades old routine facts,
conversations prefer lasting evidence, and the inspector shows both memory
counts and the displayed fact's retention class.
Next:
1. Add bounded importance/retention rules for known facts, as sequenced in
`LEARNING_ROADMAP.md`.
1. Add a compact retained-memory/person-history view and one visible social
reaction cue, as sequenced in `LEARNING_ROADMAP.md`.
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
+21 -10
View File
@@ -37,7 +37,7 @@ transfer occurred.
## Persistence and determinism
`SimulationStateRecord` schema v6 stores the ordered event stream,
`SimulationStateRecord` schema v7 stores the ordered event stream,
`next_event_id`, directed relationships that may reference an exact event, and
per-NPC known-event references with first-acquisition provenance. Schema v1 and
v2 saves migrate to an empty stream beginning at ID zero. Parsing rejects
@@ -63,6 +63,15 @@ performed/witnessed facts can cross this one social hop, so this is not yet a
rumour cascade. Relationship appraisal uses the listener's state when the fact
is acquired, not a reconstruction of their needs when the old event occurred.
Known facts are now bounded without deleting objective history. A fact is
lasting while it remains that NPC's current trust cause; other facts are recent.
An NPC keeps at most three recent facts, and a deterministic review once per
simulated-day-sized interval removes recent facts at least one day old. Current
causes remain so `Relationship` and `Because` never point at forgotten
evidence. Conversations prefer lasting direct facts, then the most recently
acquired direct fact. Communicated provenance snapshots how the speaker knew
the event, so a listener's memory stays valid after the speaker forgets.
The food-loop regression verifies this chain:
```text
@@ -78,15 +87,17 @@ save/restore continuity.
`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.
The selected-NPC inspector shows lasting/recent counts and labels the displayed
fact with both acquisition provenance and retention class.
## 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. Proximity is the only current direct
witness rule, and communication is intentionally one-hop and tied to shared
activity arrival. Line of sight, hearing, acquisition timestamps, multi-hop
rumours, secrecy, false beliefs, multi-event causal graphs, and memory
retention belong in later event/history slices. They should extend this record
family without making prose authoritative or recomputing old evidence from
current positions.
The objective stream is currently kept in full for the small simulation
garden; only per-NPC known references are bounded. Before large populations or
long-running worlds, add measured archival/summary rules and query indexes.
Proximity is the only current direct witness rule, and communication is
intentionally one-hop and tied to shared activity arrival. Line of sight,
hearing, personalized reinforcement/decay, multi-hop rumours, secrecy, false
beliefs, and multi-event causal graphs belong in later event/history slices.
They should extend this record family without making prose authoritative or
recomputing old evidence from current positions.
+18 -3
View File
@@ -684,10 +684,25 @@ The first communicated-knowledge slice is complete:
malformed-provenance rejection, event-history invariance, save/checksum, and
informed-choice regressions cover the complete slice.
The first importance/retention slice is complete:
- acquisition ticks order facts by when an NPC learned them rather than by the
objective event ID;
- a current relationship cause is lasting, while each NPC keeps at most three
other recent facts;
- a deterministic daily-sized review forgets recent facts at least one day old
without deleting objective event history or rolling back trust;
- communication prefers lasting direct evidence, and a source-method snapshot
keeps listener provenance valid after the teller forgets;
- the inspector shows lasting/recent counts, while schema-v7 migration,
boundary, capacity, cause-protection, save/checksum, and informed-choice
regressions cover the slice.
This advances the first Milestone 6 evidence-to-choice path without claiming
full memory or belief simulation. The practical next slice is importance and
retention for known facts before expanding into distortion, secrecy, rumours,
or opportunity generation.
full belief simulation. The practical next sequence is a compact retained
memory/person-history view and a visible social-reaction cue, then one bounded
Milestone 7 rumour/opportunity proof without generalized distortion or
free-form dialogue.
Recently completed:
+16 -10
View File
@@ -415,8 +415,8 @@ Focused `RefCounted` collaborators keep rule ownership visible:
village resource views;
- `SimulationEventLog` owns deterministic event history and queries;
- `EventKnowledgeSystem` owns per-NPC known-event references, immutable
first-acquisition provenance, actor/nearby evidence capture, and bounded
one-hop communication;
first-acquisition time/provenance, actor/nearby evidence capture, bounded
one-hop communication, and deterministic recent-memory retention;
- `RelationshipSystem` owns directed relationship state, event-driven trust
consequences, and deterministic social queries.
@@ -523,7 +523,7 @@ NpcVisual navigates through the active world
│ ├── definitions/ Stable IDs and custom definition resources
│ ├── economy/ Inventory and storage transactions
│ ├── events/ Ordered event history and queries
│ ├── knowledge/ Per-NPC facts, provenance, and bounded transfer
│ ├── knowledge/ Per-NPC facts, provenance, transfer, and retention
│ ├── persistence/ Validated local save-slot storage
│ ├── relationships/ Directed social consequences and queries
│ └── state/ Versioned simulation-state records
@@ -533,6 +533,7 @@ NpcVisual navigates through the active world
│ ├── deterministic_simulation_test.gd
│ ├── food_storage_loop_test.gd
│ ├── jajce_world_scaffold_test.gd
│ ├── knowledge_retention_consequence_test.gd
│ ├── jajce_runtime_integration_test.gd
│ ├── npc_visual_lifecycle_test.gd
│ ├── relationship_consequence_test.gd
@@ -571,7 +572,7 @@ These are expected prototype constraints, not necessarily isolated bugs:
gathering use `ResourceNode` instances with no fallback, food transfer uses
the typed pantry `StorageNode`, and patrol/study/rest use `ActivitySite`.
- Current NPC, village, resource, storage, event, knowledge, relationship,
clock, and RNG state serialize through world schema v6. F5/F9 provide one
clock, and RNG state serialize through world schema v7. F5/F9 provide one
validated local quicksave; a save menu, metadata, and player-transform
persistence remain deferred.
- Simulation-owned resource records retain live amounts, reservations, and
@@ -586,12 +587,14 @@ These are expected prototype constraints, not necessarily isolated bugs:
located items.
- NPCs have home positions, schedule periods, carried food/wood, and directed
familiarity/trust. They retain direct or one-hop communicated knowledge of a
food deposit with first-acquisition provenance, but do not yet have wider
social dimensions, goals, line-of-sight/hearing evidence, importance/decay,
false beliefs, or multi-hop rumours.
food deposit with first-acquisition provenance. Current trust causes are
lasting; other knowledge is capped and reviewed after one simulated day.
NPCs do not yet have wider social dimensions, goals, line-of-sight/hearing
evidence, personalized reinforcement/decay, false beliefs, or multi-hop
rumours.
- The reason inspector exposes current decisions, utility rejections, one exact
relationship cause, and the latest known fact with its speaker when
communicated, but deeper historical decision traces are not yet retained.
relationship cause, memory counts, and the latest known fact with its speaker
and retention class, but a broader person-history view is not yet present.
- Active navigation is used as if all agents are local; no simulation LOD exists.
- Unloaded traveling NPCs preserve their state but do not yet advance through
abstract travel time.
@@ -836,7 +839,10 @@ shared non-storage activity, an already-working direct knower can tell one fact
to an arriving nearby villager. The same event remains visible as known fact
and relationship cause, the inspector names the speaker, and the listener's
future work can change without duplicating event history. Importance and
retention for known facts is the next systems slice.
retention now keep current relationship causes lasting, cap other memories,
and forget routine facts at deterministic daily-sized reviews without deleting
the objective event. A compact retained-memory/person-history view and visible
social-reaction cue are the next systems slice.
The remaining simulation-garden target still aims for:
+33 -11
View File
@@ -3,7 +3,7 @@
## Current contract
`SimulationStateRecord` is the versioned JSON boundary for the current
simulation. The current world schema is v6 and captures:
simulation. The current world schema is v7 and captures:
- simulation seed, tick interval, tick count, clock remainder, and elapsed
clock ticks;
@@ -18,14 +18,15 @@ simulation. The current world schema is v6 and captures:
- directed relationship records with familiarity, trust, and the stable event
ID that last changed trust;
- per-NPC known-event records that reference objective event history without
copying it, including first-acquisition method and communicator provenance.
copying it, including first-acquisition method, acquisition tick, and
historical communicator provenance.
The top-level identity is:
```json
{
"schema": "the_steward.simulation",
"schema_version": 6
"schema_version": 7
}
```
@@ -57,7 +58,7 @@ its future random sequence.
It also verifies clock remainder, resource amount/reservation/enabled
round-tripping, presentation unload/rebind, directed relationship/cause
round-tripping, divergent known-event state, communicated provenance, and
rejection of unsupported schemas.
deterministic retention boundaries, and rejection of unsupported schemas.
NPCStateRecord v2 adds the resolved travel destination and whether it is
active. Nested v1 NPC records migrate explicitly with no invented active
@@ -120,10 +121,31 @@ event.
World schema v5 migrates actor-owned knowledge to `performed`; non-actor
knowledge becomes `legacy` because v5 may contain either a proximity witness or
an older implied relationship fact. Parsing never invents that missing
provenance. Current communicated records require a distinct existing source
who knows the same event through `performed` or `witnessed` acquisition. This
enforces the current one-hop boundary and makes validation independent of array
ordering.
provenance. At runtime, communication requires a distinct source who currently
knows the event through `performed` or `witnessed` acquisition. Persisted
records validate that direct-method snapshot even after the source forgets.
This enforces the current one-hop boundary and makes validation independent of
array ordering.
SimulationStateRecord v7 / KnownEventStateRecord v3 adds `acquired_tick` and a
snapshot of the direct speaker's acquisition method. Direct facts use the
objective event tick; newly communicated facts use the conversation tick. The
speaker snapshot keeps historical provenance valid even if the speaker later
forgets their own copy, while runtime communication still requires a currently
known performed/witnessed fact and remains one-hop.
World schema v6 migrates direct acquisition to the objective event tick.
Communicated and ambiguous legacy facts receive a fresh retention lease at the
saved simulation tick because their exact acquisition time was not previously
stored. The v6 source record supplies the persisted direct-method snapshot.
Importance is intentionally derived rather than duplicated: a fact is
`lasting` while it is the current trust cause for one of that knower's directed
relationships; every other fact is `recent`. Current causal facts are protected
so relationship state remains explainable. Each NPC keeps at most three recent
facts, and recent facts at least one simulated day old are removed at the next
deterministic daily-sized review. The objective event stream is never pruned by
this rule.
## Resource authority
@@ -161,11 +183,11 @@ This phase does not yet provide:
- a save-slot menu, metadata, thumbnails, autosaves, or multiple profiles;
- migrations from any historical world schema other than the explicitly
supported v1v5 layouts;
supported v1v6 layouts;
- player inventory or player relationship records;
- broader relationship dimensions, line-of-sight/hearing evidence,
acquisition timestamps, importance/retention, memory decay, or multi-hop
rumours;
continuous or personalized memory decay, reinforcement, false beliefs, or
multi-hop rumours;
- persistence for the player transform or presentation-only scene state.
Those features should build on this boundary rather than inventing parallel