feat(#58): trade & embargoes — economy layer (v0.35.0) #69

Merged
kamilkrzywda merged 1 commits from feat/58-trade-embargo into master 2026-10-15 19:30:59 +02:00
Owner

Fixes #58

v0.35.0 — Trade & Embargoes

A bilateral trade + embargo economy layer with a deterministic per-turn effect:

  • TurnResult.economy = { trade, embargo } (required, default empty) — the model can declare/lift bilateral trade agreements (symmetric, stored sorted a < b) and unilateral embargoes (ordered from → target). No lift = declare/impose; lift: true = end/lift.
  • GameState.trades / GameState.embargoes — required, [] on creation; rows saved before v0.35 load with them defaulted to [] (additive, never wiped).
  • Per-turn effect (fully deterministic, no hidden randomness) — every committed turn: each active trade grants both parties a small economy gain; each active embargo dips the target only. Clamped to 0–100, mirrored to every owned region (regionStats), and each affected nation's derived stats re-derived (same 0-region/no-entry guards as the hybrid dip). Sole ownership is untouched — the layer moves stats, never territory.
  • War auto-suspension — any trade or embargo whose two nations are on opposite sides of an active war (#56) is removed: a war severs the economic link. Runs after the turn's war declare/end ops, before the effect.
  • isMeaningful counts non-empty economy ops; the system prompt documents the field (at most 1–2 ops per turn, narrated in events, warring pairs auto-suspended) and the user payload carries the active trades/embargoes so the model can lift them.
  • Stub returns an empty economy (never declares) — the CI e2e (LLM_STUB=1) is unaffected; the path is covered by unit tests only (20 new tests in server/engine.test.ts + a legacy-load test in server/db.test.ts).

All four local checks pass (typecheck, lint, unit tests 407/407, build). Full details in CHANGELOG.md and AGENTS.md.

Fixes #58 ## v0.35.0 — Trade & Embargoes A bilateral trade + embargo economy layer with a deterministic per-turn effect: - **`TurnResult.economy = { trade, embargo }`** (required, default empty) — the model can declare/lift **bilateral trade agreements** (symmetric, stored sorted `a < b`) and **unilateral embargoes** (ordered `from → target`). No `lift` = declare/impose; `lift: true` = end/lift. - **`GameState.trades` / `GameState.embargoes`** — required, `[]` on creation; rows saved before v0.35 load with them defaulted to `[]` (additive, never wiped). - **Per-turn effect (fully deterministic, no hidden randomness)** — every committed turn: each active trade grants **both** parties a small economy gain; each active embargo dips the **target only**. Clamped to 0–100, mirrored to every owned region (`regionStats`), and each affected nation's derived `stats` re-derived (same 0-region/no-entry guards as the hybrid dip). Sole ownership is untouched — the layer moves stats, never territory. - **War auto-suspension** — any trade or embargo whose two nations are on opposite sides of an **active** war (#56) is removed: a war severs the economic link. Runs after the turn's war declare/end ops, before the effect. - `isMeaningful` counts non-empty economy ops; the system prompt documents the field (at most 1–2 ops per turn, narrated in `events`, warring pairs auto-suspended) and the user payload carries the active `trades`/`embargoes` so the model can `lift` them. - **Stub** returns an empty economy (never declares) — the CI e2e (LLM_STUB=1) is unaffected; the path is covered by unit tests only (20 new tests in `server/engine.test.ts` + a legacy-load test in `server/db.test.ts`). All four local checks pass (typecheck, lint, unit tests 407/407, build). Full details in `CHANGELOG.md` and `AGENTS.md`.
kamilkrzywda added 1 commit 2026-10-15 19:26:45 +02:00
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-10-15 19:30:58 +02:00
kamilkrzywda merged commit dd9fd6a09d into master 2026-10-15 19:30:59 +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#69