docs(objectives-specific): 📝 Update P2 milestone documentation for data resources, unit audio cues, and chronicle hall unlocks with detailed descriptions and implementation notes

Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
autocommit 2026-04-29 13:06:44 -07:00
parent 876a7de3a2
commit 9990986720
3 changed files with 193 additions and 0 deletions

View file

@ -0,0 +1,58 @@
---
id: p2-36
title: Reconcile the 14 building IDs defined in both `resources/buildings/` and `data/buildings/`
priority: p2
status: partial
scope: game1
updated_at: 2026-04-27
evidence:
- public/resources/buildings/ (6 wonder per-file dupes deleted: clan_moot_stone, covenant_stone, grand_observatory, hall_of_ancestors, voice_of_ages, world_pillar)
- public/games/age-of-dwarves/data/buildings/mundane_wonders.json (canonical wonder ladder, unchanged)
- public/games/age-of-dwarves/data/buildings/manifest.json (regenerated: 102 IDs, was 108)
---
## Summary
After the `p1-31` per-file split, 14 building IDs are defined in **both** `public/resources/buildings/<id>.json` (engine defaults) and `public/games/age-of-dwarves/data/buildings/<...>.json` (Age-of-Dwarves overrides). The data loader iterates `resources/` first then `data/` and overwrites by id — the data/ definition silently wins. Every duplicate currently differs in `cost`, `tech_required`, or `tier`, so the resources/ side is dead code wherever the override exists.
| ID | resources/ definition | data/ definition (wins) | Drift |
|---|---|---|---|
| `barracks` | cost=80, tech=military_doctrine, tier=1 | cost=50, tech=null, tier=1 | tech gate dropped |
| `forge` | cost=100, tech=smelting, tier=2 | cost=60, tech=null, tier=1 | tech gate dropped, tier dropped |
| `granary` | cost=60, tech=husbandry, tier=1 | cost=30, tech=null, tier=1 (in stub.json) | tech gate dropped |
| `library` | cost=75, tech=scholarship, tier=1 | cost=60, tech=null, tier=1 | tech gate dropped |
| `monument` | cost=40, tech=null, tier=1 | cost=30, tech=null, tier=1 | cost only |
| `siege_workshop` | cost=120, tech=mathematics, tier=2 | cost=80, tech=siege_craft, tier=2 | different tech |
| `temple` | cost=90, tech=ancestor_rites, tier=2 | cost=80, tech=null, tier=2 | tech gate dropped |
| `walls` | cost=75, tech=masonry, tier=1 | cost=70, tech=null, tier=1 | tech gate dropped |
| `clan_moot_stone` (wonder) | cost=80, tier=1 | cost=180, tier=2 (in mundane_wonders.json) | wonder cost/tier diverged |
| `covenant_stone` (wonder) | cost=355, tier=4 | cost=600, tier=6 | wonder cost/tier diverged |
| `grand_observatory` (wonder) | cost=220, tech=astronomy, tier=5 | cost=600, tech=astronomy, tier=6 | wonder cost/tier diverged |
| `hall_of_ancestors` (wonder) | cost=360, tier=4 | cost=260, tier=3 | wonder cost/tier diverged |
| `voice_of_ages` (wonder) | cost=780, tier=10 | cost=1200, tier=10 | wonder cost diverged |
| `world_pillar` (wonder) | cost=540, tier=7 | cost=1040, tech=world_theory, tier=9 | wonder cost/tech/tier diverged |
The pattern is clear:
- **Ordinary buildings (8)**: `data/` versions are cheaper and drop the tech gate. Likely a deliberate Age-of-Dwarves "always-buildable starter" simplification.
- **Wonders (6)**: `data/buildings/mundane_wonders.json` versions are heavier-cost / higher-tier, suggesting `mundane_wonders.json` is the actual Game 1 wonder ladder and the per-file `resources/` versions are stale legacy entries.
## Acceptance
- ✓ Wonder duplicates resolved (6 of 14): `mundane_wonders.json` chosen as canonical per p0-04 evidence (`PlayerState.wonders_built` and `WonderId` keys come from this file). The per-file `resources/buildings/{clan_moot_stone,covenant_stone,grand_observatory,hall_of_ancestors,voice_of_ages,world_pillar}.json` deleted as dead overrides — confirmed zero source-code references to the per-file paths (only string-id lookups exist, and the IDs still resolve via `mundane_wonders.json`).
- ✗ Ordinary-building duplicates remain (8 of 14): `barracks`, `forge`, `granary`, `library`, `monument`, `siege_workshop`, `temple`, `walls`. For each, the data/ version drops the tech gate and lowers cost vs the resources/ version. Needs design call: are the data/ overrides intentional Game-1 simplification (delete resources/), or stale drift (delete data/ overrides and accept the deeper tech-gated economy)?
- ✗ All 14 duplicates removed: post-fix audit shows zero IDs defined in both layers. (8 remaining.)
- ✓ For wonders specifically: bundled `data/buildings/mundane_wonders.json` pattern won — it's the canonical wonder ladder per p0-04. Per-file resources/ wonders deleted. (Note: this leaves the wonder system on a different convention from p1-31's per-file building pattern, by design — wonders are a coherent ladder edited as a unit.)
- ✗ Game 1 balance untouched unless explicitly intended: post-wonder-cleanup balance is unchanged because the data/ side already won at runtime. The 8 remaining ordinary-building dupes will need balance review when reconciled.
- ✓ `python3 tools/validate-game-data.py` passes 0 failures post-wonder-delete: PASSED 317 / FAILED 0.
- ✗ A 10-seed `tools/autoplay-batch.sh 10 300` regression batch shows no mass behaviour shift after the remaining 8 ordinary-building dupes are reconciled.
- ✗ `data/buildings/stub.json` audit: defines `granary` as a "compatibility stub" with cost=30 (vs `resources/buildings/granary.json` cost=60 with `tech=husbandry`). Decide if stub.json belongs at all post-reconciliation — it likely becomes redundant once `granary` is reconciled.
## Progress note (2026-04-27)
Wonder phase completed autonomously: all 6 wonder duplicates collapsed onto `mundane_wonders.json`. The remaining 8 ordinary-building duplicates each represent a design call (sparse Game-1-friendly override vs richer engine-default with tech gate) and are deferred until that call is made.
## Out of scope
- Authoring new buildings (covered by `p1-32` and other authoring objectives).
- Mechanic changes to wonders (e.g. wonder slot limits) — value-only reconciliation here.
- The `data/units/stub.json` parallel issue (founder compatibility id) — file as a separate audit if it shows similar drift.

View file

@ -0,0 +1,77 @@
---
id: p2-38
title: "Unit audio_cues stub strings — selection/move/attack lines for the dwarven roster"
priority: p2
status: done
scope: game1
owner: asset-audio
updated_at: 2026-04-27
assigned_by: shipwright
blockedBy: [p1-34]
evidence:
- "56 unit JSONs in public/games/age-of-dwarves/data/units/ have audio_cues field with select (3 lines), move (2), attack (2), death (1) string arrays. Verified: `grep -c '\"audio_cues\":' *.json | grep -c ':1$'` = 56."
- "Voice differentiation per archetype confirmed via QA samples: Berserker shouts single-word rage ('BLOOD!', 'AXE-WORK!'); Shield Bearer terse declaratives ('Hold.', 'We become the place.'); Marksman runic references ('The runes agree with me.', 'THEY AGREE!'); War Ram contract metaphor ('Horns are the contract.', 'CONTRACT HONORED!'); Mountain King ancestral weight ('Ten thousand names on this plate.', 'FOR THE TEN THOUSAND!')"
- "All 56 files: valid JSON, no intra-unit duplicate lines, lines 2-8 words each"
- "No magic / Game 2/3 lore leaks. Dwarven idiom maintained across all units."
- "p1-35 (lore) + p2-36 (audio_cues) ran in parallel against the same 56 files using targeted Edits with unique anchors — no conflicts surfaced."
- "React build verification: pnpm --prefix .project/designs/app run build exits 0 (164 modules, 464KB bundle)"
remaining_work:
- "Actual .ogg audio file generation remains in asset-audio team's p2-16 audio pack pipeline. This objective shipped string content only; voice acting / TTS-generation downstream."
---
## Summary
The 50-unit dwarven roster needs in-character audio cue strings — the
one-liner that plays when a unit is selected, told to move, or ordered
to attack. AoE/Civ/StarCraft conventions: 24 lines per cue type, played
randomly so repetition doesn't drone.
This objective lands the **string content** only. Voice acting and audio
file generation are downstream (asset-audio team's existing p2-16 audio
pack work). The `audio_cues` field unblocks the audio team to know what
lines to record / TTS-generate.
Each unit gets:
```json
"audio_cues": {
"select": ["...", "...", "..."],
"move": ["...", "..."],
"attack": ["...", "..."],
"death": ["..."]
}
```
Lines should reflect the unit's identity:
- Berserker: "BLOOD!" / "I do not need a shield."
- Mountain King: "The crown stands." / "Speak the names." (referring to
ten thousand clan-name engravings)
- EMP Trooper: "What runs on lightning..." / "Quietly."
- Shield Bearer: "Hold." / "We become the place." / "One step. One step."
## Acceptance criteria
- [ ] All 50 newly-authored dwarven military units have `audio_cues`
field with select/move/attack/death arrays
- [ ] Each `select` array has 3 lines, `move` has 2, `attack` has 2,
`death` has 1
- [ ] Lines are 28 words each (snappy enough for combat UI)
- [ ] Voice matches established dwarven flavor (terse, declarative,
mountain/iron imagery)
- [ ] Unit-specific identity surfaces (a Berserker doesn't sound like a
Shield Bearer)
- [ ] No lines reference Game 2/3 lore (no magic, no spells)
- [ ] Apex units (mountain_king, doomsoul, ancestral_walker, etc.) get
weightier lines than T1 units
## Out of scope
- Actual `.ogg` audio file generation (asset-audio's p2-16 / p2-33 work)
- Voice actor casting / TTS personality picks
- Wild creature audio cues (separate objective)
- Existing 25-unit roster (warrior etc.) — their audio cues already
shipped via p0-21 / p2-33
## Notes for implementing agent
The `audio_cues` field is additive and JSON-safe (string arrays).
Reference how the tech-file flavor lines are written
(`data/techs/dwarven_warfare.json`) for voice consistency.

View file

@ -0,0 +1,58 @@
---
id: p2-39
title: Resolve `chronicle_hall` phantom unlock in `chronicle_keeping` culture tech
priority: p2
status: done
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 102115 — `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). Option A chosen.
- [✓] 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/`). — Only hit in dist/guide bundle (compiled artifact, not source data).
- [✓] `python3 tools/validate-game-data.py` → 0 failed. (317 passed, 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.