Quest: Remove game-concept prerequisite types from PrerequisiteType enum
Source: STATUS.md § Potential Extensions resolution (2026-03-25), Quest DC#2
Summary
PrerequisiteType enum contains CharacterLevel and Reputation — game implementation concepts baked into a Bannou schema enum. These violate the same composability principle that the FAQ "Why Are There No Skill/Magic/Combat Plugins?" articulates: every game defines "level" and "reputation" differently. These should not be first-class Bannou types.
Current State
Schema (schemas/quest-api.yaml):
PrerequisiteType:
type: string
enum: [QuestCompleted, CharacterLevel, Reputation, ItemOwned, CurrencyAmount]
With dedicated fields on PrerequisiteDefinition:
minLevel — for CHARACTER_LEVEL type
factionCode — for REPUTATION type
minReputation — for REPUTATION type
Code (QuestService.Helpers.cs):
case PrerequisiteType.CharacterLevel: routes to CheckDynamicPrerequisiteAsync("character_level", ...)
case PrerequisiteType.Reputation: routes to CheckDynamicPrerequisiteAsync("reputation", ...)
- Both silently pass when no provider is registered (graceful degradation = no gate)
Code behavior: These enum values ALREADY route through the dynamic provider path — they're not built-in L2 checks. The enum values are cosmetic; the code treats them as dynamic.
Required Changes
Schema (schemas/quest-api.yaml)
- Remove
CharacterLevel and Reputation from PrerequisiteType enum
- Remove dedicated fields (
minLevel, factionCode, minReputation) from PrerequisiteDefinition
- Add generic dynamic prerequisite fields to
PrerequisiteDefinition:
providerName (string, nullable) — identifies which IPrerequisiteProviderFactory to route to
code (string, nullable) — the prerequisite code passed to the provider's CheckAsync
minValue (integer, nullable) — numeric threshold for the provider to check against
- Alternatively: Make
PrerequisiteType a Category B opaque string (game-configurable codes) instead of a closed enum, with built-in handlers for known strings ("quest_completed", "currency_amount", "item_owned") and dynamic routing for everything else
Code (QuestService.Helpers.cs)
- Remove
case PrerequisiteType.CharacterLevel: and case PrerequisiteType.Reputation: — the default: case already routes to CheckDynamicPrerequisiteAsync
- Update
CheckDynamicPrerequisiteAsync to use the generic fields (providerName, code, minValue)
Internal model (QuestModels.cs)
- Remove
MinLevel, FactionCode, MinReputation from PrerequisiteDefinitionModel
- Add generic fields matching schema changes
Documentation
docs/plugins/QUEST.md — Already updated (DC#2 rewritten, type classification table updated)
docs/maps/QUEST.md — Already updated (dependency table note added)
docs/reference/SERVICE-HIERARCHY.md — ⚠️ FROZEN. Line 590 incorrectly lists character_level as a built-in type calling ICharacterClient. Needs correction: either remove the row or reclassify as dynamic/game-specific. Requires explicit user approval to edit.
bannou-service/Providers/IPrerequisiteProviderFactory.cs — XML docs incorrectly list character_level as built-in. Correct to reflect dynamic-only routing.
Regeneration
- After schema changes:
cd scripts && ./generate-models.sh quest + cd scripts && ./generate-service.sh quest
Why This Matters
The silent no-op is a functional gap today — quests with CharacterLevel or Reputation prerequisites have zero enforcement. But the fix is NOT adding a specific provider for these game concepts. The fix is removing the game concepts from the enum and letting games define their own prerequisite types through the dynamic provider path — the infrastructure that already exists and works correctly (see AchievementPrerequisiteProviderFactory as the reference implementation).
Related
- STATUS.md resolved this as "REJECTED — game concepts, not Bannou primitives"
- FAQ: WHY-ARE-THERE-NO-SKILL-MAGIC-OR-COMBAT-PLUGINS correctly frames skill/magic prerequisites as thin L5 adapters
- DIVINITY-GENERATION-ARCHITECTURE.md § "Bag of Kills" shows how capabilities flow through wallets → Seed growth, not through baked-in prerequisite types
Quest: Remove game-concept prerequisite types from PrerequisiteType enum
Source: STATUS.md § Potential Extensions resolution (2026-03-25), Quest DC#2
Summary
PrerequisiteTypeenum containsCharacterLevelandReputation— game implementation concepts baked into a Bannou schema enum. These violate the same composability principle that the FAQ "Why Are There No Skill/Magic/Combat Plugins?" articulates: every game defines "level" and "reputation" differently. These should not be first-class Bannou types.Current State
Schema (
schemas/quest-api.yaml):With dedicated fields on
PrerequisiteDefinition:minLevel— for CHARACTER_LEVEL typefactionCode— for REPUTATION typeminReputation— for REPUTATION typeCode (
QuestService.Helpers.cs):case PrerequisiteType.CharacterLevel:routes toCheckDynamicPrerequisiteAsync("character_level", ...)case PrerequisiteType.Reputation:routes toCheckDynamicPrerequisiteAsync("reputation", ...)Code behavior: These enum values ALREADY route through the dynamic provider path — they're not built-in L2 checks. The enum values are cosmetic; the code treats them as dynamic.
Required Changes
Schema (
schemas/quest-api.yaml)CharacterLevelandReputationfromPrerequisiteTypeenumminLevel,factionCode,minReputation) fromPrerequisiteDefinitionPrerequisiteDefinition:providerName(string, nullable) — identifies whichIPrerequisiteProviderFactoryto route tocode(string, nullable) — the prerequisite code passed to the provider'sCheckAsyncminValue(integer, nullable) — numeric threshold for the provider to check againstPrerequisiteTypea Category B opaque string (game-configurable codes) instead of a closed enum, with built-in handlers for known strings ("quest_completed", "currency_amount", "item_owned") and dynamic routing for everything elseCode (
QuestService.Helpers.cs)case PrerequisiteType.CharacterLevel:andcase PrerequisiteType.Reputation:— thedefault:case already routes toCheckDynamicPrerequisiteAsyncCheckDynamicPrerequisiteAsyncto use the generic fields (providerName,code,minValue)Internal model (
QuestModels.cs)MinLevel,FactionCode,MinReputationfromPrerequisiteDefinitionModelDocumentation
docs/plugins/QUEST.md— Already updated (DC#2 rewritten, type classification table updated)docs/maps/QUEST.md— Already updated (dependency table note added)docs/reference/SERVICE-HIERARCHY.md—character_levelas a built-in type callingICharacterClient. Needs correction: either remove the row or reclassify as dynamic/game-specific. Requires explicit user approval to edit.bannou-service/Providers/IPrerequisiteProviderFactory.cs— XML docs incorrectly listcharacter_levelas built-in. Correct to reflect dynamic-only routing.Regeneration
cd scripts && ./generate-models.sh quest+cd scripts && ./generate-service.sh questWhy This Matters
The silent no-op is a functional gap today — quests with
CharacterLevelorReputationprerequisites have zero enforcement. But the fix is NOT adding a specific provider for these game concepts. The fix is removing the game concepts from the enum and letting games define their own prerequisite types through the dynamic provider path — the infrastructure that already exists and works correctly (seeAchievementPrerequisiteProviderFactoryas the reference implementation).Related