Summary
Roster-level costs in the engine's mapped state omit any cost type whose only references come from entries reached via entryLink. Discovered by muster golden-roster fixtures against real BSData/wh40k-11e data: a Necrons roster with a linked Detachment shows correct selection-level costs but an incomplete roster-level total set.
Mechanism (code-verified on feat/yaml-reader @ c980b14; also present on main)
EntryResolver.AddEntryOrFlatten (src/WarHub.ArmouryModel.RosterEngine/EntryResolver.cs:~182, non-group branch) stores Symbol = entry — the link container — instead of the resolved target entry.
StateMapper.CollectReferencedCostTypes (RosterEngine.Spec/StateMapper.cs:~416-429) walks symbol.Costs on those stored symbols; the link container has no costs, so the cost type is never marked referenced.
StateMapper.ComputeRosterCosts (~324-347) gates roster-cost emission on referencedCostTypeIds.Contains(...) → the cost type is dropped from roster totals.
Expected vs actual
- Expected: roster
costs include every cost type referenced by any resolved selection (e.g. pts totals from linked entries).
- Actual: cost types referenced only through entryLinked entries are absent from roster-level costs (selection-level values are correct).
Fix options
a. Store the resolved target symbol (resolved) in AddEntryOrFlatten's non-group branch, or
b. Make CollectReferencedCostTypes traverse through link symbols to their targets.
Repro fixture: BSData/wh40k-11e branch amis92:muster-fixtures, tests/rosters/necrons-single-unit-cost.yaml (assertion moved to selection level as a workaround; see file comment).
🤖 Generated with Claude Code
https://claude.ai/code/session_01KcYK8hmTmXi8eLWpg9LGKJ
Summary
Roster-level
costsin the engine's mapped state omit any cost type whose only references come from entries reached viaentryLink. Discovered by muster golden-roster fixtures against real BSData/wh40k-11e data: a Necrons roster with a linked Detachment shows correct selection-level costs but an incomplete roster-level total set.Mechanism (code-verified on feat/yaml-reader @ c980b14; also present on main)
EntryResolver.AddEntryOrFlatten(src/WarHub.ArmouryModel.RosterEngine/EntryResolver.cs:~182, non-group branch) storesSymbol = entry— the link container — instead of the resolved target entry.StateMapper.CollectReferencedCostTypes(RosterEngine.Spec/StateMapper.cs:~416-429) walkssymbol.Costson those stored symbols; the link container has no costs, so the cost type is never marked referenced.StateMapper.ComputeRosterCosts(~324-347) gates roster-cost emission onreferencedCostTypeIds.Contains(...)→ the cost type is dropped from roster totals.Expected vs actual
costsinclude every cost type referenced by any resolved selection (e.g.ptstotals from linked entries).Fix options
a. Store the resolved target symbol (
resolved) inAddEntryOrFlatten's non-group branch, orb. Make
CollectReferencedCostTypestraverse through link symbols to their targets.Repro fixture: BSData/wh40k-11e branch amis92:muster-fixtures, tests/rosters/necrons-single-unit-cost.yaml (assertion moved to selection level as a workaround; see file comment).
🤖 Generated with Claude Code
https://claude.ai/code/session_01KcYK8hmTmXi8eLWpg9LGKJ