The single source of truth now keys ownership by region key (one per owned
sub-region) instead of a parent-country ISO_A3:
- shared/types.ts, shared/protocol.ts: TerritoryChange / RegionMap / regionOwner
doc flips; mapFeatureOwner now reads the feature's stamped properties.regionKey
(never the repacked numeric feature.id, nor the sub-region id — the #6 guard).
- server/regions.ts (new, turf-free): loads region-keys.json + regions.geo.json
once at boot; expands a nation's ISO_A3 list to its sub-regions' keys, builds
the LLM 'regions' reference table (key -> "name (parent)"), and exposes the
set of valid keys. Degrades gracefully when the files are missing.
- server/engine.ts: buildSystemPrompt instructs the model to use region keys;
buildUserPrompt gains an optional regionReference table; applyTurnResult gains
an optional validKeys set so hallucinated keys are ignored.
- server/index.ts: loads region data at boot; expands each nation's country list
to region keys at game creation; the jump route passes the reference + valid
keys through runTurn.
The stub is unchanged (it emits an empty, region-key-conformant territoryChanges).