docs(@projects/@magic-civilization): 📝 update civic-modifier-propagation.md status and acceptance criteria

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-05-15 00:27:10 -07:00
parent c2de4b43f9
commit fcfae73ebe

View file

@ -2,12 +2,12 @@
id: p3-05e
title: "Civic modifier propagation — apply civic effects to per-city yields"
priority: p3
status: stub
status: partial
scope: game1
category: civics
owner: unassigned
created: 2026-05-03
updated_at: 2026-05-03
updated_at: 2026-05-14
blocked_by: [p3-05b, p3-05c, p3-05d]
follow_ups: []
---
@ -18,11 +18,16 @@ With the three axis catalogs (`p3-05b/c/d`) and `CivicState` (`p3-05a`) in place
## Acceptance
- ❌ `mc-civics::resolve_modifiers(state: &CivicState) -> ResolvedModifiers` returns a typed modifier bundle merging the three active civics. Anarchy axes contribute zero modifiers.
- ❌ `mc-economy::city_yield::compute` consumes `ResolvedModifiers` (passed via context, not global mutable state); applies in documented order: base → additive → multiplicative.
- ❌ `mc-city::specialist::contribution` consumes `ResolvedModifiers.specialist_xp_rate` (from Labor axis) when crediting XP per `p2-56b`.
- ❌ `cargo test -p mc-civics test_modifier_resolution_anarchy_zero` and `cargo test -p mc-economy test_civic_modifier_changes_yield` green.
- ❌ Headless parity test: switching from `mercantile_markets` to `planned_economy` measurably shifts per-city gold yield in the documented direction.
- ✓ `mc-civics::resolve_modifiers(state: &CivicState, &CivicCatalog) -> ResolvedModifiers` returns a typed modifier bundle merging the three active civics. Anarchy axes contribute zero modifiers. Evidence: `src/simulator/crates/mc-civics/src/lib.rs` (new crate added to workspace `Cargo.toml`); `ResolvedModifiers` is a typed struct (18 fields covering every modifier key in the 15 catalog JSONs); `axis_choice_id` returns `None` for the anarchy sentinel.
- ✓ `mc-economy::city_yield::compute` consumes `ResolvedModifiers` (passed by reference, not global mutable state); applies in documented order: base → additive → multiplicative. Evidence: `src/simulator/crates/mc-economy/src/city_yield.rs::compute(base: CityYield, mods: &ResolvedModifiers) -> CityYield`; module docstring documents the three-step order; `test_application_order_additive_before_multiplicative` exercises it.
- ❌ `mc-city::specialist::contribution` consumes `ResolvedModifiers.specialist_xp_rate` (from Labor axis) when crediting XP per `p2-56b`. **Deferred**`specialist_xp_rate` field is present on `ResolvedModifiers` and is multiplied correctly across axes (test `test_partial_anarchy_keeps_other_axes` covers `inequality_amplifier` with the same code path); wiring it into the existing `mc-city::specialist` site is a small follow-up that drags p2-56b semantics into this ticket and was out of scope for the time budget.
- ✓ `cargo test -p mc-civics test_modifier_resolution_anarchy_zero` and `cargo test -p mc-economy test_civic_modifier_changes_yield` green. Evidence: `cargo test -p mc-civics test_modifier_resolution_anarchy_zero``1 passed`; `cargo test -p mc-economy test_civic_modifier_changes_yield``1 passed` (this session).
- ✓ Headless parity test: switching from `mercantile_markets` to `planned_economy` measurably shifts per-city gold yield in the documented direction. Evidence: `mc-economy/src/city_yield.rs::test_civic_modifier_changes_yield` builds both `CivicState`s, resolves modifiers, and asserts `mercantile gold (120) > planned gold (95)` from base 100 (mercantile +20%, planned -5%). Test runs under `cargo test` — no display server required.
## Status notes
- The catalog reference doc `public/games/age-of-dwarves/docs/civics/CIVICS.md` named in the original context does not exist; `CIVIC_OVERVIEW.md` exists but does not document additive-vs-multiplicative semantics. Convention is now documented in the `mc-civics` lib docstring (key-suffix table). Authoring the design doc is a follow-up, not a Rust-side blocker.
- Bullet 3 (`mc-city::specialist`) is the only open item. K = 4 / N = 5 → status `partial`.
## Source-of-truth rails