118 lines
5.6 KiB
Markdown
118 lines
5.6 KiB
Markdown
# Feature slice: regional simulation and persistence
|
||
|
||
The regional package is the scale foundation for one authority spanning
|
||
settlements, routes, caravans, named people, aggregate cohorts, and polities.
|
||
It is intentionally additive: the current Jajce `SimulationManager` remains
|
||
the playable local facade while the regional contracts prove deterministic
|
||
unloaded work and conservation in isolation.
|
||
|
||
## Regional record model
|
||
|
||
`RegionalWorldState` is a primitive-only, versioned aggregate with deterministic
|
||
indexes for:
|
||
|
||
- `LocationStateRecord` — world/location identity, type, address, and history;
|
||
- `SettlementStateRecord` — location/polity, tier, founding group, stockpile;
|
||
- `RouteStateRecord` — endpoints, travel ticks, direction, history;
|
||
- `MobileGroupStateRecord` — caravan/army identity, membership, route state,
|
||
cargo ledger, capacity, arrival/departure ticks, and cargo event cursor;
|
||
- `PersonStateRecord` — globally unique named people and memberships;
|
||
- `PopulationCohortRecord` — conserved aggregate residents;
|
||
- `PolityStateRecord` and `DiplomaticRelationRecord` — sparse regional politics.
|
||
|
||
Membership is explicit and validated: a person is at one location or in one
|
||
mobile group, routes connect existing locations, groups reference existing
|
||
routes/members, and IDs are globally unique and append-only. Records contain
|
||
stable IDs and primitive values only; no scene, `NodePath`, resource, or
|
||
callable can enter the regional payload.
|
||
|
||
## Deterministic scheduled work
|
||
|
||
`ScheduledJobRecord` and `RegionalJobScheduler` order due work by:
|
||
|
||
```text
|
||
(due_tick, phase, entity_id, stable_sequence)
|
||
```
|
||
|
||
The scheduler supports O(log n) insertion/cancellation, deterministic due
|
||
draining, repeats, dedupe keys, a serialized cursor, and strict restore
|
||
validation. A frame or service budget may process one, eight, or unlimited jobs
|
||
per call, but all budgets must produce the same order, checksum, and final
|
||
backlog. Dynamic jobs inserted while draining are ordered into the same queue,
|
||
not handled by an ad-hoc frame loop.
|
||
|
||
`KeyedRandom` derives values from `(world_seed, system_id, entity_id,
|
||
occurrence)`, so update order and save/load do not consume another entity's
|
||
random stream. `AnalyticalRegionalUpdates` advances elapsed needs, growth, and
|
||
periodic work from last-updated ticks instead of scanning every entity each
|
||
tick.
|
||
|
||
## The caravan proof
|
||
|
||
`RegionalCaravanService` owns an envelope containing `RegionalWorldState`,
|
||
`RegionalJobScheduler`, and `WorldEventStore`. `depart()` validates origin,
|
||
destination, route, cargo capacity, group status, and exact state; it withdraws
|
||
the cargo and schedules a typed arrival. The arrival handler updates the group,
|
||
deposits the exact cargo into the destination settlement, and appends the causal
|
||
load/depart/arrive/deposit chain. Presentation mode is an input label for the
|
||
test, never an authority branch.
|
||
|
||
The service is transactional: invalid jobs, forged event pairs, stale event
|
||
cursors, duplicate departure pairs, and malformed restore envelopes fail with
|
||
no partial mutation. `to_dictionary()`, `from_dictionary()`, and `checksum()`
|
||
provide deterministic save/restore. The test runs always-loaded, never-loaded,
|
||
and load/unload presentation modes through the same authoritative service.
|
||
|
||
## Chunked persistence
|
||
|
||
`RegionalChunkedPersistence` captures the service into a manifest plus fixed
|
||
primitive chunks:
|
||
|
||
- one global index;
|
||
- one location chunk per location;
|
||
- one mobile-group chunk per group;
|
||
- one scheduler chunk;
|
||
- fixed-size event segments.
|
||
|
||
Each descriptor contains record count, byte size, and SHA-256 checksum. Restore
|
||
rejects missing, duplicated, unknown, reordered, tampered, out-of-scope, or
|
||
non-primitive chunks. `load_active_location_metadata()` reads the global index
|
||
and one location while retaining authoritative references to unloaded chunks.
|
||
|
||
`RegionalChunkedFileStore` writes immutable fixed-width generation directories,
|
||
validates a temporary generation before install, updates a small current
|
||
pointer, recovers the newest valid generation when the pointer is stale, and
|
||
keeps at least two valid generations when pruning. It uses Godot's available
|
||
flush/close/rename primitives; a platform fsync is not exposed by this layer.
|
||
The store has explicit path, file-count, chunk-size, generation-size, and
|
||
primitive-tree bounds.
|
||
|
||
## Current integration boundary
|
||
|
||
The regional package is not yet the production authority for `main.tscn`:
|
||
|
||
- Jajce local saves still use `SaveSlotStore` and `SimulationStateRecord` v16;
|
||
- `RegionalCaravanService` is a complete isolated transfer proof, not the live
|
||
economy's 20-trade scheduler;
|
||
- event retention/rollups and regional chunk files are not yet one integrated
|
||
long-horizon save transaction;
|
||
- loaded/unloaded local NPC travel still has the old active-visual boundary;
|
||
- cohort promotion, settlement growth, offices, diplomacy, armies, and
|
||
aggregate conflict remain planned.
|
||
|
||
Do not create one `SimulationManager` per settlement or caravan. The next
|
||
production step is an explicit regional facade that delegates to these records
|
||
and services, while the active adapter presents only a bounded relevant context.
|
||
|
||
## Scale evidence
|
||
|
||
`RegionalScaleBenchmark` builds five settlements, 20 caravans × 12 named
|
||
members, 2,000 named people, 50,000 aggregate residents, and 2,025 jobs. It
|
||
proves conservation, canonical roundtrip, budget parity, and repeatable
|
||
checksums. It does **not** claim rendered frame time, a complete market, a
|
||
30-day economy, or weak-PC GPU performance.
|
||
|
||
See [Regional simulation contract](REGIONAL_SIMULATION.md),
|
||
[regional baseline 01](benchmarks/REGIONAL_SCALE_BASELINE_01.md), and
|
||
[Testing and benchmarks](FEATURE_TESTING_AND_BENCHMARKS.md).
|