# Phase 1: Level-Up (PF2e regelkonform) - Context

**Gathered:** 2026-04-27
**Status:** Ready for planning

<domain>
## Phase Boundary

Charakter steigt im Wizard regelkonform mit allen sechs Wahlachsen auf (Boost, Klassentalent, Fertigkeitstalent, Allgemein-Talent, Skill-Increase, Ancestry-Talent, Klassenmerkmal). Voraussetzungen werden geprüft, abgeleitete Werte (HP-Max, Saves, AC, Klassen-DC, Wahrnehmung) werden automatisch neu berechnet, bestätigtes Level-Up ist atomar persistiert mit Snapshot-Vorher-Historie. Free-Archetype-Variante und Spellcaster-Slot-/Cantrip-/Repertoire-Progression sind eingeschlossen.

**Außerhalb der Phase:** Level-Up-Historie-Ansicht (UI), Reverse-Level-Up, neue Klassen über Core+APG hinaus, Multi-Classing.

</domain>

<decisions>
## Implementation Decisions

### Prereq-DSL-Scope (LVL-09)
- **D-01:** Evaluierbare Patterns: Skill-Rang (Trained/Expert/Master/Legendary in named skill), Feat-Besitz (named feat), Level, Klasse, Ancestry, Heritage. Ergibt laut Research ~80%+ Coverage gängiger Feats.
- **D-02:** Nicht-evaluierbar (→ Warnung): Deity, Spellcasting-Tradition, Multi-Class-Archetyp-Sonderfälle, Free-Text-Bedingungen wie "You worship a god of...".
- **D-03:** UI bei nicht-evaluierbarer Prereq: gelbes Warn-Icon mit Tooltip am Talent + Confirm-Dialog mit dem Voraussetzungs-Text beim "Wählen"-Klick (kein Hard-Block — bestätigt das bereits in REQUIREMENTS festgelegte "Warnung statt Block").
- **D-04:** Datenquelle der Prereq-Strings: bestehende `Feat.prerequisites: String?`-Spalte (existiert bereits in `server/prisma/schema.prisma:560` — keine Migration für Feld-Erweiterung nötig).
- **D-05:** Evaluator läuft im Wizard UND beim Pathbuilder-Import.
- **D-06:** Bei Import-Verletzung: Import läuft durch, Charakter wird angelegt, Banner am Charakter-Header zeigt "X Talente mit nicht erfüllter Voraussetzung" mit Liste. Kein Block.

### Free-Archetype-Regel (LVL-13)
- **D-07:** Pathbuilder-Verhalten nach Dedication: Slot zeigt Talente JEDES Archetyps (Multi-Archetype erlaubt). Vor Dedication: Slot zeigt nur Dedication-Talente.
- **D-08:** Toggle-Storage: pro Charakter in den Char-Settings (einmal setzen, gilt für alle künftigen Level-Ups). Wizard-Schritt 0 zeigt eine Lese-Anzeige des Toggle-Status.
- **D-09:** Pathbuilder-Auto-Detect: FA-Toggle wird beim Import automatisch auf "aktiv" gesetzt, wenn Pathbuilder-JSON FA-Marker oder zusätzliche Class-Feat-Slots an geraden Levels enthält. Spieler kann nachträglich ändern.

### Wizard-Flow + DRAFT-Persistenz (LVL-11, LVL-12)
- **D-10:** Step-by-Step-Modal mit dynamisch eingeblendeten Schritten (nur die für das Level relevanten). Reihenfolge: Klassenmerkmale → Boost-Set (L5/10/15/20) → Skill-Increase (L3+) → Klassentalent (gerade Level) → Fertigkeitstalent (gerade Level) → Allgemein-Talent (3/7/11/15/19) → Ancestry-Talent (5/9/13/17) → FA-Slot (wenn aktiv) → Spellcaster-Progression → Review. Mobile-friendly (ein Wahlpunkt pro Screen).
- **D-11:** DRAFT-Persistenz: neue Prisma-Tabelle `LevelUpSession` mit FK auf Charakter, JSON-State der Wahlen, `committedAt` nullable, optional `targetLevel`. Resume-on-Reload, Cross-Device.
- **D-12:** Live-Vorschau: nur im Review-Schritt. Vorher/Nachher-Werte für HP-Max, Saves, AC, Klassen-DC, Wahrnehmung gegenübergestellt. KEIN Live-Update pro Schritt (vermeidet Per-PATCH-Recompute-Last und Inkonsistenzen).
- **D-13:** Permissions: Owner UND GM der Kampagne dürfen Level-Up starten. Konsistent mit bestehendem `checkCharacterAccess`-Pattern (`server/src/modules/characters/characters.service.ts`).
- **D-14:** Offene DRAFTs ohne Commit: bleiben unbegrenzt offen. Beim nächsten Wizard-Aufruf zeigt UI "Du hast eine offene Stufenaufstiegs-Session — fortsetzen oder verwerfen?". Ein DRAFT pro Charakter (Constraint).

### Klassen+Spellcaster-Daten (LVL-08, LVL-14)
- **D-15:** Neue Prisma-Tabelle `ClassProgression` mit Einträgen pro `(className, level)`. Felder mindestens: `grants: String[]` (z.B. "Bravery", "WeaponSpecialization"), `proficiencyChanges: Json` (Save/AC/Skill-Stufen-Änderungen), `spellSlotIncrement: Json?` (`{tradition, spellLevel, count}`), `cantripIncrement: Int?`, `repertoireIncrement: Int?`, `choiceType: String?` (z.B. "pickFromList") + `choiceOptionsRef: String?` für Wahl-Klassenmerkmale.
- **D-16:** Class-Scope v1: alle Core-Rulebook + APG Klassen (Alchemist, Barbarian, Bard, Champion, Cleric, Druid, Fighter, Investigator, Monk, Oracle, Ranger, Rogue, Sorcerer, Swashbuckler, Witch, Wizard). Remaster-Klassen sind v2.
- **D-17:** Datenquelle für Seed: Foundry PF2e-System Repository (`https://github.com/foundryvtt/pf2e`) als Quelle. TS-Seed-Script (`server/prisma/seed-class-progression.ts`) clonet/checkt das Repo und transformiert die JSONs in das `ClassProgression`-Schema. Lizenz: ORC / Paizo Community Use Policy.
- **D-18:** Spellcaster-Repertoire-Increment (LVL-14, spontane Caster wie Bard, Sorcerer, Oracle): eigener Wizard-Schritt. Slot-Increment ist automatisch nach Klasse/Level (kein User-Eingriff). Repertoire-Wahl filtert nach Tradition + bekannten Spell-Levels.
- **D-19:** Wahl-Klassenmerkmale (Cleric Doctrine, Wizard School, Fighter Weapon Mastery, etc.): Wizard erkennt `choiceType` im ClassProgression-Eintrag und schiebt einen dynamischen Sub-Schritt ein. Volle Regelkonformität — Charakter ist nach Commit "fertig".

### Carrying Forward (bereits in REQUIREMENTS / ROADMAP / PROJECT festgelegt)
- LVL-09: Warnung statt Hard-Block (REQUIREMENTS — bestätigt in D-03)
- LVL-12: Atomare Prisma-Transaktion + JSON-Snapshot-Vorher in Historieneintrag (REQUIREMENTS)
- LVL-15: Translation-Pipeline = bestehender Claude-API + DB-Cache via `Translation`-Tabelle (REQUIREMENTS)
- WebSocket: neuer `level_up_committed`-Type ergänzt das `CharacterUpdatePayload['type']`-Union (`server/src/modules/characters/characters.gateway.ts:24`). Single Broadcast nach Commit (nicht mehrere kleine Updates während Recompute) — Pattern für Folge-Phasen (ROADMAP First-Phase-Note).
- Test-Disziplin: reine Funktionen (Boost-Cap-bei-18, Skill-Increase-Cap, Prereq-Evaluator, Recompute-Formeln) bekommen Jest-Unit-Tests. Phase 1 etabliert das Pattern; Folge-Phasen erben es (ROADMAP First-Phase-Note).
- TypeScript strict, keine `any`, German UI, mobile-first, Prisma `migrate dev` (CLAUDE.md / PROJECT.md)

### Claude's Discretion
- Konkretes UI-Layout des Step-by-Step-Modals (Header, Footer-Buttons, Progress-Indicator)
- Konkrete Spaltenstruktur des Review-Schritts (Tabelle vs. zwei Spalten)
- DRAFT-API-Endpoint-Naming (`POST /characters/:id/level-up`, `PATCH /level-up/:sessionId`, `POST /level-up/:sessionId/commit`, `DELETE /level-up/:sessionId`) — Konvention folgt bestehenden CharacterController-Endpoints
- JSON-Format des Snapshot-Vorher (vorgeschlagen: voller Character + Relations-Subset)
- Genaue Error-Messages auf Deutsch (z.B. bei Prereq-Confirm, bei Boost-Cap-Hit)
- Test-Granularität (mindestens: Boost-Cap-Logik, Skill-Increase-Cap, Prereq-Evaluator pro Pattern; integration-test für Commit-Transaktion)

</decisions>

<canonical_refs>
## Canonical References

**Downstream agents MUST read these before planning or implementing.**

### Requirements & Roadmap
- `.planning/REQUIREMENTS.md` §Level-Up — alle 15 LVL-Anforderungen (LVL-01..LVL-15) mit Akzeptanzkriterien
- `.planning/ROADMAP.md` §Phase 1 — Goal, Success Criteria, Spike Required (Prereq-DSL-Scope, Free-Archetype), First-Phase-Note (Test-Disziplin, WebSocket-Channel-Trennung)
- `.planning/PROJECT.md` §Constraints — TypeScript strict, German UI, Prisma migrations only, no `any`

### Research
- `.planning/research/SUMMARY.md` §Phase A — Open Questions, Mitigationen, Pitfalls #8/#9/#10/#11
- `.planning/research/FEATURES.md` §PF2e-Specific Complexity Notes (Level-Up) — sechs Wahlachsen, Boost-Cap-bei-18, Free-Archetype-Variant, Skill-Increase-Caps, Class-Progression-Variabilität
- `.planning/research/PITFALLS.md` §Pitfall 8 boost-cap-at-18, §Pitfall 9 recompute side effects, §Pitfall 10 feat retrain orphans, §Pitfall 11 skill-increase history

### Codebase Maps
- `.planning/codebase/ARCHITECTURE.md` — NestJS Module-per-Feature, WebSocket-Gateway-Pattern, Service-Layer-Pattern
- `.planning/codebase/STRUCTURE.md` — `server/src/modules/*` und `client/src/features/*` Konventionen
- `.planning/codebase/CONVENTIONS.md` — Naming (kebab-case Files, camelCase Funktionen), DTOs, Error-Handling
- `.planning/codebase/TESTING.md` — Jest-Setup vorhanden, null Tests heute. Test-Spec-Pattern `*.spec.ts`

### Live Code (Touch Points)
- `server/prisma/schema.prisma:171` — `Character`-Modell (level, hpMax, ancestryId, classId)
- `server/prisma/schema.prisma:222` — `CharacterAbility` (Boost-Ziele)
- `server/prisma/schema.prisma:233` — `CharacterFeat` (Talent-Slots, source: Klasse/Ancestry/Allgemein/Fertigkeit/Bonus/Archetyp)
- `server/prisma/schema.prisma:246` — `CharacterSkill` (Proficiency-Stufen)
- `server/prisma/schema.prisma:257` — `CharacterSpell` (Repertoire/Vorbereitung)
- `server/prisma/schema.prisma:544` — `Feat` mit `prerequisites: String?` (existiert)
- `server/src/modules/characters/characters.service.ts` — `checkCharacterAccess`-Pattern, Service-Methoden
- `server/src/modules/characters/characters.gateway.ts:22-26` — `CharacterUpdatePayload`-Union (Erweiterung um `level_up_committed`)
- `server/src/modules/characters/pathbuilder-import.service.ts` — Touch-Point für Prereq-Validation beim Import
- `server/prisma/migrations/` — bestehende Migrationen, Naming-Konvention `YYYYMMDDHHMMSS_description`

### External (PF2e Domain)
- Archives of Nethys: Leveling Up `https://2e.aonprd.com/Rules.aspx?ID=2065`
- Archives of Nethys: Ability Boosts `https://2e.aonprd.com/Rules.aspx?ID=75`
- Archives of Nethys: Skill Increases `https://2e.aonprd.com/Rules.aspx?ID=2109`
- Archives of Nethys: Free Archetype `https://2e.aonprd.com/Rules.aspx?ID=2751`
- Foundry PF2e-System Repository (Datenquelle für ClassProgression-Seed): `https://github.com/foundryvtt/pf2e`

</canonical_refs>

<code_context>
## Existing Code Insights

### Reusable Assets
- `Character`, `CharacterAbility`, `CharacterFeat`, `CharacterSkill`, `CharacterSpell`-Modelle decken die Datenstruktur für Level-Up-Targets ab — kein neues Charakter-Schema nötig.
- `Feat.prerequisites: String?` existiert bereits — der Prereq-DSL-Evaluator parst diese Strings, keine Schema-Migration für das Feld.
- `Translation`-Tabelle + `@anthropic-ai/sdk`-Pipeline sind etabliert — neue Talent-Voraussetzungs-Texte und Klassenmerkmal-Beschreibungen laufen durch die bestehende Cache.
- `CharactersService.checkCharacterAccess` (Owner OR GM-of-campaign) ist die Permission-Vorlage für die neuen LevelUp-Endpoints.
- `CharactersGateway.broadcast()` mit `CharacterUpdatePayload` ist der WebSocket-Vorlauf — `level_up_committed` wird einfach im `type`-Union ergänzt.
- Jest 30.x ist im `server/package.json` konfiguriert (`testRegex: ".*\\.spec\\.ts$"`) — Test-Files werden alongside Source angelegt (`server/src/modules/leveling/*.spec.ts`).

### Established Patterns
- **Atomic Prisma Transaction** mit `prisma.$transaction([...])` für mehrere Mutations — anwendbar für Commit (Snapshot + Mutationen + History-Eintrag).
- **NestJS Module-per-Feature**: neuer `LevelingModule` unter `server/src/modules/leveling/` (Service + Controller + DTOs). Wizard-API geht über REST, NICHT über WebSocket. WebSocket-Broadcast nur als Side-Effect des Commit-Endpoints.
- **Mobile-first Modal-Pattern**: `rounded-t-2xl sm:rounded-2xl` (Bottom-Sheet auf Mobile, zentriert auf Desktop) — wie in bestehenden Charakter-Modals.
- **DTO-Validation**: class-validator-Decorators in `server/src/modules/leveling/dto/*.dto.ts` (Pattern siehe `characters/dto/`).

### Integration Points
- `client/src/features/characters/components/character-sheet-page.tsx` bekommt einen "Stufe steigen"-Button (im Header oder Status-Tab).
- `client/src/features/characters/components/level-up-wizard.tsx` (NEU) — Modal-Komponente mit Step-State, importiert kebab-case-konform.
- `server/src/modules/characters/pathbuilder-import.service.ts` ruft den neuen `PrereqEvaluatorService` während des Imports auf und sammelt Verletzungen für das Banner.
- `server/src/app.module.ts` registriert `LevelingModule`.
- Neue Prisma-Migration: `add_level_up_sessions_and_class_progression` (kombiniert beide neuen Tabellen oder zwei Migrationen — Discretion des Planners).

### Cross-Cutting (von ROADMAP First-Phase-Note)
- **Test-Net wird in dieser Phase aufgesetzt** und für reine Funktionen in allen Folge-Phasen weitergeführt. Erste Tests: `apply-attribute-boost.spec.ts` (Cap-bei-18), `skill-increase-cap.spec.ts`, `prereq-evaluator.spec.ts`, `recompute-derived-stats.spec.ts`.
- **WebSocket-Channel-Trennung**: `level_up_committed` als sauberer neuer Kanal-Type. Atomare Transaktion + ein einziger Broadcast (statt mehrerer kleiner Updates) — gleiches Muster wird in Phase 4 (Dice-Gateway), Phase 5 (Battle-Sub-Rooms), Phase 6 (GM-Live-Tools-Audit) angewandt.

</code_context>

<specifics>
## Specific Ideas

- Der Wizard imitiert das Pathbuilder-Verhalten so weit wie möglich, weil die Gruppe Pathbuilder gewohnt ist (Free-Archetype Multi-Archetype nach Dedication, Toggle pro Charakter, Auto-Detect aus Import).
- Foundry PF2e-System ist die bevorzugte Datenquelle für PF2e-Regeldaten (klar parsebar, ORC-lizenziert, aktiv gepflegt) — gilt auch als Vorlage für künftige PF2e-Daten-Phasen.
- Banner-Pattern für nachträgliche Validation-Verletzungen ist neu, aber dem Pitfall #10 (feat retrain orphans) gegenüber robust.

</specifics>

<deferred>
## Deferred Ideas

- **Level-up-Historie-Ansicht im Charakterbogen** — auf v2 verschoben (LVL-V2-01 in REQUIREMENTS)
- **Reverse-Level-Up** (bestätigtes Level rückgängig machen) — auf v2 verschoben (LVL-V2-02 in REQUIREMENTS)
- **Variant-Class-Features** (z.B. Rogue Eldritch Trickster, Druid Wild Order Variants) — bei v2-Erweiterung mitnehmen, wenn Class-Scope ausgebaut wird
- **Multi-Classing** — explizit Out-of-Scope (PF2e hat kein klassisches Multi-Class; Archetypes decken das funktional ab)
- **Live-Recompute-Vorschau in jedem Wizard-Schritt** — verworfen zugunsten Review-only (Performance + Konsistenz)
- **Remaster-Klassen** (Magus, Summoner, Kineticist, Thaumaturge, Gunslinger, Inventor, Psychic) — v2; Class-Scope v1 ist Core+APG

</deferred>

---

*Phase: 01-level-up-pf2e-regelkonform*
*Context gathered: 2026-04-27*
