The bare name/class/level form left new characters as shells (1 HP, all-10
abilities, no proficiencies). Now creation and level-up are guided and auto-populate.
- Hand-authored progression tables (no SRD class/slot data exists on disk):
src/lib/rules/{dnd5e,pf2e}/progression.ts — core classes' hit die/HP, key
abilities, save & perception proficiencies, trained-skill counts, caster type;
5e full/half/pact spell-slot tables, pf2e slot approximation; ASI/boost/skill
schedules.
- src/lib/rules/progression.ts: getClassDefs/getClassDef, classSkillChoices/Count,
buildCharacter() (HP from hit die + CON over levels, trained saves/skills, spell
slots + ability), planLevelUp() (HP gain, new slots, ASI/boost/skill choices),
applyIncreases/bumpRank. Pure + 12 unit tests.
- Multi-step CreationWizard (Basics → Abilities → Skills → Review) replaces the
old form; pulls PF2e ancestry HP/speed from the bestiary; review previews HP/AC/
saves/skills/slots; lands on a ready-to-play sheet.
- LevelUpModal reworked into a guided wizard: auto HP + spell slots, presents the
level's actual choices (5e ASI/feat, pf2e ability boosts + skill increase) and
applies them; keeps the strategic build-route advisor.
e2e helper drives the wizard; updated 7 specs to the new flow; new character-wizard
spec asserts a complete level-3 Wizard (HP 17, slots 4xL1 2xL2).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Instead of proposing a fresh alternative encounter, the non-AI path now:
- adds MORE of the creatures already present ('Add 2 more Goblin'), computing the
exact count needed and accounting for the 5e encounter multiplier, or
- adds a thematically related stronger creature from the bestiary (shared name
token, level/CR-appropriate) when that reaches the target with fewer bodies.
Only builds a fresh group when the encounter is empty. Apply clones the existing
combatant (works for homebrew/custom too) or pulls from the pool.
Existing creatures are also offered to the AI as candidates so it can likewise
say 'add another goblin'.
New suggestReinforcements() + baseName() in encounter.ts with unit tests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Level-up build-route advisor (src/features/characters/sheet/LevelUpAdvisor.tsx +
useLevelUpAdvisor): ~4 system-aware routes plus a custom one; choosing a route
expands it into concrete next-level steps. AI when configured, deterministic
fallback (src/lib/assistant/levelup.ts) otherwise. Embedded in the existing
HP-only LevelUpModal, which stays primary.
- Level-up prompts/schemas added to prompts.ts (buildRoutes/buildSteps), each
leading with the system constraint + class + next level.
- Campaign Insights section on the Assistant page renders deterministic themes,
with an optional 'ask the assistant to expand' affordance when AI is on.
levelup + prompt unit tests (4 routes both systems, system vocabulary, custom
route); e2e for the deterministic route→steps flow and the insights section.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- src/lib/assistant/prompts.ts: balanceSuggestionSchema + buildBalancePrompt
(system message leads with the grounding constraint; restricts choices to the
provided compendium candidates).
- useEncounterAdvisor hook: builds context → picks system-correct candidates →
asks the LLM (when configured) for a structured pick, validates + filters names
to the candidate set, else falls back to the deterministic buildSuggestedEncounter.
Apply adds the creatures transactionally via encountersRepo.mutate.
- EncounterTipCard in the combat tracker: leads with the detected difficulty
tendency (or the current difficulty), offers a one-click grounded suggestion
(AI or deterministic) with propose→confirm Apply.
prompts unit tests + e2e for both the deterministic apply flow and the AI path
(stubbed provider); the AI test also confirms candidate-grounding (only
shortlisted creatures survive).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- src/lib/assistant/context.ts: buildCampaignContext() assembles a system-aware
snapshot led by an explicit systemConstraint (anti cross-system hallucination),
party, recent encounters with computed difficulty, quest/note summaries.
pickCreatureCandidates() pulls level/CR-appropriate creatures from the correct
bestiary so LLM tips are grounded in real data.
- src/lib/assistant/patterns.ts: difficultyTendency() + detectThemes() classify
whether the DM's encounters skew too easy/hard, rating each fight against its
party-level snapshot.
- Encounter schema gains optional partyLevelsSnapshot + outcome (Dexie v7, additive).
Combat tracker snapshots PC levels at start and rates difficulty against them.
17 assistant unit tests (context + patterns).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Bring-your-own-key assistant config in a dedicated persisted store
(src/stores/assistantStore.ts); partialize drops the key from localStorage
when 'remember' is off. Key lives in localStorage only, so it's auto-excluded
from Dexie backups.
- Provider-agnostic LLM client (src/lib/llm) over fetch, no SDK: Anthropic
Messages + OpenAI-compatible Chat Completions (covers OpenAI/OpenRouter/
Ollama/LM Studio via custom base URL). Structured JSON output parsed +
Zod-validated; timeouts; typed error kinds; key never leaked in errors.
- Settings 'Assistant (AI)' section with provider/model/baseUrl/key, remember
+ enabled toggles, and Test connection.
- CSP connect-src widened to any https + localhost for the BYO endpoint.
10 client unit tests; settings e2e asserts config persists and the key is
never present in an exported backup.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Deterministic advisors (src/lib/assistant): party resources (downed/bloodied/
spent slots/rest nudges), session prep (dangling [[wiki links]], active quests,
empty journal), live combat hints (turn, downed combatants) — pure + tested
- Data-driven encounter builder: greedily assembles level/CR-appropriate monsters
to a target difficulty via the Phase-3 budget; one click builds + opens combat
- Assistant page: suggestion cards with one-click actions (goto, long rest,
create note); wired into routes, dashboard, command palette
- 8 advisor/builder unit tests + assistant e2e
Conversational LLM layer intentionally deferred (no provider/key in this env);
the deterministic advisor is the offline default per the plan.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Homebrew entity (monster/spell/item/feat/condition) — Dexie v6, repo, hook,
cascade-deleted with campaign
- Homebrew editor page: per-kind fields + description, create/edit/delete
- Compendium merges campaign homebrew of the matching kind (HB badge, generic
HomebrewDetail) with the same cross-links (add monster->combat, spell/item->character)
- Content packs: export/import homebrew as JSON (validated, ids reassigned)
- System extensibility documented via the existing RulesSystem registry seam
- Fix: card editors (homebrew/npc/quest/note) debounce-save the FULL snapshot, not
partial patches — editing two fields fast no longer drops an edit
New homebrew e2e + cascade test coverage.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Player View (/play): read-only projector screen — party HP bars + conditions,
active-encounter initiative with current turn; enemy HP hidden behind a
Healthy/Bloodied/Down status band; Fullscreen button
- SyncAdapter seam (src/lib/sync): local-first default via Dexie liveQuery;
documents where a future networked (WebSocket/CRDT) backend plugs in
- Dashboard + routes get a Player View entry
- Robustness: encountersRepo.mutate() does transactional read-modify-write so
rapid combat mutations can't overwrite each other (old C19 race); tracker uses it
New player-view e2e. Networked multiplayer backend intentionally deferred.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Ability generation: standard array, point buy (27-pt, validated), 4d6kh3 roll;
AbilityGenModal with assign-from-pool + steppers (pure abilityGen lib + tests)
- Level-up flow: increment level, HP gain (average or roll hit die + CON)
- Print / save-to-PDF: print button + @media print hides app chrome and roll tray
- Plan: added Phase 11 (data-driven Assistant) to the roadmap
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Advantage/Disadvantage are now toggle modes (rollStore.mode) applied to d20
rolls everywhere (dice page, sheet skills/saves/attacks), preserving modifiers;
applyRollMode() rewrites the first d20 -> 2d20kh1/kl1
- addCombatant auto-numbers duplicate names (Goblin 1, Goblin 2, …); the first
duplicate also renames the original. Quantity add relies on this.
- Tests for applyRollMode + duplicate numbering
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Dice notation: exploding (Nd6!) and reroll-below (Nd6r2), capped + tested
- Degrees of success / roll-vs-DC (PF2e ±10 + nat 20/1 steps; 5e crit on nat 20/1)
- Global roll tray (shared store + RollTray in layout) with animated result + degree
- Roll from the character sheet: skills, saves, and attack to-hit/damage are
clickable and post to the tray + history (rollAndShow/rollCheck helpers)
- Saved roll macros per campaign (persisted) on the Dice page
10 new unit tests (notation explode/reroll, degrees), interactive-dice e2e.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Condition durations + auto-expiry: timed conditions tick down on the affected
combatant's turn and drop at 0 (engine tickConditions; UI rounds field + (Nr) chip)
- Initiative: Roll-all (d20 + per-combatant bonus, re-sort anchored) + group/quantity add
- Combat log: per-round event feed (turns, round changes, damage/heal, expiries,
removals) + in-memory Undo of the last change
- Encounter difficulty budget: 5e XP thresholds + PF2e level budget (pure lib +
tests); live difficulty/XP-award readout from monster combatants vs the party
- Combatants carry initBonus + cr/level; compendium add-to-combat passes them
18 new unit tests (durations, applyInitiatives, budget), new combat-depth e2e.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The AoN action index was polluted with ~2,300 trait-fragment entries
('(concentrate)', 'envision', 'command'...) and the same basic actions repeated
per source. Filter to real Title-cased names and dedupe by name (keep richest):
3,950 -> 646 real actions (also cleaned in the live data file, 3.9M -> 859K).
- pf2eMeta now shows action cost (Single Action/Reaction/...) instead of 'common'
- Added an Action cost filter to the Actions category
- Hide noisy 'common' rarity in PF2e detail facts
- Scraper postProcess() makes future fetches clean too
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Drop the 300-row cap; show the true filtered count (e.g. '8,402 results')
- Virtualize the results list (@tanstack/react-virtual) so thousands of rows
render smoothly
- Sort dropdown: Name A-Z/Z-A plus a numeric axis per category (CR for monsters,
Level for spells/feats/PF2e categories)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Scraped PF2e reference from Archives of Nethys ES into public/data/pf2e/
(spells, creatures, feats, equipment, weapons, armor, ancestries, heritages,
backgrounds, archetypes, actions, conditions, deities) via scripts/fetch_pf2e.ts
- Registry-driven compendium: system toggle + per-category nav + generic filters
- 5e expanded: weapons, armor, feats, conditions added alongside spells/monsters/items
- PF2e data served as static assets (fetched, not bundled) for fast native parse
- Cross-links: add spell->spellbook / item->inventory to a campaign character;
add monster/creature -> open encounter
- Condition tooltips in combat sourced from the conditions glossary
- Tests: registry filter unit tests, compendium e2e (browse + cross-link)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- System-aware condition list (5e PHB / pf2e) in src/lib/rules/conditions.ts
- Dropdown replaces free-text input; non-valued conditions add instantly,
valued ones (Exhaustion, Frightened N, etc.) show a value field, plus Custom
- Already-applied conditions disabled in the list; chips remain click-to-remove
- New e2e covering preset + valued add and tag removal
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- Inventory + currency + encumbrance vs carrying capacity
- Class resources with correct short/long/daily rest recovery (applyRest)
- Spellcasting: slots (+pact), known/prepared spells, derived DC + attack
- Defenses: 5e death saves/inspiration/exhaustion, pf2e dying/wounded/hero points
- Derived weapon attacks + passive perception via extended RulesSystem
- Dexie v2 migration backfills new fields; debounced save flushes on pagehide
- 9 new unit tests, new character-depth e2e; all green
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>