# 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).