- Update CharacterStatsService constructor to accept CharacterVitalsService
- Compute currentHp via CharacterVitalsService.effectiveHp() instead of raw pass-through
- Add hpRegenPerSecond and hpRegenSince fields to EffectiveCharacterStats return type
- Update spec with new test cases for regeneration calculation and field pass-through
- Equipment and combat tests now fail as expected (separate tasks will fix constructor calls)
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Also updates the pre-existing exact-equality playerState assertion in
combat-equipment-integration.spec.ts, which broke from the new
potionsRemaining field but wasn't listed in the task brief's file scope.
Fixes 4 Important findings from the final whole-branch review:
- /inventory never called WorldStore.load(), leaving the TopBar stuck on
"loading" and characterLevel() silently defaulting to 1 for any character
above level 1. Mirrors the same guard already used in HuntPageComponent.
- The combat/equipment snapshot-immutability integration test asserted only
status/round, never the actual playerState snapshot the whole test claims
to prove is untouched after a post-fight equip.
- Documented (comment only, no behavior change) that the demo character's
armor dropping from the old hardcoded 6 to 0 is an intentional,
spec-sanctioned tradeoff (Slice 0.5 spec Section19), not a bug.
- inventory.store.spec.ts's equip test used an identical inventory fixture
before and after equip(), so a regression dropping the post-equip
inventory re-fetch would still have passed. Now asserts the refetched
fixture is actually reflected.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The equippedItemInSelectedSlot computed is the riskiest logic this
component owns, but every existing test mocked selectedItem() as null,
so the slot-matching branch never ran and a regression to "any equipped
item" would have gone unnoticed. Adds a test with three items across two
slots that asserts the detail panel receives the same-slot equipped item,
not just any equipped item.
The CharacterItem idempotency check was looking up by the seed's own
literal id instead of the (characterId, itemDefinitionId) unique index
that CharacterItem actually enforces. If the demo character had already
looted a worn-short-sword naturally, re-running the seed would miss
that row and try to insert a colliding duplicate, breaking seeding
instead of being a safe no-op. Look up by the real domain key and reuse
whatever id is found when wiring up the CharacterEquipment row.
Reorders the Verbrannte Straße POIs to plan §8's authored sequence
(hunt, investigate, search, then the scout) — purely a keyboard tab-order
fix, since hotspots are placed by percentage, not list order.
Rewrites the location page's viewport-height reserve as a calc() over the
same rem values the top bar and footer already declare as their own
min-block-size, with file:line pointers to both, instead of an opaque
191px constant. Doesn't remove the underlying coupling (still no
ResizeObserver / shared token), but a future edit to either component's
minimum height now has a documented, unit-matching term to update instead
of an unexplained magic number.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Brings in the encounter-status feature (cleared/resumed hunt encounters)
and its own independent Verwilderter Straßenhund / Verkohlter Plünderer
assets. Both branches added the same two monsters at the same time;
resolved by keeping master's asset set as canonical (images/combat/icons/,
images/combat/sprites/) rather than maintaining a parallel copy under
images/monsters/icons/ — dropped that directory and pointed the seed's
MonsterDefinition.iconPath, the local-view test fixtures and the frontend
icon lookup at the existing combat/icons paths instead. Kept this
branch's COMBAT_MONSTER_SCALE entries for the two monsters, since master
never added them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>