feat(abilities): add migration & refugees lever (v0.42.0, #64)
CI / build + unit + e2e (pull_request) Successful in 2m12s

Add the 10th modular LLM ability: a turn-transient TurnResult.migration
lever declaring population flows between nations (migration / refugees /
diaspora / exodus). The source loses a little population + economy, the
destination gains a little (a large influx also strains its stability),
and the from<->to relation is nudged one step toward the positive end of
the ally/neutral/rival/hostile ladder (capped by kind; a war is never
touched). Deterministic per-scale tables, no hidden randomness, clamped
0-100, mirrored to owned regions, re-derived aggregates; never moves
territory. Registered last in ABILITIES; user prompt unchanged
(user.txt golden byte-identical), system goldens re-baselined. Fixes #64.
This commit is contained in:
2026-10-16 10:15:45 +00:00
parent e0f3d0313b
commit 7e4faa73d3
13 changed files with 1142 additions and 55 deletions
+23 -4
View File
@@ -1,8 +1,8 @@
// The ordered LLM-ability registry.
//
// `ABILITIES` is the single source of truth for the 9 per-feature LLM abilities.
// `ABILITIES` is the single source of truth for the 10 per-feature LLM abilities.
// The engine iterates it in this order:
// takeovers → wars → hybrid → economy → industry → nuclear → leaders → ideology → disasters
// takeovers → wars → hybrid → economy → industry → nuclear → leaders → ideology → disasters → migration
// for (a) the system-prompt schema lines + constraint bullets, (b) the per-ability
// validate calls inside validateTurnResult, (c) the payload fields in buildUserPrompt,
// (d) the ordered apply block inside applyTurnResult, (e) the isMeaningful check,
@@ -23,13 +23,16 @@ import { nuclear } from './nuclear';
import { leaders } from './leaders';
import { ideology } from './ideology';
import { disasters } from './disasters';
import { migration } from './migration';
import type { Ability, AbilityField } from './types';
/**
* The 9 per-feature LLM abilities in their canonical apply order.
* The 10 per-feature LLM abilities in their canonical apply order.
* The order matters: it determines the order of the schema lines in the
* system prompt, the order of the validate calls, the order of the apply
* steps, and the order of the payload fields in the user prompt.
* steps, and the order of the payload fields in the user prompt. New
* abilities are APPENDED last — never reorder existing entries (their order
* is pinned by the goldens and the stub's byte-identical output).
*/
export const ABILITIES: readonly Ability<AbilityField>[] = [
takeovers,
@@ -41,6 +44,7 @@ export const ABILITIES: readonly Ability<AbilityField>[] = [
leaders,
ideology,
disasters,
migration,
];
// ── type re-exports ────────────────────────────────────────────────────────────
@@ -139,3 +143,18 @@ export {
DISASTER_SEVERITIES,
DISASTER_EFFECTS,
} from './disasters';
// ── migration ────────────────────────────────────────────────────────────────
export {
validateMigrationOps,
applyMigrationOp,
shiftRelationTowardPositive,
isMigrationKind,
isMigrationScale,
MIGRATION_KINDS,
MIGRATION_SCALES,
MIGRATION_SOURCE_EFFECTS,
MIGRATION_DESTINATION_EFFECTS,
LARGE_INFLUX_STABILITY_DIP,
} from './migration';