# D&D NPC Artifact This document defines the durable D&D NPC-list artifact, its JSON codec, and the selectable production NPC pipeline. The normalized JSON payload can be passed explicitly to the spell extractor as an optional caster-name registry or to the combat extractor and normalizer as an actor registry. It remains a reference, not spell or combat evidence. The NPC interaction extractor and normalizer also consume this registry for canonical identity; registry source references remain provenance and never become interaction evidence. Their occurrence contract is defined in the [D&D NPC interaction artifact](dnd-npc-interaction-artifacts.md). ## Identity - Artifact kind: `dnd/npc-list` - Durable schema ID: `notarius.dnd.npcs` - Durable schema name: `notarius_dnd_npcs_v1` - Durable schema version: `v1` - Media type: `application/json` - Identity policy: `dnd.npcs.identity.v1` The durable JSON Schema is owned by the D&D NPC codec. NPC IDs are derived from the Unicode-normalized, case-folded canonical name using the identity policy. The durable codec enforces the artifact shape and ID syntax; registry identity validation remains a separate deterministic concern. The extractor's private LLM response schema is a separate structural transport contract. It omits framework-assigned NPC and source IDs and admits semantic candidates for the deterministic shape and source-reference validators; it is not part of this durable contract. ## Output Shape The payload is one object with a required top-level `npcs` array: ```json {"npcs": []} ``` The array may be empty. Every object and nested object rejects unknown fields. ## NPC Fields Each NPC contains exactly these required fields: - `id`: `npc:sha256:` followed by 64 lowercase hexadecimal characters; - `name`: the canonical display name; - `source_refs`: at least one source reference supporting the NPC record. Each source reference contains required `source_id`, `start_unit_id`, and `end_unit_id`; unit IDs are positive integers. Source document identity, unit existence, and range ordering are validated by the source-reference validator when the artifact is used by a pipeline. ## Codec Boundary `EncodeCandidate` and `DecodeCandidate` provide strict single-value JSON serialization while preserving typed values that still need semantic validation. `Encode` and `Decode` are the approved-artifact boundary and require all durable structural fields, non-empty required strings, valid source reference shapes, and the NPC ID pattern. Codec metadata contains only `npc_count`. Schema bytes and returned metadata are independent values so callers cannot mutate codec-owned state. ## Production Pipeline The production identities are: - extractor: `dnd/npcs`; - artifact kind: `dnd/npc-list`; - normalizer: `dnd/npcs`; and - durable schema: `notarius.dnd.npcs`, version `v1`, media type `application/json`. The extractor maps private model records to the current source identity and assigns deterministic IDs. Extraction validation checks shape, source references, and source relatedness. The normalizer first consolidates equal canonical-name matches, then may make one document-level LLM-assisted identity decision per configured normalize attempt for eligible distinctly named records. Consolidation is name-based: it retains a supplied canonical display name, keeps the earliest affected output position, derives its ID again, and unions exact evidence in canonical order. Ambiguous, invalid, or conflicting proposals are not applied; independently safe matches may still be retained. After the retry budget is exhausted, the safe result is accepted with bounded normalization warnings and the usual validation. The durable v1 artifact shape does not add aliases, proposal fields, or any other semantic-normalization representation. The extraction prompt asks only for individually identifiable NPC names backed by source evidence. Groups, generic roles, invented labels, and descriptive or relationship enrichment are outside the contract. The default extraction chain is `generic/valid_json`, `extract/dnd/npcs/shape`, `extract/dnd/npcs/source_refs`, `generic/valid_json_schema`, and `extract/dnd/npcs/source_relatedness`. The default normalize chain is `generic/valid_json`, `extract/dnd/npcs/shape`, `normalize/dnd/npcs/identity`, `extract/dnd/npcs/source_refs`, `generic/valid_json_schema`, and `extract/dnd/npcs/source_relatedness`. Relatedness emits bounded warnings when an NPC canonical name is not present near its cited transcript text; opaque campaign references may explain such a warning but do not become evidence. ## Manifest And Artifact Handoff The NPC extractor records prompt and response-schema identities. The durable codec records only `npc_count`; raw names, source references, and payload bytes stay in the lane file rather than manifest metadata. The normalized lane can be consumed by a later ordered step through the registered canonical codec: ```yaml steps: - id: identify-npcs artifacts: npcs: extract: dnd/npcs normalize: dnd/npcs scene-descriptions: extract: dnd/scene-descriptions normalize: dnd/scene-descriptions - id: grounded-events references: npcs: artifact: step: identify-npcs lane: npcs scene_descriptions: artifact: step: identify-npcs lane: scene-descriptions artifacts: spells: extract: dnd/spells normalize: dnd/spells combat: extract: dnd/combat-turns normalize: dnd/combat-turns ``` The framework hands only accepted normalized artifacts across the barrier. It validates the canonical bytes against each consumer slot and clones the NPC operation-time reference for spell and combat consumers. The accompanying scene-description reference is required by the combat extractor for eligibility only; its consumer contract is defined in the [D&D combat-turn artifact contract](dnd-combat-turn-artifacts.md). Generated provenance records the artifact kind, schema identity, media type, canonical digest, size, and producer step/lane/module, but not names, source ranges, or payload bytes. External normalized files remain supported as explicit references and retain their file provenance. NPC source references are registry provenance and are never accepted as spell or combat evidence. Current transcript units remain the only event evidence. Consumers receive a separate names-only projection in normalized registry order, for example `{"npcs":[{"name":"Mira Thorn"}]}`. The projection omits IDs and evidence. Its digest covers the exact projected bytes and is used for consumer-local checkpoint identity, while the full durable artifact digest remains the manifest and generated-reference provenance identity. The unbound projection is exactly `{"npcs":[]}` and also has a projection digest.