12 KiB
D&D Module Internals
This guide records the conventions shared by the production D&D module family. It complements Module Internals, which owns generic registration and extension mechanics, and Configuration, which owns the selectable keys, bindings, reference syntax, and default validator chains.
Durable Artifact Contracts
The nine lanes have separate durable wire contracts. This guide deliberately does not repeat their JSON shapes or schemas.
| Lane | Durable contract |
|---|---|
| Spells | spell artifacts |
| NPCs | NPC artifacts |
| Combat turns | combat-turn artifacts |
| Item events | item-event artifacts |
| NPC interactions | NPC-interaction artifacts |
| Scene descriptions | scene-description artifacts |
| Enemy events | enemy-event artifacts |
| Locations | location artifacts |
| Location occurrences | location-occurrence artifacts |
Family Composition
The D&D registrar registers the family’s artifact codecs, extractors, typed
append-order mergers, normalizers, validators, prompt assets, fallback LLM
profile asset, and default validator chains. Each extractor and normalizer has
a stable module spec, explicit execution class, strict option decoding, and a
typed builder. Scene chunking, every extractor, NPC normalization, and location
normalization are registered as llm_backed; the remaining current D&D mergers
and normalizers are deterministic. The metadata is available to catalog inspection and
resolved-pipeline debug data and determines which selected bindings inherit the
pipeline profile. Configuration remains the canonical owner of the exact keys,
profile precedence, and validator order.
Private structured-LLM response schemas are deliberately minimal. They reject invalid JSON structure, missing required fields, incompatible types, and unknown fields, while preserving semantic candidates for deterministic validation. Do not promote a private response envelope into a durable schema; the contracts above define durable data.
Prompt Construction
D&D LLM-facing content lives beneath assets/dnd/. Each module contributes a
local prompt.yaml declaration and instructions.md; input-specific files
such as a catalog, registry, grounding projection, or candidate collection are
local only when that module needs them. New extractor content uses its feature
subtree, while families with both extraction and normalization content use their
extract and normalize subtrees. Shared visual-provenance fragments use
the common-dnd- prefix.
The owning module’s manifest is the source of truth for which local and shared
assets are selected, their mount paths, their message order, cache controls,
and the files included in its prompt fingerprint. Shared fragments belong to
the D&D shared implementation and are selected by name rather than copied into
module directories. The root assets package is a content-only boundary; its
physical ownership and rationale are defined by
ADR-0011.
Put each rule at its narrowest owner:
- universal behavior belongs in the shared system asset;
- D&D-family behavior belongs in a selected
common-dnd-asset; - rules for an input projection belong with that input asset;
- lane-specific policy belongs in the module’s
instructions.md; and - transport-envelope shape belongs in the private response schema.
A rule is eligible for the system prompt only when every D&D LLM prompt needs it regardless of lane, inputs, or response shape. Module instructions must not repeat rules selected from shared assets or schemas. Reintroduce such repetition only after observational evaluation with representative transcripts shows that it improves results at the intended target models and cost; structural prompt tests alone are not that evidence.
Every maintained D&D LLM prompt selects dnd-extraction as its default
profile. The D&D registrar registers the fallback, while an operator can
replace it with a complete profile of the same ID from the configured PromptKit
source. Deployment profile selection is documented in
Configuration.
The transcript assets have distinct consumers. Scene chunking consumes the
complete-session common-dnd-transcript-full.md; extraction prompts consume
the current-chunk common-dnd-transcript-chunk.md; and NPC and location
normalization consume common-dnd-transcript-windows.md alongside their
candidate collections. Player, party, glossary, and compatible campaign
references provide disambiguating context, not evidence. Reference material is
canonically ordered before rendering so equivalent inputs remain stable.
Extraction prompts render the common system and identity messages first, then cached campaign references and the cached chunk transcript. Evidence policy and any lane-specific registry, catalog, or grounding projection follow that prefix. The final module instructions message is ephemeral. This keeps the reusable extraction prefix identical while preserving the lane-specific suffix.
Scene chunking intentionally uses a different order: system, cached campaign references, uncached module instructions, then the final ephemeral full transcript. Entity normalization also has its own order: system, uncached module instructions, ephemeral reconciliation policy, uncached candidates, and final ephemeral transcript windows. These orders and cache controls are prompt behavior; change them only through the owning manifest and prompt declaration.
Evidence, Candidates, And Normalization
The current transcript is the only durable evidence source. Extractors assign the current source identity, preserve candidate evidence ranges for validators, and canonically order or remove exact duplicate ranges without asking the model to repair semantic errors. Campaign context and generated artifacts may ground names or control routing, but they never establish evidence for a D&D result.
Default chains keep responsibilities separate: structural validators assess the candidate, source-reference validators resolve cited ranges against the current source, durable-schema validation checks an approved representation, and relatedness validators report advisory evidence concerns. The configured order is documented in Configuration.
Enemy-event extraction additionally rejects a second engaged observation for
the same comparison identity within one scene-scoped result. Normalization may
combine results from distinct scenes, so it intentionally does not apply that
rule. Configuration owns the exact validator key and chain position.
Normalizers are deterministic for spells, combat turns, item events, NPC interactions, scene descriptions, enemy events, and location occurrences. They canonicalize display values and evidence, use source-document order for stable output, and issue bounded warnings for changes or collapsed duplicates. The NPC and location normalizers are intentional exceptions: each first produces a deterministic candidate set, then may use a bounded structured-LLM proposal to reconcile identity groups. Invalid or unusable proposals retain the deterministic result and surface retry or fallback diagnostics; the model does not directly replace durable records.
Generated References And Grounding
Normalized D&D artifacts can be handed to a later step through a generated reference binding. The framework verifies artifact compatibility and retains producer provenance; consumers resolve the handed-off artifact into an immutable, validated projection for each operation. External files are checked during preparation, while generated artifacts are resolved at the handoff.
NPC registries are names-only grounding projections: they may canonicalize
actors for spells and combat turns and are required for NPC interactions, but
they do not supply evidence. Scene-description registries are eligibility-only
projections: they retain the current chunk’s classification data, not scene
prose or evidence, and exist to route combat extraction. Enemy-event extraction
also projects combat turns to actor and turn_kind and filters NPC
interactions to combat_opponent names and kinds. Location registries project
ordered {id, name} pairs to location-occurrence extraction and normalization;
exact ID/name matching keeps same-name locations distinguishable. These compact
projections, like NPC grounding, are source-free guidance and never event
evidence.
Lane-Specific Rules
The following differences are intentional and should remain explicit when a shared helper changes.
| Lane | Intentional behavior |
|---|---|
| Spells | May use a spell-catalog overlay and optional NPC grounding; the catalog validator supplies domain-specific semantic checks. |
| NPCs | Does not consume an NPC registry. Its normalizer is the LLM-assisted reconciliation exception described above. |
| Combat turns | Requires a scene-description artifact. It calls the LLM only for an exact combat classification; exact non-combat classifications return an accepted empty result, while missing or mismatched classifications return an empty result with a bounded warning. Optional NPC grounding never becomes evidence. |
| Item events | Uses campaign context for disambiguation but has no NPC-registry or scene-description dependency. |
| NPC interactions | Requires the normalized NPC registry at extraction and normalization, using it for canonical actor grounding only. |
| Scene descriptions | Produces the classifications consumed by combat routing; it does not consume an NPC registry or provide evidence for combat artifacts. |
| Enemy events | Requires NPC, scene-description, combat-turn, and NPC-interaction artifacts. It calls the LLM only for an exact combat classification, records ordered observations rather than terminal state, and normalizes recognized names through the NPC registry while preserving grounded collective labels. |
| Locations | Produces a source-anchored, session-scoped registry. Its LLM-assisted reconciliation is proposal-only and never collapses same-name places without validated identity and evidence rules. |
| Location occurrences | Requires the normalized location registry for both extraction and normalization. Its durable occurrence categories distinguish explicit speculation from unsupported inference; the deterministic normalizer enforces exact registry grounding and never turns registry provenance into occurrence evidence. |
The combat and scene-description contracts describe their exact handoff and empty-result behavior in more detail: combat turns and scene descriptions. The enemy-event contract defines its durable semantics; Configuration owns its selectable bindings and validation chains.
Focused Verification
When changing D&D behavior, test the affected codec, extractor, normalizer, validator, prompt-asset manifest, and registry projection. Also test generated handoffs at the integration boundary and run the full D&D module suite:
go test ./internal/modules/dnd/...
go test ./internal/modules/integration/...