docs: add current developer feature index
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# Feature slice: saves, schema, migrations, and continuation
|
||||
|
||||
The local playable world and the regional proof use different persistence
|
||||
boundaries. Both are primitive-only, versioned, deterministic, and validated
|
||||
before mutation.
|
||||
|
||||
## Local save boundary
|
||||
|
||||
`SimulationStateRecord` is currently schema **v16**. It contains the local
|
||||
simulation seed/clock scope, village/NPC/animal/resource/storage/player/
|
||||
combatant/faction records, ordered economic events, relationships, knowledge,
|
||||
legacy opportunities, situations, journal entries, commitments, and bounded
|
||||
semantic conversation acts. `SimulationManager.create_state_record()` creates
|
||||
it; `serialize_state()` emits canonical JSON; `restore_state()` preflights and
|
||||
then atomically restores dependent systems.
|
||||
|
||||
Top-level v16 adds non-empty `world_id` and `location_id`. Activity success and
|
||||
blocked facts carry the same scope. A save recorded under another active adapter
|
||||
is rejected before clock, economy, NPC, or event state is mutated. This closes
|
||||
the context-reinterpretation hole where equal local coordinates could be
|
||||
treated as the same world.
|
||||
|
||||
The record stores IDs, primitive values, event IDs, and semantic topic IDs. It
|
||||
never stores scripts, nodes, `NodePath`s, callables, imported assets, dialogue
|
||||
prose, or transient HUD/balloon state.
|
||||
|
||||
## Migration policy
|
||||
|
||||
Nested records migrate at their own version; the top-level schema accepts an
|
||||
explicit historical range and normalizes old fields before cross-record
|
||||
validation. Current supported migrations include:
|
||||
|
||||
- legacy village/storage and event streams;
|
||||
- directed relationships and causal knowledge provenance;
|
||||
- opportunity history and its v2 lifecycle;
|
||||
- animal routine/definition IDs;
|
||||
- player citizen needs/health;
|
||||
- combatants, factions, and enemy definition IDs;
|
||||
- situations, journal entries, commitments, and conversation acts;
|
||||
- world/location scope v16;
|
||||
- explicitly marked legacy unstructured `task_blocked` facts.
|
||||
|
||||
Old definition values are not snapshotted. The current build supplies balance
|
||||
and handler definitions while mutable saved state is preserved. Unknown future
|
||||
schema versions fail closed until a migration exists.
|
||||
|
||||
## Validation invariants
|
||||
|
||||
Restore checks include:
|
||||
|
||||
- unique IDs and next-ID cursors above restored history;
|
||||
- valid definition/action/item/storage references;
|
||||
- actor/target/cost/effect contracts for activity facts;
|
||||
- animal reservations and feed event agreement;
|
||||
- relationship causes pointing at valid known events;
|
||||
- knowledge provenance and one-hop communication rules;
|
||||
- situation/journal/commitment references and statuses;
|
||||
- scope consistency for the event log and activity facts;
|
||||
- no future event tick or forged actor/source/destination fields.
|
||||
|
||||
The test suite deliberately removes derived knowledge/opportunity state and
|
||||
tamper-tests facts, so validation does not rely on a secondary projection to
|
||||
catch corruption.
|
||||
|
||||
## Local file safety
|
||||
|
||||
`SaveSlotStore` validates the complete JSON before replacement, restricts slot
|
||||
names and size, preserves a previous file, and can recover a backup after an
|
||||
interrupted replacement. `F5`/`F9` use the current quicksave path in `main.tscn`.
|
||||
The player transform and presentation-only scene state are intentionally not
|
||||
saved.
|
||||
|
||||
## Regional persistence boundary
|
||||
|
||||
`RegionalChunkedPersistence` and `RegionalChunkedFileStore` are the regional
|
||||
counterpart. They serialize a `RegionalCaravanService` envelope into global,
|
||||
location, mobile-group, scheduler, and event-segment chunks, with manifest and
|
||||
per-file checksums. The file store uses immutable generations, a current
|
||||
pointer, recovery scanning, and conservative pruning. Partial active-location
|
||||
loads are metadata-only and cannot silently resurrect a removed location.
|
||||
|
||||
This regional codec is not yet the backend for local `SaveSlotStore`. Integrate
|
||||
it only after the production regional facade, event retention, and lazy context
|
||||
loading have one atomic manifest contract.
|
||||
|
||||
## How to change state safely
|
||||
|
||||
1. Add the field to the narrow nested record first.
|
||||
2. Define `SCHEMA_VERSION`, validation, canonical `to_dictionary()`, and an
|
||||
explicit migration from the prior version.
|
||||
3. Update top-level construction/restore/checksum only after the nested record
|
||||
round-trips.
|
||||
4. Add malformed/tamper, old-save migration, save/load, and deterministic
|
||||
continuation tests.
|
||||
5. Update [SIMULATION_STATE_SCHEMA.md](SIMULATION_STATE_SCHEMA.md) and this
|
||||
guide with the actual version and compatibility range.
|
||||
|
||||
The full field-by-field history remains in [Simulation State Schema](SIMULATION_STATE_SCHEMA.md).
|
||||
Reference in New Issue
Block a user