docs(diplomacy): 📝 reconcile start-state spec to courier model + track AI war-dec gap
Two diplomacy models contradicted each other in the written record: p1-01
diplomacy-lite ('all pairs start at war, missing key → war') vs the newer
courier-diplomacy (COMMUNICATIONS.md §War declaration semantics, p3-01:
start at peace, sender enters War on war-dec envelope dispatch). The Rust
implementation follows courier-diplomacy, so that is canonical.
- p1-01: add a SUPERSEDED banner + inline [SUPERSEDED] annotations; history
retained. Canonical rule is start-at-peace, war via dispatched war-dec.
- COMMUNICATIONS.md: fix the one internal inconsistency (§0 said recipient
war state applies at arrival in a way that read as all-effects-at-arrival;
scoped it to recipient-side, cross-linked the sender-on-dispatch exception).
- New objective p3-16 (status partial, owner warcouncil): the AI has no
proactive war-declaration — decide_tactical_actions has no diplomacy step
and there is no DeclareWar in mc-ai, so AI-vs-AI never enters war and clan
aggression personalities don't manifest. Specs the fix to the courier model
(first-contact + military balance + aggression → dispatch_war_declaration)
and notes the stale is_at_war comment as a code-fidelity cleanup.
- Register p3-16 under warcouncil; regen objectives dashboard.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
5eed0bb579
commit
6b3b571806
7 changed files with 172 additions and 11 deletions
|
|
@ -521,4 +521,5 @@
|
|||
| [p3-13d](p3-13d-anomalous-events.md) | ✅ done | P3 | Anomalous events — aurora, fog_bank, thermal_anomaly | [unassigned](../team-leads/unassigned.md) | 🟢 |
|
||||
| [p3-14](p3-14-game-start-script.md) | ✅ done | P3 | Declarative game-start script + runner — data-driven, moddable opening sequence | [shipwright](../team-leads/shipwright.md) | 🟢 |
|
||||
| [p3-15](p3-15-hotseat-multiplayer.md) | ✅ done | P3 | Local hotseat multiplayer — multiple humans alternating on one device | [shipwright](../team-leads/shipwright.md) | 🟢 |
|
||||
| [p3-16](p3-16-ai-proactive-war-declaration.md) | 🟡 partial | P3 | AI proactive war-declaration via the courier system | [warcouncil](../team-leads/warcouncil.md) | 🟢 |
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@
|
|||
| **P0** | 0 | 0 | 0 | 0 | 0 | 44 | 44 |
|
||||
| **P1** | 0 | 0 | 0 | 0 | 1 | 88 | 89 |
|
||||
| **P2** | 0 | 0 | 0 | 0 | 1 | 132 | 133 |
|
||||
| **P3 (oos)** | 0 | 0 | 0 | 0 | 29 | 26 | 55 |
|
||||
| **total** | **0** | **0** | **0** | **0** | **31** | **290** | **321** |
|
||||
| **P3 (oos)** | 0 | 1 | 0 | 0 | 29 | 26 | 56 |
|
||||
| **total** | **0** | **1** | **0** | **0** | **31** | **290** | **322** |
|
||||
|
||||
</td><td valign='top' style='padding-left:2em'>
|
||||
|
||||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
| Team Lead | Remaining |
|
||||
|---|---|
|
||||
| — | 0 |
|
||||
| [warcouncil](../team-leads/warcouncil.md) | 1 |
|
||||
|
||||
</td></tr></table>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"generated_at": "2026-06-23T17:17:04Z",
|
||||
"generated_at": "2026-06-24T00:06:25Z",
|
||||
"totals": {
|
||||
"done": 290,
|
||||
"in_progress": 0,
|
||||
"partial": 0,
|
||||
"partial": 1,
|
||||
"stub": 0,
|
||||
"missing": 0,
|
||||
"oos": 31,
|
||||
"total": 321
|
||||
"total": 322
|
||||
},
|
||||
"objectives": [
|
||||
{
|
||||
|
|
@ -549,7 +549,7 @@
|
|||
"owner": "shipwright",
|
||||
"updated_at": "2026-04-17",
|
||||
"blocked_by": [],
|
||||
"summary": "`mc-trade` now has a full diplomacy surface: `declare_war` / `offer_peace` / `evaluate_trade_offer` / `apply_trade_offer` free functions plus `DiplomacyEvent` enum and `TradeOffer` struct. `TurnProcessor` exposes `action_declare_war`, `action_offer_peace`, `action_offer_trade`, and `action_accept_trade_offer` as public methods callable from GDExtension. EA policy: AI always rejects player-initiated peace offers and gold-for-luxury offers; automated luxury swaps flow through the existing `evaluate_trades` path. Relation state machine (`Relation::Neutral/Peace/Friendly/War`) was already present in `mc-trade::relation`.\n\nAI attack decisions are gated on `Relation::War` via `_is_at_war` in `simple_heuristic_ai.gd`. `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within` all skip players whose relation is Peace or Friendly. Missing key defaults to War (EA: all pairs start at war). GUT coverage in `test_simple_heuristic_ai_war_gate.gd`."
|
||||
"summary": "`mc-trade` now has a full diplomacy surface: `declare_war` / `offer_peace` / `evaluate_trade_offer` / `apply_trade_offer` free functions plus `DiplomacyEvent` enum and `TradeOffer` struct. `TurnProcessor` exposes `action_declare_war`, `action_offer_peace`, `action_offer_trade`, and `action_accept_trade_offer` as public methods callable from GDExtension. EA policy: AI always rejects player-initiated peace offers and gold-for-luxury offers; automated luxury swaps flow through the existing `evaluate_trades` path. Relation state machine (`Relation::Neutral/Peace/Friendly/War`) was already present in `mc-trade::relation`.\n\nAI attack decisions are gated on `Relation::War` via `_is_at_war` in `simple_heuristic_ai.gd`. `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within` all skip players whose relation is Peace or Friendly. ~~Missing key defaults to War (EA: all pairs start at war).~~ **[SUPERSEDED — see banner: canonical start state is PEACE; war begins on war-dec dispatch per COMMUNICATIONS.md / p3-01.]** GUT coverage in `test_simple_heuristic_ai_war_gate.gd`."
|
||||
},
|
||||
{
|
||||
"id": "p1-02",
|
||||
|
|
@ -3567,6 +3567,17 @@
|
|||
"updated_at": "2026-06-19",
|
||||
"blocked_by": [],
|
||||
"summary": ""
|
||||
},
|
||||
{
|
||||
"id": "p3-16",
|
||||
"title": "AI proactive war-declaration via the courier system",
|
||||
"priority": "p3",
|
||||
"status": "partial",
|
||||
"scope": "game1",
|
||||
"owner": "warcouncil",
|
||||
"updated_at": "2026-06-23",
|
||||
"blocked_by": [],
|
||||
"summary": "The canonical courier-diplomacy model (`COMMUNICATIONS.md` §\"War declaration\nsemantics\") assumes a player **dispatches a war-dec envelope** to enter war: the\n**sender** enters `War` immediately on dispatch and its units can attack the same\nturn; the **recipient** flips to `War` on delivery/interception; **defenders\nalways retaliate when struck** regardless of formal `RelationState`. Pairs start\nat **peace** (`mc-player-api/src/projection.rs::project_tactical_relations` defaults\nunset pairs to 0 = peace; `mc-player-api/src/comms_dispatch.rs` flips the shared\n`RelationState` cell to `War` only on delivery).\n\n**The gap:** the AI has **no proactive war-declaration logic**. `mc-ai`'s tactical\nentry point `decide_tactical_actions` (`src/simulator/crates/mc-ai/src/tactical/mod.rs`)\nruns movement → combat → settle → production → citizens with **no diplomacy step**,\nand there is **zero** `DeclareWar` / war-dec action anywhere in `mc-ai` (no\nstrategic action variant, no caller of `comms_dispatch::dispatch_war_declaration`\n— the only non-test caller is the human dispatch path at\n`mc-player-api/src/dispatch.rs:1605`). `mc-ai/src/diplomacy.rs` covers only the\np3-01 courier open-borders / shared-map offer/accept heuristics — not war.\n\nConsequence (observed in a 200-turn hotseat self-play): AIs never initiate war →\n`collect_enemy_city_positions` (`tactical/movement.rs`) is always empty because it\nis gated through `is_at_war` (movement.rs:366) → no `locked_target` is ever set →\nmilitary units never maneuver (48 successful moves across 200 turns). Because war\nnever comes in AI-vs-AI play, the five clan personalities\n(`public/games/age-of-dwarves/data/ai_personalities.json`, `aggression` 1–10,\nwarmonger = 9) do **not** manifest distinct aggression: per\n`mc-ai/src/tactical/thresholds.rs`, `aggression` only tunes combat posture **once\nalready at war**, so a difference that only fires after war-declaration never\nfires at all.\n\nThis objective adds the missing strategic decision step so the AI dispatches a\nwar-dec envelope through the courier system when conditions warrant, entering the\nexisting at-war combat path and making personality `aggression` actually drive\nbehavior."
|
||||
}
|
||||
],
|
||||
"blocked": [
|
||||
|
|
@ -3813,5 +3824,10 @@
|
|||
]
|
||||
}
|
||||
],
|
||||
"remaining_by_lead": []
|
||||
"remaining_by_lead": [
|
||||
{
|
||||
"owner": "warcouncil",
|
||||
"remaining": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,18 +21,31 @@ evidence:
|
|||
- ~/Desktop/magic_civ_diplomacy.png
|
||||
---
|
||||
|
||||
> ## ♻️ Start-state semantics SUPERSEDED (2026-06-23)
|
||||
>
|
||||
> This objective's original EA rule — **"missing relation key defaults to War (EA: all pairs start at war)"** — has been **superseded by the courier-diplomacy model**. The canonical, current rule is:
|
||||
>
|
||||
> - **Pairs start at PEACE.** Unset relation pairs default to peace (0), not war.
|
||||
> - **War begins on dispatch of a war-dec envelope.** Per `public/games/age-of-dwarves/docs/military/COMMUNICATIONS.md` §"War declaration semantics": the **sender** enters `War` immediately on envelope dispatch; the **recipient** flips to `War` on delivery/interception; **defenders always retaliate when struck** regardless of formal `RelationState`.
|
||||
>
|
||||
> Authoritative sources for the current model: `COMMUNICATIONS.md` §"War declaration semantics" (canonical design) and **`.project/objectives/p3-01-courier-diplomacy.md`** (implementing objective, `scope: game1-stretch`). The Rust implementation matches courier-diplomacy: `mc-player-api/src/comms_dispatch.rs` manages `relations` as a map (`relations.entry(key).or_default()` = peace), and `mc-player-api/src/projection.rs::project_tactical_relations` defaults unset pairs to 0 = peace.
|
||||
>
|
||||
> The four "missing → war / all pairs start at war" mentions below are **retained as history** and annotated inline with `[SUPERSEDED]`. The GDScript `_is_at_war` reference cited in `evidence:` reflects the old GDScript-AI prototype, which is itself tech-debt per Rail 1 (`p0-26-ai-tactical-rust-port.md`). Do not treat the war-start behavior in this file as current.
|
||||
>
|
||||
> **Open follow-up:** the canonical model assumes the AI dispatches war-decs ("the AI's 'war mode' branch", `COMMUNICATIONS.md:180`), but `mc-ai` has no proactive war-declaration logic — tracked by **`p3-16-ai-proactive-war-declaration.md`**.
|
||||
|
||||
## Summary
|
||||
|
||||
`mc-trade` now has a full diplomacy surface: `declare_war` / `offer_peace` / `evaluate_trade_offer` / `apply_trade_offer` free functions plus `DiplomacyEvent` enum and `TradeOffer` struct. `TurnProcessor` exposes `action_declare_war`, `action_offer_peace`, `action_offer_trade`, and `action_accept_trade_offer` as public methods callable from GDExtension. EA policy: AI always rejects player-initiated peace offers and gold-for-luxury offers; automated luxury swaps flow through the existing `evaluate_trades` path. Relation state machine (`Relation::Neutral/Peace/Friendly/War`) was already present in `mc-trade::relation`.
|
||||
|
||||
AI attack decisions are gated on `Relation::War` via `_is_at_war` in `simple_heuristic_ai.gd`. `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within` all skip players whose relation is Peace or Friendly. Missing key defaults to War (EA: all pairs start at war). GUT coverage in `test_simple_heuristic_ai_war_gate.gd`.
|
||||
AI attack decisions are gated on `Relation::War` via `_is_at_war` in `simple_heuristic_ai.gd`. `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within` all skip players whose relation is Peace or Friendly. ~~Missing key defaults to War (EA: all pairs start at war).~~ **[SUPERSEDED — see banner: canonical start state is PEACE; war begins on war-dec dispatch per COMMUNICATIONS.md / p3-01.]** GUT coverage in `test_simple_heuristic_ai_war_gate.gd`.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- ✓ `Relation::{Peace, War}` state per player pair; `declare_war` sets relation to War, clears traded_luxuries, mirrors to both players via `action_declare_war` on `TurnProcessor`. Covered by `processor.rs::tdip1_declare_war_sets_war_in_both_players` (4 assertions).
|
||||
- ✓ `TradeOffer { from, to, gold: u32, luxury_id: String }` with `evaluate_trade_offer` (reject, EA) and `apply_trade_offer` (accept, human path). `action_accept_trade_offer` on `TurnProcessor` deducts gold + credits luxury. Covered by `mc-trade/lib.rs::apply_trade_offer_swaps_gold_and_luxury` and `processor.rs::tdip3_accept_trade_offer_updates_ledgers`.
|
||||
- ✓ GDScript diplomacy panel exposes declare-war / offer-trade — `scenes/hud/diplomacy_panel.{tscn,gd}` renders one row per AI rival (clan name, relation badge, action buttons). At-war rows show **Offer Peace** + **Offer Trade**; at-peace rows show **Declare War** + **Offer Trade**. Trade submodal has gold `SpinBox` + luxury `OptionButton` (populated from human's `owned_luxuries`) + Send/Close. Actions route through `Diplomacy.declare_war`, `Diplomacy.offer_peace`, `Diplomacy.offer_trade` (new static methods in `src/modules/empire/diplomacy.gd`). `declare_war` flips `GameState.diplomacy[key]` to `"war"`, clears both players' `traded_luxuries`, emits `EventBus.relation_changed` + new `EventBus.war_declared`. EA policy: `offer_peace` and `offer_trade` always emit `peace_rejected` / `trade_offer_rejected` (no state mutation — mirrors Rust `action_offer_peace`/`action_offer_trade` EA behavior). Wired into `top_bar.tscn` via new `DiplomacyButton` + `KEY_F8` hotkey (F1/F9 already taken by Encyclopedia/Stats). GUT coverage: `test_diplomacy_panel.gd` — **9/9 passing on apricot** (panel instantiates with 2 rows, empty-label fallback, declare_war flips relation + emits signal, declare_war clears luxuries, peace/trade rejections emit with correct payload, self-target is no-op, idempotent war, all 3 signals registered on EventBus). Screenshot at `~/Desktop/magic_civ_diplomacy.png` shows both action-state paths (Ironhold at War / Goldvein at Neutral) in one frame.
|
||||
- ✓ AI decisions respect peace/war (no attacks during peace) — `_is_at_war` static helper in `simple_heuristic_ai.gd` gates `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within`; defaults to War when no relation key (EA: all pairs start at war). GUT tests in `test_simple_heuristic_ai_war_gate.gd` cover peace/war/friendly/missing-key cases.
|
||||
- ✓ AI decisions respect peace/war (no attacks during peace) — `_is_at_war` static helper in `simple_heuristic_ai.gd` gates `_collect_enemy_units`, `_collect_enemy_city_positions`, and `_enemy_within`; ~~defaults to War when no relation key (EA: all pairs start at war)~~ **[SUPERSEDED — canonical start state is PEACE per COMMUNICATIONS.md / p3-01]**. GUT tests in `test_simple_heuristic_ai_war_gate.gd` cover peace/war/friendly/missing-key cases.
|
||||
|
||||
## Non-goals
|
||||
|
||||
|
|
|
|||
130
.project/objectives/p3-16-ai-proactive-war-declaration.md
Normal file
130
.project/objectives/p3-16-ai-proactive-war-declaration.md
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
---
|
||||
id: p3-16
|
||||
title: AI proactive war-declaration via the courier system
|
||||
priority: p3
|
||||
status: partial
|
||||
scope: game1
|
||||
owner: warcouncil
|
||||
updated_at: 2026-06-23
|
||||
evidence:
|
||||
- src/simulator/crates/mc-ai/src/tactical/mod.rs (decide_tactical_actions — no diplomacy step)
|
||||
- src/simulator/crates/mc-ai/src/tactical/movement.rs (is_at_war gate + collect_enemy_city_positions)
|
||||
- src/simulator/crates/mc-player-api/src/comms_dispatch.rs (dispatch_war_declaration — the war-dec entry point the AI must call)
|
||||
- public/games/age-of-dwarves/docs/military/COMMUNICATIONS.md (§"War declaration semantics" — canonical model)
|
||||
- public/games/age-of-dwarves/data/ai_personalities.json (aggression axis 1–10)
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
The canonical courier-diplomacy model (`COMMUNICATIONS.md` §"War declaration
|
||||
semantics") assumes a player **dispatches a war-dec envelope** to enter war: the
|
||||
**sender** enters `War` immediately on dispatch and its units can attack the same
|
||||
turn; the **recipient** flips to `War` on delivery/interception; **defenders
|
||||
always retaliate when struck** regardless of formal `RelationState`. Pairs start
|
||||
at **peace** (`mc-player-api/src/projection.rs::project_tactical_relations` defaults
|
||||
unset pairs to 0 = peace; `mc-player-api/src/comms_dispatch.rs` flips the shared
|
||||
`RelationState` cell to `War` only on delivery).
|
||||
|
||||
**The gap:** the AI has **no proactive war-declaration logic**. `mc-ai`'s tactical
|
||||
entry point `decide_tactical_actions` (`src/simulator/crates/mc-ai/src/tactical/mod.rs`)
|
||||
runs movement → combat → settle → production → citizens with **no diplomacy step**,
|
||||
and there is **zero** `DeclareWar` / war-dec action anywhere in `mc-ai` (no
|
||||
strategic action variant, no caller of `comms_dispatch::dispatch_war_declaration`
|
||||
— the only non-test caller is the human dispatch path at
|
||||
`mc-player-api/src/dispatch.rs:1605`). `mc-ai/src/diplomacy.rs` covers only the
|
||||
p3-01 courier open-borders / shared-map offer/accept heuristics — not war.
|
||||
|
||||
Consequence (observed in a 200-turn hotseat self-play): AIs never initiate war →
|
||||
`collect_enemy_city_positions` (`tactical/movement.rs`) is always empty because it
|
||||
is gated through `is_at_war` (movement.rs:366) → no `locked_target` is ever set →
|
||||
military units never maneuver (48 successful moves across 200 turns). Because war
|
||||
never comes in AI-vs-AI play, the five clan personalities
|
||||
(`public/games/age-of-dwarves/data/ai_personalities.json`, `aggression` 1–10,
|
||||
warmonger = 9) do **not** manifest distinct aggression: per
|
||||
`mc-ai/src/tactical/thresholds.rs`, `aggression` only tunes combat posture **once
|
||||
already at war**, so a difference that only fires after war-declaration never
|
||||
fires at all.
|
||||
|
||||
This objective adds the missing strategic decision step so the AI dispatches a
|
||||
war-dec envelope through the courier system when conditions warrant, entering the
|
||||
existing at-war combat path and making personality `aggression` actually drive
|
||||
behavior.
|
||||
|
||||
## Why partial (not done)
|
||||
|
||||
The downstream consumption path (at-war combat, `collect_enemy_city_positions`,
|
||||
`locked_target` maneuver, `aggression`-tuned combat posture) **already exists and
|
||||
works** once a pair is at war — that half is shipped. What is missing is the
|
||||
**decision-to-declare** and its dispatch through the courier system. No new code
|
||||
has landed for the decision step yet; this file specs it.
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] **Strategic war-dec decision step.** Add a diplomacy decision step to the AI
|
||||
turn so that, per turn, the AI evaluates each *contacted* rival (first-contact
|
||||
gate per `COMMUNICATIONS.md` §4) and decides whether to declare war. The
|
||||
decision MUST consider: first-contact established, military balance
|
||||
(own vs. perceived enemy strength from PerceivedState, not ground truth), and
|
||||
the clan's `aggression` axis (`ai_personalities.json`). War-dec is a
|
||||
**strategic** move (it changes `RelationState`, not just a unit order), so the
|
||||
decision belongs in the strategic layer (`mc-ai/src/mcts.rs` /
|
||||
`evaluator.rs` action set, or a dedicated `mc-ai/src/diplomacy.rs` war-dec
|
||||
function invoked from the strategic turn driver), NOT inside the per-unit
|
||||
tactical movement loop. Mirror the existing courier-offer pattern in
|
||||
`mc-ai/src/diplomacy.rs` (clan hard-rules + axis-driven fallback).
|
||||
- [ ] **Dispatch through the courier system.** When the AI decides to declare war
|
||||
it MUST route through `mc_player_api::comms_dispatch::dispatch_war_declaration(state, sender, target)`
|
||||
— the same entry point the human war-dec action uses
|
||||
(`mc-player-api/src/dispatch.rs:1605`). This makes the **sender** enter `War`
|
||||
immediately on dispatch (sender units can attack that turn) and the
|
||||
**recipient** flip on delivery/interception, exactly per
|
||||
`COMMUNICATIONS.md` §"War declaration semantics". The AI MUST NOT directly
|
||||
mutate the relation cell or bypass the envelope — that would break the
|
||||
perceived-state / comm-tier asymmetry the courier model is built on.
|
||||
- [ ] **Personality differentiation manifests.** With the decision step live, a
|
||||
warmonger clan (`aggression` 9, e.g. Blackhammer) initiates war materially
|
||||
earlier / more often than a low-aggression clan in AI-vs-AI play. Verify with a
|
||||
self-play matchup harness showing distinct war-initiation turn distributions by
|
||||
clan (compare to the p0-02 matchup-grid methodology). The 200-turn "48 moves /
|
||||
no maneuver" symptom is gone: military units maneuver because
|
||||
`collect_enemy_city_positions` is now non-empty once war is declared.
|
||||
- [ ] **Tests headless.** `mc-ai` unit tests for the war-dec decision function
|
||||
(clan × military-balance × first-contact cases, including the floor where a
|
||||
low-aggression clan declines). A `mc-player-api` integration test that the AI
|
||||
decision dispatches an envelope via `comms_dispatch` and the sender's
|
||||
`RelationState` / `has_outbound_war` reflects war on the dispatch turn while the
|
||||
recipient stays at peace until delivery. All green on apricot.
|
||||
|
||||
## Code-fidelity cleanup (do alongside)
|
||||
|
||||
`mc-ai/src/tactical/movement.rs::is_at_war` (lines 366–369) still carries a stale
|
||||
comment — "default to war when a relation slot is missing … so the attack gate
|
||||
stays open in fresh games where the diplomacy table has not been initialized" —
|
||||
that mirrors the **superseded** p1-01 "all pairs start at war" model. It is
|
||||
harmless today only because `project_tactical_relations`
|
||||
(`mc-player-api/src/projection.rs:1312`) pre-fills the relations vec so no slot is
|
||||
ever missing. Once the canonical peace-start model is fully wired, this fallback's
|
||||
comment (and ideally the missing-slot → war default itself) should be corrected to
|
||||
reflect peace-start semantics. **This is a `.rs` change — not part of this
|
||||
docs-and-plan sync; flagged for the implementing specialist (warcouncil / mc-ai).**
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `p1-01` (diplomacy-lite, ✅ — peace/war state + the at-war combat path the AI
|
||||
enters; start-state semantics superseded by courier-diplomacy, see that file's
|
||||
banner).
|
||||
- `p3-01` (courier-diplomacy, ✅ game1-stretch — the war-dec envelope substrate
|
||||
and `comms_dispatch` dispatch path).
|
||||
- `COMMUNICATIONS.md` §"War declaration semantics" — canonical design this is
|
||||
built to.
|
||||
- Coordinates with `p0-02` (clan personalities) — this is what makes the
|
||||
`aggression` axis manifest in AI-vs-AI war initiation.
|
||||
|
||||
## Non-goals
|
||||
|
||||
- Peace-making / treaty AI beyond declaring war (the AI's offer/accept of peace is
|
||||
a separate decision; out of scope here).
|
||||
- Alliances / coalitions / joint-attack coordination (Game 2).
|
||||
- New `aggression`-axis tuning values — this objective wires the axis into a new
|
||||
decision, it does not retune the personalities themselves (that is p0-02 /
|
||||
p1-36 territory).
|
||||
|
|
@ -18,6 +18,7 @@ objectives:
|
|||
- p1-29h-stateful-tactical-decisiveness
|
||||
- p1-29i-refound-suppression
|
||||
- p1-29j-autoplay-rust-action-application
|
||||
- p3-16
|
||||
---
|
||||
|
||||
## Mandate
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ All three dispatch types produce the same payload shape:
|
|||
Envelope { sender, recipient, payload, route, dispatched_turn, eta_turn }
|
||||
```
|
||||
|
||||
Effects (war state, treaty signature, vision-share activation, intel-log entry) apply at envelope **arrival**, not dispatch.
|
||||
Effects on the **recipient** (recipient-side war state, treaty signature, vision-share activation, intel-log entry) apply at envelope **arrival**, not dispatch. The one **sender-side** exception is the war declaration: the sender enters `War` the instant it dispatches a war-dec envelope, so its units can attack the same turn — see [§War declaration semantics](#war-declaration-semantics). All effects on the *recipient* (including the recipient's own flip to `War`) still gate on arrival/interception.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue