fix(@projects/@magic-civilization): 🐛 update balance tuning objectives and data schemas

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
Natalie 2026-04-18 06:39:59 -07:00
parent 212472544f
commit 1803e9857b
5 changed files with 24 additions and 14 deletions

View file

@ -183,3 +183,5 @@ The specific bullets citing canopy fields + weather_event records in `turn_stats
2026-04-18 02:20 tourguide p1-16 DONE + wave-A relic cleanup: scope-hygiene rewrites across HomePage (Hero/Pitch/FEATURES/LoreSection — magic paragraphs gated via <EpisodeGate min=2>), CommunicationsPage (Archon Telepathy row gated), PromotionsPage (removed disciplines/infusions imports + replaced Mana Infusions block with Game 2 pointer note), survival-guide/data.ts (Life T3 spell → mundane quarantine-district mechanic), PersonalityAxesPage (channels-ley-lines prose → knowledge-infrastructure prose), OverviewTab (High Archon roadmap row → succession-crisis roadmap row). Grep gate `grep -RE 'magic schools|High Archon|mana nodes|ley lines' | grep -v 'EpisodeGate|>= 2|VITE_DEV_GUIDE|//'` returns zero hits. New `e2e/scope-hygiene.spec.ts` (5 routes × 11 forbidden substrings) → 5/5 green against CI=1 prod build (VITE_DEV_GUIDE=0). All-routes e2e 51/51 green unchanged. Deployed to mc.next.black.local via direct-IP workaround (plum mDNS cache glitch). Rate-limited guide-web agent landed 4/6 files; tourguide patched the remaining 2 after the limit lifted. p2-32 JSON data files (map-topologies, ep1-systems, homepage-features, shipping-roadmap) authored in parallel by the game-data agent — consumer-swap pending. [ref: tourguide, p1-16, p2-32]
2026-04-18 03:45 tourguide waves B/C/D + race-gate landed: **p2-32 DONE** — all four data-driven consumers swapped (HomePage FEATURES, MapTypesPage, EpisodeDwarvesPage, OverviewTab roadmap tables) read from `homepage-features.json` / `map-topologies.json` / `episodes/ep1-systems.json` / `shipping-roadmap.json` via `@data/` alias; 4 new JSON schemas in `data/schemas/` wired into `tools/validate-game-data.py::validate_guide_data` (203 PASS, 0 FAIL incl. the 4 new files). **p2-30 PARTIAL**`PagePrimitives.tsx` extended with `DataCard` (`$variant` base/compact/topology), `StatsGrid`, `StatCell`, `QualityIndicator`; MapTypesPage (engine) + ExpansionsPage + TeamPage (meta) migrated; Biome/Species/FloraBar deferred as biggest mechanical diffs. **p2-31 PARTIAL**`useUrlFilter<T>(key, values, fallback)` hook extracted to `public/games/age-of-dwarves/guide/src/hooks/useUrlFilter.ts` (re-exported from `@magic-civ/guide-engine`), `ObjectivesTab` rebased + `ClimateEventsPage` migrated; `shareable-urls.spec.ts` covers weather-category deep links; Species/Biome migrations paired with p2-30 primitives swap (deferred). **p2-29 PARTIAL** — WelcomeModal race grid now dynamic: `raceOptions = ALL_ELIGIBLE_RACES.filter(r => r.episode <= activeEpisode)` via `useEpisode()`, `App.tsx` filters `playableRaces` before `PreferencesProvider` so `resolveRace('random')` cannot roll a non-episode race (Game 1 = Dwarves only, dev bundle = all 16 races with episode fields); HomePage FEATURES data-driven with `min_episode` gating; dedicated `welcome.spec.ts` Dwarf-Female → Begin → theming spec still pending. Homepage-features.json correction: "16 Asymmetric Races" reclassified `min_episode: 2`; added "Five Rival Dwarf Clans" (Iron Legion / Forge-Wrights / Deep Delvers / Gold Hall / Stonekeepers) as the Game 1 flagship card. [ref: tourguide, p2-29, p2-30, p2-31, p2-32]
2026-04-18 05:40 tourguide waves B/C/D PROMOTED to DONE via 3-agent experts-team (`tourguide-waves-finish-20260418-0524`, all guide-web specialists, slot peak 3/10). **p2-29 DONE**`welcome.spec.ts` e2e authored at `public/games/age-of-dwarves/guide/e2e/welcome.spec.ts` (welcome-tester): 12 assertions walking `page.goto('/')` → Dwarf + Female buttons → `getByPlaceholder('Leave blank to use the default leader name')` filled with "Brenna Ironshield" → `Enter the Guide` → HomePage `<LoreEyebrow>` visible + name in `<strong>` + Dwarf vocab + zero forbidden Game 2+ substrings + zero console/pageerror events (IGNORED patterns match sibling specs). Role/label/text locators only — no CSS classes. Authored not executed; apricot Forgejo runner owns the verification run. **p2-30 DONE** — BiomeBrowserPage + SpeciesBrowserPage migrated to shared primitives (biome-migrator + species-migrator). BiomeBrowserPage: Card/CardHeader/CardTitle/StatRow/QualityRange/etc. deleted, replaced with `DataCard($variant="compact")` + `StatsGrid` + `StatCell` + `QualityIndicator`; `PieSvg` stroke now reads `theme.colors.background.primary` instead of `#1a1510`. SpeciesBrowserPage: full rewrite onto `useGuideData().speciesLibrary` (lens-aware), `createPortal` detail modal, three consumer wrappers (dwarves/kzzkyt/elves) reduced to 6-line shims. FloraBar → `<StackedBarChart segments={...} height={6} />` primitive in `PagePrimitives.tsx` (callers pass resolved theme tokens). Flora palette promoted to theme: `buildTheme.ts::FLORA_PALETTE` (dark + light) injected as `theme.colors.flora.{canopy, undergrowth, fungi}` — naming follows the `biome.flora_climax.*` data fields rather than the brief's placeholder `dense/sparse/dead`. Three new `styled-components-augmentation.d.ts` files (one per episode guide) redeclare `DefaultTheme` with `Omit<ThemeInterface, 'colors'> & { colors: ThemeInterface['colors'] & { flora: ... } }` because `@lilith/ui-theme` declares `colors` as an inline literal that can't be interface-merged. Final greps: `grep -E "(#1a9928|#8cc634|#9040a0)" BiomeBrowserPage.tsx` → 0; `grep -E "^const (Card|CardHeader|CardTitle|StatRow|TraitRow) = styled" [Biome|Species]BrowserPage.tsx` → 0. **p2-31 DONE**`useUrlFilter` adoption fanned out: BiomeBrowserPage (`?category=` + `?biome=<id>` inline scroll-highlight with `role="tablist"` a11y), SpeciesBrowserPage (`?role=&biome=&quality=&species=<id>` with portal modal on history stack so Back closes). Plum verification: `pnpm typecheck` + `pnpm build` (4.96s) clean on the dwarves guide; three terminations (welcome-tester, species-migrator, biome-migrator) clean. apricot Forgejo runner owns `welcome.spec.ts` + all-routes + scope-hygiene e2e when next dispatched. [ref: tourguide, p2-29, p2-30, p2-31]
2026-04-18 p1-05 LUXURY-UNGATE FALSIFIED (shipwright): tested the "un-gate ivory + furs" lever that p1-05's Remaining section listed as a JSON-only path to closing bullet 5 (luxury variance min≥3). Set `revealed_by_tech: null` on ivory + furs in `public/resources/resources.json`, ran apricot batch 20260418_062941. Per-seed p0 luxury counts: 0,0,0,5,0,0,0,0,0,0 — min=0, only seed 3 (which ran full T300 without early domination) hit 5. Un-gate makes luxury tiles VISIBLE from turn 1 but players still need time to: (a) expand borders to reach them, (b) research the improvement tech, (c) build the improvement. Fast-combat games ending by T75-T150 via domination don't have any of that time. **The real blocker is game length, not tech gates**. Reverted the un-gate. Updated p1-05 objective to cite this falsification evidence and mark "no Shipwright-side lever remains" — closure requires warcouncil's p0-08 domination tempo tune to push median game length past T250. p1-05 stays `partial` per integrity rule. [ref: p1-05]

View file

@ -66,10 +66,16 @@ need re-tuning against the Rust rate in a follow-up pass.
- [x] Median `combats ≥ 120`**median 808**.
- [ ] **Luxury variance ≥ 3 distinct luxuries per seed**
per-seed p0 distinct luxuries in p016b: 3,1,3,1,2,1,8,3,3,0 (min 0).
Regressed from score_fix3 min=3 due to faster combat tempo in
p016b ending games before luxury-gating techs finish. Tune lives
in `resources.json` tech-gates but requires coordination with
p0-08 domination pacing — out of p1-05 JSON-only scope.
**Tested un-gating approach 2026-04-18 and found ineffective**:
batch `apricot-20260418_062941` un-gated furs + ivory (removed
`trapping` tech-gate) → per-seed luxuries: 0,0,0,5,0,0,0,0,0,0
(only seed 3 had 5, and it ran full T300 without early domination).
Un-gating revealed luxury tiles but games still end too fast for
border-expansion + improvement construction on those tiles. Revert
applied — the true blocker is game-length (p0-08 domination tempo),
not the tech gate. Only seeds reaching T250+ produce luxury variance
≥3 regardless of resources.json state. Closure requires slower
domination pacing, which is warcouncil / p0-08 scope.
- [x] **Strategic gate rejections ≥ 1 across the batch**
1670 `strategic_gate_rejected` events in p016b across all 10 seeds.
- [ ] **`personality_win_balance` PASS** per p0-02 acceptance. *(50-game
@ -80,9 +86,10 @@ need re-tuning against the Rust rate in a follow-up pass.
## Remaining to reach done
1. Luxury variance min≥3 per seed — requires either un-gating 2-3 early
luxuries in `resources.json` (ivory, furs, salt) OR slowing early
combat so games reach 150+ turns consistently. Coordinate with p0-08.
1. Luxury variance min≥3 per seed — un-gating experiment falsified (see
batch `apricot-20260418_062941`). Real blocker is game length; closure
requires warcouncil's p0-08 domination tempo tune to push median game
length past T250. **No Shipwright-side lever remains.**
2. Personality win balance — warcouncil 50-game sample (p0-02 owner).
## Depends on

View file

@ -1,11 +1,11 @@
{
"generated_at": "2026-04-18T13:04:18Z",
"generated_at": "2026-04-18T13:38:49Z",
"totals": {
"done": 54,
"missing": 8,
"oos": 18,
"partial": 17,
"stub": 4,
"partial": 17,
"oos": 18,
"missing": 8,
"total": 101
},
"objectives": [

View file

@ -343,7 +343,7 @@
"forest",
"arctic"
],
"revealed_by_tech": null,
"revealed_by_tech": "trapping",
"yields": {
"food": 0,
"production": 0,
@ -378,7 +378,7 @@
"grassland",
"desert"
],
"revealed_by_tech": null,
"revealed_by_tech": "trapping",
"yields": {
"food": 0,
"production": 1,

View file

@ -7,7 +7,8 @@
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
# SCRIPT_DIR is src/simulator → REPO_ROOT is two parents up, not one.
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
OUT_DIR="$REPO_ROOT/.local/build/wasm"
mkdir -p "$OUT_DIR"