From ad99dd924725ce3b3aaa77971663f101436bc2a7 Mon Sep 17 00:00:00 2001 From: Natalie Date: Tue, 28 Apr 2026 01:44:26 -0400 Subject: [PATCH] =?UTF-8?q?fix(@projects/@magic-civilization):=20?= =?UTF-8?q?=F0=9F=90=9B=20resolve=20phantom=20unlock=20in=20chronicle=5Fke?= =?UTF-8?q?eping=20culture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../p2-39-chronicle-hall-phantom-unlock.md | 59 +++++++++++++++++ .../objectives/p3-01-courier-diplomacy.md | 6 +- .../p3-03-courier-route-resolver.md | 63 +++++++++++++++++++ 3 files changed, 125 insertions(+), 3 deletions(-) create mode 100644 .project/objectives/p2-39-chronicle-hall-phantom-unlock.md create mode 100644 .project/objectives/p3-03-courier-route-resolver.md diff --git a/.project/objectives/p2-39-chronicle-hall-phantom-unlock.md b/.project/objectives/p2-39-chronicle-hall-phantom-unlock.md new file mode 100644 index 00000000..4adedef8 --- /dev/null +++ b/.project/objectives/p2-39-chronicle-hall-phantom-unlock.md @@ -0,0 +1,59 @@ +--- +id: p2-39 +title: Resolve `chronicle_hall` phantom unlock in `chronicle_keeping` culture tech +priority: p2 +status: open +scope: game1 +updated_at: 2026-04-27 +evidence: + - public/resources/culture/oral_tradition.json (line 96 — `chronicle_keeping.unlocks.buildings = ["chronicle_hall"]`) + - public/games/age-of-dwarves/data/buildings/mundane_wonders.json (line 102–115 — `bardic_circle`, the actual `chronicle_keeping`-gated wonder) + - .project/objectives/p3-01-courier-diplomacy.md (cycle 3 audit that surfaced the phantom) +--- + +## Summary + +The `chronicle_keeping` culture tech (era_4 oral_tradition pillar) declares +`unlocks.buildings = ["chronicle_hall"]`, but no `chronicle_hall` building file +exists anywhere in `public/resources/buildings/` or +`public/games/age-of-dwarves/data/buildings/`. Surfaced by the p3-01 cycle 3 +audit when the era_4 Rune Scribe culture path tried to extend +`chronicle_hall.enables_units` and discovered it was a phantom. + +The actual building gated on `culture_required: "chronicle_keeping"` is +`bardic_circle` (mundane_wonders.json:102 — tier 4, era 2 wonder). The phantom +is a stale unlock string left over from an earlier design. + +This is a pre-existing data integrity bug, separate from p3-01's courier scope. + +## Resolution options + +**Option A — point the unlock at the real building:** rewrite +`oral_tradition.json:96` from `"chronicle_hall"` to `"bardic_circle"`. Smallest +diff. Truthful given current data. + +**Option B — author a real `chronicle_hall` building:** an era_4 normal (non-wonder) +culture-tech-unlocked institution. Distinct from `bardic_circle` (wonder, tier 4). +Bigger diff. Adds a new strategic institution and unblocks the era_4 Rune Scribe +culture path that p3-01 abandoned. + +**Default to Option A** unless explicitly requested otherwise. Option B becomes +viable only if the design wants culture-side courier production at era_4, which +is currently out of scope. + +## Acceptance criteria + +- [ ] Decide A vs B (default A). +- [ ] If A: edit `public/resources/culture/oral_tradition.json:96` `"chronicle_hall"` → `"bardic_circle"`. Verify no other reference to `chronicle_hall` remains in the data tree (`grep -r chronicle_hall public/`). +- [ ] If B: author `public/resources/buildings/chronicle_hall.json` conforming to `building.schema.json`. Add to `public/games/age-of-dwarves/data/buildings/manifest.json`. +- [ ] `python3 tools/validate-game-data.py` → 0 failed. +- [ ] Run dashboard regen. + +## Non-goals + +- Authoring or rebalancing the era_4 Rune Scribe culture path (separate scope inside p3-01 if pursued later). +- Audit of other phantom unlocks across the culture trees (out of scope; address one at a time as discovered). + +## Dependencies + +- None. Pure data integrity fix. diff --git a/.project/objectives/p3-01-courier-diplomacy.md b/.project/objectives/p3-01-courier-diplomacy.md index 87eb67a4..1696ae58 100644 --- a/.project/objectives/p3-01-courier-diplomacy.md +++ b/.project/objectives/p3-01-courier-diplomacy.md @@ -88,13 +88,13 @@ flavor stays Game 3 (Elves). ## Acceptance criteria -- [ ] **Data pack — units (8 remaining + 1 done)**: 9 new unit JSONs in `public/games/age-of-dwarves/data/units/` matching the Dwarven ladder above: `foot_runner` ✓ (cycle 1), `tunnel_runner`, `rune_scribe`, `hold_courier`, `beacon_bearer`, `steam_messenger`, `resonance_telegrapher`, `hold_network_warden`. (No era_10 unit — Adamantine Echo is wonder-only.) Each declares its era, prerequisite tech, prerequisite building, movement speed, intercept rules, and upgrade-from chain. +- [x] **Data pack — units** (cycles 1–3, **8 unit files** total — locked design has no era_10 unit since Adamantine Echo is wonder-only): all 8 authored in `public/games/age-of-dwarves/data/units/` matching the Dwarven ladder: `foot_runner`, `tunnel_runner`, `rune_scribe`, `hold_courier`, `beacon_bearer`, `steam_messenger`, `resonance_telegrapher`, `hold_network_warden`. Each declares era, `tech_required`, movement speed, `courier_tier.delay_class`, and `upgrades_to` chain. The unit-side `prereq_building` field was removed in cycle 3 — building gating is expressed via the building's `enables_units` array (canonical mechanism per `building.schema.json`). - [ ] **Data pack — buildings (revised 2026-04-27, audited 2026-04-27)**: 6 new building files (the linear hub chain + era_10 wonder): `messenger_hut`, `hold_post`, `steam_forgery_annex`, `resonance_chamber`, `hold_network_citadel`, `adamantine_echo` — all authored cycle 1/2. Plus 1 existing non-wonder building extended with `enables_units` for the only legitimate culture path: `gathering_hall` (era_3 / Tunnel Runner). Era 4-9 culture paths abandoned after audit: every era_5+ culture-tech-unlocked building is `wonder_type: "world"`, and `chronicle_hall` (era_4) is a phantom (no file exists, only referenced in culture-tech unlocks). - [ ] **Data pack — improvements (revised 2026-04-27)**: 5 improvement files in `public/resources/improvements/` (canonical store) — `tunnel` (era_3), `hold_road` (era_5, upgrade of `road`), `steam_track` (era_7, severable), `resonance_wire` (era_8, severable), and **`beacon_tower`** (era_6, killable hilltop structure built by engineer, provides LOS chain — relocated from buildings/). Cycle 2 wrote the first 4; beacon_tower needs c3 to relocate + restructure to improvement schema. - [ ] **Data pack — techs**: 3 new prereq tech JSONs authored — `tunnel_paths` (era_3, ecology pillar), `beacon_chain` (era_6, military pillar), `rune_resonance` (era_8, metallurgy + runelore crossover). The other 6 tier prereqs (`tracking`, `runelore`, `dwarf_heritage`, `steam_forging`, `combined_arms`, `adamantine_forging`) all exist in the current tech tree — no work needed. - [x] **Rust — `mc-trade` extension** (cycle 4): `DiplomaticAgreement` enum + `OpenBordersAgreement` + `SharedMapAgreement` types landed; `TradeLedger` migrated to `Vec` with `next_agreement_id` counter; existing luxury-swap call sites projected through the `LuxurySwap` variant. -- [ ] **Rust — courier route resolver** (cycle 4 partial): `step_shared_map_agreements` driver + `CourierMapView` trait scaffold + `CourierRoute` state struct + 3 lifecycle integration tests passing. Remaining: actual hex-graph pathfinding, per-tier movement-speed table, severable-improvement integration. -- [x] **Rust — events** (cycle 4): six payload-bearing event structs (`CourierDispatched`, `CourierIntercepted`, `MapDelivered`, `OpenBordersSigned`, `OpenBordersExpired`, `SharedMapExpired`), each carrying `agreement_id`. The originally-listed `TelegraphLinePillaged`/`SemaphoreTowerDestroyed`/`WirelessJammed` were Earth-flavored and superseded by the Dwarven ladder; severable-improvement events fold into the route resolver's intercept path instead. +- [ ] **Rust — courier route resolver scaffold** (cycle 4 partial — physics layer split into [p3-03](p3-03-courier-route-resolver.md)): `step_shared_map_agreements` driver + `CourierMapView` trait + `CourierRoute` state struct + 3 lifecycle integration tests using `MockMap` fixture all landed in p3-01 cycle 4. The remaining work — real hex pathfinding, per-tier movement-speed table, severable-improvement integration, Hold-Network reroute, Adamantine Echo instant sync — moved to **p3-03** so it can land independently. Bullet 6 flips to ✓ once p3-03 closes. +- [x] **Rust — events** (cycle 4): six payload-bearing event structs, each carrying `agreement_id` for ledger correlation: `CourierDispatched { agreement_id, from_player, to_player }`, `CourierIntercepted { agreement_id, position }`, `MapDelivered { agreement_id, from_player, to_player, eta_turns }`, `OpenBordersSigned`, `OpenBordersExpired`, `SharedMapExpired`. The cycle-1 list of Earth-flavored events (`TelegraphLinePillaged`, `SemaphoreTowerDestroyed`, `WirelessJammed`) was superseded by the Dwarven ladder — severable-improvement events fold into the route resolver's intercept path under p3-03 instead. - [ ] **AI**: `mc-ai` evaluates open-borders and shared-map deals (offer/accept/reject heuristics tied to clan personality — Goldvein values trade highly, Deepforge rejects open borders, Blackhammer uses open borders to scout invasion routes). - [ ] **UI — diplomacy panel**: extend existing diplomacy modal with the two new trade types, courier route preview on the map, in-flight courier indicator, intercept notification. - [ ] **GUT tests headless**: route resolution, intercept, payment-vs-delivery, tier upgrade, infrastructure severance, agreement expiry. diff --git a/.project/objectives/p3-03-courier-route-resolver.md b/.project/objectives/p3-03-courier-route-resolver.md new file mode 100644 index 00000000..1db6f692 --- /dev/null +++ b/.project/objectives/p3-03-courier-route-resolver.md @@ -0,0 +1,63 @@ +--- +id: p3-03 +title: Courier route resolver — real hex pathfinding, per-tier movement, severable infrastructure +priority: p3 +status: open +scope: game1-stretch +owner: envoy +updated_at: 2026-04-27 +evidence: + - .project/objectives/p3-01-courier-diplomacy.md (parent — bullet 6 split out into this objective) + - src/simulator/crates/mc-trade/src/lib.rs (`CourierMapView` trait + `CourierRoute` struct + `step_shared_map_agreements`, scaffold landed in p3-01 cycle 4) + - src/simulator/crates/mc-trade/tests/courier_lifecycle.rs (3 lifecycle integration tests using `MockMap`) + - public/games/age-of-dwarves/data/units/{foot_runner,…,hold_network_warden}.json (8 courier units with `courier_tier` metadata) + - public/resources/improvements/{tunnel,hold_road,steam_track,resonance_wire,beacon_tower}.json (route infrastructure, `severable` flagged on steam_track + resonance_wire) +--- + +## Summary + +p3-01 cycle 4 landed the **types** for courier-gated diplomacy +(`DiplomaticAgreement` enum, `OpenBordersAgreement`, `SharedMapAgreement`, +`CourierRoute`, `CourierMapView` trait, `step_shared_map_agreements` driver, six +event payloads). It also landed three lifecycle integration tests against a +`MockMap` fixture that hard-codes intercept probability. + +This objective owns the **physics layer** that lets those types resolve against +the actual game world: hex pathfinding from sender capital to receiver capital, +per-tier movement-speed table feeding ETA calculations, and integration with +severable improvements (Steam Track, Resonance Wire, Beacon Tower) so that a +mid-route pillage actually intercepts the courier. + +Splitting this out of p3-01 lets the parent objective close at "data + types + +lifecycle" once AI/UI/tests/proof scenes land, while the route-resolver work +stays its own bounded chunk of mc-trade ↔ mc-map glue. + +## Acceptance criteria + +- [ ] **Real `CourierMapView` impl in mc-turn (or new `mc-courier` crate)**: implements the trait against the real `mc-map` hex grid + improvements layer. No fixture intercept probabilities — intercept must be deterministic from world state. +- [ ] **Hex pathfinding sender_capital → receiver_capital**: A* or Dijkstra over the courier's allowed terrain (Foot Runner avoids mountains, Tunnel Runner prefers tunnels, Steam Messenger requires Steam Track, Resonance Telegrapher requires Resonance Wire, etc.). Path stored in `CourierRoute` for replay + UI overlay. +- [ ] **Per-tier movement-speed table**: lookup keyed by `courier_tier.delay_class` from each unit JSON. Step function consumes movement points per turn against path length to produce ETA + per-turn position update. +- [ ] **Severable-improvement integration**: pillaging a Steam Track / Resonance Wire / Beacon Tower hex on a courier's planned route emits `CourierIntercepted` (route severed) on the next step. Integration test: courier in transit, pillage event fires, intercept resolves, payment retained. +- [ ] **Hold-Network mesh re-route (era_9+)**: when sender + receiver both control a Hold-Network Citadel, severed links auto re-route through the nearest alternate path within X hexes. Failing that, the intercept resolves normally. +- [ ] **Adamantine Echo instant sync (era_10)**: when both sender + receiver have built the Adamantine Echo wonder, shared-map deals deliver next turn regardless of physical route. Encodes the "wonder collapses delay to zero" mechanic from the locked design table. +- [ ] **Per-turn `CourierDispatched`/`MapDelivered` events emitted with real positions**: not the fixture stub. Position field reflects the hex the courier currently occupies. +- [ ] **Tests**: + - Real-map pathfinding: foot_runner from one capital to another, ETA matches movement table. + - Severance: pillage Steam Track mid-route → intercept on next step. + - Hold-Network reroute: severed Steam Track with two Hold-Network Citadels → reroute, no intercept. + - Adamantine Echo: agreement delivered next turn even with no intervening infrastructure. + - Tier upgrade: re-running the same agreement after tier upgrade shrinks ETA. +- [ ] **Updated p3-01 bullet 6**: link this objective and flip 6 to ✓ once these criteria all close. + +## Non-goals + +- AI heuristics for courier dispatch (p3-01 bullet 8, separate cycle). +- UI courier overlay on the diplomacy map (p3-01 bullet 9). +- Proof scenes (p3-01 bullet 11). +- Per-clan personality tuning of intercept aggression — stays in mc-ai. + +## Dependencies + +- **Inputs:** p3-01 cycle 4 types + driver (already landed). `mc-map` hex grid + improvements layer (existing). Per-tier movement values from the 8 courier unit JSONs (already authored). +- **Blocks on:** none — all prerequisites are landed. +- **Enables:** p3-01 bullet 6 closure; p3-01 bullets 8/9/10/11 can land in parallel against this objective's API.