Track perks unlocked per grant and remove only those on race loss instead
of restoring a full pre-apply snapshot; re-run ReevaluateAfterLevelUp at
post-rollback levels so a concurrent winner's path-auto unlocks survive.
Capture pre-skill-apply XP and perk snapshots; on TryRecord loss reverse
each applied skill row via negative delta and restore the perk snapshot so
level-up unlocks from the loser call are reverted without clobbering a
concurrent winner's XP.
Rename freeze-first loader tests, add PrototypeE7M2QuestCatalogRulesTests
for cross-ref paths, align missing skill-def error with Python, and
document bundle schema path resolution in server README.
Register bundle JSON Schemas, parse bundle DTOs on QuestDefRow, and run
E7M2 prototype gates (presence, freeze table, cross-ref, mission_reward)
with skill catalog input from DI.
Document quest_start, quest_step_complete, quest_complete, and quest_accept_denied
anchors for future E9.M1 ingest with README, manual QA, and module doc updates.
Wire QuestStateOperations.TryAccept at POST /game/players/{id}/quests/{questId}/accept
with shared quest row projection, integration tests, and Bruno accept flows.
Add QuestObjectiveWiring with auto step advance/complete, hook into
GatherOperations, CraftOperations, EncounterCompletionOperations, and
QuestStateOperations accept/advance for inventory_has_item checks.
Add CanWritePlayer to IPlayerQuestStateStore and check before
prerequisite gate; map TryActivate/TryAdvanceStep store failures
from progress snapshots instead of always unknown_player.
Align test DI resolution with encounter pattern, add unknown_quest
advance/complete tests, catalog quest id constants, refactor
TryMarkComplete readability, and update decomposition docs.
Fix persistence test AAA layout, empty-id denial theory, frozen id constants,
Postgres rollback/JSONB read, XML doc cref, README Bruno link, and review doc.
Introduces IPlayerQuestStateStore (in-memory + V008 Postgres), QuestStepState
snapshots, DI wiring, AAA unit tests, and docs for E7M1-05 before NEO-117 ops.
Recipe and reward-table loaders registered schemas without locking,
corrupting SchemaRegistry.Global when xUnit spun up multiple
WebApplicationFactory hosts concurrently in CI.
Add IEncounterCompleteEventStore with in-memory implementation, record
events on successful TryCompleteAndGrant, and expand reward_delivery
hook comments for future QuestRewardBundle routing.
In-memory IEncounterProgressStore and IEncounterCompletionStore with
EncounterProgressOperations for activation, defeat tracking, and
all-targets-defeated checks; unit tests and docs.
Thin IEncounterDefinitionRegistry / IRewardTableDefinitionRegistry adapters
over NEO-101 catalogs with TryNormalizeKnown, DI registration, and 18 AAA tests.
Telegraph damage now looks up behavior attackAbilityId for baseDamage and
maxRange instead of using aggroRadius. Adds three NPC attack abilities, maxRange
on AbilityDef, attackAbilityId on NpcBehaviorDef, and cross-ref validation.
Clear threat holder and reset runtime to idle when combat-target HP
is defeated — on cast accept and as an AdvanceOne guard so telegraph
cycles cannot continue after the killing blow.
Replace NEO-93 placeholder comments with full telegraph_fired and
npc_state_transition E9.M1 anchors in NpcRuntimeOperations; document
in server README and E5.M2 module alignment.
Do not move the lazy-tick marker backward when nowUtc regresses; reject
non-positive catalog durations and break the phase loop when cursor stalls.
Co-authored-by: Cursor <cursoragent@cursor.com>
Fixture reset cleared NPC rows but left a stale lazy-tick marker, causing
catch-up bursts after re-acquire. Reset to MinValue with prototype rows.
Co-authored-by: Cursor <cursoragent@cursor.com>