44 KiB
Canonical D&D Entity Registries And Occurrences Implementation Plan
Objective
Implement the target state defined in Canonical D&D Entity Registries And Occurrences. NPCs, locations, and items will each have one canonical registry lane and one registry-backed occurrence lane, with consistent module, artifact, schema, prompt, reference, validation, package, asset, example, and documentation vocabulary.
This is a breaking pre-release migration. The completed implementation must not retain compatibility aliases for old module keys, artifact kinds, types, schemas, prompts, validators, reference slots, or asset paths. The stages below deliberately change durable contracts before moving the corresponding module namespace so that each prompt remains bounded for gpt-5.6-terra and the repository can compile and pass focused tests after every stage.
Complete the stages in numerical order. Each stage is sized for one implementation prompt. Do not combine stages unless a later review explicitly revises this plan.
Final Contract Matrix
Use these exact final identities. Do not invent variants during implementation.
| Entity role | Module key | Go artifact type | Artifact kind | Durable schema ID | Durable root |
|---|---|---|---|---|---|
| NPC registry | dnd/npc-registry |
dnd.NPCRegistry |
dnd/npc-registry |
notarius.dnd.npc_registry |
npcs |
| NPC occurrences | dnd/npc-occurrences |
dnd.NPCOccurrenceList |
dnd/npc-occurrence-list |
notarius.dnd.npc_occurrences |
occurrences |
| Location registry | dnd/location-registry |
dnd.LocationRegistry |
dnd/location-registry |
notarius.dnd.location_registry |
locations |
| Location occurrences | dnd/location-occurrences |
dnd.LocationOccurrenceList |
dnd/location-occurrence-list |
notarius.dnd.location_occurrences |
occurrences |
| Item registry | dnd/item-registry |
dnd.ItemRegistry |
dnd/item-registry |
notarius.dnd.item_registry |
items |
| Item occurrences | dnd/item-occurrences |
dnd.ItemOccurrenceList |
dnd/item-occurrence-list |
notarius.dnd.item_occurrences |
occurrences |
All durable contracts use schema version v1 and media type
application/json. Registry records have required id, name, and
source_refs. NPC, location, and item occurrences have required npc_id,
location_id, or item_id respectively, plus required name, kind, and
source_refs. Item occurrence quantity, from, and to remain semantically
conditional durable fields.
Use these exact identity policies and digest inputs:
- NPC:
dnd.npc_registry.identity.v1, SHA-256 of compact JSON[policy, comparison_name], prefixnpc:sha256:; - location:
dnd.location_registry.identity.v1, SHA-256 of compact JSON[policy, comparison_name, source_id, start_unit_id, end_unit_id]using the earliest canonical evidence anchor, prefixlocation:sha256:; and - item:
dnd.item_registry.identity.v1, SHA-256 of compact JSON[policy, comparison_name], prefixitem:sha256:.
Registry reference slots and corresponding PromptKit inputs are exactly
npc_registry, location_registry, and item_registry. Enemy-event grounding
uses npc_occurrences for the renamed NPC occurrence artifact.
Rules For Every Stage
- Read and follow
docs/policy/architecture.md,docs/policy/documentation.md, anddocs/policy/testing.mdbefore editing. - Preserve the fixed pipeline architecture, typed artifact zone, ordered-step barrier, generated-reference provenance, whole-run failure behavior, scheduler, checkpoint, and output boundaries. This feature requires no new framework workflow primitive and no new ADR.
- Keep
assets/assets.goas the root assets package's only Go file. It remains a read-only content boundary with no business logic, PromptKit dependency, registry behavior, or module registration. - Keep D&D semantics inside
internal/modules/dndandassets/dnd. Do not implement the future generic LLM-assisted deduplicator in this work set. - Do not create compatibility type aliases, duplicate module registrations, legacy schema decoders, fallback reference-slot names, copied prompt assets, or deprecated-key shims. Intermediate stages may retain a current module key until its explicit namespace-migration stage, but must not register both old and new keys.
- Preserve minimal evidence-grounded contracts. Registry references are source-free grounding and never occurrence evidence. Every occurrence must cite current-transcript ranges independently.
- Private structured-response schemas must reject unknown fields and include
every declared property in
required. Use nullable private fields for semantically absent item values and map them deterministically to omitted durable fields. - Preserve prompt-cache construction: extraction prompts share the byte-identical system/identity/reference/chunk prefix; evidence and registry projections follow that prefix; module instructions remain final. Registry normalizers retain system, instructions, shared reconciliation policy, candidates, and transcript-window order.
- Update current-behavior documentation when a stage changes an implemented
contract. Do not describe a not-yet-registered item module outside
docs/roadmap/before its production-registration stage. - Keep default tests offline, deterministic, and credential-free. Use package behavior tests for codecs, identity, registry resolution, normalization, and validators; integration tests for generated handoffs; and CLI tests for assembled examples. Do not add live-LLM tests, exact prompt snapshots, private asset inventories, or duplicate change-detector tests.
- Preserve unrelated user changes. Use
gofmt,git diff --check, and focused tests in every stage. Do not retire this roadmap or the feature roadmap as part of implementation.
Stage 1: Migrate The NPC Registry Durable Contract And Identity
Goal
Adopt the final NPC registry type, artifact kind, schema identity, and identity
algorithm while the selectable module temporarily remains dnd/npcs.
Required changes
- In
internal/modules/dnd/types.go, replaceNPCListKindandNPCListwithNPCRegistryKindandNPCRegistry. RetainNPCwith requiredID,Name, andSourceRefs, and retain the durable root fieldnpcs. - Update every typed consumer, merger, evidence projection, validator,
normalizer, extractor, test fixture, integration helper, and registry
registration to use
dnd.NPCRegistryanddnd.NPCRegistryKind. Do not leave a Go alias for the retired names. - In the existing NPC codec package, replace the durable schema with
dnd_npc_registry.v1.json, schema IDnotarius.dnd.npc_registry, schema namenotarius_dnd_npc_registry_v1, and versionv1. Keep the strictnpcsenvelope andapplication/jsonmedia type. - Change the NPC identity policy to
dnd.npc_registry.identity.v1. Derive IDs from compact JSON[policy, comparison_name], not the current bare comparison string. Preserve Unicode NFKC, apostrophe normalization, whitespace collapse, case folding, empty-input rejection, lowercase SHA-256, and the existing ID prefix. - Update registry validation and tests to prove the documented bytes, policy namespace, deterministic IDs, uniqueness, concurrency safety, malformed-ID rejection, and non-mutation. Update dependent fixtures to use newly derived IDs rather than copied old digests.
- Update the current
docs/integrations/dnd-npc-artifacts.mdin place so its artifact kind, schema identity, Go-independent ID algorithm, and wire example match this stage. It must continue to namednd/npcsas the current producer until Stage 2.
Acceptance criteria
- No production Go code refers to
NPCListorNPCListKind. - The registered codec round-trips the strict
NPCRegistryv1contract and reports the target kind and schema identity. - All current NPC-grounded consumers compile against
NPCRegistrywithout changing their reference-slot names yet. - There is no compatibility alias or decoder for
dnd/npc-listornotarius.dnd.npcs.
Validation
Run gofmt on every Go file changed in this stage, then run:
go test ./internal/modules/dnd/... ./internal/modules/integration/...
git diff --check
Stage 2: Move The NPC Registry Module Into Its Canonical Namespace
Goal
Rename the NPC registry's selectable modules, packages, prompts, assets, validators, capabilities, and reference slots without changing the durable record shape completed in Stage 1.
Required changes
- Move the stage packages to Go-compatible canonical paths:
codec/npcregistry,extract/npcregistry,normalize/npcregistry, andvalidate/npcregistry/.... Domain helpers underinternal/modules/dnd/npcsmay remain because they own NPC identity rather than a selectable module. - Set extract and normalize module keys to
dnd/npc-registry. Rename all NPC validator keys from.../dnd/npcs/...to.../dnd/npc-registry/..., and rename the provided capability todnd.npc_registry. - Move
assets/dnd/npcs/{extract,normalize}toassets/dnd/npc-registry/{extract,normalize}. Use prompt IDsdnd.npc_registryanddnd.npc_registry.normalize; use private schema IDnotarius.dnd.npc_registry.llm, schema namenotarius_dnd_npc_registry_llm_v1, and filenamednd_npc_registry_llm.v1.json. - Rename
common-dnd-npcs.mdtocommon-dnd-npc-registry.md. Change the rendered PromptKit input and every module-facing reference slot fromnpcstonpc_registryin spells, combat turns, the still-current NPC-interaction modules, and enemy events. Preserve requiredness: optional for spell and combat grounding, required where the current consumer already requires an NPC registry. - Update immutable NPC registry projections to render ordered
{id, name}pairs where identity is required and the narrowest source-free name projection where a consumer intentionally needs names only. Do not expose registry source references to prompts. - Update central module, codec, merger, evidence, validator, default-chain,
prompt, and profile registration. Update the cross-lane prompt composition
test for the new prompt ID and
npc_registryinput without duplicating its ordering assertions in module-local tests. - Rename the integration contract to
docs/integrations/dnd-npc-registry-artifacts.md, update inbound links, and update the implemented module catalog, configuration reference, current internal D&D guide, and maintained examples for the new key and slot. - Remove the old package trees, asset tree, prompt IDs, module/validator keys,
capability, shared filename, and reference-slot name. The durable JSON field
npcs, the record typeNPC, and domain helper package namenpcsare not legacy module identifiers and should remain.
Acceptance criteria
dnd/npc-registryis the only selectable NPC registry extract/normalize key.- All NPC-registry consumers expose
npc_registryand accept onlydnd/npc-registryartifacts. - Prompt and schema assets load only from
assets/dnd/npc-registryand retain the documented cache order. - Current docs and examples contain no claim that
dnd/npcsis selectable.
Validation
go test ./internal/modules/dnd/... ./internal/modules/integration/... ./internal/cli/...
go run ./cmd/notarius config validate --config examples/dnd-minimal.config.yml --pipeline dnd-session
git diff --check
Stage 3: Redesign The NPC Occurrence Durable Contract
Goal
Replace the NPC-interaction value contract with the final registry-ID-backed
NPC occurrence contract while the selectable module temporarily remains
dnd/npc-interactions.
Required changes
- Replace
NPCInteractionListKind,NPCInteractionList,NPCInteractionKind, andNPCInteractionwithNPCOccurrenceListKind,NPCOccurrenceList,NPCOccurrenceKind, andNPCOccurrence. The envelope field isoccurrences; each record has requirednpc_id,name,kind, andsource_refs. - Retain the six existing category values and their precedence and splitting semantics. Change only the contract vocabulary and registry identity link; do not add relationship, sentiment, biography, or persistent-state fields.
- In the current codec package, adopt
dnd/npc-occurrence-list, durable schema IDnotarius.dnd.npc_occurrences, schema namenotarius_dnd_npc_occurrences_v1, and strict filednd_npc_occurrences.v1.json. - Change the current NPC-interaction private response contract to require
npc_idas well asname,kind, andsource_refs. Use private schema IDnotarius.dnd.npc_occurrences.llm, schema namenotarius_dnd_npc_occurrences_llm_v1, and a renamed schema file even though the prompt ID moves in Stage 4. - Project ordered
{id, name}NPC registry entries into extraction. Require the model to return an exact supplied pair. Extraction, normalization, and registry validators must reject unknown IDs and mismatched ID/name pairs rather than repairing by name similarity. - Update deterministic ordering, exact-duplicate identity, clone/evidence
helpers, merge functions, normalizers, validators, and diagnostics to include
npc_id. Preserve source chronology and distinct kinds/evidence. - Update enemy-event grounding to consume
NPCOccurrenceList, filteringcombat_opponentoccurrences while carrying only source-free grounding values. Do not add NPC IDs to the enemy-event durable contract. - Update
docs/integrations/dnd-npc-interaction-artifacts.mdin place to the new durable schema, root, and fields while accurately retaining the current producer key until Stage 4.
Acceptance criteria
- No production Go code refers to an
NPCInteraction*artifact type. - The durable artifact uses
occurrencesand validates exact NPC ID/name pairs. - Unknown IDs and mismatches are detected independently at extraction, normalization, and validation boundaries without mutation.
- Enemy-event grounding behavior remains source-free and category-filtered.
Validation
go test ./internal/modules/dnd/codec/npcinteractions ./internal/modules/dnd/extract/npcinteractions ./internal/modules/dnd/normalize/npcinteractions ./internal/modules/dnd/validate/npcinteractions/... ./internal/modules/dnd/extract/enemyevents ./internal/modules/dnd/normalize/enemyevents
go test ./internal/modules/dnd/... ./internal/modules/integration/...
git diff --check
Stage 4: Move NPC Occurrences Into Their Canonical Namespace
Goal
Complete the NPC migration by replacing interaction module/package vocabulary and updating the enemy-event dependency.
Required changes
- Move the codec, extract, normalize, validate, and D&D helper packages from
npcinteractionstonpcoccurrenceswhere they own the occurrence artifact. - Set extract and normalize keys to
dnd/npc-occurrences; rename validator keys and the provided capability to thenpc-occurrences/dnd.npc_occurrencesvocabulary. - Move
assets/dnd/npc-interactionstoassets/dnd/npc-occurrences. Change the extraction prompt ID todnd.npc_occurrences, update instructions from “interactions” to “occurrences” without changing category semantics, and keep the target private schema identity established in Stage 3. - Rename the generated reference and PromptKit grounding input consumed by
enemy events from
npc_interactionstonpc_occurrences. Update combat grounding assets, reference specs, fingerprint metadata, checkpoint inputs, and tests consistently. - Update central registration, default validator chains, artifact evidence and merge registration, prompt-cache tests, configuration keys, examples, and current documentation.
- Rename the integration contract to
docs/integrations/dnd-npc-occurrence-artifacts.mdand update every link from NPC registry, enemy event, combat, internal D&D, configuration, and JSON output documentation. - Delete every old package, key, schema, prompt, capability, asset, and current-
behavior reference for
dnd/npc-interactionsandnpc_interactions. Do not retain a module alias.
Acceptance criteria
dnd/npc-occurrencesis the only selectable NPC occurrence key.- Enemy events require
npc_occurrencesof kinddnd/npc-occurrence-list. - Current catalogs, examples, and documentation use occurrence vocabulary.
- No production package or asset directory named
npcinteractionsornpc-interactionsremains.
Validation
go test ./internal/modules/dnd/... ./internal/modules/integration/... ./internal/cli/...
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 5: Migrate The Location Registry Durable Contract And Identity
Goal
Adopt the final location registry type, artifact kind, schema identity, and
identity-policy namespace while the selectable module remains dnd/locations.
Required changes
- Replace
LocationListKindandLocationListwithLocationRegistryKindandLocationRegistry. RetainLocationand the durablelocationsroot. - Update all typed location-registry consumers, especially location-occurrence extraction, normalization, validation, reference resolution, merge, evidence, registration, and tests. Do not leave aliases.
- In the current location codec package, use kind
dnd/location-registry, schema IDnotarius.dnd.location_registry, schema namenotarius_dnd_location_registry_v1, and strict filednd_location_registry.v1.json. - Change the identity policy to
dnd.location_registry.identity.v1and retain the exact compact JSON input[policy, comparison_name, source_id, start_unit_id, end_unit_id]. Continue to select the earliest canonical evidence anchor without mutating caller data. Accept the resulting pre-release ID invalidation. - Update identity, registry, codec, same-name-location, normalization, and dependent occurrence fixtures. Tests must prove same-name distinct anchors, deterministic ordering, invalid component rejection, and exact documented bytes.
- Update
docs/integrations/dnd-location-artifacts.mdin place for the target kind, schema, and identity policy while retainingdnd/locationsas the current module key until Stage 6.
Acceptance criteria
- No production Go code refers to
LocationListorLocationListKind. - Same-name locations with distinct evidence anchors remain distinguishable.
- The codec and generated-reference compatibility use
dnd/location-registry. - No old kind, schema identity, or identity-policy compatibility path remains.
Validation
go test ./internal/modules/dnd/locations/... ./internal/modules/dnd/codec/locations ./internal/modules/dnd/extract/locations ./internal/modules/dnd/normalize/locations ./internal/modules/dnd/extract/locationoccurrences ./internal/modules/dnd/normalize/locationoccurrences ./internal/modules/dnd/validate/locations/... ./internal/modules/dnd/validate/locationoccurrences/...
go test ./internal/modules/dnd/... ./internal/modules/integration/...
git diff --check
Stage 6: Move And Tighten The Location Registry Module
Goal
Move location registry code and assets into the canonical namespace and enforce the roadmap's named-or-uniquely-designated eligibility policy.
Required changes
- Move the stage packages to
codec/locationregistry,extract/locationregistry,normalize/locationregistry, andvalidate/locationregistry/.... Entity identity and immutable registry helpers may remain underinternal/modules/dnd/locations. - Set extract and normalize keys to
dnd/location-registry; rename validator keys and the provided capability todnd.location_registry. - Move
assets/dnd/locations/{extract,normalize}toassets/dnd/location-registry/{extract,normalize}. Use prompt IDsdnd.location_registryanddnd.location_registry.normalize; use private schema IDnotarius.dnd.location_registry.llm, schema namenotarius_dnd_location_registry_llm_v1, and filenamednd_location_registry_llm.v1.json. - Change the location-registry extraction instructions to accept only a stable
proper name or unique in-world designation. Explicitly exclude generic,
temporary, relative, and descriptive phrases such as
the room,the bar,the hallway,outside, andupstairs. Do not use capitalization as the eligibility test and do not add a brittle deterministic word blacklist. - Rename the required location-occurrence reference slot and PromptKit input
from
locationstolocation_registry. Preserve the ordered source-free{id, name}projection and exact ID/name validation at extraction and normalization. - Update location-occurrence instructions so a generic current-chunk phrase may resolve to an existing named registry location only when context supports that coreference; it may not create a registry entity or substitute registry provenance for evidence.
- Update central registration, prompt composition, validator chains,
configuration, examples, and current docs. Rename the integration contract
to
docs/integrations/dnd-location-registry-artifacts.mdand update links. - Remove old module/package/asset/prompt/validator/capability identities and
old reference-slot names. The durable
locationsfield and domain helper package remain valid.
Acceptance criteria
dnd/location-registryis the only selectable location registry key.- Registry prompts exclude generic locations, while occurrence prompts permit supported coreference to an existing registry entity.
- Location occurrences require
location_registryof kinddnd/location-registryat extract and normalize stages. - No production compatibility alias for
dnd/locationsremains.
Validation
go test ./internal/modules/dnd/... ./internal/modules/integration/... ./internal/cli/...
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 7: Add The Item Registry Domain Foundation
Goal
Implement the item registry's typed durable contract, deterministic identity, codec, and immutable reference projection without registering a selectable pipeline module yet.
Required changes
- Add
ItemRegistryKind,ItemRegistry, andItemto the D&D domain types. The strict envelope is{"items":[...]}; each item has requiredid,name, andsource_refs. - Add an item identity package under
internal/modules/dnd/items/identity. Implement comparison normalization consistent with the NPC identity text family, policydnd.item_registry.identity.v1, compact JSON[policy, comparison_name], prefixitem:sha256:, syntax checks, registry uniqueness validation, and deterministic errors. - Add immutable item registry resolution under
internal/modules/dnd/items/registry. It must decode through the canonical codec, validate IDs, preserve same-name/type policy, return defensive copies, and produce an ordered source-free{id, name}projection suitable for a later reference slot. - Add
internal/modules/dnd/codec/itemregistrywith strict durable schemadnd_item_registry.v1.json, IDnotarius.dnd.item_registry, namenotarius_dnd_item_registry_v1, versionv1, and media typeapplication/json. - Test codec round trips, strict unknown-field rejection, candidate encoding, metadata, identity bytes, empty/malformed identities, duplicate IDs, defensive copies, projection order, and non-mutation.
- Do not register the codec or describe the item registry as selectable in current configuration or integration docs yet. The feature roadmap remains the canonical description until Stage 9.
Acceptance criteria
- The new type, identity, codec, and registry packages pass independently.
- Item IDs are name/type identities rather than per-instance identities.
- The projection exposes IDs and names but no source references.
- No generic framework package depends on D&D item types.
Validation
Run gofmt on every Go file changed in this stage, then run:
go test ./internal/modules/dnd/items/... ./internal/modules/dnd/codec/itemregistry
go test ./internal/modules/dnd/...
git diff --check
Stage 8: Implement Item Registry Extraction And Validation
Goal
Add the item-registry extraction module, private response contract, prompt assets, canonical mapping, and extraction validators without production registration.
Required changes
- Add
internal/modules/dnd/extract/itemregistrywith keydnd/item-registry, artifact kinddnd/item-registry, LLM-backed execution, the ordinary campaign reference slots, and prompt IDdnd.item_registry. - Add
assets/dnd/item-registry/extractcontainingprompt.yaml, one coherentinstructions.md, and strict private schemadnd_item_registry_llm.v1.jsonwith IDnotarius.dnd.item_registry.llmand namenotarius_dnd_item_registry_llm_v1. The private response contains required itemnameandsource_refs; deterministic code supplies source identity and derives the durable item ID. - Encode the roadmap eligibility policy precisely: accept named unique items,
concrete reusable item types, stable unique designations, and separate
currency denominations; reject vague
loot,treasure,some gear, generic weapons, inferred properties, quantities, and uniqueness. - Reuse the shared extraction prompt prefix and evidence policy. Keep the item registry instructions final and ephemeral. Do not add item occurrence, holder, inventory, or ledger rules to this prompt.
- Canonicalize display whitespace and evidence, derive IDs through the item identity package, preserve candidate evidence for validation, and order candidates deterministically. Do not semantically collapse aliases in the extractor.
- Add
validate/itemregistry/shape,source_refs, andsource_relatednesspackages and keys using the final module vocabulary. Keep relatedness advisory according to existing D&D conventions. - Add focused behavior, schema, prompt preparation, metadata-redaction, cancellation/error, and validator tests. Do not call a live model and do not snapshot full prompt text.
- Do not add the module to the production D&D registrar until its normalizer and complete default chains exist in Stage 9.
Acceptance criteria
- Direct module construction prepares and maps a strict item-registry response.
- Currency denominations and reusable item types are eligible; vague categories are excluded by prompt policy without a capitalization heuristic.
- Extracted records contain deterministic IDs and owned evidence slices.
- No current module catalog advertises an incomplete lane.
Validation
go test ./internal/modules/dnd/extract/itemregistry ./internal/modules/dnd/validate/itemregistry/...
go test ./internal/modules/dnd/...
git diff --check
Stage 9: Implement Item Registry Normalization And Production Registration
Goal
Complete and register the item registry as the third production registry family.
Required changes
- Add
internal/modules/dnd/normalize/itemregistrywith keydnd/item-registry, LLM-backed execution, prompt IDdnd.item_registry.normalize, and the same retry/fallback contract used by NPC and location registry normalization. - Deterministically preprocess candidate names, evidence, IDs, and exact duplicates. Then use the existing shared D&D entity-reconciliation proposal mechanics with item-specific candidates and selected transcript windows. Validated groups may choose one supplied canonical display name and union evidence; unsafe, overlapping, unknown, or uncertain groups preserve the deterministic result with bounded diagnostics.
- Add
assets/dnd/item-registry/normalizewithprompt.yaml,instructions.md, andcandidates.md. Item instructions own only same-item- kind/designation judgment and canonical display preference. The shared reconciliation fragment alone owns opaque keys and safe group mechanics. - Explicitly prevent reconciliation across currency denominations, materially different item types, or merely nearby objects. Do not create per-instance identities or infer properties.
- Add
validate/itemregistry/identityand its default normalize-chain position. Test retry, invalid structured output, operational error, warning bounds, idempotence, order, non-mutation, and content-safe diagnostics. - Register the item registry codec, evidence projection, append-order merger, extractor, normalizer, validators, default chains, prompt assets, and module metadata in the D&D registrar. Add it to the centralized extraction prompt composition test.
- Create the current durable contract at
docs/integrations/dnd-item-registry-artifacts.md. Update configuration and internal module catalogs enough to describe the now-selectable registry, but defer the complete multi-step example until item occurrences consume it.
Acceptance criteria
dnd/item-registryis selectable for extraction and normalization with complete production validator chains.- The normalizer uses proposal-only LLM semantics and deterministic application.
- Codec, merge, evidence, prompt, metadata, and registry registrations are all type-compatible.
- The current docs accurately describe the implemented item registry without claiming that item occurrences consume it yet.
Validation
go test ./internal/modules/dnd/items/... ./internal/modules/dnd/codec/itemregistry ./internal/modules/dnd/extract/itemregistry ./internal/modules/dnd/normalize/itemregistry ./internal/modules/dnd/validate/itemregistry/... ./internal/modules/dnd/register
go test ./internal/modules/dnd/... ./internal/cli/...
git diff --check
Stage 10: Redesign Item Events As Registry-Backed Item Occurrences
Goal
Adopt the final item occurrence durable contract and required item-registry
grounding while the selectable module temporarily remains dnd/item-events.
Required changes
- Replace
ItemEventListKind,ItemEventList,ItemEventKind, andItemEventwithItemOccurrenceListKind,ItemOccurrenceList,ItemOccurrenceKind, andItemOccurrence. Use durable rootoccurrences; each record has requireditem_id,name,kind, andsource_refs, plus conditionalquantity,from, andto. - Preserve the five existing kinds and all holder, quantity, currency, ordering, and exact-duplicate semantics. Rename the D&D helper behavior to occurrence vocabulary in code, but defer physical package moves to Stage 11.
- In the current codec package, adopt kind
dnd/item-occurrence-list, schema IDnotarius.dnd.item_occurrences, schema namenotarius_dnd_item_occurrences_v1, and strict filednd_item_occurrences.v1.json. - Change the private response schema to
notarius.dnd.item_occurrences.llm/notarius_dnd_item_occurrences_llm_v1indnd_item_occurrences_llm.v1.json. Require every property. Represent absentquantity,from, andtoas nullable private fields and map them to the durable conditional fields without fabricating values. - Add required
item_registryreference slots to both extraction and normalization, accepting onlydnd/item-registry,application/json, and an explicit size bound. Resolve one immutable registry per operation and render ordered source-free{id, name}entries after the shared evidence message. - Require the model to return an exact registry ID/name pair. Extraction must reject or omit unknown/mismatched pairs without creating an item. The deterministic normalizer must canonicalize recognized names by ID and retain unknown values for the registry validator to reject according to the current validation architecture.
- Add a registry membership validator to the item occurrence extract and
normalize chains. Update shape, invariant, source-reference, relatedness,
merge, evidence, clone, metadata, warning, and ordering behavior for
item_idand the new envelope. - Update the maintained complete example immediately: produce
dnd/item-registryin the earlier registry step and bind its generated artifact asitem_registryto the still-currentdnd/item-eventsextract and normalize stages. Keep the example valid at the end of this stage. - Update
docs/integrations/dnd-item-event-artifacts.mdin place to the target durable shape and required registry behavior while retaining the current producer key until Stage 11.
Acceptance criteria
- No production Go code uses an
ItemEvent*artifact type. - Every item occurrence carries an exact item-registry ID/name pair.
- Extraction and normalization both declare the identical required registry slot; validation detects unknown and mismatched identities.
- The complete example resolves with an earlier item registry and no same-step dependency.
Validation
go test ./internal/modules/dnd/itemevents ./internal/modules/dnd/codec/itemevents ./internal/modules/dnd/extract/itemevents ./internal/modules/dnd/normalize/itemevents ./internal/modules/dnd/validate/itemevents/... ./internal/modules/dnd/register ./internal/modules/integration/...
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 11: Move Item Occurrences Into Their Canonical Namespace
Goal
Complete the item migration by replacing item-event module, package, prompt, validator, asset, and documentation vocabulary.
Required changes
- Move
internal/modules/dnd/itemeventstoitemoccurrencesand move codec, extract, normalize, and validate packages to the correspondingitemoccurrencespaths. - Set extract and normalize keys to
dnd/item-occurrences; rename validator keys and the provided capability todnd.item_occurrences. - Move
assets/dnd/item-eventstoassets/dnd/item-occurrences. Use prompt IDdnd.item_occurrences, the target private schema identity from Stage 10, and occurrence terminology throughout module instructions. - Update all imports, central registrations, default chains, metadata, fingerprints, prompt composition cases, configuration keys, example lanes, generated references, output expectations, and tests.
- Rename the integration contract to
docs/integrations/dnd-item-occurrence-artifacts.mdand update links from item registry, configuration, internal D&D, and JSON output documentation. - Delete every old
itemevents,item-events,dnd/item-events,dnd.item_events,notarius.dnd.item_events,events-envelope fixture, and old schema/asset path that represented the retired artifact. Do not remove unrelated uses of the ordinary word “event” in other D&D lanes.
Acceptance criteria
dnd/item-occurrencesis the only selectable item occurrence key.- All item occurrence packages, prompts, validators, schemas, and docs use the canonical vocabulary.
- The complete example binds
item_registryinto both stages of the renamed lane. - No compatibility alias for item events remains.
Validation
go test ./internal/modules/dnd/... ./internal/modules/integration/... ./internal/cli/...
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 12: Verify The Complete Ordered Entity Pipeline
Goal
Make the maintained complete configuration and representative integration tests prove the final three-registry/three-occurrence architecture.
Required changes
- Finalize
examples/dnd-complete.config.ymlwith an earlier registry step containingnpc-registry,location-registry, anditem-registrylanes alongside scene descriptions. The next step contains NPC, location, and item occurrences plus spell and combat lanes. The derived enemy step consumesnpc_registry,npc_occurrences, combat turns, and scene descriptions. - Use generated-reference aliases
npc_registry,location_registry,item_registry, andnpc_occurrences. Preserve explicit step-and-lane selectors and stage-local spell-catalog bindings. Do not infer dependencies from matching names. - Update scene-plan eligibility configuration for all renamed lane labels while preserving the shared chunk plan and exact combat-scene routing semantics.
- Add or revise one representative integration workflow that executes the ordered handoffs with deterministic fake LLM responses and proves exact artifact-kind compatibility, registry projection, independent occurrence evidence, and final publication for all three entity families.
- Test compatible external path references for each registry through existing reference preparation. Do not duplicate the framework's exhaustive topology and failure-propagation cases; add only D&D-specific compatibility coverage.
- Test rejection of a wrong registry artifact kind and invalid same-step or forward binding at the existing resolver/integration boundary if those risks are not already credibly covered with the new kinds.
- Update CLI maintained-example contract tests and production catalog tests so both D&D examples load, validate, resolve, and list only implemented module and validator identities.
Acceptance criteria
- The complete example validates offline and resolves all generated handoffs.
- A representative assembled run proves all three registry-to-occurrence paths.
- External compatible registry artifacts remain supported.
- Cross-family integration tests protect compatibility without repeating package-level identity and validator cases.
Validation
go test ./internal/modules/integration/... ./internal/cli/... ./internal/modules/dnd/register
go run ./cmd/notarius config validate --config examples/dnd-minimal.config.yml --pipeline dnd-session
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 13: Consolidate Current Documentation And Examples
Goal
Bring every canonical current-behavior document into alignment with the final implemented entity family without duplicating contracts across documents.
Required changes
- Update
docs/config.mdas the canonical owner of selectable module keys, validator keys, default chains, reference slots, requiredness, size limits, execution classes, profile behavior, and ordered binding examples. - Update
docs/internal/dnd.mdfor ten final D&D artifact lanes, the three registry normalizers, source-free ID/name projections, occurrence grounding, package/asset ownership, and lane-specific differences. Link to integration contracts instead of repeating their schemas or categories. - Update
docs/internal/modules.md,docs/internal/overview.md, README, CLI, operations, JSON output, and other current documents only where they actually name affected modules, artifacts, examples, or links. Preserve each document's canonical scope under the documentation policy. - Ensure the six target integration contracts are the only canonical durable
entity contracts:
dnd-npc-registry-artifacts.md,dnd-npc-occurrence-artifacts.md,dnd-location-registry-artifacts.md,dnd-location-occurrence-artifacts.md,dnd-item-registry-artifacts.md, anddnd-item-occurrence-artifacts.md. - Each integration contract must define its exact kind, schema ID/name/version, media type, strict wire shape, identity or occurrence policy, evidence boundary, normalization behavior, consumers, and compatibility statement. Cross-link rather than copying common reference or output semantics.
- Verify that only
examples/dnd-minimal.config.ymlandexamples/dnd-complete.config.ymlremain as maintained D&D configurations, that both are secret-free, and that documentation links to rather than reproduces them. - Keep future or historical discussion in
docs/roadmap/and ADRs. Do not rewrite accepted ADRs as current reference documentation, add a changelog, or delete the active roadmap files.
Acceptance criteria
- Current docs contain only implemented final names and contracts.
- Each volatile fact has one canonical owner and all links resolve.
- Maintained examples are valid, copyable, and tested.
- No documentation claims compatibility with the retired pre-release names.
Validation
go test ./internal/cli/... ./internal/modules/integration/...
go run ./cmd/notarius config validate --config examples/dnd-minimal.config.yml --pipeline dnd-session
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check
Stage 14: Final Contract Audit And Repository Verification
Goal
Perform a final gap audit, remove stale implementation remnants, and prove the completed feature at repository scope.
Required changes
- Search production code, assets, tests, examples, and current documentation
for retired exact identities, including:
dnd/npcs,dnd/npc-interactions,dnd/locations,dnd/item-events,dnd/npc-list,dnd/npc-interaction-list,dnd/location-list,dnd/item-event-list, old schema IDs/names, old prompt IDs, old capability names,common-dnd-npcs.md, and old reference-slot names. Excludedocs/roadmap/, where migration context intentionally names the old values. - Search for retired Go artifact identifiers
NPCList,NPCInteraction,LocationList, andItemEvent. Distinguish legitimate words or unrelated concepts from compatibility remnants; remove every actual old contract or alias. - Verify the final package and asset trees contain only canonical registry and
occurrence stage packages. Confirm every D&D prompt subtree has
prompt.yamlandinstructions.md, manifests select only existing assets, and all prompt/schema fingerprints are content-safe. - Verify every private D&D response schema has
additionalProperties: false, includes every declared property inrequired, and uses the exact final private identity. Verify durable schemas independently through their codecs; do not conflate private and durable contracts. - Review default validator chains for all six entity modules. Each registry must have shape, identity, source-reference, schema, and relatedness coverage; each occurrence must additionally enforce exact registry membership and domain invariants at the appropriate stages.
- Review tests against
docs/policy/testing.md. Consolidate redundant cross-layer assertions, retain regression coverage for identities and handoffs, and do not add asset inventories or exact prefix-length detectors. - Run repository-wide tests, vet, build, example validation, and whitespace checks. Fix any defect discovered; do not merely document it as follow-up if it is within this roadmap's scope.
- Report any optional live-model observations separately. Live model quality is useful human evaluation but is not a credentialed automated acceptance gate and must not block deterministic completion.
Acceptance criteria
- The target end state in
entity-registries.mdis fully implemented. - No production compatibility alias or stale current-behavior name remains.
- All six entity modules register with exact typed contracts and default chains.
- Both maintained configurations validate offline.
- The full repository test, vet, and build checks pass with a clean diff check.
Validation
go test -count=1 ./...
go vet ./...
go build ./cmd/notarius
go run ./cmd/notarius config validate --config examples/dnd-minimal.config.yml --pipeline dnd-session
OPENROUTER_API_KEY=validation-placeholder go run ./cmd/notarius config validate --config examples/dnd-complete.config.yml --pipeline dnd-session
git diff --check