feat(#61): named leaders — assassination / death / appointment with succession (v0.38.0)
CI / build + unit + e2e (pull_request) Successful in 2m33s

Per-nation named leaders (Nation.leader) and a required TurnResult.leaders
lever ({ changes: [{ target, name, cause }] }). Each change sets the target
nation's leader and applies a deterministic stability dip by cause
(assassination -15, death -3, appointed 0) mirrored to its regions and
re-derived into its stats, plus a narration event (military for an
assassination, political for a death/appointment). An assassination/death
requires the target to already have a leader (a leaderless target is
dropped); an appointment always creates/sets one. Unknown/ambiguous targets
are dropped, never thrown.

- shared/types.ts: optional Nation.leader
- shared/protocol.ts: LeaderCause/LeaderChange/LeaderOps, LEADER_STABILITY_EFFECT,
  TurnResult.leaders (required, between nuclear and markers), leader in nationForPrompt
- server/engine.ts: validateLeaderOps, applyLeaderChange, the applyTurnResult
  leader block (after nuclear, before markers), isMeaningful, system-prompt
  contract + constraint, validateTurnResult + runTurn fallback
- server/stub.ts: leaders always { changes: [] } (e2e unaffected)
- tests: 15 engine.test.ts leader tests + 2 db.test.ts round-trips
- version 0.37.0 -> 0.38.0, CHANGELOG entry
This commit is contained in:
2026-10-15 20:09:19 +00:00
parent b6dcd3f979
commit 8730a56170
8 changed files with 469 additions and 41 deletions
+8
View File
@@ -80,6 +80,14 @@ export interface Nation {
* `isNuclearCapable` in `protocol.ts`).
*/
nuclear?: boolean;
/**
* The nation's current named leader (v0.38, #61). Optional — a legacy game
* (or a nation the LLM has never given a leader to) has none, which is the
* "no leader" baseline. The LLM changes it via `TurnResult.leaders`
* (assassination / death / appointment, see `LeaderChange` in `protocol.ts`);
* each change carries a deterministic stability effect + a narration event.
*/
leader?: { name: string };
}
/** Categories a narrative event can take. */