# Canonical D&D Entity Registries And Occurrences

## Purpose

This roadmap defines the target state for D&D entity extraction in Notarius.
NPCs, locations, and items should follow one legible architecture: a registry
lane first identifies canonical entities, and a later occurrence lane consumes
that registry to extract independently evidenced facts about those entities.

The work is a clean pre-release contract redesign. It should remove the current
mixture of bare plural, interaction, occurrence, and event terminology; add the
missing item registry; tighten entity eligibility; and make generated-reference
relationships visible in module, artifact, schema, prompt, validation, example,
and documentation names.

This roadmap owns the desired behavior and policy. The
[implementation plan](implementation.md) owns sequencing and task breakdowns.

## Background

Notarius already implements most of the required platform mechanics:

- ordered pipeline steps create a barrier between registry production and
  occurrence extraction;
- generated artifact references are validated for topology, media type,
  artifact kind, schema, and codec compatibility before execution;
- NPC and location registries have deterministic identities and bounded
  LLM-assisted reconciliation;
- NPC interactions and location occurrences consume normalized registry
  artifacts as source-free grounding; and
- validators keep registry provenance separate from occurrence evidence.

The remaining D&D domain contracts are inconsistent:

- `dnd/npcs` produces a registry, but its name does not communicate that role;
- `dnd/npc-interactions` is an occurrence lane under a narrower name;
- `dnd/locations` produces a registry while `dnd/location-occurrences` already
  uses the desired downstream terminology;
- `dnd/item-events` extracts occurrences directly and has no canonical item
  registry; and
- current location eligibility permits generic labels that are not suitable
  canonical nouns for reuse by downstream consumers.

[ADR-0009](../adr/0009-minimal-evidence-grounded-extraction-artifacts.md)
already establishes that changing encounter-level facts belong in occurrence
artifacts rather than registry attributes. [ADR-0008](../adr/0008-ordered-pipeline-steps.md)
already establishes explicit ordered artifact handoffs. This feature applies
those decisions consistently; it does not change the platform architecture.

## Goals

The completed feature should:

- make registry producers and occurrence consumers immediately recognizable by
  their names;
- provide registry and occurrence lanes for NPCs, locations, and items;
- require every entity occurrence to resolve to one canonical registry ID and
  display name;
- tighten registry eligibility so entries are stable nouns or designations
  that a downstream consumer can reuse;
- preserve minimal, evidence-grounded durable artifacts;
- keep registry provenance distinct from occurrence evidence;
- use ordered generated references rather than inferred dependencies;
- preserve domain-specific occurrence categories and identity rules where the
  entity types genuinely differ;
- use a clean pre-release migration with no aliases or compatibility shims; and
- leave the codebase with three concrete registry implementations from which a
  later generic deduplication design can be evaluated.

## Non-Goals

This work does not introduce:

- a general workflow DAG or implicit dependency inference;
- a generic framework-level LLM deduplication module;
- campaign-wide or cross-run registries;
- an inventory, currency balance, possession ledger, or current-state model;
- item-instance tracking for interchangeable objects;
- narrative descriptions, biographies, relationships, ownership summaries, or
  other enrichment on registry entries;
- occurrence-derived attributes copied back onto registry entries;
- NPC IDs on spell, combat-turn, or enemy-event artifacts merely because those
  lanes consume NPC grounding;
- migration tooling for old checkpoints or durable artifacts; or
- compatibility aliases for retired module keys, artifact kinds, prompt IDs,
  reference slots, schemas, or validator keys.

## Canonical Naming

### Modules

Registry extractors and their matching normalizers use
`dnd/<singular-entity>-registry`. Occurrence extractors and their matching
normalizers use `dnd/<singular-entity>-occurrences`.

| Role | Current module key | Target module key |
| --- | --- | --- |
| NPC registry | `dnd/npcs` | `dnd/npc-registry` |
| NPC occurrences | `dnd/npc-interactions` | `dnd/npc-occurrences` |
| Location registry | `dnd/locations` | `dnd/location-registry` |
| Location occurrences | `dnd/location-occurrences` | `dnd/location-occurrences` |
| Item registry | none | `dnd/item-registry` |
| Item occurrences | `dnd/item-events` | `dnd/item-occurrences` |

The same key is used for a lane's extract and normalize modules, as it is for
other current D&D lanes. Stage identity continues to distinguish those module
registrations.

### Durable artifacts

Registry artifact kinds name the registry directly. Occurrence artifact kinds
retain the `-list` suffix because their durable value is an ordered collection
of independently evidenced observations.

| Role | Target artifact kind | Target schema ID | Root collection |
| --- | --- | --- | --- |
| NPC registry | `dnd/npc-registry` | `notarius.dnd.npc_registry` | `npcs` |
| NPC occurrences | `dnd/npc-occurrence-list` | `notarius.dnd.npc_occurrences` | `occurrences` |
| Location registry | `dnd/location-registry` | `notarius.dnd.location_registry` | `locations` |
| Location occurrences | `dnd/location-occurrence-list` | `notarius.dnd.location_occurrences` | `occurrences` |
| Item registry | `dnd/item-registry` | `notarius.dnd.item_registry` | `items` |
| Item occurrences | `dnd/item-occurrence-list` | `notarius.dnd.item_occurrences` | `occurrences` |

All redesigned durable schemas remain version `v1`. Notarius is pre-release,
and these names replace rather than version or alias the retired contracts.
Schema names should follow the corresponding underscore form, such as
`notarius_dnd_item_registry_v1`.

Canonical Go types, codec packages, validator packages, prompt IDs, private
response-schema identities, capability names, and asset subtrees should use the
same registry/occurrence vocabulary. Prompt IDs should be
`dnd.<entity>_registry`, `dnd.<entity>_registry.normalize`, and
`dnd.<entity>_occurrences` as applicable.

The corresponding durable integration contracts should be:

- `docs/integrations/dnd-npc-registry-artifacts.md`;
- `docs/integrations/dnd-npc-occurrence-artifacts.md`;
- `docs/integrations/dnd-location-registry-artifacts.md`;
- `docs/integrations/dnd-location-occurrence-artifacts.md`;
- `docs/integrations/dnd-item-registry-artifacts.md`; and
- `docs/integrations/dnd-item-occurrence-artifacts.md`.

Those documents will become canonical only when the contracts are implemented;
until then, this roadmap is the sole owner of the proposed names and behavior.

### References

Registry-consuming modules expose explicit reference slots named:

- `npc_registry`;
- `location_registry`; and
- `item_registry`.

Generated-reference aliases in maintained examples should use those same names.
The reference slot, not a matching lane label, owns dependency resolution. Each
slot accepts only the corresponding registry artifact kind and media type and
retains an explicit size bound.

Existing NPC-grounded consumers such as spells, combat turns, enemy events, and
NPC occurrences should use `npc_registry`. Location occurrences should use
`location_registry`, and item occurrences should require `item_registry` at
both extraction and normalization.

## Registry Contract

Every registry answers one narrow question: which reusable canonical entities
of this type are established by the current transcript?

Each registry record contains only:

- a deterministic application-owned `id`;
- a canonical display `name`; and
- one or more transcript `source_refs` establishing the entity identity.

Registries do not contain encounter roles, occurrence categories, descriptions,
summaries, aliases, relationships, inventories, holder state, or inferred
attributes. Their source references establish registry provenance only.

Registry extraction remains chunk-scoped. Merge and normalization combine
candidate records across chunks, canonicalize evidence in source-document
order, apply deterministic identity rules, and may use a bounded structured-LLM
proposal to reconcile semantic duplicates. The model proposes duplicate groups;
deterministic code validates keys, membership, overlap, canonical selection,
and application. Invalid or uncertain proposals preserve the safe deterministic
result and produce bounded diagnostics.

The existing shared D&D entity-reconciliation substrate should support all
three registries. Entity-specific candidate construction, identity judgment,
canonical-name preference, and consolidation remain in the owning D&D module.
This feature must not move D&D policy into generic framework packages.

## Entity Eligibility And Identity

Eligibility is based on whether the transcript establishes a stable reusable
referent, not on capitalization alone. Transcript capitalization is unreliable,
and a capitalized generic phrase is not automatically a canonical entity.

### NPC registry

Include an NPC when the transcript establishes an individually identifiable
non-player character through a proper name or a stable unique designation. A
title or descriptive designation qualifies only when the transcript uses it as
a persistent identity, such as `the Masked Envoy`; a transient generic role
such as `a guard`, `the bartender`, or `one of the bandits` does not qualify.

Exclude player characters, speakers known only by player identity, anonymous
groups, creature categories, generic roles, speculative identities, and labels
invented merely to make an occurrence referable.

NPC IDs use the `npc:sha256:` prefix and identity policy
`dnd.npc_registry.identity.v1`. The digest is the lowercase SHA-256 of compact
JSON for `[policy, comparison_name]`, where the comparison name uses the
existing Unicode, apostrophe, whitespace, and case normalization. Semantic
reconciliation may collapse supported aliases but may not merge distinct people
merely because their names or roles are similar.

### Location registry

Include a location only when the transcript establishes a stable proper name or
unique in-world designation, such as `Waterdeep`, `The Yawning Portal`, or a
uniquely named chamber. Exclude generic, temporary, relative, or purely
descriptive references such as `the room`, `the bar`, `the hallway`, `outside`,
or `upstairs`.

A later occurrence may resolve a generic phrase such as `the bar` to an existing
named registry location when the current transcript context supports that
coreference. The generic phrase must not create a new registry entry.

Location IDs use the `location:sha256:` prefix and identity policy
`dnd.location_registry.identity.v1`. The digest is the lowercase SHA-256 of
compact JSON for `[policy, comparison_name, source_id, start_unit_id,
end_unit_id]`, using the earliest canonical evidence anchor. Source anchoring
keeps distinct places with the same display name distinguishable. Nested places
and same-name places remain distinct unless a validated semantic proposal
establishes that candidates identify the same physical place.

### Item registry

Items do not need proper names. Include a reusable, transcript-established item
name at the narrowest useful type or unique-designation level, including:

- named unique objects;
- concrete item types such as `Healing Potion` when the transcript establishes
  that type;
- stable unique designations used by the session; and
- individual currency denominations such as `Silver Pieces`.

Exclude vague or non-reusable descriptions such as `loot`, `treasure`, `some
gear`, `a weapon`, or `something valuable` unless the transcript supplies a
more stable name or designation. Do not infer mechanical subtype, magic
properties, denomination, quantity, or uniqueness.

An item-registry record identifies a canonical item kind or designation, not a
physical instance. Interchangeable objects with the same canonical name share
one registry identity and are distinguished in occurrences by evidence,
quantity, and holder transitions. A genuinely named unique object naturally
has its own canonical identity.

Item IDs use the `item:sha256:` prefix and identity policy
`dnd.item_registry.identity.v1`. The digest is the lowercase SHA-256 of compact
JSON for `[policy, comparison_name]`, using the same text normalization family
as other entity registries. Item normalization may reconcile transcript-
supported aliases and abbreviation variants but may not collapse distinct
denominations or materially different item types.

## Occurrence Contract

Every occurrence answers a separate question: what source-grounded event or
relationship to a known registry entity occurred in this transcript passage?

Each occurrence record contains:

- the exact entity ID from its required registry;
- the exact canonical display name associated with that ID;
- one bounded occurrence kind; and
- one or more source references from the current transcript.

Entity-specific fields are allowed only when required by that occurrence
contract. Registry IDs and names provide grounding; registry source references
never become occurrence evidence. Unknown IDs and mismatched ID/name pairs are
rejected rather than guessed, reassigned, or repaired from display-name
similarity.

Occurrence extractors may resolve an alias, pronoun, generic reference, or
abbreviation to an existing registry entry only when the current chunk supports
that coreference. They may not add entities to the registry. Omit an occurrence
when entity resolution or the occurrence itself is not adequately supported.

Occurrence normalization is deterministic. It validates registry membership,
canonicalizes the display name from the registry, orders and deduplicates source
references, preserves distinct observations, orders records by source-document
chronology and stable domain tie-breakers, and collapses only exact duplicates.

### NPC occurrences

The durable record contains required `npc_id`, `name`, `kind`, and
`source_refs`. It retains the current interaction categories:

- `mentioned`;
- `noncombat_presence`;
- `dialogue`;
- `combat_ally`;
- `combat_opponent`; and
- `other`.

The precedence and splitting rules of the current NPC-interaction contract
remain applicable. Renaming the artifact does not turn it into a biography,
relationship model, sentiment analysis, or persistent NPC state.

Enemy-event grounding consumes `combat_opponent` NPC occurrences under the new
contract. Other NPC-grounded lanes continue to consume the registry directly.

### Location occurrences

The durable record continues to contain required `location_id`, `name`, `kind`,
and `source_refs`. It retains the current categories and precedence:

- `visited`;
- `planned`;
- `recalled`; and
- `mentioned`.

Generic current-chunk language may resolve to a named registry location, but
the occurrence must cite the current transcript passage that supports both the
resolution and the occurrence category.

### Item occurrences

The durable record contains required `item_id`, `name`, `kind`, and
`source_refs`, plus the current semantically conditional `quantity`, `from`,
and `to` fields. It retains the current categories:

- `discovered`;
- `acquired`;
- `lost`;
- `consumed`; and
- `transferred`.

Holder and quantity rules remain unchanged: discovery has no holder; acquisition
requires a gaining holder; loss and consumption require a losing holder; and
transfer requires distinct losing and gaining holders. Currency remains an
ordinary item occurrence with an explicit denomination and a quantity only
when the transcript establishes one.

Item occurrences do not compute inventory, merge successive state changes,
convert denominations, infer unspoken holders, or distinguish physical
instances that the transcript does not identify.

Private LLM response schemas should remain strict and compatible with providers
that require every declared property to be required. Nullable or explicit
absence representations may be used privately for semantically conditional
item fields; deterministic mapping owns omission from the durable artifact when
the public contract calls for an absent field.

## Pipeline End State

A complete D&D pipeline produces all three registries in an earlier step and
binds them explicitly into later consumers. Conceptually:

```text
registry step
  npc-registry
  location-registry
  item-registry
  scene-descriptions

occurrence and action step
  npc-occurrences      <- npc-registry
  location-occurrences <- location-registry
  item-occurrences     <- item-registry
  spells               <- optional npc-registry
  combat-turns         <- optional npc-registry + required scene descriptions

derived enemy step
  enemy-events <- npc-registry + npc-occurrences + combat turns + scene descriptions
```

Steps remain barriers with the existing whole-run failure behavior. A required
registry producer that fails, rejects, or does not publish an accepted
normalized artifact prevents its dependent later step and fails the run under
the existing ordered-pipeline contract. Configuration with a same-step or
forward generated reference remains invalid.

The maintained complete D&D example should use generated references for these
same-run handoffs. Registry slots continue to accept compatible external path
references under the existing configuration contract; this feature does not
remove the ability to supply a previously produced or independently maintained
registry artifact.

The shared scene plan remains pipeline-wide. This feature changes eligible
lanes and reference bindings, not chunking or scheduling semantics.

## Validation And Normalization

Each registry receives production defaults for:

- JSON and durable-schema validity;
- registry shape and required evidence;
- deterministic identity and uniqueness;
- source-reference validity;
- source relatedness; and
- safe bounded reconciliation during normalization.

Each occurrence family receives production defaults for:

- JSON and durable-schema validity;
- occurrence shape and kind-specific invariants;
- exact registry ID/name membership;
- source-reference validity;
- source relatedness; and
- deterministic ordering and exact-duplicate removal.

Validator and capability keys should adopt the new module vocabulary. Registry
membership validators consume the same immutable registry projection used by
the extractor and normalizer. Validators do not use registry provenance as a
substitute for occurrence evidence and do not mutate supplied artifacts or
references.

Warnings remain bounded, content-safe, and deterministic. Prompt, schema,
registry, and identity fingerprints remain represented by hashes or stable
identities rather than raw content in manifests and diagnostics.

## Package And Asset Organization

Implementation packages should make the two roles visible, using Go-compatible
names such as `npcregistry`, `npcoccurrences`, `locationregistry`, and
`itemoccurrences` beneath the existing extract, normalize, codec, and validate
families. Entity-specific identity and immutable registry-resolution helpers
remain inside the D&D domain.

LLM assets should use corresponding subtrees beneath `assets/dnd/`, for example
`assets/dnd/npc-registry/{extract,normalize}` and
`assets/dnd/item-occurrences`. The root `assets` package remains a single-file,
content-only filesystem boundary with no business logic, registration, or
PromptKit dependency.

All extraction prompts retain the shared D&D prompt prefix and chunk scope.
Registry prompts own only entity eligibility and canonical-name policy;
occurrence prompts own only occurrence semantics and entity-specific fields.
Registry input fragments own the meaning of their source-free projections.

## Migration Policy

The redesign is intentionally breaking and immediate:

- remove retired module and validator keys;
- remove retired artifact kinds, schema IDs, schema names, Go types, prompt IDs,
  private schema identities, reference slots, capability names, asset paths,
  and generated-reference aliases;
- do not register aliases or decode old shapes;
- do not retain duplicate integration documents for old contracts; and
- accept invalidation of old checkpoints, prompt fingerprints, provider caches,
  example output, and other reconstructible pre-release state.

New contracts use version `v1`; `v2` does not communicate useful compatibility
information while there is no supported release to preserve. Current-behavior
documentation, maintained examples, module catalogs, and integration contracts
must change atomically with implementation.

## Evaluation Expectations

Implementation should be assessed against representative transcript cases that
cover:

- named NPCs, stable NPC designations, transient roles, aliases, and anonymous
  groups;
- named locations, same-name locations, nested locations, generic spatial
  phrases, and supported generic coreferences to named places;
- named items, ordinary item types, ambiguous descriptions, aliases, quantities,
  transfers, consumption, and each currency denomination;
- registry candidates mentioned across multiple chunks;
- unsupported occurrence links and mismatched registry ID/name pairs; and
- output from cost-effective smaller models as well as the default production
  profile.

Deterministic tests should protect schemas, identity rules, registry resolution,
reference compatibility, ordering, validation, normalization, and assembled
multi-step configuration. Live model quality remains an opt-in human evaluation
activity rather than a default automated gate.

## Target End State

The feature is complete when:

- the six canonical entity modules are the only selectable NPC, location, and
  item registry/occurrence modules;
- all six durable artifacts use the target kinds, schema identities, root
  collections, minimal record shapes, and `v1` contracts defined here;
- every occurrence contains and validates an exact registry ID/name pair;
- NPC, location, and item registry eligibility follows the policies above;
- the maintained complete pipeline uses explicit generated registry references
  across ordered steps, while compatible external registry references remain
  supported;
- item occurrences no longer run independently of an accepted item registry;
- spell, combat, enemy, and occurrence consumers use the renamed registry slots
  without treating registry provenance as evidence;
- current module catalogs, default validator chains, prompts, assets, examples,
  integration contracts, internal documentation, and tests use only the new
  vocabulary; and
- repository searches find no production compatibility aliases or stale current-
  behavior claims for `dnd/npcs`, `dnd/npc-interactions`, `dnd/locations`, or
  `dnd/item-events`.
