feat(abilities): disasters & pandemics lever (v0.41.0) #76

Merged
kamilkrzywda merged 1 commits from feat/63-disasters-pandemics into master 2026-10-16 11:20:16 +02:00
Owner

Adds the 9th modular LLM ability: a turn-transient TurnResult.disasters lever that lets the LLM declare natural/man-made disasters (earthquake / flood / volcanic / wildfire / famine / plague / epidemic) on a nation or a region, applying a deterministic (type, severity) stat dip (no hidden randomness).

Fixes #63

What changed

Feature (v0.41.0)

  • shared/protocol.ts: new DisasterType / DisasterSeverity / DisasterEvent / DisastersOps and the required TurnResult.disasters field (between ideology and markers; default { events: [] }).
  • server/abilities/disasters.ts: the new ability module — validate (defensive, never throws), apply (deterministic dip: clamped 0–100, mirrored to the target's regions via regionStats, then the target nation's derived stats re-derived with the same 0-region / no-entry guards), the DISASTER_EFFECTS deterministic (type, severity) table, the schema line + constraint bullet, isMeaningful, an inert stub(), and an empty payload(). It owns no GameState field (turn-transient, exactly like hybrid) — no db.ts change.
  • Target resolution mirrors hybrid (a region key hits its sole owner; a 0/2+-owner key is dropped, never thrown) but has no from field, so the hybrid's self-target drop does not apply.
  • Registered last in ABILITIES (after ideology).

Prompt goldens

  • system-no-tool.txt / system-tool.txt regenerated (each gains exactly the disasters schema line + the constraint bullet).
  • user.txt is byte-identical (the disasters payload() is empty — verified by checksum).

Tests

  • New server/abilities/disasters.test.ts (33 tests).
  • registry.test.ts updated to the 9-ability contract (order, fullDefaultTurn(), meaningfulFor, re-export pin).
  • All 555 unit tests pass; typecheck + lint + build clean. The stub is disasters-inert, so e2e (CI, LLM_STUB=1) is unaffected.

Secondary cleanups (from the v0.40.0 refactor)

  • AGENTS.md: server/abilities/ added to the Layout tree; a “how to add a new ability” Conventions bullet and a “Disasters & pandemics” bullet.
  • Deleted the orphaned validateTakeovers JSDoc.
  • Folded both inline as unknown casts into the single top-level ./abilities import (AbilityCtx + UserPromptCtx).
  • De-duplicated str (now imported from ./abilities/shared).

Version bumped 0.40.0 → 0.41.0.

Adds the 9th modular LLM ability: a **turn-transient** `TurnResult.disasters` lever that lets the LLM declare natural/man-made disasters (earthquake / flood / volcanic / wildfire / famine / plague / epidemic) on a nation or a region, applying a **deterministic** `(type, severity)` stat dip (no hidden randomness). **Fixes #63** ## What changed **Feature (v0.41.0)** - `shared/protocol.ts`: new `DisasterType` / `DisasterSeverity` / `DisasterEvent` / `DisastersOps` and the required `TurnResult.disasters` field (between `ideology` and `markers`; default `{ events: [] }`). - `server/abilities/disasters.ts`: the new ability module — `validate` (defensive, never throws), `apply` (deterministic dip: clamped 0–100, mirrored to the target's regions via `regionStats`, then the target nation's derived `stats` re-derived with the same 0-region / no-entry guards), the `DISASTER_EFFECTS` deterministic `(type, severity)` table, the schema line + constraint bullet, `isMeaningful`, an inert `stub()`, and an empty `payload()`. It owns **no** `GameState` field (turn-transient, exactly like `hybrid`) — **no `db.ts` change**. - Target resolution mirrors `hybrid` (a region key hits its **sole** owner; a 0/2+-owner key is dropped, never thrown) but has **no** `from` field, so the hybrid's self-target drop does **not** apply. - Registered last in `ABILITIES` (after `ideology`). **Prompt goldens** - `system-no-tool.txt` / `system-tool.txt` regenerated (each gains exactly the `disasters` schema line + the constraint bullet). - `user.txt` is **byte-identical** (the `disasters` `payload()` is empty — verified by checksum). **Tests** - New `server/abilities/disasters.test.ts` (33 tests). - `registry.test.ts` updated to the 9-ability contract (order, `fullDefaultTurn()`, `meaningfulFor`, re-export pin). - All **555** unit tests pass; `typecheck` + `lint` + `build` clean. The stub is disasters-inert, so e2e (CI, `LLM_STUB=1`) is unaffected. **Secondary cleanups (from the v0.40.0 refactor)** - `AGENTS.md`: `server/abilities/` added to the Layout tree; a “how to add a new ability” Conventions bullet and a “Disasters & pandemics” bullet. - Deleted the orphaned `validateTakeovers` JSDoc. - Folded both inline `as unknown` casts into the single top-level `./abilities` import (`AbilityCtx` + `UserPromptCtx`). - De-duplicated `str` (now imported from `./abilities/shared`). **Version** bumped `0.40.0 → 0.41.0`.
kamilkrzywda added 1 commit 2026-10-16 11:18:16 +02:00
feat(abilities): add disasters & pandemics lever (v0.41.0, #63)
CI / build + unit + e2e (pull_request) Successful in 1m55s
c90e9ae753
Add the 9th modular LLM ability: a turn-transient `TurnResult.disasters`
lever letting the LLM declare natural/man-made disasters (earthquake /
flood / volcanic / wildfire / famine / plague / epidemic) on a nation or
a region, applying a DETERMINISTIC (type, severity) stat dip (no hidden
randomness). Like the hybrid layer it owns no GameState field, needs no
db.ts change, and leaves no durable list — an ongoing plague/epidemic is
simply re-declared each turn it persists.

- shared/protocol.ts: DisasterType / DisasterSeverity / DisasterEvent /
  DisastersOps, and `TurnResult.disasters` (between `ideology` and
  `markers`; required, default `{ events: [] }`).
- server/abilities/disasters.ts: the ability module (validate / apply /
  schemaLine / constraint / isMeaningful / inert stub / empty payload; no
  stateFields). `DISASTER_EFFECTS` is the deterministic (type, severity)
  dip table (population never touched). Target resolution mirrors hybrid
  (a region key hits its SOLE owner; 0/2+ owners dropped) but has NO
  `from` field, so there is no self-target drop. Dips clamp to 0-100,
  mirror to the target's regions (regionStats), and re-derive the target
  nation's stats (same 0-region / no-entry guards).
- Registered last in ABILITIES (after ideology). System-prompt goldens
  regenerated (one schema line + one constraint bullet each); the
  user.txt golden stays byte-identical (payload() is {}).
- New server/abilities/disasters.test.ts (33 tests); registry.test.ts
  updated to the 9-ability contract.
- Secondary cleanups from the v0.40 refactor: AGENTS.md (abilities/ in
  the Layout tree + a "how to add a new ability" bullet + a disasters
  bullet), delete the orphaned validateTakeovers JSDoc, fold both inline
  `as unknown` casts into the top-level ./abilities import, and de-dup
  `str` (now imported from ./abilities/shared).

Version bumped 0.40.0 -> 0.41.0.
kamilkrzywda scheduled this pull request to auto merge when all checks succeed 2026-10-16 11:19:01 +02:00
kamilkrzywda merged commit e0f3d0313b into master 2026-10-16 11:20:16 +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#76