feat(abilities): migration & refugees lever (v0.42.0, #64) #77

Merged
kamilkrzywda merged 1 commits from feat/64-migration into master 2026-10-16 12:20:03 +02:00
Owner

Add the 10th modular LLM ability (v0.40.0/#67 system): a turn-transient TurnResult.migration lever letting the model declare population flows between nations.

What it does

Each op is { kind, from, to?, scale, detail? }:

  • kind: migration | refugees | diaspora | exodus (exodus has no to)
  • scale: small | moderate | large

Deterministic per-scale effects (no hidden randomness), clamped 0-100, mirrored to each nation's regions, aggregates re-derived:

Scale Source loses (pop, eco) Destination gains (pop, eco) extra
small -1, -1 +1, +1 —
moderate -2, -2 +2, +2 —
large -4, -3 +3, +3 destination stability -2

The from<->to relation then moves one step toward the positive end of the ally/neutral/rival/hostile ladder via shiftRelationTowardPositive (the mirror of the hybrid layer's shiftRelationTowardHostile): capped at ally for refugees (hosting refugees builds the strongest goodwill), neutral for migration/diaspora, and not at all for exodus; a war relation is never touched (the nudge neither fabricates nor escalates a war).

Properties

  • Turn-transient (like hybrid / disasters): no new GameState field, no db.ts change, no durable list.
  • Never moves territory — sole ownership is untouched (a no-man's-land re-claim stays the regionChanges lever's job).
  • Drop-first resolution: an unknown / ambiguous source, a missing / unknown / ambiguous destination, or a self-flow (from === to) drops the whole op (the source is untouched).
  • Registered last in ABILITIES (existing order untouched); the stub is migration-inert, so e2e (CI, LLM_STUB=1) is unaffected.

Tests

  • New server/abilities/migration.test.ts (38 tests); registry.test.ts updated to the 10-ability contract.
  • System goldens system-no-tool.txt / system-tool.txt re-baselined (each gains the schema line + constraint bullet); user.txt byte-identical (no new user-payload keys).
  • Local verification: typecheck + lint + 593/593 unit tests + build all green.

Design note (interpretation of #64)

The Gitea #64 body sketched a simpler flows: { type: 'refugees' | 'settlers' } shape that included a settler re-claim of no-man's-land. The refined, approved design implemented here is the richer four-kind nation-to-nation stat layer that deliberately never moves territory.

Fixes #64

Add the **10th** modular LLM ability (v0.40.0/#67 system): a **turn-transient** `TurnResult.migration` lever letting the model declare population flows between nations. ## What it does Each op is `{ kind, from, to?, scale, detail? }`: - **kind**: `migration` | `refugees` | `diaspora` | `exodus` (`exodus` has no `to`) - **scale**: `small` | `moderate` | `large` Deterministic per-scale effects (no hidden randomness), clamped 0-100, mirrored to each nation's regions, aggregates re-derived: | Scale | Source **loses** (pop, eco) | Destination **gains** (pop, eco) | extra | |-------|----------------------------|----------------------------------|-------| | small | -1, -1 | +1, +1 | — | | moderate | -2, -2 | +2, +2 | — | | large | -4, -3 | +3, +3 | destination stability -2 | The `from`<->`to` relation then moves **one step toward the positive** end of the ally/neutral/rival/hostile ladder via `shiftRelationTowardPositive` (the mirror of the hybrid layer's `shiftRelationTowardHostile`): capped at `ally` for `refugees` (hosting refugees builds the strongest goodwill), `neutral` for `migration`/`diaspora`, and not at all for `exodus`; a `war` relation is **never** touched (the nudge neither fabricates nor escalates a war). ## Properties - **Turn-transient** (like `hybrid` / `disasters`): no new `GameState` field, no `db.ts` change, no durable list. - **Never moves territory** — sole ownership is untouched (a no-man's-land re-claim stays the `regionChanges` lever's job). - Drop-first resolution: an unknown / ambiguous source, a missing / unknown / ambiguous destination, or a **self-flow** (`from` === `to`) drops the whole op (the source is untouched). - Registered **last** in `ABILITIES` (existing order untouched); the stub is migration-inert, so e2e (CI, `LLM_STUB=1`) is unaffected. ## Tests - New `server/abilities/migration.test.ts` (**38 tests**); `registry.test.ts` updated to the **10-ability** contract. - System goldens `system-no-tool.txt` / `system-tool.txt` re-baselined (each gains the schema line + constraint bullet); **`user.txt` byte-identical** (no new user-payload keys). - Local verification: `typecheck` + `lint` + **593/593** unit tests + `build` all green. ## Design note (interpretation of #64) The Gitea #64 body sketched a simpler `flows: { type: 'refugees' | 'settlers' }` shape that included a settler **re-claim of no-man's-land**. The refined, approved design implemented here is the richer four-kind nation-to-nation **stat** layer that deliberately never moves territory. **Fixes #64**
kamilkrzywda added 1 commit 2026-10-16 12:17:21 +02:00
feat(abilities): add migration & refugees lever (v0.42.0, #64)
CI / build + unit + e2e (pull_request) Successful in 2m12s
7e4faa73d3
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.
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-10-16 12:20:00 +02:00
kamilkrzywda merged commit 13f91845fd into master 2026-10-16 12:20:03 +02:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: OpenCode/History#77