194 lines
12 KiB
Markdown
194 lines
12 KiB
Markdown
# D&D Module Internals
|
||
|
||
This guide records the conventions shared by the production D&D module family.
|
||
It complements [Module Internals](modules.md), which owns generic registration
|
||
and extension mechanics, and [Configuration](../config.md), which owns the
|
||
selectable keys, bindings, reference syntax, and default validator chains.
|
||
|
||
## Durable Artifact Contracts
|
||
|
||
The ten lanes have separate durable wire contracts. This guide deliberately
|
||
does not repeat their JSON shapes or schemas.
|
||
|
||
| Lane | Durable contract |
|
||
| --- | --- |
|
||
| Spells | [spell artifacts](../integrations/dnd-spell-artifacts.md) |
|
||
| NPC registry | [NPC registry artifacts](../integrations/dnd-npc-registry-artifacts.md) |
|
||
| Combat turns | [combat-turn artifacts](../integrations/dnd-combat-turn-artifacts.md) |
|
||
| Item occurrences | [item-occurrence artifacts](../integrations/dnd-item-occurrence-artifacts.md) |
|
||
| Item registry | [item-registry artifacts](../integrations/dnd-item-registry-artifacts.md) |
|
||
| NPC occurrences | [NPC-occurrence artifacts](../integrations/dnd-npc-occurrence-artifacts.md) |
|
||
| Scene descriptions | [scene-description artifacts](../integrations/dnd-scene-description-artifacts.md) |
|
||
| Enemy events | [enemy-event artifacts](../integrations/dnd-enemy-event-artifacts.md) |
|
||
| Location registry | [location-registry artifacts](../integrations/dnd-location-registry-artifacts.md) |
|
||
| Location occurrences | [location-occurrence artifacts](../integrations/dnd-location-occurrence-artifacts.md) |
|
||
|
||
## 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, and NPC, location, and item-registry
|
||
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. Production lane code belongs with its D&D codec,
|
||
extractor, normalizer, and validator packages; registry projections and
|
||
identity helpers remain in their owning entity packages rather than in a
|
||
consumer lane.
|
||
|
||
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](../adr/0011-centralize-llm-assets.md).
|
||
|
||
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](../config.md#promptkit-profiles).
|
||
|
||
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, location, and item
|
||
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](../config.md#production-validator-keys-and-default-chains).
|
||
|
||
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 occurrences, NPC
|
||
occurrences, 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, location, and item registries project ordered, source-free `{id, name}`
|
||
pairs to their respective occurrence extractors and normalizers. Exact ID/name
|
||
matching preserves every identity the registry recognizes, including same-name
|
||
locations with distinct source anchors. The NPC registry additionally supplies
|
||
names-only actor grounding to spells, combat turns, and enemy events.
|
||
Scene descriptions are eligibility-only projections: they retain current-chunk
|
||
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 occurrences to `combat_opponent` names and kinds.
|
||
These projections are guidance only 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. |
|
||
| NPC registry | 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 occurrences | Requires the normalized item registry for exact ID/name grounding at extraction and normalization. Campaign context may disambiguate, but the registry never becomes occurrence evidence. |
|
||
| Item registry | Produces source-grounded item types and unique designations. Its LLM-assisted reconciliation is proposal-only, preserves distinct currency denominations and item types, and does not create per-instance identities. |
|
||
| NPC occurrences | 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-occurrence 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. |
|
||
| Location registry | Produces a source-anchored, session-scoped registry from stable proper names or unique in-world designations. 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](../integrations/dnd-location-occurrence-artifacts.md#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](../integrations/dnd-combat-turn-artifacts.md) and
|
||
[scene descriptions](../integrations/dnd-scene-description-artifacts.md).
|
||
The [enemy-event contract](../integrations/dnd-enemy-event-artifacts.md)
|
||
defines its durable semantics; [Configuration](../config.md) 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:
|
||
|
||
~~~sh
|
||
go test ./internal/modules/dnd/...
|
||
go test ./internal/modules/integration/...
|
||
~~~
|