Translates the four static Angular label maps (SLOT_LABELS, RARITY_LABELS,
DANGER_LABELS, LOCATION_TYPE_LABELS) and the inventory detail panel's
hardcoded item-type fallback per the English Game Content Foundation
design doc glossary. Updates every spec assertion across the web app that
checks rendered text sourced from these maps, including specs owned by
later tasks (combat-page, encounter-card, inventory-page) where they
render one of these labels.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Translates the six REPUTATION_RANKS labels in reputation-rank.ts
(Geachtet/Vertraut/Anerkannt/Bekannt/Geduldet/Fremder -> Esteemed/
Trusted/Recognized/Known/Tolerated/Stranger), per the glossary in
docs/superpowers/specs/2026-08-21-english-game-content-foundation-design.md
section 4. Keys and thresholds are unchanged.
Also updates reputation.service.spec.ts and reputation.controller.spec.ts,
which asserted the German rankLabel value returned by
resolveReputationRank() via the service/controller layer.
Converts all German player-facing content in the API's seed files to
English per the English Game Content Foundation glossary: item
name/description, monster name, location name/description, all
local-location POI/action content, and the border-guard reputation
faction. Technical keys are unchanged.
10 tasks, batched by layer (per subagent-driven-development's batching
guidance -- this is same-shape content/copy work across ~40 files, not
one task per file): API seed content, API reputation rank labels, web
static label maps, web error-message maps, then five feature-area
template sweeps (combat, inventory, world/travel, hunting,
layout/shared), closing with the shared test fixture and a repo-wide
grep sweep as the Definition-of-Done gate.
Unlike Slice 0.6.5, this plan has no designed red-build window: every
task changes string VALUES only, never a field/interface a sibling
task still reads, so both the API build and the Angular bundle compile
stay green throughout.
All test-filter commands in every task were run and verified against
this worktree before being written into the plan, rather than assumed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Full-repo survey of every player-facing German string (seed content,
API-computed reputation rank labels, five client-side error-message
translation maps, six static Angular label maps, all combat-log
generation, ~30 component templates), plus rulings on everything the
source spec leaves open: monster keys stay unchanged (only name
changes), no migration is needed (content lives in seed-file values,
not schema), reputation rank labels move on the API side, combat log
templates are freely composed rather than translated 1:1, and the
Renown/Reputation German-only "Ansehen"/"Ruf" split carries over as
"World Renown"/"Reputation" without the German-specific collision
problem that motivated it.
A complete glossary gives every implementer the exact English value to
use verbatim -- no translation judgment calls left to task execution.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Reconciles Slice 0.6.5 (Renown & Reputation Foundation) against master's
persistent-HP-and-regeneration slice, which landed independently and
touches several of the same files (Character entity, CombatService,
EquipmentService, the inventory detail panel).
Conflict resolutions:
- CharacterStatsService/EquipmentService constructor wiring: kept
master's CharacterVitalsService injection, which this branch's
version of the same files didn't have yet.
- CombatService.performAction: kept master's HP-guard logic
(characterTooWounded, vitals pause-on-enter) alongside this branch's
multi-line calculate() call style.
- Inventory detail panel (.html/.ts/.scss/.spec.ts): master had
redesigned the panel (wrapping section, rarity styling, flavour
text, a shared inventory.labels.ts) on top of the OLD level-gated
component, since this branch's removal of the level gate (R4, Task
8/14) hadn't reached master yet. Kept master's visual redesign in
full, but with the level-gate concept removed throughout: no
requiredLevel stat block, no meetsLevelRequirement() branch in the
equip button, no now-dead .detail__value--unmet SCSS rule. Kept both
branches' independent tests (non-equippable-item, flavour-text).
- inventory-page.component.ts: dropped master's dead characterLevel
computed (nothing in the template read it, and the level concept is
gone); kept its independent bagCells/bagUsed/bagCapacity grid
feature, which has nothing to do with renown or level.
Post-merge fixture repairs (three files failed the Angular bundle
compile because they predate master's hpRegenPerSecond/hpRegenSince
fields or master's item description field, neither conflict-marked
since git considered them non-overlapping edits):
- app.spec.ts: a 'renders loaded character values' test added on
master after this branch forked still used the abolished level/
experience fields on its decoy fixture -- retargeted to renown.
- inventory-detail-panel.component.spec.ts: the ashPelt fixture added
by this branch's final-review follow-up predates master's required
description field.
- top-bar.component.spec.ts: this branch's fixture predates master's
required hpRegenPerSecond/hpRegenSince fields.
No database migration touches the same column: master's
1792000000000-AddHpRegeneration only adds characters.hp_regen_since,
independent of this slice's 1791000000000-CreateRenownAndReputation.
Timestamp ordering between the two was already correct with no rename
needed.
Verified: API 288/288 (267 from this slice + 21 from master), API
build zero errors, web 237/237 (230 from this slice + 7 from master).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The branch review approved the slice with no blocking findings. These
are the substantive non-blocking ones.
N1, the one no per-task review could see: every seeded monster rolls
silverMin/silverMax = 0 (R7), so the victory screen showed "Silber +0"
after every fight in the shipped game. Three tasks were each correct in
isolation -- the mechanism stays, the values are zero, the field still
exists -- and the composite was wrong. Now conditional, with a test.
This does not contradict R16: R16 deleted the XP block because the
field ceased to exist, leaving nothing to hide. Silver still exists and
can be non-zero, so a conditional is the right tool.
N2: world.store.ts still said a combat "granted XP and silver". Same
false-fact-in-a-comment defect fixed in b5bcd50, one file over.
N4: resolveReputationRank threw a TypeError on negative input, since
findIndex returns -1 and REPUTATION_RANKS[-1] is undefined. Unreachable
today, but grantReputation is public and accepts any number.
N5/N6: grantReputation resolved factions without the enabled filter the
read path applies, so a disabled faction could accumulate invisible
reputation -- "disabled" was not actually a kill switch. The dense read
also had no ORDER BY, so the list could reorder between requests.
N8: design 13 requires silver stay 0 for every seeded monster; only two
of four were pinned. Re-adding silver to the others would have shipped
silently.
N9: spec 36's "a normal kill grants no Renown" had no test. It was
structurally guaranteed but unasserted -- now locked down against a
later slice wiring renown into combat.
N10: an impossible renown: 0 fixture, and RENOWN_MIN exported but never
used to clamp the floor.
API 268/268, web 230/230, API build zero errors.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
When I dropped Silber and Erfahrung from the burned road's seeded
reward preview (e5752c7, because R7 zeroed every monster's silver on
that road), I updated the server content but not the web fixture that
mirrors it. burnedRoadFixture() still advertised Silber, and the
sidebar spec still asserted it rendered -- so the web tests were
proving the UI shows a category the API no longer sends.
Also clears dead level/experience fixture fields and an experience key
in a reward-service mock from combat-equipment-integration.spec.ts.
They were inert (nothing read them) but they date from after the
API-side sweep and describe fields the entity and DTO no longer have.
API 267/267, web 229/229.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The panel's three-way actions block had no test for its middle branch:
an item with equipmentSlot null should show "Nicht ausrüstbar" and no
equip button. The gap predates this slice -- Task 14's review found it
while confirming the removed level gate had not cost coverage.
Deferred until now on purpose: the web bundle could not compile for the
whole slice, so committing this earlier would have meant shipping a test
I had never executed.
Load-bearing: dropping the !isEquippable() guard would fall through to
the else branch and render the button, failing the assertion.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two location panels still labelled their recommended range "Empfohlene
Stufe". The player no longer has a Stufe -- this slice replaced the
1-7 level scale with Ansehen 1-15, so the UI was recommending a scale
the character cannot be measured on.
Source slice doc section 3 defines this concept as Recommended Renown
per region (Aschenfelder 1-5). The seeded values already sit inside
that range (south-gate 1-1, burned-road 1-2), so only the label was
wrong -- no data change needed.
The min_recommended_level / max_recommended_level column and property
names are left as-is: internal naming, no user-visible effect, and
renaming them would reach across the API, the entity, the DTO and the
seed for no behavioural gain.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Task 17 (final task) of Renown & Reputation Foundation. Fixes the last 3
compile errors blocking the web suite (app.spec.ts, world.store.spec.ts)
by aligning CharacterResponse fixtures to the real renown-only shape, and
removes the two remaining dead 'experience' reward-preview leftovers
(current-location fixture entry, location-icon glyph) now that the API
no longer seeds them. Full web suite: 24 files / 228 tests, all green,
for the first time this entire slice.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The comment claimed the server had granted "silver and renown" on a
combat win. It does not: grantVictoryRewards adds silver and item drops,
and nothing in apps/api/src/combat or apps/api/src/rewards touches
renown at all. Renown comes from milestones only.
Introduced when I committed Task 15's staged work after its agent was
cut off mid-step; caught by the task review.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Add hpRegenPerSecond and hpRegenSince fields to CharacterResponse
- Update inventory-page.component.spec.ts fixture with new fields
- Add CHARACTER_TOO_WOUNDED error mapping to combat.store
- Add test for CHARACTER_TOO_WOUNDED error mapping
- Update app.spec.ts and world.store.spec.ts fixtures for compilation
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The re-anchor test in equipment.service.spec.ts anchored hpRegenSince
at null, which meant currentHp already equaled the old maxHp and
nothing in equip() could change it whether settle() ran correctly, was
a no-op, or read the wrong (post-change) maxHp. Anchor currentHp at 90
with hpRegenSince 600s before the harness's fixed clock so settle()
must actually cap accumulated regen at the OLD maxHp for the assertion
to hold, catching both failure modes the original fixture missed.
Design ruling R16: the victory screen removes the data-reward-experience
element and its "Erfahrung" line outright rather than hiding them behind
a conditional. CombatReward is now { silver, items }.
The surviving spec assertion checks that [data-reward-experience] is
absent, so it would genuinely fail if the block came back -- rather than
merely observing that some text changed.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The API can no longer emit ITEM_LEVEL_REQUIREMENT_NOT_MET (Task 8 removed
the level gate server-side) and InventoryItem.item no longer carries
requiredLevel (Task 12). Drop the characterLevel input, the
meetsLevelRequirement computed, the associated template branch and copy,
and the dead German error-message mapping. Update fixtures across the
inventory specs to the real InventoryItem/CharacterResponse shapes.
The Topbar rendered the English word "Renown", replacing the German
"Stufe" it showed before. That contradicted the slice's own global
constraint that all user-facing copy is German, and it was the single
English string in a component visible on every screen -- next to
"Silber", "Lebenspunkte" and "Charakterdaten werden geladen".
This was a spec defect, not an implementation one: the design doc and
the task brief both prescribed "Renown" literally. The document's
working language leaked into a copy-locked line.
"Ruf" is not available as the German term -- this project already uses
it for the separate per-faction Reputation system, and the two are
deliberately kept distinct. "Ansehen" (standing/prestige) is unclaimed
and matches the spec's own definition of Renown as the character's
overall significance in the world.
Records the decision as R17 in the design doc so later Renown UI does
not reintroduce the English term, and renames the now-inaccurate
top-bar__level class to top-bar__renown (nothing else referenced it).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- 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>
The location view's "Mögliche Belohnungen" preview listed Silber and
Erfahrung. This slice made both false:
- Experience no longer exists as a concept (spec 1).
- Every monster seeded on this road now rolls silverMin/silverMax = 0
(design R7), so a kill yields no silver. Silver reaches the player
through turn-ins instead.
The list's own comment states the rule it was breaking: the view may not
promise a drop the roll does not guarantee (spec 8). Equipment and
material stay -- the loot tables still back both.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
combat.service.spec.ts mocked CombatRewardService, so it never noticed
that design R8 removed CombatRewardDto.experience. Its mocks returned
{ experience, silver, items } and one assertion required experience: 8
back out -- encoding a contract the production DTO no longer has. A mock
lying about the real shape is worse than no test: it would keep passing
if the real DTO drifted further.
The rollback test deliberately wrote two independent fields so its
assertions could not pass vacuously ("rolled back" vs "never written").
Swapped the abolished experience for renown rather than dropping to a
single field, preserving that intent.
Monster level is untouched -- it is a monster stat this slice keeps, not
the abolished character level.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Design ruling R7 abolishes XP as a concept and says the column goes with
it, but no task in the plan actually dropped it -- the plan only dropped
characters.experience and combat_rewards.experience_granted. Task 9
removed experienceReward from the seed literals, leaving
monster_definitions.experience_reward as a NOT NULL column with no
default that nothing supplies. The first monster insert against a real
database would have failed on a constraint violation.
No suite here could have caught it: none of them connect to Postgres.
Drops the column in the slice migration (which has never been run, so
amending it in place is correct rather than stacking a second one),
removes the entity field, and clears the three test fixtures that still
set it. silver_min/silver_max deliberately stay -- spec 15 keeps a
direct currency drop available as a lore-valid exception, and XP has no
such carve-out.
Also retargets the seed idempotency test off renown: 1, which is the
seed's own default and so could not distinguish "preserved" from
"reset to default".
NOTE ON SCOPE: this commit also absorbs a Prettier reformatting pass
that was already sitting uncommitted in the working tree, which is why
it touches ~59 files. That churn is purely cosmetic line-rewrapping --
verified by inspection, and the suite is green at 267/267 with the build
at exactly the 3 expected errors owned by Tasks 10 and 11. The repo is
not Prettier-clean at baseline (119 files still flagged), so this was a
partial run by an earlier step, not a deliberate repo-wide format.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The comment sat two lines above the deleted experience computation and
still named XP as something the guard protects. Only silver survives.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
TurnInService locks and validates the character row before touching
inventory, silver, or reputation, but no test exercised that branch.
Both sibling services in this slice (renown, reputation) have the
equivalent test; this closes the gap.
`characterNotFound` is shared from travel.errors and so is not a
TurnInDomainError -- assert on the wire contract (code + status) the
way reputation.service.spec.ts does for the same shared error.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>