Add NPC registry grounding for spell extraction

This commit is contained in:
2026-07-21 03:12:03 +00:00
parent fb043325e1
commit 20cfbfd311
26 changed files with 901 additions and 58 deletions

View File

@@ -1,8 +1,9 @@
# D&D NPC Artifact
This document defines the durable D&D NPC-list artifact and its JSON codec.
The artifact type and codec are implemented, but no selectable production
pipeline currently produces this 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;
it remains a reference, not spell evidence.
## Identity
@@ -55,3 +56,51 @@ 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 then consolidates records
by canonical identity or canonical-name/alias matches, preserves the first
record's display and output position, unions relationships and exact evidence,
rewrites unambiguous relationship targets to canonical names, and validates
the retained registry's identity. No LLM is used for consolidation.
The default extraction chain is `generic/valid_json`,
`generic/valid_json_schema`, `extract/dnd/npcs/shape`,
`extract/dnd/npcs/source_refs`, and
`extract/dnd/npcs/source_relatedness`. The normalize chain adds
`normalize/dnd/npcs/identity` before the source-reference and relatedness
checks. Relatedness emits bounded warnings when an NPC canonical name or
alias is not present near its cited transcript text; opaque campaign
references may explain such a warning but do not become evidence.
## Manifest And Sequential Consumption
The NPC extractor records prompt and response-schema identities. The durable
codec records only `npc_count`; raw names, aliases, descriptions, source
references, and payload bytes stay in the lane file rather than manifest
metadata. The normalized lane is independently reusable as a file reference:
```sh
go run ./cmd/notarius run dnd-spells \
--config examples/dnd-npc-spell-sequential.config.yml \
--input examples/seriatim-minimal-transcript.json \
--reference spells.extract.npcs=./npc-output/<run-id>/lanes/npcs.json
```
The spell extractor strictly decodes and identity-validates this file, accepts
source references belonging to another session as registry provenance, and
uses only canonical names and aliases for caster grounding. Those NPC source
references are never accepted as spell evidence. The spell run's manifest
keeps raw file provenance under `references` and records only the prepared
registry's semantic digest and count in extractor metadata.

View File

@@ -94,6 +94,22 @@ Reference slot keys and accepted file types are defined in
supporting disambiguation material, not source evidence, and are not
addressable through `source_refs`.
## Optional NPC Grounding
The `dnd/spells` extractor accepts an optional `npcs` reference containing one
normalized NPC artifact as `application/json`, up to 1 MiB. Preparation uses
the approved NPC codec and identity policy to validate the file, re-encodes
canonical durable JSON, and supplies that JSON as a spell-owned prompt input.
It helps the model prefer canonical caster names and recognize aliases; it
does not establish that a spell was cast.
NPC source references may identify the run that produced the registry or any
other session. They remain registry provenance and are never copied into a
spell cast's `source_refs`; every spell evidence range must still identify the
current transcript. When the slot is absent, the prompt receives exactly
`{"npcs":[]}` and the run has no NPC reference provenance or NPC checkpoint
fingerprint.
## Normalization Behavior
When the `dnd/spells` normalizer is selected, each recognized spell name is
@@ -153,7 +169,9 @@ manifest metadata:
"response_schema_sha256": "sha256:...",
"catalog_base_id": "dnd-5e-2014-srd-spells",
"catalog_digest": "sha256:...",
"catalog_overlay_ids": ["campaign.example"]
"catalog_overlay_ids": ["campaign.example"],
"npc_registry_digest": "sha256:...",
"npc_count": 3
},
"normalizer": {
"catalog_base_id": "dnd-5e-2014-srd-spells",
@@ -172,8 +190,15 @@ identity fields when that module is selected. Overlay origin, media type, byte
size, and raw digest are recorded separately in the manifest's reference
provenance; see the [JSON output contract](json-output.md#manifestjson).
The `npc_registry_digest` and `npc_count` fields in the example are present only
when the optional NPC registry is bound. They contain no NPC names, aliases,
source references, paths, or raw bytes.
The extractor's prompt hash, private response-schema hash, and effective catalog
digest also contribute independently scoped semantic checkpoint fingerprints.
Changing any of those prepared contracts intentionally produces a cold
checkpoint miss. Fingerprints contain only digests, never prompt, schema,
catalog, or reference content.
catalog, or reference content. When an NPC registry is bound, its semantic
digest contributes an additional local `npc_registry` fingerprint; the
manifest metadata contains only that digest and `npc_count`. Raw NPC file
provenance remains independently recorded in the manifest's `references` list.

View File

@@ -151,7 +151,8 @@ accepts only artifacts whose codec media type is `application/json`. The file
contains the codec-owned JSON bytes pretty-printed.
The schema of each lane payload is owned by that artifact contract. For the
current D&D spell lane, see [D&D Spell Artifact](dnd-spell-artifacts.md).
current D&D lanes, see [D&D Spell Artifact](dnd-spell-artifacts.md) and
[D&D NPC Artifact](dnd-npc-artifacts.md).
## `rejected.json`